You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by jd...@apache.org on 2008/08/13 05:09:53 UTC

svn commit: r685423 - in /archiva/trunk/archiva-modules: archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/ archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ archiva-base/archiva-repository-layer/src/main/ja...

Author: jdumay
Date: Tue Aug 12 20:09:52 2008
New Revision: 685423

URL: http://svn.apache.org/viewvc?rev=685423&view=rev
Log:
MRM-907 - Remove VersionedReference/ProjectReference/ArtifactReference from RepositoryProxyConnectors

* Merging from https://svn.apache.org/repos/asf/archiva/branches/metadata-rejig-1.2


Modified:
    archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
    archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java
    archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/MetadataTransferTest.java
    archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/MetadataTools.java
    archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataMerge.java
    archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataWriter.java
    archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
    archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java Tue Aug 12 20:09:52 2008
@@ -32,7 +32,6 @@
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
 import org.apache.maven.archiva.configuration.ConfigurationNames;
@@ -40,9 +39,7 @@
 import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration;
 import org.apache.maven.archiva.model.ArtifactReference;
 import org.apache.maven.archiva.model.Keys;
-import org.apache.maven.archiva.model.ProjectReference;
 import org.apache.maven.archiva.model.RepositoryURL;
-import org.apache.maven.archiva.model.VersionedReference;
 import org.apache.maven.archiva.policies.DownloadErrorPolicy;
 import org.apache.maven.archiva.policies.DownloadPolicy;
 import org.apache.maven.archiva.policies.PolicyConfigurationException;
@@ -51,13 +48,11 @@
 import org.apache.maven.archiva.policies.PreDownloadPolicy;
 import org.apache.maven.archiva.policies.ProxyDownloadException;
 import org.apache.maven.archiva.policies.urlcache.UrlFailureCache;
-import org.apache.maven.archiva.repository.ContentNotFoundException;
 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
 import org.apache.maven.archiva.repository.RemoteRepositoryContent;
 import org.apache.maven.archiva.repository.RepositoryContentFactory;
 import org.apache.maven.archiva.repository.RepositoryException;
 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
-import org.apache.maven.archiva.repository.layout.LayoutException;
 import org.apache.maven.archiva.repository.metadata.MetadataTools;
 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
 import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers;
@@ -269,13 +264,13 @@
 
         return null;
     }
