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