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