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