-
-    public File fetchFromProxies( ManagedRepositoryContent repository, VersionedReference metadata )
+    
+    public File fetchMetatadaFromProxies(ManagedRepositoryContent repository, String logicalPath)
     {
         File workingDir = createWorkingDirectory(repository);
         try
         {
-            File localFile = toLocalFile( repository, metadata );
+            File localFile = new File(repository.getRepoRoot(), logicalPath);
 
             Properties requestProperties = new Properties();
             requestProperties.setProperty( "filetype", "metadata" );
@@ -286,14 +281,13 @@
             for ( ProxyConnector connector : connectors )
             {
                 RemoteRepositoryContent targetRepository = connector.getTargetRepository();
-                String targetPath = metadataTools.toPath( metadata );
 
-                File localRepoFile = toLocalRepoFile( repository, targetRepository, targetPath );
+                File localRepoFile = toLocalRepoFile( repository, targetRepository, logicalPath );
                 long originalMetadataTimestamp = getLastModified( localRepoFile );
 
                 try
                 {
-                    transferFile( connector, targetRepository, targetPath, repository, workingDir, localRepoFile, requestProperties, true );
+                    transferFile( connector, targetRepository, logicalPath, repository, workingDir, localRepoFile, requestProperties, true );
 
                     if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
                     {
@@ -302,20 +296,20 @@
                 }
                 catch ( NotFoundException e )
                 {
-                    log.debug( "Versioned Metadata " + Keys.toKey( metadata )
+                    log.debug( "Metadata " + logicalPath
                                            + " not found on remote repository \""
-                                           + targetRepository.getRepository().getId() + "\"." );
+                                           + targetRepository.getRepository().getId() + "\".", e );
                 }
                 catch ( NotModifiedException e )
                 {
-                    log.debug( "Versioned Metadata " + Keys.toKey( metadata )
+                    log.debug( "Metadata " + logicalPath
                                            + " not updated on remote repository \""
-                                           + targetRepository.getRepository().getId() + "\"." );
+                                           + targetRepository.getRepository().getId() + "\".", e );
                 }
                 catch ( ProxyException e )
                 {
                     log.warn( "Transfer error from repository \"" + targetRepository.getRepository().getId() +
-                        "\" for versioned Metadata " + Keys.toKey( metadata ) +
+                        "\" for versioned Metadata " + logicalPath +
                         ", continuing to next repository. Error message: " + e.getMessage() );
                     log.debug( "Full stack trace", e );
                 }
@@ -330,126 +324,11 @@
             {
                 try
                 {
-                    metadataTools.updateMetadata( repository, metadata );
-                }
-                catch ( LayoutException e )
-                {
-                    log.warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage() );
-                    // TODO: add into repository report?
+                    metadataTools.updateMetadata( repository, logicalPath );
                 }
                 catch ( RepositoryMetadataException e )
                 {
                     log.warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
-                }
-                catch ( IOException e )
-                {
-                    log.warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
-                }
-                catch ( ContentNotFoundException e )
-                {
-                    log.warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
-                }
-            }
-
-            if ( fileExists( localFile ) )
-            {
-                return localFile;
-            }
-        }
-        finally
-        {
-            FileUtils.deleteQuietly(workingDir);
-        }
-
-        return null;
-    }
-
-    public File fetchFromProxies( ManagedRepositoryContent repository, ProjectReference metadata )
-    {
-        File workingDir = createWorkingDirectory(repository);
-        try
-        {
-            File localFile = toLocalFile( repository, metadata );
-
-            Properties requestProperties = new Properties();
-            requestProperties.setProperty( "filetype", "metadata" );
-            boolean metadataNeedsUpdating = false;
-            long originalTimestamp = getLastModified( localFile );
-
-            List<ProxyConnector> connectors = getProxyConnectors( repository );
-            for ( ProxyConnector connector : connectors )
-            {
-                RemoteRepositoryContent targetRepository = connector.getTargetRepository();
-                String targetPath = metadataTools.toPath( metadata );
-
-                File localRepoFile = toLocalRepoFile( repository, targetRepository, targetPath );
-                long originalMetadataTimestamp = getLastModified( localRepoFile );
-                try
-                {
-                    transferFile( connector, targetRepository, targetPath, repository, workingDir, localRepoFile, requestProperties, true );
-
-                    if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
-                    {
-                        metadataNeedsUpdating = true;
-                    }
-                }
-                catch ( NotFoundException e )
-                {
-                    log.debug( "Project Metadata " + Keys.toKey( metadata ) + " not found on remote repository \""
-                                           + targetRepository.getRepository().getId() + "\"." );
-                }
-                catch ( NotModifiedException e )
-                {
-                    log.debug( "Project Metadata " + Keys.toKey( metadata )
-                                           + " not updated on remote repository \""
-                                           + targetRepository.getRepository().getId() + "\"." );
-                }
-                catch ( ProxyException e )
-                {
-                    log.warn( "Transfer error from repository \"" + targetRepository.getRepository().getId() +
-                        "\" for project metadata " + Keys.toKey( metadata ) +
-                        ", continuing to next repository. Error message: " + e.getMessage() );
-                    log.debug( "Full stack trace", e );
-                }
-
-            }
-
-            if ( hasBeenUpdated( localFile, originalTimestamp ) )
-            {
-                metadataNeedsUpdating = true;
-            }
-
-            if ( metadataNeedsUpdating )
-            {
-                try
-                {
-                    metadataTools.updateMetadata( repository, metadata );
-                }
-                catch ( LayoutException e )
-                {
-                    log.warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage() );
-                    // TODO: add into repository report?
-                }
-                catch ( RepositoryMetadataException e )
-                {
-                    log
-                        .warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
-                }
-                catch ( IOException e )
-                {
-                    log
-                        .warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
-                }
-                catch ( ContentNotFoundException e )
-                {
-                    log
-                        .warn( "Unable to update metadata " + localFile.getAbsolutePath() + ": " + e.getMessage(), e );
-                    // TODO: add into repository report?
                 }
             }
 
@@ -510,18 +389,6 @@
         return repository.toFile( artifact );
     }
 
-    private File toLocalFile( ManagedRepositoryContent repository, ProjectReference metadata )
-    {
-        String sourcePath = metadataTools.toPath( metadata );
-        return new File( repository.getRepoRoot(), sourcePath );
-    }
-
-    private File toLocalFile( ManagedRepositoryContent repository, VersionedReference metadata )
-    {
-        String sourcePath = metadataTools.toPath( metadata );
-        return new File( repository.getRepoRoot(), sourcePath );
-    }
-
     /**
      * Simple method to test if the file exists on the local disk.
      *
@@ -555,7 +422,7 @@
      * @param remoteRepository  the remote repository get the resource from.
      * @param remotePath        the path in the remote repository to the resource to get.
      * @param repository        the managed repository that will hold the file
-     * @param localFile         the local file to place the downloaded resource into
+     * @param resource          the local file to place the downloaded resource into
      * @param requestProperties the request properties to utilize for policy handling.
      * @param executeConsumers  whether to execute the consumers after proxying
      * @return the local file that was downloaded, or null if not downloaded.
@@ -565,10 +432,10 @@
      * @throws ProxyException       if transfer was unsuccessful.
      */
     private File transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
-                               ManagedRepositoryContent repository, File workingDirectory, File localFile, Properties requestProperties,
+                               ManagedRepositoryContent repository, File workingDirectory, File resource, Properties requestProperties,
                                boolean executeConsumers )
         throws ProxyException, NotModifiedException
