]> source.dussan.org Git - archiva.git/commitdiff
[MRM-694]
authorMaria Odea B. Ching <oching@apache.org>
Tue, 20 May 2008 14:34:48 +0000 (14:34 +0000)
committerMaria Odea B. Ching <oching@apache.org>
Tue, 20 May 2008 14:34:48 +0000 (14:34 +0000)
-handle virtual repos in webdav browse
-add new DavResource for virtual repos

git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@658261 13f79535-47bb-0310-9956-ffa450edef68

archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java
archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java

index c3d98394c0588cb8112293840cc0c379e39cb6ec..ef80939c0fbbda03f2b25538c966614a3351814c 100644 (file)
@@ -125,20 +125,7 @@ public class RepositoryServletRepositoryGroupTest
         
         super.tearDown();
     }
-    
-    
-    /*
-     * Test Case 1
-     */
-    public void testGetValidRepositoryGroupRootPathReturnBadRequest()
-        throws Exception
-    {
-        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS );
-        WebResponse response = sc.getResponse( request );
         
-        assertResponseBadRequest( response );
-    }
-    
     /*
      * Test Case 3.c
      */
@@ -217,11 +204,20 @@ public class RepositoryServletRepositoryGroupTest
         
         WebRequest request = new PutMethodWebRequest( putUrl, is, "text/plain" );
         WebResponse response = sc.getResponse( request );
-        
+         
         assertResponseBadRequest( response );
     }
     
-    
+    public void testBrowseRepositoryGroup()
+        throws Exception
+    {
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS );
+        WebResponse response = sc.getResponse( request );
+                
+        assertNotNull( "Should have received a response", response );
+        assertResponseOK( response );
+    }
+        
     protected void assertResponseBadRequest( WebResponse response )
     {
         assertNotNull( "Should have recieved a response", response );
index efef673c0fb1d554c48f88d9a42f1cffa15b54a6..f8f71dfbc9904cf41861b681f2e7db6061724fdf 100644 (file)
@@ -123,7 +123,7 @@ public class ArchivaDavResourceFactory
     public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request,
                                        final DavServletResponse response )
         throws DavException
