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