-    {
+    {     
         String url = remoteRepository.getURL().getUrl();
         if ( !url.endsWith( "/" ) )
         {
@@ -601,15 +468,15 @@
         // Handle pre-download policy
         try
         {
-            validatePolicies( this.preDownloadPolicies, connector.getPolicies(), requestProperties, localFile );
+            validatePolicies( this.preDownloadPolicies, connector.getPolicies(), requestProperties, resource );
         }
         catch ( PolicyViolationException e )
         {
             String emsg = "Transfer not attempted on " + url + " : " + e.getMessage();
-            if ( fileExists( localFile ) )
+            if ( fileExists( resource ) )
             {
                 log.info( emsg + ": using already present local file." );
-                return localFile;
+                return resource;
             }
 
             log.info( emsg );
@@ -623,7 +490,7 @@
 
         File tmpMd5 = null;
         File tmpSha1 = null;
-        File tmpLocalFile = null;
+        File tmpResource = null;
         
         Wagon wagon = null;
         try
@@ -639,12 +506,12 @@
             boolean connected = connectToRepository( connector, wagon, remoteRepository );
             if ( connected )
             {
-                tmpLocalFile = transferSimpleFile( wagon, remoteRepository, remotePath, repository, workingDirectory, localFile );
+                tmpResource = transferSimpleFile( wagon, remoteRepository, remotePath, repository, workingDirectory, resource );
 
                 // TODO: these should be used to validate the download based on the policies, not always downloaded to
                 //   save on connections since md5 is rarely used
-                tmpSha1 = transferChecksum( wagon, remoteRepository, remotePath, repository, workingDirectory, localFile, ".sha1" );
-                tmpMd5 = transferChecksum( wagon, remoteRepository, remotePath, repository, workingDirectory, localFile, ".md5" );
+                tmpSha1 = transferChecksum( wagon, remoteRepository, remotePath, repository, workingDirectory, resource, ".sha1" );
+                tmpMd5 = transferChecksum( wagon, remoteRepository, remotePath, repository, workingDirectory, resource, ".md5" );
             }
         }
         catch ( NotFoundException e )
@@ -706,32 +573,36 @@
         // Handle post-download policies.
         try
         {
-            validatePolicies( this.postDownloadPolicies, connector.getPolicies(), requestProperties, tmpLocalFile );
+            validatePolicies( this.postDownloadPolicies, connector.getPolicies(), requestProperties, tmpResource );
         }
         catch ( PolicyViolationException e )
         {
             log.info( "Transfer invalidated from " + url + " : " + e.getMessage() );
             executeConsumers = false;
-            if ( !fileExists( tmpLocalFile ) )
+            if ( !fileExists( tmpResource ) )
             {
-                localFile = null;
+                resource = null;
             }
         }
 
-        if (localFile != null)
+        if (resource != null)
         {
-            moveFileIfExists(tmpMd5, localFile);
-            moveFileIfExists(tmpSha1, localFile);
-            moveFileIfExists(tmpLocalFile, localFile);
+            synchronized (resource.getAbsolutePath().intern())
+            {
+                File directory = resource.getParentFile();
+                moveFileIfExists(tmpMd5, directory);
+                moveFileIfExists(tmpSha1, directory);
+                moveFileIfExists(tmpResource, directory);
+            }
         }
 
         if ( executeConsumers )
         {
             // Just-in-time update of the index and database by executing the consumers for this artifact
-            consumers.executeConsumers( connector.getSourceRepository().getRepository(), localFile );
+            consumers.executeConsumers( connector.getSourceRepository().getRepository(), resource );
         }
         
-        return localFile;
+        return resource;
     }
     
     
@@ -740,13 +611,14 @@
      * Moves the file into repository location if it exists
      * 
      * @param fileToMove this could be either the main artifact, sha1 or md5 checksum file.
-     * @param localFile this is always the main artifact
+     * @param directory directory to write files to
      */
-    private void moveFileIfExists(File fileToMove, File localFile) throws ProxyException
+    private void moveFileIfExists(File fileToMove, File directory) throws ProxyException
     {
         if (fileToMove != null && fileToMove.exists())
         {
-            moveTempToTarget(fileToMove, new File(localFile.getParentFile(), fileToMove.getName()));
+            File newLocation = new File(directory, fileToMove.getName());
+            moveTempToTarget(fileToMove, newLocation);
         }
     }
 

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java Tue Aug 12 20:09:52 2008
@@ -20,8 +20,6 @@
  */
 
 import org.apache.maven.archiva.model.ArtifactReference;
-import org.apache.maven.archiva.model.ProjectReference;
-import org.apache.maven.archiva.model.VersionedReference;
 import org.apache.maven.archiva.policies.ProxyDownloadException;
 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
 
@@ -50,20 +48,7 @@
      */
     public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
         throws ProxyDownloadException;
-
-    /**
-     * Performs the metadata fetch operation against the target repositories
-     * of the provided source repository.
-     * 
-     * If the metadata is found, it is downloaded and placed into the source repository
-     * filesystem.
-     * 
-     * @param repository the source repository to use. (must be a managed repository)
-     * @param metadata the metadata to fetch.
-     * @return the file that was obtained, or null if no content was obtained
-     */
-    public File fetchFromProxies( ManagedRepositoryContent repository, VersionedReference metadata );
-
+    
     /**
      * Performs the metadata fetch operation against the target repositories
      * of the provided source repository.
@@ -75,7 +60,7 @@
      * @param metadata the metadata to fetch.
      * @return the file that was obtained, or null if no content was obtained
      */
-    public File fetchFromProxies( ManagedRepositoryContent repository, ProjectReference metadata );
+    public File fetchMetatadaFromProxies( ManagedRepositoryContent repository, String logicalPath );
 
     /**
      * Performs the fetch operation against the target repositories

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/MetadataTransferTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/MetadataTransferTest.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/MetadataTransferTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/MetadataTransferTest.java Tue Aug 12 20:09:52 2008
@@ -905,7 +905,7 @@
 
         ProjectReference metadata = createProjectReference( requestedResource );
 
-        File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, metadata );
+        File downloadedFile = proxyHandler.fetchMetatadaFromProxies( managedDefaultRepository, managedDefaultRepository.toMetadataPath(metadata) );
 
         assertNotNull( "Should have downloaded a file.", downloadedFile );
         assertNoTempFiles( expectedFile );
@@ -929,7 +929,7 @@
         File expectedFile = new File( managedDefaultDir, requestedResource );
         ProjectReference metadata = createProjectReference( requestedResource );
 
-        File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, metadata );
+        File downloadedFile = proxyHandler.fetchMetatadaFromProxies( managedDefaultRepository, managedDefaultRepository.toMetadataPath(metadata) );
 
         assertNull( downloadedFile );
         assertNoTempFiles( expectedFile );
@@ -948,7 +948,7 @@
 
         VersionedReference metadata = createVersionedReference( requestedResource );
 
-        File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, metadata );
+        File downloadedFile = proxyHandler.fetchMetatadaFromProxies( managedDefaultRepository, managedDefaultRepository.toMetadataPath(metadata) );
 
         assertNotNull( "Should have downloaded a file.", downloadedFile );
         assertNoTempFiles( expectedFile );
@@ -972,7 +972,7 @@
         File expectedFile = new File( managedDefaultDir, requestedResource );
         VersionedReference metadata = createVersionedReference( requestedResource );
 
-        File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, metadata );
+        File downloadedFile = proxyHandler.fetchMetatadaFromProxies( managedDefaultRepository, managedDefaultRepository.toMetadataPath(metadata) );
 
         assertNull( downloadedFile );
         assertNoTempFiles( expectedFile );

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/MetadataTools.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/MetadataTools.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/MetadataTools.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/MetadataTools.java Tue Aug 12 20:09:52 2008
@@ -55,6 +55,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -65,6 +66,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Matcher;
+import org.apache.commons.io.FileUtils;
 
 /**
  * MetadataTools
@@ -369,6 +371,31 @@
             return null;
         }
     }
+    
+    public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
+                                                        String logicalResource, String proxyId )
+    {
+        String metadataPath = getRepositorySpecificName( proxyId, logicalResource );
+        File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
+        
+        if ( !metadataFile.exists() || !metadataFile.isFile() )
+        {
+            // Nothing to do. return null.
+            return null;
+        }
+
+        try
+        {
+            return RepositoryMetadataReader.read( metadataFile );
+        }
+        catch ( RepositoryMetadataException e )
+        {
+            // TODO: [monitor] consider a monitor for this event.
+            // TODO: consider a read-redo on monitor return code?
+            log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
+            return null;
+        }
+    }
 
     public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
                                                         VersionedReference reference, String proxyId )
@@ -394,6 +421,97 @@
             return null;
         }
     }
+    
+    public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource) throws RepositoryMetadataException
+    {
+        final File metadataFile = new File(managedRepository.getRepoRoot(), logicalResource);
+        ArchivaRepositoryMetadata metadata = null;
+        
+        //Gather and merge all metadata available
+        List<ArchivaRepositoryMetadata> metadatas = getMetadatasForManagedRepository(managedRepository, logicalResource);
+        for (ArchivaRepositoryMetadata proxiedMetadata : metadatas)
+        {
+            if (metadata == null)
+            {
+                metadata = proxiedMetadata;
+                continue;
+            }
+            metadata = RepositoryMetadataMerge.merge(metadata, proxiedMetadata);
+        }
+        
+        Set<String> availableVersions = new HashSet<String>(metadata.getAvailableVersions());
+        availableVersions = findPossibleVersions(availableVersions, metadataFile.getParentFile());
+
+        if (availableVersions.size() > 0)
+        {
+            updateMetadataVersions(availableVersions, metadata);
+        }
+        
+        RepositoryMetadataWriter.write(metadata, metadataFile);
+        
+        ChecksummedFile checksum = new ChecksummedFile( metadataFile );
+        checksum.fixChecksums( algorithms );
+    }
+    
+    /**
+     * Skims the parent directory of a metadata in vain hope of finding 
+     * subdirectories that contain poms.
+     * 
+     * @param metadataParentDirectory
+     * @return origional set plus newley found versions
+     */
+    private Set<String> findPossibleVersions(Set<String> versions, File metadataParentDirectory)
+    {
+        Set<String> result = new HashSet<String>(versions);
+        for (File directory : metadataParentDirectory.listFiles())
+        {
+            if (directory.isDirectory())
+            {
+                for (File possiblePom : directory.listFiles())
+                {
+                    if (possiblePom.getName().endsWith(".pom"))
+                    {
+                        result.add(directory.getName());
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    
+    private List<ArchivaRepositoryMetadata> getMetadatasForManagedRepository( ManagedRepositoryContent managedRepository, String logicalResource )
+    {
+        List<ArchivaRepositoryMetadata> metadatas = new ArrayList<ArchivaRepositoryMetadata>();
+        File file = new File(managedRepository.getRepoRoot(), logicalResource);
+        if (file.exists())
+        {
+            try
+            {
+               ArchivaRepositoryMetadata existingMetadata = RepositoryMetadataReader.read(file);
+               if (existingMetadata != null)
+               {
+                    metadatas.add(existingMetadata);
+               }
+            }
+            catch (RepositoryMetadataException e)
+            {
+                log.debug("Could not read metadata at " + file.getAbsolutePath() + ". Metadata will be removed.");
+                FileUtils.deleteQuietly(file);
+            }
+        }
+        
+        for (String proxyId : proxies.get(managedRepository.getId()))
+        {
+            ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, logicalResource, proxyId );
+            if (proxyMetadata != null)
+            {
+                metadatas.add(proxyMetadata);
+            }
+        }
+        
+        return metadatas;
+    }
+    
 
     /**
      * Update the metadata to represent the all versions/plugins of
@@ -404,6 +522,7 @@
      *
      * We must treat this as a group or a project metadata file as there is no way to know in advance
      *
+     * @deprecated 
      * @param managedRepository the managed repository where the metadata is kept.
      * @param reference         the reference to update.
      * @throws LayoutException
@@ -463,42 +582,7 @@
 
         if ( !allVersions.isEmpty() )
         {
-            // Sort the versions
-            List<String> sortedVersions = new ArrayList<String>( allVersions );
-            Collections.sort( sortedVersions, VersionComparator.getInstance() );
-
-            // Split the versions into released and snapshots.
-            List<String> releasedVersions = new ArrayList<String>();
-            List<String> snapshotVersions = new ArrayList<String>();
-
-            for ( String version : sortedVersions )
-            {
-                if ( VersionUtil.isSnapshot( version ) )
-                {
-                    snapshotVersions.add( version );
-                }
-                else
-                {
-                    releasedVersions.add( version );
-                }
-            }
-
-            Collections.sort( releasedVersions, VersionComparator.getInstance() );
-            Collections.sort( snapshotVersions, VersionComparator.getInstance() );
-
-            String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
-            String releaseVersion = null;
-
-            if ( CollectionUtils.isNotEmpty( releasedVersions ) )
-            {
-                releaseVersion = releasedVersions.get( releasedVersions.size() - 1 );
-            }
-
-            // Add the versions to the metadata model.
-            metadata.setAvailableVersions( sortedVersions );
-
-            metadata.setLatestVersion( latestVersion );
-            metadata.setReleasedVersion( releaseVersion );
+            updateMetadataVersions( allVersions ,metadata );
         }
         else
         {
@@ -521,6 +605,46 @@
         checksum.fixChecksums( algorithms );
     }
 
+    private void updateMetadataVersions(Collection<String> allVersions, ArchivaRepositoryMetadata metadata) 
+    {
+        // Sort the versions
+        List<String> sortedVersions = new ArrayList<String>(allVersions);
+        Collections.sort(sortedVersions, VersionComparator.getInstance());
+
+        // Split the versions into released and snapshots.
+        List<String> releasedVersions = new ArrayList<String>();
+        List<String> snapshotVersions = new ArrayList<String>();
+
+        for (String version : sortedVersions) 
+        {
+            if (VersionUtil.isSnapshot(version)) 
+            {
+                snapshotVersions.add(version);
+            }
+            else 
+            {
+                releasedVersions.add(version);
+            }
+        }
+
+        Collections.sort(releasedVersions, VersionComparator.getInstance());
+        Collections.sort(snapshotVersions, VersionComparator.getInstance());
+
+        String latestVersion = sortedVersions.get(sortedVersions.size() - 1);
+        String releaseVersion = null;
+
+        if (CollectionUtils.isNotEmpty(releasedVersions)) 
+        {
+            releaseVersion = releasedVersions.get(releasedVersions.size() - 1);
+        }
+
+        // Add the versions to the metadata model.
+        metadata.setAvailableVersions(sortedVersions);
+
+        metadata.setLatestVersion(latestVersion);
+        metadata.setReleasedVersion(releaseVersion);
+    }
+
     private Date toLastUpdatedDate( long lastUpdated )
     {
         Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
@@ -601,6 +725,7 @@
      * 2) If this is a RELEASE reference, and the metadata file does not exist, then
      * create the metadata file with contents required of the VersionedReference
      *
+     * @deprecated
      * @param managedRepository the managed repository where the metadata is kept.
      * @param reference         the versioned reference to update
      * @throws LayoutException

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataMerge.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataMerge.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataMerge.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataMerge.java Tue Aug 12 20:09:52 2008
@@ -19,12 +19,15 @@
  * under the License.
  */
 
+import java.util.ArrayList;
 import org.apache.maven.archiva.model.ArchivaModelCloner;
 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
 import org.apache.maven.archiva.model.SnapshotVersion;
 
 import java.util.Iterator;
 import java.util.List;
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.archiva.model.Plugin;
 
 /**
  * RepositoryMetadataMerge 
@@ -51,13 +54,20 @@
         ArchivaRepositoryMetadata merged = new ArchivaRepositoryMetadata();
 
         merged.setGroupId( merge( mainMetadata.getGroupId(), sourceMetadata.getGroupId() ) );
-
+        merged.setArtifactId(  merge(mainMetadata.getArtifactId(), sourceMetadata.getArtifactId()));
+        merged.setVersion( merge(mainMetadata.getVersion(), sourceMetadata.getVersion()) );
         merged.setReleasedVersion( merge( mainMetadata.getReleasedVersion(), sourceMetadata.getReleasedVersion() ) );
         merged.setSnapshotVersion( merge( mainMetadata.getSnapshotVersion(), sourceMetadata.getSnapshotVersion() ) );
-        merged.setLastUpdated( merge( mainMetadata.getLastUpdated(), sourceMetadata.getLastUpdated() ) );
-        merged.setAvailableVersions( mergeAvailableVersions( mainMetadata.getAvailableVersions(), sourceMetadata
-            .getAvailableVersions() ) );
-
+        merged.setAvailableVersions( mergeAvailableVersions( mainMetadata.getAvailableVersions(), sourceMetadata.getAvailableVersions() ) );
+        merged.setPlugins( mergePlugins( mainMetadata.getPlugins(), sourceMetadata.getPlugins() ) );
+        
+        //Don't set if merge was not possible
+        long lastUpdated = mergeTimestamp( mainMetadata.getLastUpdated(), sourceMetadata.getLastUpdated());
+        if (lastUpdated > -1)
+        {
+            merged.setLastUpdated(  Long.toString(lastUpdated) );
+        }
+        
         return merged;
     }
 
@@ -70,6 +80,31 @@
 
         return ( val.trim().length() <= 0 );
     }
+    
+    private static long mergeTimestamp(String mainTimestamp, String sourceTimestamp)
+    {
+        if (sourceTimestamp == null && mainTimestamp != null)
+        {
+            return convertTimestampToLong(mainTimestamp);
+        }
+        
+        if (mainTimestamp == null && sourceTimestamp != null)
+        {
+            return convertTimestampToLong(sourceTimestamp);
+        }
+        
+        if (sourceTimestamp == null && mainTimestamp == null)
+        {
+            return -1;
+        }
+        
+        return mergeTimestamp(convertTimestampToLong(mainTimestamp), convertTimestampToLong(sourceTimestamp));
+    }
+    
+    private static long mergeTimestamp(long mainTimestamp, long sourceTimestamp)
+    { 
+        return Math.max( mainTimestamp, sourceTimestamp );
+    }
 
     private static SnapshotVersion merge( SnapshotVersion mainSnapshotVersion, SnapshotVersion sourceSnapshotVersion )
     {
@@ -84,13 +119,47 @@
         }
 
         SnapshotVersion merged = new SnapshotVersion();
-
-        merged.setTimestamp( merge( mainSnapshotVersion.getTimestamp(), sourceSnapshotVersion.getTimestamp() ) );
-        merged
-            .setBuildNumber( Math.max( mainSnapshotVersion.getBuildNumber(), sourceSnapshotVersion.getBuildNumber() ) );
+       
+        long mainSnapshotLastUpdated = convertTimestampToLong(mainSnapshotVersion.getTimestamp());
+        long sourceSnapshotLastUpdated = convertTimestampToLong(sourceSnapshotVersion.getTimestamp());
+                        
+        long lastUpdated = mergeTimestamp(mainSnapshotLastUpdated, sourceSnapshotLastUpdated);
+        
+        if (lastUpdated == mainSnapshotLastUpdated)
+        {
+            merged.setTimestamp(mainSnapshotVersion.getTimestamp());
+            merged.setBuildNumber(mainSnapshotVersion.getBuildNumber());
+        }
+        else
+        {
+            merged.setTimestamp(sourceSnapshotVersion.getTimestamp());
+            merged.setBuildNumber(sourceSnapshotVersion.getBuildNumber());
+        }
 
         return merged;
     }
+    
+    private static long convertTimestampToLong(String timestamp)
+    {
+        if (timestamp == null)
+        {
+            return -1;
+        }
+        
+        return getLongFromTimestampSafely(StringUtils.replace(timestamp, ".", ""));
+    }
+    
+    private static long getLongFromTimestampSafely( String timestampString )
+    {
+        try
+        {
+            return Long.parseLong(timestampString);
+        }
+        catch (NumberFormatException e)
+        {
+            return -1;
+        }
+    }
 
     private static String merge( String main, String source )
     {
@@ -101,6 +170,64 @@
 
         return main;
     }
+    
+    private static List mergePlugins(List mainPlugins, List sourcePlugins)
+    {
+        if ( sourcePlugins == null )
+        {
+            return mainPlugins;
+        }
+        
+        if ( mainPlugins == null )
+        {
+            return clonePlugins( sourcePlugins );
+        }
+        
+        List merged = clonePlugins( mainPlugins );
+        
+        Iterator it = sourcePlugins.iterator();
+        while ( it.hasNext() )
+        {
+            Plugin plugin = (Plugin) it.next();
+            if ( !merged.contains( plugin ) )
+            {
+                merged.add( plugin );
+            }
+        }
+
+        return merged;
+    }
+    
+    /**
+     * Clones a list of plugins.
+     * 
+     * This method exists because ArchivaModelCloner.clonePlugins() 
+     * only works with artifact references.
+     * 
+     * @param plugins
+     * @return list of cloned plugins
+     */
+    private static List<Plugin> clonePlugins(List<Plugin> plugins)
+    {
+        if (plugins == null)
+        {
+            return null;
+        }
+        
+        ArrayList result = new ArrayList();
+        
+        for (Plugin plugin : plugins)
+        {
+            Plugin clonedPlugin = new Plugin();
+            clonedPlugin.setArtifactId(plugin.getArtifactId());
+            clonedPlugin.setModelEncoding(plugin.getModelEncoding());
+            clonedPlugin.setName(plugin.getName());
+            clonedPlugin.setPrefix(plugin.getPrefix());
+            result.add(plugin);
+        }
+        
+        return result;
+    }
 
     private static List mergeAvailableVersions( List mainAvailableVersions, List sourceAvailableVersions )
     {

Modified: archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataWriter.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataWriter.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataWriter.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/metadata/RepositoryMetadataWriter.java Tue Aug 12 20:09:52 2008
@@ -36,6 +36,7 @@
 import java.io.Writer;
 import java.util.Iterator;
 import java.util.List;
+import org.apache.commons.io.FileUtils;
 
 /**
  * RepositoryMetadataWriter 
@@ -48,6 +49,7 @@
     public static void write( ArchivaRepositoryMetadata metadata, File outputFile )
         throws RepositoryMetadataException
     {
+        boolean thrown = false;
         FileWriter writer = null;
         try
         {
@@ -57,12 +59,17 @@
         }
         catch ( IOException e )
         {
+            thrown = true;
             throw new RepositoryMetadataException( "Unable to write metadata file: " + outputFile.getAbsolutePath()
                 + " - " + e.getMessage(), e );
         }
         finally
         {
             IOUtils.closeQuietly( writer );
+            if (thrown)
+            {
+                FileUtils.deleteQuietly(outputFile);
+            }
         }
     }
 
@@ -74,7 +81,7 @@
         Element root = DocumentHelper.createElement( "metadata" );
         doc.setRootElement( root );
 
-        root.addElement( "groupId" ).setText( metadata.getGroupId() );
+        addOptionalElementText( root, "groupId", metadata.getGroupId());
         addOptionalElementText( root, "artifactId", metadata.getArtifactId() );
         addOptionalElementText( root, "version", metadata.getVersion() );
 

Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java Tue Aug 12 20:09:52 2008
@@ -514,7 +514,7 @@
         // Is it a Metadata resource?
         if ( repositoryRequest.isDefault( resource.getPath() ) && repositoryRequest.isMetadata( resource.getPath() ) )
         {
-            return fetchMetadataFromProxies( managedRepository, request, resource );
+            return connectors.fetchMetatadaFromProxies(managedRepository, resource.getPath()) != null;
         }
 
         // Not any of the above? Then it's gotta be an artifact reference.
@@ -546,45 +546,6 @@
         return false;
     }
 
-    private boolean fetchMetadataFromProxies( ManagedRepositoryContent managedRepository, DavServletRequest request,
-                                              LogicalResource resource )
-        throws DavException
-    {
-        ProjectReference project;
-        VersionedReference versioned;
-
-        try
-        {
-
-            versioned = metadataTools.toVersionedReference( resource.getPath() );
-            if ( versioned != null )
-            {
-                connectors.fetchFromProxies( managedRepository, versioned );
-                return true;
-            }
-        }
-        catch ( RepositoryMetadataException e )
-        {
-            /* eat it */
-        }
-
-        try
-        {
-            project = metadataTools.toProjectReference( resource.getPath() );
-            if ( project != null )
-            {
-                connectors.fetchFromProxies( managedRepository, project );
-                return true;
-            }
-        }
-        catch ( RepositoryMetadataException e )
-        {
-            /* eat it */
-        }
-
-        return false;
-    }
-
     /**
      * A relocation capable client will request the POM prior to the artifact, and will then read meta-data and do
      * client side relocation. A simplier client (like maven 1) will only request the artifact and not use the

Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java?rev=685423&r1=685422&r2=685423&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java Tue Aug 12 20:09:52 2008
@@ -77,6 +77,7 @@
     protected static final String REPO_GROUP_WITH_INVALID_REPOS = "group-with-invalid-repos";
     
     
+    @Override
     protected void setUp()
         throws Exception
     {
@@ -119,6 +120,7 @@
         saveConfiguration( archivaConfiguration );
     }
     
+    @Override
     protected void tearDown()
         throws Exception
     {
@@ -244,8 +246,7 @@
                 "<version>1.5</version><version>2.0</version></versions><lastUpdated>20080709095554</lastUpdated>" +
                 "</versioning></metadata>", null );
         
-        WebRequest request =
-            new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/dummy/" +
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/dummy/" +
                 "dummy-merged-metadata-resource/maven-metadata.xml" );
         WebResponse response = sc.getResource( request );              
         
@@ -276,7 +277,7 @@
         response = sc.getResource( request );
         
         assertResponseOK( response );
-        assertEquals( "d2321a573e0488bca571b624f891104009408dd8  maven-metadata-group-with-valid-repos.xml", response.getText() );
+        assertEquals( "add113b0d7f8c6adb92a5015a7a3701081edf998  maven-metadata-group-with-valid-repos.xml", response.getText() );
         
         // request the md5 checksum of the metadata
         request =
@@ -285,7 +286,7 @@
         response = sc.getResource( request );
                 
         assertResponseOK( response );
-        assertEquals( "79d271fbe8bd1d17b23273937750d407  maven-metadata-group-with-valid-repos.xml", response.getText().trim() );
+        assertEquals( "5b85ea4aa5f52bb76760041a52f98de8  maven-metadata-group-with-valid-repos.xml", response.getText().trim() );
     }
         
     protected void assertResponseMethodNotAllowed( WebResponse response )