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 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package org.apache.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 org.apache.archiva.admin.model.RepositoryAdminException;
  21. import org.apache.archiva.configuration.ArchivaConfiguration;
  22. import org.apache.archiva.configuration.ConfigurationEvent;
  23. import org.apache.archiva.configuration.ConfigurationListener;
  24. import org.apache.archiva.redback.integration.filter.authentication.HttpAuthenticator;
  25. import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
  26. import org.apache.archiva.repository.ManagedRepository;
  27. import org.apache.archiva.repository.RepositoryRegistry;
  28. import org.apache.archiva.security.ServletAuthenticator;
  29. import org.apache.jackrabbit.webdav.DavException;
  30. import org.apache.jackrabbit.webdav.DavLocatorFactory;
  31. import org.apache.jackrabbit.webdav.DavMethods;
  32. import org.apache.jackrabbit.webdav.DavResource;
  33. import org.apache.jackrabbit.webdav.DavResourceFactory;
  34. import org.apache.jackrabbit.webdav.DavServletResponse;
  35. import org.apache.jackrabbit.webdav.DavSessionProvider;
  36. import org.apache.jackrabbit.webdav.WebdavRequest;
  37. import org.apache.jackrabbit.webdav.WebdavRequestImpl;
  38. import org.apache.jackrabbit.webdav.WebdavResponse;
  39. import org.apache.jackrabbit.webdav.WebdavResponseImpl;
  40. import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
  41. import org.slf4j.Logger;
  42. import org.slf4j.LoggerFactory;
  43. import org.springframework.context.ConfigurableApplicationContext;
  44. import org.springframework.web.context.WebApplicationContext;
  45. import org.springframework.web.context.support.WebApplicationContextUtils;
  46. import javax.servlet.ServletConfig;
  47. import javax.servlet.ServletException;
  48. import javax.servlet.http.HttpServletRequest;
  49. import javax.servlet.http.HttpServletResponse;
  50. import java.io.IOException;
  51. import java.util.concurrent.locks.ReentrantReadWriteLock;
  52. /**
  53. * RepositoryServlet
  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. RepositoryRegistry repositoryRegistry;
  62. private DavLocatorFactory locatorFactory;
  63. private DavResourceFactory resourceFactory;
  64. private DavSessionProvider sessionProvider;
  65. protected final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
  66. @Override
  67. public void init( ServletConfig servletConfig )
  68. throws ServletException
  69. {
  70. super.init( servletConfig );
  71. initServers( servletConfig );
  72. }
  73. /**
  74. * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
  75. * to support different realms
  76. *
  77. * @param request
  78. * @param response
  79. * @throws ServletException
  80. * @throws java.io.IOException
  81. */
  82. @Override
  83. protected void service( HttpServletRequest request, HttpServletResponse response )
  84. throws ServletException, IOException
  85. {
  86. WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
  87. // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
  88. int methodCode = DavMethods.getMethodCode( request.getMethod() );
  89. boolean noCache = DavMethods.isDeltaVMethod( webdavRequest ) && !( DavMethods.DAV_VERSION_CONTROL == methodCode
  90. || 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 void initServers( ServletConfig servletConfig ) {
  145. long start = System.currentTimeMillis();
  146. WebApplicationContext wac =
  147. WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
  148. rwLock.writeLock().lock();
  149. try {
  150. configuration = wac.getBean("archivaConfiguration#default", ArchivaConfiguration.class);
  151. configuration.addListener(this);
  152. repositoryRegistry = wac.getBean( ArchivaRepositoryRegistry.class);
  153. resourceFactory = wac.getBean("davResourceFactory#archiva", DavResourceFactory.class);
  154. locatorFactory = new ArchivaDavLocatorFactory();
  155. ServletAuthenticator servletAuth = wac.getBean(ServletAuthenticator.class);
  156. HttpAuthenticator httpAuth = wac.getBean("httpAuthenticator#basic", HttpAuthenticator.class);
  157. sessionProvider = new ArchivaDavSessionProvider(servletAuth, httpAuth);
  158. } finally {
  159. rwLock.writeLock().unlock();
  160. }
  161. long end = System.currentTimeMillis();
  162. log.debug( "initServers done in {} ms", (end - start) );
  163. }
  164. @Override
  165. public void configurationEvent( ConfigurationEvent event )
  166. {
  167. if ( event.getType() == ConfigurationEvent.SAVED )
  168. {
  169. try
  170. {
  171. initRepositories();
  172. }
  173. catch ( RepositoryAdminException e )
  174. {
  175. log.error( e.getMessage(), e );
  176. throw new RuntimeException( e.getMessage(), e );
  177. }
  178. }
  179. }
  180. private void initRepositories()
  181. throws RepositoryAdminException
  182. {
  183. initServers( getServletConfig() );
  184. }
  185. public ManagedRepository getRepository( String prefix )
  186. throws RepositoryAdminException
  187. {
  188. return repositoryRegistry.getManagedRepository( prefix );
  189. }
  190. ArchivaConfiguration getConfiguration()
  191. {
  192. return configuration;
  193. }
  194. @Override
  195. protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
  196. {
  197. // check for read or write access to the resource when resource-based permission is implemented
  198. return true;
  199. }
  200. @Override
  201. public DavSessionProvider getDavSessionProvider()
  202. {
  203. return sessionProvider;
  204. }
  205. @Override
  206. public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
  207. {
  208. this.sessionProvider = davSessionProvider;
  209. }
  210. @Override
  211. public DavLocatorFactory getLocatorFactory()
  212. {
  213. return locatorFactory;
  214. }
  215. @Override
  216. public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
  217. {
  218. locatorFactory = davLocatorFactory;
  219. }
  220. @Override
  221. public DavResourceFactory getResourceFactory()
  222. {
  223. return resourceFactory;
  224. }
  225. @Override
  226. public void setResourceFactory( final DavResourceFactory davResourceFactory )
  227. {
  228. resourceFactory = davResourceFactory;
  229. }
  230. @Override
  231. public String getAuthenticateHeaderValue()
  232. {
  233. throw new UnsupportedOperationException();
  234. }
  235. public String getAuthenticateHeaderValue( String repository )
  236. {
  237. return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";
  238. }
  239. @Override
  240. public void destroy()
  241. {
  242. rwLock.writeLock().lock();
  243. try {
  244. configuration.removeListener(this);
  245. resourceFactory = null;
  246. configuration = null;
  247. locatorFactory = null;
  248. sessionProvider = null;
  249. WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
  250. if (wac instanceof ConfigurableApplicationContext) {
  251. ((ConfigurableApplicationContext) wac).close();
  252. }
  253. super.destroy();
  254. } finally {
  255. rwLock.writeLock().unlock();
  256. }
  257. }
  258. }