1 package org.apache.maven.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.jackrabbit.webdav.DavException;
23 import org.apache.jackrabbit.webdav.DavLocatorFactory;
24 import org.apache.jackrabbit.webdav.DavMethods;
25 import org.apache.jackrabbit.webdav.DavResource;
26 import org.apache.jackrabbit.webdav.DavResourceFactory;
27 import org.apache.jackrabbit.webdav.DavServletResponse;
28 import org.apache.jackrabbit.webdav.DavSessionProvider;
29 import org.apache.jackrabbit.webdav.WebdavRequest;
30 import org.apache.jackrabbit.webdav.WebdavRequestImpl;
31 import org.apache.jackrabbit.webdav.WebdavResponse;
32 import org.apache.jackrabbit.webdav.WebdavResponseImpl;
33 import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
34 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
35 import org.apache.maven.archiva.configuration.ConfigurationEvent;
36 import org.apache.maven.archiva.configuration.ConfigurationListener;
37 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
38 import org.apache.archiva.security.ServletAuthenticator;
39 import org.codehaus.redback.integration.filter.authentication.HttpAuthenticator;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.springframework.context.ConfigurableApplicationContext;
43 import org.springframework.web.context.WebApplicationContext;
44 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;
51 import java.io.IOException;
57 public class RepositoryServlet
58 extends AbstractWebdavServlet
59 implements ConfigurationListener
61 private Logger log = LoggerFactory.getLogger( RepositoryServlet.class );
63 private ArchivaConfiguration configuration;
65 private Map<String, ManagedRepositoryConfiguration> repositoryMap;
67 private DavLocatorFactory locatorFactory;
69 private DavResourceFactory resourceFactory;
71 private DavSessionProvider sessionProvider;
73 private final Object reloadLock = new Object();
75 public void init( javax.servlet.ServletConfig servletConfig )
76 throws ServletException
78 super.init( servletConfig );
79 initServers( servletConfig );
83 * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
84 * to support different realms
88 * @throws ServletException
89 * @throws java.io.IOException
92 protected void service( HttpServletRequest request, HttpServletResponse response )
93 throws ServletException, IOException
95 WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
96 // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
97 int methodCode = DavMethods.getMethodCode( request.getMethod() );
98 boolean noCache = DavMethods.isDeltaVMethod( webdavRequest ) && !( DavMethods.DAV_VERSION_CONTROL == methodCode
99 || DavMethods.DAV_REPORT == methodCode );
100 WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
101 DavResource resource = null;
105 // make sure there is a authenticated user
106 if ( !getDavSessionProvider().attachSession( webdavRequest ) )
111 // check matching if=header for lock-token relevant operations
113 getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
115 if ( !isPreconditionValid( webdavRequest, resource ) )
117 webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
120 if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
122 super.service( request, response );
126 catch ( UnauthorizedDavException e )
128 webdavResponse.setHeader( "WWW-Authenticate", getAuthenticateHeaderValue( e.getRepositoryName() ) );
129 webdavResponse.sendError( e.getErrorCode(), e.getStatusPhrase() );
131 catch ( BrowserRedirectException e )
133 response.sendRedirect( e.getLocation() );
135 catch ( DavException e )
137 if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
139 final String msg = "Should throw " + UnauthorizedDavException.class.getName();
141 webdavResponse.sendError( e.getErrorCode(), msg );
143 else if ( e.getCause() != null )
145 webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
149 webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
154 getDavSessionProvider().releaseSession( webdavRequest );
158 public synchronized void initServers( ServletConfig servletConfig )
160 WebApplicationContext wac =
161 WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
163 configuration = wac.getBean( "archivaConfiguration#default", ArchivaConfiguration.class );
164 configuration.addListener( this );
166 repositoryMap = configuration.getConfiguration().getManagedRepositoriesAsMap();
168 for ( ManagedRepositoryConfiguration repo : repositoryMap.values() )
170 File repoDir = new File( repo.getLocation() );
172 if ( !repoDir.exists() )
174 if ( !repoDir.mkdirs() )
176 // Skip invalid directories.
177 log( "Unable to create missing directory for " + repo.getLocation() );
183 resourceFactory = wac.getBean("davResourceFactory#archiva", DavResourceFactory.class );
184 locatorFactory = new ArchivaDavLocatorFactory();
186 ServletAuthenticator servletAuth = wac.getBean( ServletAuthenticator.class );
187 HttpAuthenticator httpAuth = wac.getBean( "httpAuthenticator#basic", HttpAuthenticator.class );
189 sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth );
191 log.info( "initServers done" );
194 public void configurationEvent( ConfigurationEvent event )
196 if ( event.getType() == ConfigurationEvent.SAVED )
202 private void initRepositories()
204 synchronized ( repositoryMap )
206 repositoryMap.clear();
207 repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
210 synchronized ( reloadLock )
212 initServers( getServletConfig() );
216 public synchronized ManagedRepositoryConfiguration getRepository( String prefix )
218 if ( repositoryMap.isEmpty() )
220 repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
222 return repositoryMap.get( prefix );
225 ArchivaConfiguration getConfiguration()
227 return configuration;
230 protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
232 // check for read or write access to the resource when resource-based permission is implemented
237 public DavSessionProvider getDavSessionProvider()
239 return sessionProvider;
242 public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
244 this.sessionProvider = davSessionProvider;
247 public DavLocatorFactory getLocatorFactory()
249 return locatorFactory;
252 public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
254 locatorFactory = davLocatorFactory;
257 public DavResourceFactory getResourceFactory()
259 return resourceFactory;
262 public void setResourceFactory( final DavResourceFactory davResourceFactory )
264 resourceFactory = davResourceFactory;
267 public String getAuthenticateHeaderValue()
269 throw new UnsupportedOperationException();
272 public String getAuthenticateHeaderValue( String repository )
274 return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";
278 public void destroy()
280 configuration.removeListener( this );
282 resourceFactory = null;
283 configuration = null;
284 locatorFactory = null;
285 sessionProvider = null;
286 repositoryMap.clear();
287 repositoryMap = null;
289 WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( getServletContext() );
291 if ( wac instanceof ConfigurableApplicationContext )
293 ( (ConfigurableApplicationContext) wac ).close();