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