-    {
+    {        
         checkLocatorIsInstanceOfRepositoryLocator( locator );
         ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
         
@@ -134,23 +134,21 @@ public class ArchivaDavResourceFactory
 
         boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() );
         boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
-        
+                
         if ( repoGroupConfig != null )
-        {
-            if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).equals( "/" ) ||
-                WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
+        {   
+            if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
             {
                 throw new DavException( HttpServletResponse.SC_BAD_REQUEST, "Bad request to repository group <" +
                     repoGroupConfig.getId() + ">" );
             }
             repositories.addAll( repoGroupConfig.getRepositories() );
             
-            // do not allow write request for repo groups
-            if( isPut )
-            {
-                throw new DavException( HttpServletResponse.SC_FORBIDDEN, "Write request is not allowed for <" +
-                    repoGroupConfig.getId() + ">" );
-            }
+            // handle browse requests for virtual repos
+            if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).endsWith( "/" ) )                
+            {                    
+                return getResource( repositories, archivaLocator );                
+            }            
         }
         else
         {
@@ -231,7 +229,7 @@ public class ArchivaDavResourceFactory
     
     public DavResource createResource( final DavResourceLocator locator, final DavSession davSession )
         throws DavException
-    {
+    {        
         checkLocatorIsInstanceOfRepositoryLocator( locator );
         ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
 
@@ -666,4 +664,44 @@ public class ArchivaDavResourceFactory
         }
     }
     
+    private DavResource getResource( List<String> repositories, ArchivaDavResourceLocator locator )
+        throws DavException
+    {
+        List<File> mergedRepositoryContents = new ArrayList<File>();        
+        LogicalResource logicalResource =
+            new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
+        
+        for( String repository : repositories )
+        {
+            ManagedRepositoryContent managedRepository = null;
+
+            try
+            {
+                managedRepository = getManagedRepository( repository );
+            }
+            catch ( DavException de )
+            {
+                throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" +
+                    repository + ">" );
+            }
+            
+            if ( !locator.getResourcePath().startsWith( ArchivaVirtualDavResource.HIDDEN_PATH_PREFIX ) )
+            {
+                if( managedRepository != null )
+                {   
+                    File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
+                    if( resourceFile.exists() )
+                    {
+                        mergedRepositoryContents.add( resourceFile );
+                    }                    
+                }
+            }
+        }      
+                
+        ArchivaVirtualDavResource resource =
+            new ArchivaVirtualDavResource( mergedRepositoryContents, logicalResource.getPath(), mimeTypes, locator, this );
+                
+        return resource;
+    }
+    
 }
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java
new file mode 100644 (file)
index 0000000..af671f5
--- /dev/null
@@ -0,0 +1,348 @@
+package org.apache.maven.archiva.webdav;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.lock.LockManager;
+import org.apache.jackrabbit.webdav.lock.Scope;
+import org.apache.jackrabbit.webdav.lock.Type;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.apache.jackrabbit.webdav.property.ResourceType;
+import org.apache.maven.archiva.webdav.util.IndexWriter;
+import org.apache.maven.archiva.webdav.util.MimeTypes;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+
+/**
+ * DavResource for virtual repositories
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class ArchivaVirtualDavResource
+    implements DavResource
+{
+    public static final String HIDDEN_PATH_PREFIX = ".";
+    
+    private static final String COMPLIANCE_CLASS = "1";
+
+    private MimeTypes mimeTypes;
+
+    private ArchivaDavResourceLocator locator;
+
+    private DavResourceFactory factory;
+
+    private String logicalResource;
+
+    private DavPropertySet properties;
+
+    private boolean propsInitialized = false;  
+
+    private static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL";
+    
+    private final List<File> localResources;
+    
+    public ArchivaVirtualDavResource( List<File> localResources, String logicalResource, MimeTypes mimeTypes,
+                                      ArchivaDavResourceLocator locator, DavResourceFactory factory )
+    {
+        this.localResources = localResources;
+        this.logicalResource = logicalResource;
+        this.mimeTypes = mimeTypes;
+        this.locator = locator;
+        this.factory = factory;
+        this.properties = new DavPropertySet();
+    }
+
+    public void spool( OutputContext outputContext )
+        throws IOException
+    {
+        Collections.sort( localResources );
+        List<File> localResourceFiles = new ArrayList<File>();
+
+        for ( File resourceFile : localResources )
+        {
+            if ( resourceFile.exists() )
+            {
+                localResourceFiles.add( resourceFile );
+            }
+        }
+
+        IndexWriter writer = new IndexWriter( this, localResourceFiles, logicalResource );
+        writer.write( outputContext );
+    }
+
+    public void addLockManager( LockManager arg0 )
+    {
+        
+    }
+
+    public void addMember( DavResource arg0, InputContext arg1 )
+        throws DavException
+    {
+        
+    }
+
+    public MultiStatusResponse alterProperties( List arg0 )
+        throws DavException
+    {       
+        return null;
+    }
+
+    public MultiStatusResponse alterProperties( DavPropertySet arg0, DavPropertyNameSet arg1 )
+        throws DavException
+    {        
+        return null;
+    }
+
+    public void copy( DavResource arg0, boolean arg1 )
+        throws DavException
+    {        
+
+    }
+
+    public boolean exists()
+    {
+        // localResources are already filtered (all files in the list are already existing)
+        return true;
+    }
+
+    public ActiveLock getLock( Type arg0, Scope arg1 )
+    {       
+        return null;
+    }
+
+    public ActiveLock[] getLocks()
+    {        
+        return null;
+    }
+
+    public DavResourceIterator getMembers()
+    {
+        return null;
+    }
+    
+    public String getSupportedMethods()
+    {
+        return METHODS;
+    }
+
+    public long getModificationTime()
+    {
+        return 0;
+    }
+
+    public boolean hasLock( Type arg0, Scope arg1 )
+    {       
+        return false;
+    }
+
+    public boolean isCollection()
+    {
+        return true;
+    }
+
+    public boolean isLockable( Type arg0, Scope arg1 )
+    {        
+        return false;
+    }
+
+    public ActiveLock lock( LockInfo arg0 )
+        throws DavException
+    {
+        return null;
+    }
+
+    public void move( DavResource arg0 )
+        throws DavException
+    {
+     
+    }
+
+    public ActiveLock refreshLock( LockInfo arg0, String arg1 )
+        throws DavException
+    {        
+        return null;
+    }
+
+    public void removeMember( DavResource arg0 )
+        throws DavException
+    {
+        
+    }
+
+    public void unlock( String arg0 )
+        throws DavException
+    {
+        
+    }
+
+    public String getComplianceClass()
+    {
+        return COMPLIANCE_CLASS;
+    }   
+
+    public DavResourceLocator getLocator()
+    {
+        return locator;
+    }
+
+    public String getResourcePath()
+    {
+        return locator.getResourcePath();
+    }
+
+    public String getHref()
+    {
+        return locator.getHref( isCollection() );
+    }
+    
+    public DavResourceFactory getFactory()
+    {
+        return factory;
+    }
+
+    public String getDisplayName()
+    {
+        String resPath = getResourcePath();
+        
+        return ( resPath != null ) ? Text.getName( resPath ) : resPath;
+    }
+    
+    public DavSession getSession()
+    {        
+        return null;
+    }
+
+    public DavPropertyName[] getPropertyNames()
+    {
+        return getProperties().getPropertyNames();
+    }
+
+    public DavProperty getProperty( DavPropertyName name )
+    {
+        initProperties();
+        return properties.get( name );
+    }
+
+    public DavPropertySet getProperties()
+    {
+        initProperties();
+        return properties;
+    }
+
+    public void setProperty( DavProperty property )
+        throws DavException
+    {
+    }
+
+    public void removeProperty( DavPropertyName propertyName )
+        throws DavException
+    {
+    }
+
+    public DavResource getCollection()
+    {   
+        DavResource parent = null;
+        if ( getResourcePath() != null && !getResourcePath().equals( "/" ) )
+        {
+            String parentPath = Text.getRelativeParent( getResourcePath(), 1 );
+            if ( parentPath.equals( "" ) )
+            {
+                parentPath = "/";
+            }
+            DavResourceLocator parentloc = locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath );
+            try
+            {
+                // go back to ArchivaDavResourceFactory!
+                parent = factory.createResource( parentloc, null );
+            }
+            catch ( DavException e )
+            {
+                // should not occur
+            }
+        }
+        return parent;
+    }
+    
+    /**
+     * Fill the set of properties
+     */
+    protected void initProperties()
+    {
+        if ( !exists() || propsInitialized )
+        {
+            return;
+        }
+
+        // set (or reset) fundamental properties
+        if ( getDisplayName() != null )
+        {
+            properties.add( new DefaultDavProperty( DavPropertyName.DISPLAYNAME, getDisplayName() ) );
+        }
+        if ( isCollection() )
+        {
+            properties.add( new ResourceType( ResourceType.COLLECTION ) );
+            // Windows XP support
+            properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "1" ) );
+        }
+        else
+        {
+            properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE ) );
+
+            // Windows XP support
+            properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "0" ) );
+        }
+       
+        // Need to get the ISO8601 date for properties
+        DateTime dt = new DateTime( 0 );
+        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
+        String modifiedDate = fmt.print( dt );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.GETLASTMODIFIED, modifiedDate ) );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.CREATIONDATE, modifiedDate ) );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.GETCONTENTLENGTH, 0 ) );
+
+        propsInitialized = true;
+    }
+
+}
index 4c41a6ee903001ad7b1c3ec2b4b446b2ee17ee6d..3c6b07f2047d6fe7c4cf4b565a21447cade4e6e8 100644 (file)
@@ -26,7 +26,9 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.io.PrintWriter;
 import java.io.File;
 
