]> source.dussan.org Git - archiva.git/blob
cb46493c883fd7ad820d35c76827bb4916d52836
[archiva.git] /
1 package org.apache.maven.archiva.webdav;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Map;
25
26 import javax.servlet.ServletConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
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;
56
57 /**
58  * RepositoryServlet
59  * 
60  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
61  * @version $Id$
62  */
63 public class RepositoryServlet
64     extends AbstractWebdavServlet
65     implements ConfigurationListener
66 {
67     private Logger log = LoggerFactory.getLogger( RepositoryServlet.class );
68
69     private ArchivaConfiguration configuration;
70
71     private Map<String, ManagedRepositoryConfiguration> repositoryMap;
72
73     private DavLocatorFactory locatorFactory;
74
75     private DavResourceFactory resourceFactory;
76
77     private DavSessionProvider sessionProvider;
78
79     private final Object reloadLock = new Object();
80
81     public void init( javax.servlet.ServletConfig servletConfig )
82         throws ServletException
83     {
84         super.init( servletConfig );
85         initServers( servletConfig );
86     }
87
88     /**
89      * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
90      * to support different realms
91      * 
92      * @param request
93      * @param response
94      * @throws ServletException
95      * @throws java.io.IOException
96      */
97     @Override
98     protected void service( HttpServletRequest request, HttpServletResponse response )
99         throws ServletException, IOException
100     {
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() );
104         boolean noCache =
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;
109         
110         try
111         {   
112             // make sure there is a authenticated user
113             if ( !getDavSessionProvider().attachSession( webdavRequest ) )
114             {
115                 return;
116             }
117
118             // check matching if=header for lock-token relevant operations
119             resource =
120                 getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
121             
122             if ( !isPreconditionValid( webdavRequest, resource ) )
123             {
124                 webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
125                 return;
126             }
127             if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
128             {
129                 super.service( request, response );
130             }
131
132         }
133         catch ( UnauthorizedDavException e )
134         {
135             webdavResponse.setHeader( "WWW-Authenticate", getAuthenticateHeaderValue( e.getRepositoryName() ) );
136             webdavResponse.sendError( e.getErrorCode(), e.getStatusPhrase() );
137         }
138         catch ( BrowserRedirectException e )
139         {
140             response.sendRedirect( e.getLocation() );
141         }
142         catch ( DavException e )
143         {
144             if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
145             {
146                 final String msg = "Should throw " + UnauthorizedDavException.class.getName();
147                 log.error( msg );
148                 webdavResponse.sendError( e.getErrorCode(), msg );
149             }
150             else if ( e.getCause() != null )
151             {
152                 webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
153             }
154             else
155             {
156                 webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
157             }
158         }
159         finally
160         {
161             if( resource != null && resource.getResourcePath().endsWith( "metadata.xml" ) );
162             {
163                  String tmpFile = ( (ArchivaDavResourceFactory) getResourceFactory() ).getDefaultMergedMetadataLocation();
164                  FileUtils.deleteQuietly( new File( tmpFile ) );
165             }
166             getDavSessionProvider().releaseSession( webdavRequest );
167         }
168     }
169
170     public synchronized void initServers( ServletConfig servletConfig )
171     {
172         WebApplicationContext wac =
173             WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
174
175         configuration =
176             (ArchivaConfiguration) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaConfiguration.class.getName() ) );
177         configuration.addListener( this );
178
179         repositoryMap = configuration.getConfiguration().getManagedRepositoriesAsMap();
180
181         for ( ManagedRepositoryConfiguration repo : repositoryMap.values() )
182         {
183             File repoDir = new File( repo.getLocation() );
184
185             if ( !repoDir.exists() )
186             {
187                 if ( !repoDir.mkdirs() )
188                 {
189                     // Skip invalid directories.
190                     log( "Unable to create missing directory for " + repo.getLocation() );
191                     continue;
192                 }
193             }
194         }
195
196         resourceFactory =
197             (DavResourceFactory) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaDavResourceFactory.class ) );        
198         locatorFactory = new ArchivaDavLocatorFactory();
199         
200         ServletAuthenticator servletAuth =
201             (ServletAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( ServletAuthenticator.class.getName() ) );
202         HttpAuthenticator httpAuth =
203             (HttpAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( HttpAuthenticator.ROLE, "basic" ) );
204         
205         sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth );
206     }
207
208     public void configurationEvent( ConfigurationEvent event )
209     {
210         if ( event.getType() == ConfigurationEvent.SAVED )
211         {
212             initRepositories();
213         }
214     }
215
216     private void initRepositories()
217     {
218         synchronized ( repositoryMap )
219         {
220             repositoryMap.clear();
221             repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
222         }
223
224         synchronized ( reloadLock )
225         {
226             initServers( getServletConfig() );
227         }
228     }
229
230     public synchronized ManagedRepositoryConfiguration getRepository( String prefix )
231     {
232         if ( repositoryMap.isEmpty() )
233         {
234             repositoryMap.putAll( configuration.getConfiguration().getManagedRepositoriesAsMap() );
235         }
236         return repositoryMap.get( prefix );
237     }
238
239     ArchivaConfiguration getConfiguration()
240     {
241         return configuration;
242     }
243
244     protected boolean isPreconditionValid( final WebdavRequest request, final DavResource davResource )
245     {
246         // check for read or write access to the resource when resource-based permission is implemented
247         
248         return true;
249     }
250
251     public DavSessionProvider getDavSessionProvider()
252     {
253         return sessionProvider;
254     }
255
256     public void setDavSessionProvider( final DavSessionProvider davSessionProvider )
257     {
258         this.sessionProvider = davSessionProvider;
259     }
260
261     public DavLocatorFactory getLocatorFactory()
262     {
263         return locatorFactory;
264     }
265
266     public void setLocatorFactory( final DavLocatorFactory davLocatorFactory )
267     {
268         locatorFactory = davLocatorFactory;
269     }
270
271     public DavResourceFactory getResourceFactory()
272     {
273         return resourceFactory;
274     }
275
276     public void setResourceFactory( final DavResourceFactory davResourceFactory )
277     {
278         resourceFactory = davResourceFactory;
279     }
280
281     public String getAuthenticateHeaderValue()
282     {
283         throw new UnsupportedOperationException();
284     }
285
286     public String getAuthenticateHeaderValue( String repository )
287     {
288         return "Basic realm=\"Repository Archiva Managed " + repository + " Repository\"";
289     }
290 }