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