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