]> source.dussan.org Git - archiva.git/blob
3b4d0b27d5a135ede0af02f75b4567d4984bab15
[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 com.opensymphony.xwork.ActionContext;
23 import org.apache.jackrabbit.webdav.*;
24 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
25 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
26 import org.apache.maven.archiva.repository.RepositoryException;
27 import org.apache.maven.archiva.repository.RepositoryContentFactory;
28 import org.apache.maven.archiva.repository.layout.LayoutException;
29 import org.apache.maven.archiva.repository.content.RepositoryRequest;
30 import org.apache.maven.archiva.repository.audit.AuditListener;
31 import org.apache.maven.archiva.repository.audit.Auditable;
32 import org.apache.maven.archiva.repository.audit.AuditEvent;
33 import org.apache.maven.archiva.repository.metadata.MetadataTools;
34 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
35 import org.apache.maven.archiva.webdav.util.WebdavMethodUtil;
36 import org.apache.maven.archiva.webdav.util.MimeTypes;
37 import org.apache.maven.archiva.webdav.util.RepositoryPathUtil;
38 import org.apache.maven.archiva.proxy.RepositoryProxyConnectors;
39 import org.apache.maven.archiva.common.utils.PathUtil;
40 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
41 import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration;
42 import org.apache.maven.archiva.model.ArtifactReference;
43 import org.apache.maven.archiva.model.ProjectReference;
44 import org.apache.maven.archiva.model.VersionedReference;
45 import org.apache.maven.archiva.policies.ProxyDownloadException;
46 import org.apache.maven.archiva.security.ArchivaXworkUser;
47 import org.apache.maven.archiva.security.ServletAuthenticator;
48 import org.apache.maven.model.DistributionManagement;
49 import org.apache.maven.model.Model;
50 import org.apache.maven.model.Relocation;
51 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
52 import org.codehaus.plexus.redback.authentication.AuthenticationException;
53 import org.codehaus.plexus.redback.authentication.AuthenticationResult;
54 import org.codehaus.plexus.redback.authorization.AuthorizationException;
55 import org.codehaus.plexus.redback.authorization.UnauthorizedException;
56 import org.codehaus.plexus.redback.policy.AccountLockedException;
57 import org.codehaus.plexus.redback.policy.MustChangePasswordException;
58 import org.codehaus.plexus.redback.system.SecuritySession;
59 import org.codehaus.plexus.redback.system.SecuritySystemConstants;
60 import org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator;
61 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 import javax.servlet.http.HttpServletResponse;
66 import java.util.ArrayList;
67 import java.util.HashMap;
68 import java.util.List;
69 import java.util.Map;
70 import java.io.*;
71
72 /**
73  * @author <a href="mailto:james@atlassian.com">James William Dumay</a>
74  * @plexus.component role="org.apache.maven.archiva.webdav.ArchivaDavResourceFactory"
75  */
76 public class ArchivaDavResourceFactory
77     implements DavResourceFactory, Auditable
78 {
79     private Logger log = LoggerFactory.getLogger( ArchivaDavResourceFactory.class );
80
81     /**
82      * @plexus.requirement role="org.apache.maven.archiva.repository.audit.AuditListener"
83      */
84     private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
85
86     /**
87      * @plexus.requirement
88      */
89     private RepositoryContentFactory repositoryFactory;
90
91     /**
92      * @plexus.requirement
93      */
94     private RepositoryRequest repositoryRequest;
95
96     /**
97      * @plexus.requirement role-hint="default"
98      */
99     private RepositoryProxyConnectors connectors;
100
101     /**
102      * @plexus.requirement
103      */
104     private MetadataTools metadataTools;
105
106     /**
107      * @plexus.requirement
108      */
109     private MimeTypes mimeTypes;
110
111     /**
112      * @plexus.requirement
113      */
114     private ArchivaConfiguration archivaConfiguration;
115     
116     /**
117      * @plexus.requirement
118      */
119     private ServletAuthenticator servletAuth;
120
121     /**
122      * @plexus.requirement role-hint="basic"
123      */
124     private HttpAuthenticator httpAuth;
125     
126     public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request,
127                                        final DavServletResponse response )
128         throws DavException
129     {   
130         checkLocatorIsInstanceOfRepositoryLocator( locator );
131         ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
132         
133         RepositoryGroupConfiguration repoGroupConfig =
134             archivaConfiguration.getConfiguration().getRepositoryGroupsAsMap().get(
135                                                                                     ( (RepositoryLocator) locator ).getRepositoryId() );
136         List<String> repositories = new ArrayList<String>();
137
138         boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() );
139         boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
140                 
141         if ( repoGroupConfig != null )
142         {   
143             if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
144             {
145                 throw new DavException( HttpServletResponse.SC_BAD_REQUEST, "Bad request to repository group <" +
146                     repoGroupConfig.getId() + ">" );
147             }
148             repositories.addAll( repoGroupConfig.getRepositories() );
149             
150             // handle browse requests for virtual repos
151             if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).endsWith( "/" ) )                
152             {                    
153                 return getResource( request, repositories, archivaLocator );                
154             }            
155         }
156         else
157         {
158             repositories.add( ( (RepositoryLocator) locator ).getRepositoryId() );
159         }
160
161         DavResource resource = null;
162         DavException e = null;
163
164         for ( String repositoryId : repositories )
165         {
166             ManagedRepositoryContent managedRepository = null;
167
168             try
169             {
170                 managedRepository = getManagedRepository( repositoryId );
171             }
172             catch ( DavException de )
173             {
174                 throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" +
175                     repositoryId + ">" );
176             }
177
178             if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) )
179             {
180                 if ( managedRepository != null )
181                 {
182                     try
183                     {
184                         if( isAuthorized( request, repositoryId ) )
185                         {                        
186                             LogicalResource logicalResource =
187                                 new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
188                                                 
189                             if ( isGet )
190                             {
191                                 resource = doGet( managedRepository, request, archivaLocator, logicalResource );
192                             }
193         
194                             if ( isPut )
195                             {
196                                 resource = doPut( managedRepository, request, archivaLocator, logicalResource );
197                             }
198                         }
199                     }
200                     catch ( DavException de )
201                     {   
202                         e = de;
203                         continue;
204                     }
205                                         
206                     if( resource == null )
207                     {
208                         e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Repository does not exist" );
209                     }
210                     else
211                     {
212                         setHeaders( locator, response );
213
214                         // compatibility with MRM-440 to ensure browsing the repository works ok
215                         if ( resource.isCollection() && !resource.getLocator().getResourcePath().endsWith( "/" ) )
216                         {
217                             throw new BrowserRedirectException( resource.getHref() );
218                         }
219
220                         return resource;
221                     }
222                 }
223                 else
224                 {
225                     e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Repository does not exist" );
226                 }
227             }
228         }
229
230         throw e;
231     }
232     
233     public DavResource createResource( final DavResourceLocator locator, final DavSession davSession )
234         throws DavException
235     {        
236         checkLocatorIsInstanceOfRepositoryLocator( locator );
237         ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
238
239         DavResource resource = null;
240         if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) )
241         {
242             ManagedRepositoryContent managedRepository = getManagedRepository( archivaLocator.getRepositoryId() );
243             String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() );
244             File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource );
245             resource =
246                 new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, mimeTypes, archivaLocator,
247                                         this );
248         }
249         return resource;
250     }
251
252     private DavResource doGet( ManagedRepositoryContent managedRepository, DavServletRequest request,
253                                ArchivaDavResourceLocator locator, LogicalResource logicalResource )
254         throws DavException
255     {
256         File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
257         ArchivaDavResource resource =
258             new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator, this );
259
260         if ( !resource.isCollection() )
261         {
262             // At this point the incoming request can either be in default or
263             // legacy layout format.
264             boolean fromProxy = fetchContentFromProxies( managedRepository, request, logicalResource );
265
266             boolean previouslyExisted = resourceFile.exists();
267
268             try
269             {
270                 // Perform an adjustment of the resource to the managed
271                 // repository expected path.
272                 String localResourcePath =
273                     repositoryRequest.toNativePath( logicalResource.getPath(), managedRepository );
274                 resourceFile = new File( managedRepository.getRepoRoot(), localResourcePath );
275             }
276             catch ( LayoutException e )
277             {
278                 if ( previouslyExisted )
279                 {
280                     return resource;
281                 }
282                 throw new DavException( HttpServletResponse.SC_NOT_FOUND, e );
283             }
284
285             // Attempt to fetch the resource from any defined proxy.
286             if ( fromProxy )
287             {
288                 processAuditEvents( request, locator.getWorkspaceName(), logicalResource.getPath(), previouslyExisted,
289                                     resourceFile, " (proxied)" );
290             }
291             resource =
292                 new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator,
293                                         this );
294
295             if ( !resourceFile.exists() )
296             {
297                 resource = null;
298             }
299         }
300         return resource;
301     }
302
303     private DavResource doPut( ManagedRepositoryContent managedRepository, DavServletRequest request,
304                                ArchivaDavResourceLocator locator, LogicalResource logicalResource )
305         throws DavException
306     {
307         /*
308          * Create parent directories that don't exist when writing a file This actually makes this implementation not
309          * compliant to the WebDAV RFC - but we have enough knowledge about how the collection is being used to do this
310          * reasonably and some versions of Maven's WebDAV don't correctly create the collections themselves.
311          */
312
313         File rootDirectory = new File( managedRepository.getRepoRoot() );
314         File destDir = new File( rootDirectory, logicalResource.getPath() ).getParentFile();
315         if ( !destDir.exists() )
316         {
317             destDir.mkdirs();
318             String relPath = PathUtil.getRelative( rootDirectory.getAbsolutePath(), destDir );
319             triggerAuditEvent( request, logicalResource.getPath(), relPath, AuditEvent.CREATE_DIR );
320         }
321
322         File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
323
324         boolean previouslyExisted = resourceFile.exists();
325
326         processAuditEvents( request, locator.getRepositoryId(), logicalResource.getPath(), previouslyExisted,
327                             resourceFile, null );
328
329         return new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator,
330                                        this );
331     }
332
333     private boolean fetchContentFromProxies( ManagedRepositoryContent managedRepository, DavServletRequest request,
334                                              LogicalResource resource )
335         throws DavException
336     {
337         if ( repositoryRequest.isSupportFile( resource.getPath() ) )
338         {
339             // Checksums are fetched with artifact / metadata.
340
341             // Need to adjust the path for the checksum resource.
342             return false;
343         }
344
345         // Is it a Metadata resource?
346         if ( repositoryRequest.isDefault( resource.getPath() ) && repositoryRequest.isMetadata( resource.getPath() ) )
347         {
348             return fetchMetadataFromProxies( managedRepository, request, resource );
349         }
350
351         // Not any of the above? Then it's gotta be an artifact reference.
352         try
353         {
354             // Get the artifact reference in a layout neutral way.
355             ArtifactReference artifact = repositoryRequest.toArtifactReference( resource.getPath() );
356
357             if ( artifact != null )
358             {
359                 applyServerSideRelocation( managedRepository, artifact );
360
361                 File proxiedFile = connectors.fetchFromProxies( managedRepository, artifact );
362
363                 resource.setPath( managedRepository.toPath( artifact ) );
364
365                 return ( proxiedFile != null );
366             }
367         }
368         catch ( LayoutException e )
369         {
370             /* eat it */
371         }
372         catch ( ProxyDownloadException e )
373         {
374             log.error( e.getMessage(), e );
375             throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to fetch artifact resource." );
376         }
377         return false;
378     }
379
380     private boolean fetchMetadataFromProxies( ManagedRepositoryContent managedRepository, DavServletRequest request,
381                                               LogicalResource resource )
382         throws DavException
383     {
384         ProjectReference project;
385         VersionedReference versioned;
386
387         try
388         {
389
390             versioned = metadataTools.toVersionedReference( resource.getPath() );
391             if ( versioned != null )
392             {
393                 connectors.fetchFromProxies( managedRepository, versioned );
394                 return true;
395             }
396         }
397         catch ( RepositoryMetadataException e )
398         {
399             /* eat it */
400         }
401
402         try
403         {
404             project = metadataTools.toProjectReference( resource.getPath() );
405             if ( project != null )
406             {
407                 connectors.fetchFromProxies( managedRepository, project );
408                 return true;
409             }
410         }
411         catch ( RepositoryMetadataException e )
412         {
413             /* eat it */
414         }
415
416         return false;
417     }
418
419     /**
420      * A relocation capable client will request the POM prior to the artifact, and will then read meta-data and do
421      * client side relocation. A simplier client (like maven 1) will only request the artifact and not use the
422      * metadatas.
423      * <p>
424      * For such clients, archiva does server-side relocation by reading itself the &lt;relocation&gt; element in
425      * metadatas and serving the expected artifact.
426      */
427     protected void applyServerSideRelocation( ManagedRepositoryContent managedRepository, ArtifactReference artifact )
428         throws ProxyDownloadException
429     {
430         if ( "pom".equals( artifact.getType() ) )
431         {
432             return;
433         }
434
435         // Build the artifact POM reference
436         ArtifactReference pomReference = new ArtifactReference();
437         pomReference.setGroupId( artifact.getGroupId() );
438         pomReference.setArtifactId( artifact.getArtifactId() );
439         pomReference.setVersion( artifact.getVersion() );
440         pomReference.setType( "pom" );
441
442         // Get the artifact POM from proxied repositories if needed
443         connectors.fetchFromProxies( managedRepository, pomReference );
444
445         // Open and read the POM from the managed repo
446         File pom = managedRepository.toFile( pomReference );
447
448         if ( !pom.exists() )
449         {
450             return;
451         }
452
453         try
454         {
455             Model model = new MavenXpp3Reader().read( new FileReader( pom ) );
456             DistributionManagement dist = model.getDistributionManagement();
457             if ( dist != null )
458             {
459                 Relocation relocation = dist.getRelocation();
460                 if ( relocation != null )
461                 {
462                     // artifact is relocated : update the repositoryPath
463                     if ( relocation.getGroupId() != null )
464                     {
465                         artifact.setGroupId( relocation.getGroupId() );
466                     }
467                     if ( relocation.getArtifactId() != null )
468                     {
469                         artifact.setArtifactId( relocation.getArtifactId() );
470                     }
471                     if ( relocation.getVersion() != null )
472                     {
473                         artifact.setVersion( relocation.getVersion() );
474                     }
475                 }
476             }
477         }
478         catch ( FileNotFoundException e )
479         {
480             // Artifact has no POM in repo : ignore
481         }
482         catch ( IOException e )
483         {
484             // Unable to read POM : ignore.
485         }
486         catch ( XmlPullParserException e )
487         {
488             // Invalid POM : ignore
489         }
490     }
491
492     private void processAuditEvents( DavServletRequest request, String repositoryId, String resource,
493                                      boolean previouslyExisted, File resourceFile, String suffix )
494     {
495         if ( suffix == null )
496         {
497             suffix = "";
498         }
499
500         // Process Create Audit Events.
501         if ( !previouslyExisted && resourceFile.exists() )
502         {
503             if ( resourceFile.isFile() )
504             {
505                 triggerAuditEvent( request, repositoryId, resource, AuditEvent.CREATE_FILE + suffix );
506             }
507             else if ( resourceFile.isDirectory() )
508             {
509                 triggerAuditEvent( request, repositoryId, resource, AuditEvent.CREATE_DIR + suffix );
510             }
511         }
512         // Process Remove Audit Events.
513         else if ( previouslyExisted && !resourceFile.exists() )
514         {
515             if ( resourceFile.isFile() )
516             {
517                 triggerAuditEvent( request, repositoryId, resource, AuditEvent.REMOVE_FILE + suffix );
518             }
519             else if ( resourceFile.isDirectory() )
520             {
521                 triggerAuditEvent( request, repositoryId, resource, AuditEvent.REMOVE_DIR + suffix );
522             }
523         }
524         // Process modify events.
525         else
526         {
527             if ( resourceFile.isFile() )
528             {
529                 triggerAuditEvent( request, repositoryId, resource, AuditEvent.MODIFY_FILE + suffix );
530             }
531         }
532     }
533
534     private void triggerAuditEvent( String user, String remoteIP, String repositoryId, String resource, String action )
535     {
536         AuditEvent event = new AuditEvent( repositoryId, user, resource, action );
537         event.setRemoteIP( remoteIP );
538
539         for ( AuditListener listener : auditListeners )
540         {
541             listener.auditEvent( event );
542         }
543     }
544
545     private void triggerAuditEvent( DavServletRequest request, String repositoryId, String resource, String action )
546     {
547         triggerAuditEvent( ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ),
548                            getRemoteIP( request ), repositoryId, resource, action );
549     }
550
551     private String getRemoteIP( DavServletRequest request )
552     {
553         return request.getRemoteAddr();
554     }
555
556     public void addAuditListener( AuditListener listener )
557     {
558         this.auditListeners.add( listener );
559     }
560
561     public void clearAuditListeners()
562     {
563         this.auditListeners.clear();
564     }
565
566     public void removeAuditListener( AuditListener listener )
567     {
568         this.auditListeners.remove( listener );
569     }
570
571     private void setHeaders( DavResourceLocator locator, DavServletResponse response )
572     {
573         // [MRM-503] - Metadata file need Pragma:no-cache response
574         // header.
575         if ( locator.getResourcePath().endsWith( "/maven-metadata.xml" ) )
576         {
577             response.addHeader( "Pragma", "no-cache" );
578             response.addHeader( "Cache-Control", "no-cache" );
579         }
580
581         // TODO: [MRM-524] determine http caching options for other types of files (artifacts, sha1, md5, snapshots)
582     }
583
584     private ManagedRepositoryContent getManagedRepository( String respositoryId )
585         throws DavException
586     {
587         if ( respositoryId != null )
588         {
589             try
590             {
591                 return repositoryFactory.getManagedRepositoryContent( respositoryId );
592             }
593             catch ( RepositoryNotFoundException e )
594             {
595                 throw new DavException( HttpServletResponse.SC_NOT_FOUND, e );
596             }
597             catch ( RepositoryException e )
598             {
599                 throw new DavException( HttpServletResponse.SC_NOT_FOUND, e );
600             }
601         }
602         return null;
603     }
604
605     private void checkLocatorIsInstanceOfRepositoryLocator( DavResourceLocator locator )
606         throws DavException
607     {
608         if ( !( locator instanceof RepositoryLocator ) )
609         {
610             throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
611                                     "Locator does not implement RepositoryLocator" );
612         }
613     }
614
615     class LogicalResource
616     {
617         private String path;
618
619         public LogicalResource( String path )
620         {
621             this.path = path;
622         }
623
624         public String getPath()
625         {
626             return path;
627         }
628
629         public void setPath( String path )
630         {
631             this.path = path;
632         }
633     }
634     
635     protected boolean isAuthorized( DavServletRequest request, String repositoryId )
636         throws DavException
637     {
638         try
639         {
640             AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );            
641             SecuritySession securitySession = httpAuth.getSecuritySession();
642                        
643             return servletAuth.isAuthenticated( request, result ) &&
644                 servletAuth.isAuthorized( request, securitySession, repositoryId,
645                                           WebdavMethodUtil.isWriteMethod( request.getMethod() ) );
646         }
647         catch ( AuthenticationException e )
648         {            
649             throw new UnauthorizedDavException( repositoryId, "You are not authenticated" );
650         }
651         catch ( MustChangePasswordException e )
652         {         
653             throw new UnauthorizedDavException( repositoryId, "You must change your password." );
654         }
655         catch ( AccountLockedException e )
656         {            
657             throw new UnauthorizedDavException( repositoryId, "User account is locked." );
658         }
659         catch ( AuthorizationException e )
660         {         
661             throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
662                                     "Fatal Authorization Subsystem Error." );
663         }
664         catch ( UnauthorizedException e )
665         {         
666             throw new UnauthorizedDavException( repositoryId, e.getMessage() );
667         }
668     }
669     
670     private DavResource getResource( DavServletRequest request, List<String> repositories, ArchivaDavResourceLocator locator )
671         throws DavException
672     {
673         List<File> mergedRepositoryContents = new ArrayList<File>();        
674         LogicalResource logicalResource =
675             new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
676         
677         // flow: 
678         // if the current user logged in has permission to any of the repositories, allow user to
679         // browse the repo group but displaying only the repositories which the user has permission to access.
680         // otherwise, prompt for authentication.
681         
682         // put the current session in the session map which will be passed to ArchivaXworkUser
683         Map<String, Object> sessionMap = new HashMap<String, Object>();
684         if( request.getSession().getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY ) != null )
685         {
686             sessionMap.put( SecuritySystemConstants.SECURITY_SESSION_KEY, 
687                             request.getSession().getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY ) );
688         }
689         
690         String activePrincipal = ArchivaXworkUser.getActivePrincipal( sessionMap );        
691         boolean allow = isAllowedToContinue( request, repositories, activePrincipal );
692               
693         if( allow )
694         {            
695             for( String repository : repositories )
696             {    
697                 // for prompted authentication
698                 if( httpAuth.getSecuritySession() != null )
699                 {
700                     try
701                     {   
702                         if( isAuthorized( request, repository ) )                        
703                         {
704                             getResource( locator, mergedRepositoryContents, logicalResource, repository );
705                         }
706                     }                    
707                     catch ( DavException e )
708                     {                        
709                         continue;
710                     }
711                 }
712                 else
713                 {
714                     // for the current user logged in 
715                     try
716                     {
717                         if( servletAuth.isAuthorizedToAccessVirtualRepository( activePrincipal, repository ) )
718                         {
719                             getResource( locator, mergedRepositoryContents, logicalResource, repository );
720                         }
721                     }
722                     catch ( UnauthorizedException e )                    
723                     {                        
724                         continue;
725                     }
726                 }                
727             }
728         }
729         else
730         {
731             throw new UnauthorizedDavException( locator.getRepositoryId(), "User not authorized." );
732         }
733         
734         ArchivaVirtualDavResource resource =
735             new ArchivaVirtualDavResource( mergedRepositoryContents, logicalResource.getPath(), mimeTypes, locator, this );
736        
737         // compatibility with MRM-440 to ensure browsing the repository group works ok
738         if ( resource.isCollection() && !resource.getLocator().getResourcePath().endsWith( "/" ) )
739         {
740             throw new BrowserRedirectException( resource.getHref() );
741         }
742         
743         return resource;
744     }
745
746     private void getResource( ArchivaDavResourceLocator locator, List<File> mergedRepositoryContents,
747                               LogicalResource logicalResource, String repository )
748         throws DavException
749     {
750         ManagedRepositoryContent managedRepository = null;
751
752         try
753         {
754             managedRepository = getManagedRepository( repository );
755         }
756         catch ( DavException de )
757         {
758             throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" +
759                 repository + ">" );
760         }                            
761         
762         if ( !locator.getResourcePath().startsWith( ArchivaVirtualDavResource.HIDDEN_PATH_PREFIX ) )
763         {
764             if( managedRepository != null )
765             {   
766                 File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
767                 if( resourceFile.exists() )
768                 {                    
769                     mergedRepositoryContents.add( resourceFile );
770                 }                    
771             }
772         }
773     }
774     
775     /**
776      * Check if the current user is authorized to access any of the repos
777      *  
778      * @param request
779      * @param repositories
780      * @param activePrincipal
781      * @return
782      */
783     private boolean isAllowedToContinue( DavServletRequest request, List<String> repositories, String activePrincipal )    
784     {
785         boolean allow = false;
786         
787               
788         // if securitySession != null, it means that the user was prompted for authentication
789         if( httpAuth.getSecuritySession() != null )
790         {
791             for( String repository : repositories )
792             {
793                 try
794                 {
795                     if( isAuthorized( request, repository ) )
796                     {
797                         allow = true;
798                         break;
799                     }
800                 }
801                 catch( DavException e )
802                 {                    
803                     continue;
804                 }
805             }  
806         }
807         else
808         {   
809             for( String repository : repositories )
810             {
811                 try
812                 {
813                     if( servletAuth.isAuthorizedToAccessVirtualRepository( activePrincipal, repository ) )
814                     {
815                         allow = true;
816                         break;
817                     }
818                 }
819                 catch ( UnauthorizedException e )
820                 {                    
821                     continue;
822                 }
823             }  
824         }
825         
826         return allow;
827     }
828         
829 }