You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RepositoryServlet.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. package org.apache.maven.archiva.webdav;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. import java.io.File;
  21. import java.io.IOException;
  22. import java.util.Map;
  23. import javax.servlet.ServletConfig;
  24. import javax.servlet.ServletException;
  25. import javax.servlet.http.HttpServletRequest;
  26. import javax.servlet.http.HttpServletResponse;
  27. import org.apache.jackrabbit.webdav.DavException;
  28. import org.apache.jackrabbit.webdav.DavLocatorFactory;
  29. import org.apache.jackrabbit.webdav.DavMethods;
  30. import org.apache.jackrabbit.webdav.DavResource;
  31. import org.apache.jackrabbit.webdav.DavResourceFactory;
  32. import org.apache.jackrabbit.webdav.DavServletResponse;
  33. import org.apache.jackrabbit.webdav.DavSessionProvider;
  34. import org.apache.jackrabbit.webdav.WebdavRequest;
  35. import org.apache.jackrabbit.webdav.WebdavRequestImpl;
  36. import org.apache.jackrabbit.webdav.WebdavResponse;
  37. import org.apache.jackrabbit.webdav.WebdavResponseImpl;
  38. import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
  39. import org.apache.maven.archiva.configuration.ArchivaConfiguration;
  40. import org.apache.maven.archiva.configuration.ConfigurationEvent;
  41. import org.apache.maven.archiva.configuration.ConfigurationListener;
  42. import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
  43. import org.apache.maven.archiva.security.ServletAuthenticator;
  44. import org.codehaus.plexus.spring.PlexusToSpringUtils;
  45. import org.codehaus.redback.integration.filter.authentication.HttpAuthenticator;
  46. import org.slf4j.Logger;
  47. import org.slf4j.LoggerFactory;
  48. import org.springframework.web.context.WebApplicationContext;
  49. import org.springframework.web.context.support.WebApplicationContextUtils;
  50. /**
  51. * RepositoryServlet
  52. *
  53. * @version $Id$
  54. */
  55. public class RepositoryServlet
  56. extends AbstractWebdavServlet
  57. implements ConfigurationListener
  58. {
  59. private Logger log = LoggerFactory.getLogger( RepositoryServlet.class );
  60. private ArchivaConfiguration configuration;
  61. private Map<String, ManagedRepositoryConfiguration> repositoryMap;
  62. private DavLocatorFactory locatorFactory;
  63. private DavResourceFactory resourceFactory;
  64. private DavSessionProvider sessionProvider;
  65. private final Object reloadLock = new Object();
  66. public void init( javax.servlet.ServletConfig servletConfig )
  67. throws ServletException
  68. {
  69. super.init( servletConfig );
  70. initServers( servletConfig );
  71. }
  72. /**
  73. * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
  74. * to support different realms
  75. *
  76. * @param request
  77. * @param response
  78. * @throws ServletException
  79. * @throws java.io.IOException
  80. */
  81. @Override
  82. protected void service( HttpServletRequest request, HttpServletResponse response )
  83. throws ServletException, IOException
  84. {
  85. WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
  86. // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
  87. int methodCode = DavMethods.getMethodCode( request.getMethod() );
  88. boolean noCache =
  89. DavMethods.isDeltaVMethod( webdavRequest ) &&
  90. !( DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode );
  91. WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
  92. DavResource resource = null;
  93. try
  94. {
  95. // make sure there is a authenticated user
  96. if ( !getDavSessionProvider().attachSession( webdavRequest ) )
  97. {
  98. return;
  99. }
  100. // check matching if=header for lock-token relevant operations
  101. resource =
  102. getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
  103. if ( !isPreconditionValid( webdavRequest, resource ) )
  104. {
  105. webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
  106. return;
  107. }
  108. if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
  109. {
  110. super.service( request, response );
  111. }
  112. }
  113. catch ( UnauthorizedDavException e )
  114. {
  115. webdavResponse.setHeader( "WWW-Authenticate", getAuthenticateHeaderValue( e.getRepositoryName() ) );
  116. webdavResponse.sendError( e.getErrorCode(), e.getStatusPhrase() );
  117. }
  118. catch ( BrowserRedirectException e )
  119. {
  120. response.sendRedirect( e.getLocation() );
  121. }
  122. catch ( DavException e )
  123. {
  124. if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
  125. {
  126. final String msg = "Should throw " + UnauthorizedDavException.class.getName();
  127. log.error( msg );
  128. webdavResponse.sendError( e.getErrorCode(), msg );
  129. }
  130. else if ( e.getCause() != null )
  131. {
  132. webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
  133. }
  134. else
  135. {
  136. webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
  137. }
  138. }
  139. finally
  140. {
  141. getDavSessionProvider().releaseSession( webdavRequest );
  142. }
  143. }
  144. public synchronized void initServers( ServletConfig servletConfig )
  145. {
  146. WebApplicationContext wac =
  147. WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
  148. configuration =
  149. (ArchivaConfiguration) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaConfiguration.class.getName() ) );
  150. configuration.addListener( this );
  151. repositoryMap = configuration.getConfiguration().getManagedRepositoriesAsMap();
  152. for ( ManagedRepositoryConfiguration repo : repositoryMap.values() )
  153. {
  154. File repoDir = new File( repo.getLocation() );
  155. if ( !repoDir.exists() )
  156. {
  157. if ( !repoDir.mkdirs() )
  158. {
  159. // Skip invalid directories.
  160. log( "Unable to create missing directory for " + repo.getLocation() );
  161. continue;
  162. }
  163. }
  164. }
  165. resourceFactory =
  166. (DavResourceFactory) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaDavResourceFactory.class ) );
  167. locatorFactory = new ArchivaDavLocatorFactory();
  168. ServletAuthenticator servletAuth =
  169. (ServletAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( ServletAuthenticator.class.getName() ) );
  170. HttpAuthenticator httpAuth =
  171. (HttpAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( HttpAuthenticator.ROLE, "basic" ) );
  172. sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth );
  173. }
  174. public void configurationEvent( ConfigurationEvent event )
  175. {
  176. if ( event.getType() == ConfigurationEvent.SAVED )
  177. {
  178. initRepositories();
  179. }
  180. }
  181. private void initRepositories()
  182. {
  183. synchronized ( repositoryMap )
  184. {
  185. repositoryMap.clear();
  186. repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
  187. }
  188. synchronized ( reloadLock )
  189. {
  190. initServers( getServletConfig() );
  191. }
  192. }
  193. public synchronized ManagedRepositoryConfiguration getRepository( String prefix )
  194. {
  195. if ( repositoryMap.isEmpty() )
  196. {
  197. repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
  198. }
  199. return repositoryMap.get( prefix );
  200. }
  201. ArchivaConfiguration getConfiguration()
  202. {
  203. return configuration;
  204. }
  205. protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
  206. {
  207. // check for read or write access to the resource when resource-based permission is implemented
  208. return true;
  209. }
  210. public DavSessionProvider getDavSessionProvider()
  211. {
  212. return sessionProvider;
  213. }
  214. public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
  215. {
  216. this.sessionProvider = davSessionProvider;
  217. }
  218. public DavLocatorFactory getLocatorFactory()
  219. {
  220. return locatorFactory;
  221. }
  222. public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
  223. {
  224. locatorFactory = davLocatorFactory;
  225. }
  226. public DavResourceFactory getResourceFactory()
  227. {
  228. return resourceFactory;
  229. }
  230. public void setResourceFactory( final DavResourceFactory davResourceFactory )
  231. {
  232. resourceFactory = davResourceFactory;
  233. }
  234. public String getAuthenticateHeaderValue()
  235. {
  236. throw new UnsupportedOperationException();
  237. }
  238. public String getAuthenticateHeaderValue( String repository )
  239. {
  240. return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";
  241. }
  242. }