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
23 import java.io.IOException;
26 import javax.servlet.ServletConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
31 import org.apache.commons.io.FileUtils;
32 import org.apache.jackrabbit.webdav.DavException;
33 import org.apache.jackrabbit.webdav.DavLocatorFactory;
34 import org.apache.jackrabbit.webdav.DavMethods;
35 import org.apache.jackrabbit.webdav.DavResource;
36 import org.apache.jackrabbit.webdav.DavResourceFactory;
37 import org.apache.jackrabbit.webdav.DavServletResponse;
38 import org.apache.jackrabbit.webdav.DavSessionProvider;
39 import org.apache.jackrabbit.webdav.WebdavRequest;
40 import org.apache.jackrabbit.webdav.WebdavRequestImpl;
41 import org.apache.jackrabbit.webdav.WebdavResponse;
42 import org.apache.jackrabbit.webdav.WebdavResponseImpl;
43 import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
44 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
45 import org.apache.maven.archiva.configuration.ConfigurationEvent;
46 import org.apache.maven.archiva.configuration.ConfigurationListener;
47 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
48 import org.apache.maven.archiva.repository.audit.AuditEvent;
49 import org.apache.maven.archiva.security.ServletAuthenticator;
50 import org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator;
51 import org.codehaus.plexus.spring.PlexusToSpringUtils;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.web.context.WebApplicationContext;
55 import org.springframework.web.context.support.WebApplicationContextUtils;
60 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
63 public class RepositoryServlet
64 extends AbstractWebdavServlet
65 implements ConfigurationListener
67 private Logger log = LoggerFactory.getLogger( RepositoryServlet.class );
69 private ArchivaConfiguration configuration;
71 private Map<String, ManagedRepositoryConfiguration> repositoryMap;
73 private DavLocatorFactory locatorFactory;
75 private DavResourceFactory resourceFactory;
77 private DavSessionProvider sessionProvider;
79 private final Object reloadLock = new Object();
81 public void init( javax.servlet.ServletConfig servletConfig )
82 throws ServletException
84 super.init( servletConfig );
85 initServers( servletConfig );
89 * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
90 * to support different realms
94 * @throws ServletException
95 * @throws java.io.IOException
98 protected void service( HttpServletRequest request, HttpServletResponse response )
99 throws ServletException, IOException
101 WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
102 // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
103 int methodCode = DavMethods.getMethodCode( request.getMethod() );
105 DavMethods.isDeltaVMethod( webdavRequest ) &&
106 !( DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode );
107 WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
108 DavResource resource = null;
112 // make sure there is a authenticated user
113 if ( !getDavSessionProvider().attachSession( webdavRequest ) )
118 // check matching if=header for lock-token relevant operations
120 getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
122 if ( !isPreconditionValid( webdavRequest, resource ) )
124 webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
127 if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
129 super.service( request, response );
133 catch ( UnauthorizedDavException e )
135 webdavResponse.setHeader( "WWW-Authenticate", getAuthenticateHeaderValue( e.getRepositoryName() ) );
136 webdavResponse.sendError( e.getErrorCode(), e.getStatusPhrase() );
138 catch ( BrowserRedirectException e )
140 response.sendRedirect( e.getLocation() );
142 catch ( DavException e )
144 if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
146 final String msg = "Should throw " + UnauthorizedDavException.class.getName();
148 webdavResponse.sendError( e.getErrorCode(), msg );
150 else if ( e.getCause() != null )
152 webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
156 webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
161 if( resource != null && resource.getResourcePath().endsWith( "metadata.xml" ) );
163 String tmpFile = ( (ArchivaDavResourceFactory) getResourceFactory() ).getDefaultMergedMetadataLocation();
164 FileUtils.deleteQuietly( new File( tmpFile ) );
166 getDavSessionProvider().releaseSession( webdavRequest );
170 public synchronized void initServers( ServletConfig servletConfig )
172 WebApplicationContext wac =
173 WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
176 (ArchivaConfiguration) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaConfiguration.class.getName() ) );
177 configuration.addListener( this );
179 repositoryMap = configuration.getConfiguration().getManagedRepositoriesAsMap();
181 for ( ManagedRepositoryConfiguration repo : repositoryMap.values() )
183 File repoDir = new File( repo.getLocation() );
185 if ( !repoDir.exists() )
187 if ( !repoDir.mkdirs() )
189 // Skip invalid directories.
190 log( "Unable to create missing directory for " + repo.getLocation() );
197 (DavResourceFactory) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaDavResourceFactory.class ) );
198 locatorFactory = new ArchivaDavLocatorFactory();
200 ServletAuthenticator servletAuth =
201 (ServletAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( ServletAuthenticator.class.getName() ) );
202 HttpAuthenticator httpAuth =
203 (HttpAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( HttpAuthenticator.ROLE, "basic" ) );
205 sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth );
208 public void configurationEvent( ConfigurationEvent event )
210 if ( event.getType() == ConfigurationEvent.SAVED )
216 private void initRepositories()
218 synchronized ( repositoryMap )
220 repositoryMap.clear();
221 repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
224 synchronized ( reloadLock )
226 initServers( getServletConfig() );
230 public synchronized ManagedRepositoryConfiguration getRepository( String prefix )
232 if ( repositoryMap.isEmpty() )
234 repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
236 return repositoryMap.get( prefix );
239 ArchivaConfiguration getConfiguration()
241 return configuration;
244 protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
246 // check for read or write access to the resource when resource-based permission is implemented
251 public DavSessionProvider getDavSessionProvider()
253 return sessionProvider;
256 public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
258 this.sessionProvider = davSessionProvider;
261 public DavLocatorFactory getLocatorFactory()
263 return locatorFactory;
266 public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
268 locatorFactory = davLocatorFactory;
271 public DavResourceFactory getResourceFactory()
273 return resourceFactory;
276 public void setResourceFactory( final DavResourceFactory davResourceFactory )
278 resourceFactory = davResourceFactory;
281 public String getAuthenticateHeaderValue()
283 throw new UnsupportedOperationException();
286 public String getAuthenticateHeaderValue( String repository )
288 return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";