1 package org.apache.archiva.webdav;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.admin.model.RepositoryAdminException;
23 import org.apache.archiva.admin.model.beans.ManagedRepository;
24 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
25 import org.apache.archiva.security.ServletAuthenticator;
26 import org.apache.jackrabbit.webdav.DavException;
27 import org.apache.jackrabbit.webdav.DavLocatorFactory;
28 import org.apache.jackrabbit.webdav.DavMethods;
29 import org.apache.jackrabbit.webdav.DavResource;
30 import org.apache.jackrabbit.webdav.DavResourceFactory;
31 import org.apache.jackrabbit.webdav.DavServletResponse;
32 import org.apache.jackrabbit.webdav.DavSessionProvider;
33 import org.apache.jackrabbit.webdav.WebdavRequest;
34 import org.apache.jackrabbit.webdav.WebdavRequestImpl;
35 import org.apache.jackrabbit.webdav.WebdavResponse;
36 import org.apache.jackrabbit.webdav.WebdavResponseImpl;
37 import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
38 import org.apache.archiva.configuration.ArchivaConfiguration;
39 import org.apache.archiva.configuration.ConfigurationEvent;
40 import org.apache.archiva.configuration.ConfigurationListener;
41 import org.codehaus.redback.integration.filter.authentication.HttpAuthenticator;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.context.ConfigurableApplicationContext;
45 import org.springframework.web.context.WebApplicationContext;
46 import org.springframework.web.context.support.WebApplicationContextUtils;
48 import javax.servlet.ServletConfig;
49 import javax.servlet.ServletException;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
53 import java.io.IOException;
59 public class RepositoryServlet
60 extends AbstractWebdavServlet
61 implements ConfigurationListener
63 private Logger log = LoggerFactory.getLogger( RepositoryServlet.class );
65 private ArchivaConfiguration configuration;
67 private ManagedRepositoryAdmin managedRepositoryAdmin;
69 private Map<String, ManagedRepository> repositoryMap;
71 private DavLocatorFactory locatorFactory;
73 private DavResourceFactory resourceFactory;
75 private DavSessionProvider sessionProvider;
77 private final Object reloadLock = new Object();
79 public void init( ServletConfig servletConfig )
80 throws ServletException
82 super.init( servletConfig );
85 initServers( servletConfig );
87 catch ( RepositoryAdminException e )
89 log.error( e.getMessage(), e );
90 throw new ServletException( e.getMessage(), e );
95 * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
96 * to support different realms
100 * @throws ServletException
101 * @throws java.io.IOException
104 protected void service( HttpServletRequest request, HttpServletResponse response )
105 throws ServletException, IOException
107 WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
108 // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
109 int methodCode = DavMethods.getMethodCode( request.getMethod() );
110 boolean noCache = DavMethods.isDeltaVMethod( webdavRequest ) && !( DavMethods.DAV_VERSION_CONTROL == methodCode
111 || DavMethods.DAV_REPORT == methodCode );
112 WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
113 DavResource resource = null;
117 // make sure there is a authenticated user
118 if ( !getDavSessionProvider().attachSession( webdavRequest ) )
123 // check matching if=header for lock-token relevant operations
125 getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
127 if ( !isPreconditionValid( webdavRequest, resource ) )
129 webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
132 if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
134 super.service( request, response );
138 catch ( UnauthorizedDavException e )
140 webdavResponse.setHeader( "WWW-Authenticate", getAuthenticateHeaderValue( e.getRepositoryName() ) );
141 webdavResponse.sendError( e.getErrorCode(), e.getStatusPhrase() );
143 catch ( BrowserRedirectException e )
145 response.sendRedirect( e.getLocation() );
147 catch ( DavException e )
149 if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
151 final String msg = "Should throw " + UnauthorizedDavException.class.getName();
153 webdavResponse.sendError( e.getErrorCode(), msg );
155 else if ( e.getCause() != null )
157 webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
161 webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
166 getDavSessionProvider().releaseSession( webdavRequest );
170 public synchronized void initServers( ServletConfig servletConfig )
171 throws RepositoryAdminException
173 WebApplicationContext wac =
174 WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
176 configuration = wac.getBean( "archivaConfiguration#default", ArchivaConfiguration.class );
177 configuration.addListener( this );
179 managedRepositoryAdmin = wac.getBean( ManagedRepositoryAdmin.class );
181 repositoryMap = managedRepositoryAdmin.getManagedRepositoriesAsMap();
183 for ( ManagedRepository repo : repositoryMap.values() )
185 File repoDir = new File( repo.getLocation() );
187 if ( !repoDir.exists() )
189 if ( !repoDir.mkdirs() )
191 // Skip invalid directories.
192 log( "Unable to create missing directory for " + repo.getLocation() );
198 resourceFactory = wac.getBean( "davResourceFactory#archiva", DavResourceFactory.class );
199 locatorFactory = new ArchivaDavLocatorFactory();
201 ServletAuthenticator servletAuth = wac.getBean( ServletAuthenticator.class );
202 HttpAuthenticator httpAuth = wac.getBean( "httpAuthenticator#basic", HttpAuthenticator.class );
204 sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth );
206 log.info( "initServers done" );
209 public void configurationEvent( ConfigurationEvent event )
211 if ( event.getType() == ConfigurationEvent.SAVED )
217 catch ( RepositoryAdminException e )
219 log.error( e.getMessage(), e );
220 throw new RuntimeException( e.getMessage(), e );
225 private void initRepositories()
226 throws RepositoryAdminException
228 synchronized ( repositoryMap )
230 repositoryMap.clear();
231 repositoryMap.putAll( managedRepositoryAdmin.getManagedRepositoriesAsMap() );
234 synchronized ( reloadLock )
236 initServers( getServletConfig() );
240 public synchronized ManagedRepository getRepository( String prefix )
241 throws RepositoryAdminException
243 if ( repositoryMap.isEmpty() )
245 repositoryMap.putAll( managedRepositoryAdmin.getManagedRepositoriesAsMap() );
247 return repositoryMap.get( prefix );
250 ArchivaConfiguration getConfiguration()
252 return configuration;
255 protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
257 // check for read or write access to the resource when resource-based permission is implemented
262 public DavSessionProvider getDavSessionProvider()
264 return sessionProvider;
267 public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
269 this.sessionProvider = davSessionProvider;
272 public DavLocatorFactory getLocatorFactory()
274 return locatorFactory;
277 public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
279 locatorFactory = davLocatorFactory;
282 public DavResourceFactory getResourceFactory()
284 return resourceFactory;
287 public void setResourceFactory( final DavResourceFactory davResourceFactory )
289 resourceFactory = davResourceFactory;
292 public String getAuthenticateHeaderValue()
294 throw new UnsupportedOperationException();
297 public String getAuthenticateHeaderValue( String repository )
299 return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";
303 public void destroy()
305 configuration.removeListener( this );
307 resourceFactory = null;
308 configuration = null;
309 locatorFactory = null;
310 sessionProvider = null;
311 repositoryMap.clear();
312 repositoryMap = null;
314 WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( getServletContext() );
316 if ( wac instanceof ConfigurableApplicationContext )
318 ( (ConfigurableApplicationContext) wac ).close();