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