@@ -37,19 +39,31 @@ public class IndexWriter
 {
     private final DavResource resource;
 
-    private final File localResource;
-
     private final String logicalResource;
-
+    
+    private final List<File> localResources;
+    
+    private final boolean isVirtual;
+    
     public IndexWriter(DavResource resource, File localResource, String logicalResource)
     {
         this.resource = resource;
-        this.localResource = localResource;
+        this.localResources = new ArrayList<File>();
+        this.localResources.add( localResource );
+        this.logicalResource = logicalResource;
+        this.isVirtual = false;
+    }
+    
+    public IndexWriter( DavResource resource, List<File> localResources, String logicalResource )
+    {
+        this.resource = resource;
         this.logicalResource = logicalResource;
+        this.localResources = localResources;
+        this.isVirtual = true;
     }
 
     public void write(OutputContext outputContext)
-    {
+    {   
         outputContext.setModificationTime(new Date().getTime());
         outputContext.setContentType("text/html");
         outputContext.setETag("");
@@ -94,18 +108,50 @@ public class IndexWriter
     }
 
     private void writeHyperlinks(PrintWriter writer)
-    {
-        List<File> files = new ArrayList<File>( Arrays.asList( localResource.listFiles() ) ); 
-        Collections.sort( files );
-        
-        for ( File file : files )
+    {   
+        if( !isVirtual )
         {
-            writeHyperlink(writer, file.getName(), file.isDirectory());
+            for( File localResource : localResources )
+            {
+                List<File> files = new ArrayList<File>( Arrays.asList( localResource.listFiles() ) ); 
+                Collections.sort( files );
+                
+                for ( File file : files )
+                {
+                    writeHyperlink( writer, file.getName(), file.isDirectory(), false );
+                }
+            }
+        }
+        else 
+        {            
+            // virtual repository - filter unique directories
+            Map<String, File> uniqueChildFiles = new HashMap<String, File>();                        
+            for( File resource : localResources )
+            {
+                List<File> files = new ArrayList<File>( Arrays.asList( resource.listFiles() ) ); 
+                Collections.sort( files );
+                                
+                for ( File file : files )
+                {   
+                    if( uniqueChildFiles.get( file.getName() ) == null )
+                    {
+                        uniqueChildFiles.put( file.getName(), file );
+                    }                    
+                }
+            }
+            
+            List<File> uniqueChildFilesInList = new ArrayList<File>();
+            uniqueChildFilesInList.addAll( uniqueChildFiles.values() );
+            
+            for ( File file : uniqueChildFilesInList )
+            {   
+                writeHyperlink( writer, file.getName(), file.isDirectory(), true );
+            }
         }
     }
 
-    private void writeHyperlink(PrintWriter writer, String resourceName, boolean directory)
-    {
+    private void writeHyperlink(PrintWriter writer, String resourceName, boolean directory, boolean isBrowse )
+    {        
         if (directory)
         {
             writer.println("<li><a href=\"./" + resourceName + "/\">" + resourceName + "</a></li>");
@@ -114,5 +160,5 @@ public class IndexWriter
         {
             writer.println("<li><a href=\"./" + resourceName + "\">" + resourceName + "</a></li>");
         }
-    }
+    }    
 }
index 368e1a1d7593e49c5e4f580c56cb820e6b7fac68..5071dc3dacf6d31b7e76fc0a00e810395715843e 100644 (file)
@@ -21,7 +21,6 @@ package org.apache.maven.archiva.webdav.util;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.io.FilenameUtils;
 
 /**
  * @author <a href="mailto:james@atlassian.com">James William Dumay</a>
@@ -44,19 +43,19 @@ public class RepositoryPathUtil
 
         int slash = requestPathInfo.indexOf( '/' );
         if ( slash > 0 )
-        {
+        {   
             logicalResource = requestPathInfo.substring( slash );
-
+         
             if (logicalResource.endsWith( "/.." ) )
             {
                 logicalResource += "/";
             }
-
+            
             if ( logicalResource != null && logicalResource.startsWith( "//" ) )
             {
                 logicalResource = logicalResource.substring( 1 );
             }
-
+            
             if ( logicalResource == null )
             {
                 logicalResource = "/";
@@ -100,6 +99,13 @@ public class RepositoryPathUtil
         {
             return "/";
         }
-        return StringUtils.join(parts, '/');
+        
+        String joinedString = StringUtils.join(parts, '/');        
+        if( href.endsWith( "/" ) )
+        {
+            joinedString = joinedString + "/";
+        }
+        
+        return joinedString;
     }
 }
index 0294b3e29789b947064e9032541eb614a7a8030e..11a845c46ff9ccab4377a9f6f0e24c4ed8836619 100644 (file)
@@ -45,5 +45,8 @@ public class RepositoryPathUtilTest extends TestCase
 
         href = "repository/internal/org/apache/maven/someartifact.jar";
         assertEquals("/org/apache/maven/someartifact.jar", RepositoryPathUtil.getLogicalResource(href));
+        
+        href = "repository/internal/org/apache/maven/";
+        assertEquals( "/org/apache/maven/", RepositoryPathUtil.getLogicalResource( href ) );
     }
 }