]> source.dussan.org Git - archiva.git/commitdiff
Migrating to storage API
authorMartin Stockhammer <martin_s@apache.org>
Fri, 19 Jul 2019 17:29:01 +0000 (19:29 +0200)
committerMartin Stockhammer <martin_s@apache.org>
Fri, 19 Jul 2019 17:29:01 +0000 (19:29 +0200)
32 files changed:
archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
archiva-modules/archiva-base/archiva-configuration/pom.xml
archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java
archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java
archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java
archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java
archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java
archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java

index 5a11b910fc82b834eba925966e040edf6915f9ff..bb6a710ae26865765e2821a614cb421177da8f9d 100644 (file)
@@ -97,4 +97,5 @@ public class ChecksumUtil {
     public static List<Checksum> newChecksums(List<ChecksumAlgorithm> checksumAlgorithms) {
         return checksumAlgorithms.stream().map( a -> new Checksum(a)).collect(Collectors.toList());
     }
+
 }
index 75690291ac4b35d342d2e52c0ed1c4588c133393..fd4565cce75c064dfa44cfb3ee2f9031a683ec52 100644 (file)
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-collections4</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apache.archiva</groupId>
-      <artifactId>archiva-policies</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-test-utils</artifactId>
index ab10d7404f559206c8dede724b294b8f62670035..f8e4e4603bc610e1a3738cc17f926df4a5357ebb 100644 (file)
@@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  * @author Olivier Lamy
  * @since 2.0.0
  */
-public class Lock
+public class Lock implements Closeable
 {
     private Path file;
 
@@ -104,7 +104,7 @@ public class Lock
         return this.fileClients.remove( thread ) != null;
     }
 
-    protected void close()
+    public void close()
         throws IOException
     {
         IOException ioException = null;
index 1fbbfece53c645590f694ddff97d0e8e8c66e39f..cf1c0da4a5aceb4d7ae7f37a86f62ab850898592 100644 (file)
@@ -20,13 +20,13 @@ package org.apache.archiva.policies;
  */
 
 import org.apache.archiva.common.utils.VersionUtil;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
@@ -106,7 +106,7 @@ public abstract class AbstractUpdatePolicy
     }
 
     @Override
-    public void applyPolicy( String policySetting, Properties request, Path localFile )
+    public void applyPolicy( String policySetting, Properties request, StorageAsset localFile )
         throws PolicyViolationException, PolicyConfigurationException
     {
         if ( !StringUtils.equals( request.getProperty( "filetype" ), "artifact" ) )
@@ -157,7 +157,7 @@ public abstract class AbstractUpdatePolicy
             throw new PolicyViolationException( "NO to update, " + getUpdateMode() + " policy set to NEVER." );
         }
 
-        if ( !Files.exists(localFile) )
+        if ( !localFile.exists() )
         {
             // No file means it's ok.
             log.debug( "OK to update {}, local file does not exist.", getUpdateMode() );
@@ -176,15 +176,7 @@ public abstract class AbstractUpdatePolicy
             Calendar cal = Calendar.getInstance();
             cal.add( Calendar.DAY_OF_MONTH, -1 );
             Calendar fileCal = Calendar.getInstance();
-            try
-            {
-                fileCal.setTimeInMillis( Files.getLastModifiedTime(localFile).toMillis() );
-            }
-            catch ( IOException e )
-            {
-                fileCal.setTimeInMillis( new Date().getTime() );
-                log.error("Could not read modification time of {}", localFile);
-            }
+            fileCal.setTimeInMillis( localFile.getModificationTime().toEpochMilli() );
 
             if ( cal.after( fileCal ) )
             {
@@ -203,15 +195,7 @@ public abstract class AbstractUpdatePolicy
             Calendar cal = Calendar.getInstance();
             cal.add( Calendar.HOUR, -1 );
             Calendar fileCal = Calendar.getInstance();
-            try
-            {
-                fileCal.setTimeInMillis( Files.getLastModifiedTime(localFile).toMillis() );
-            }
-            catch ( IOException e )
-            {
-                fileCal.setTimeInMillis( new Date().getTime() );
-                log.error("Could not read modification time of {}", localFile);
-            }
+            fileCal.setTimeInMillis( localFile.getModificationTime().toEpochMilli());
 
             if ( cal.after( fileCal ) )
             {
index e92858fe8e39b432ade93a4fd46da115d1392b53..ac20dbc8edc7461f1921f00dbee5dd89a84cf3ca 100644 (file)
@@ -20,13 +20,13 @@ package org.apache.archiva.policies;
  */
 
 import org.apache.archiva.policies.urlcache.UrlFailureCache;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.inject.Inject;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -64,7 +64,7 @@ public class CachedFailuresPolicy
     }
 
     @Override
-    public void applyPolicy( String policySetting, Properties request, Path localFile )
+    public void applyPolicy( String policySetting, Properties request, StorageAsset localFile )
         throws PolicyViolationException, PolicyConfigurationException
     {
         if ( !options.contains( policySetting ) )
index 82d4d3da467f81d4d74cba2593883bfff2b397fe..8f6885a6bf20a3afd783f63ba47871148edb6639 100644 (file)
@@ -22,6 +22,7 @@ package org.apache.archiva.policies;
 import org.apache.archiva.checksum.ChecksumAlgorithm;
 import org.apache.archiva.checksum.ChecksummedFile;
 import org.apache.archiva.checksum.UpdateStatus;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,7 +81,7 @@ public class ChecksumPolicy
     }
 
     @Override
-    public void applyPolicy( String policySetting, Properties request, Path localFile )
+    public void applyPolicy( String policySetting, Properties request, StorageAsset localFile )
         throws PolicyViolationException, PolicyConfigurationException
     {
         if ( "resource".equals( request.getProperty( "filetype" ) ) )
@@ -103,16 +104,16 @@ public class ChecksumPolicy
             return;
         }
 
-        if ( !Files.exists(localFile) )
+        if ( !localFile.exists() )
         {
             // Local File does not exist.
             throw new PolicyViolationException(
-                "Checksum policy failure, local file " + localFile.toAbsolutePath() + " does not exist to check." );
+                "Checksum policy failure, local file " + localFile.getPath() + " does not exist to check." );
         }
 
-        if ( FAIL.equals( policySetting ) )
+        if ( FAIL.equals( policySetting ) && localFile.isFileBased() )
         {
-            ChecksummedFile checksum = new ChecksummedFile( localFile );
+            ChecksummedFile checksum = new ChecksummedFile( localFile.getFilePath() );
             if ( checksum.isValidChecksums( algorithms ) )
             {
                 return;
@@ -133,7 +134,7 @@ public class ChecksumPolicy
 
             try
             {
-                Files.deleteIfExists( localFile );
+                localFile.getStorage().removeAsset( localFile );
             }
             catch ( IOException e )
             {
@@ -141,12 +142,12 @@ public class ChecksumPolicy
             }
             throw new PolicyViolationException(
                 "Checksums do not match, policy set to FAIL, " + "deleting checksum files and local file "
-                    + localFile.toAbsolutePath() + "." );
+                    + localFile.getPath() + "." );
         }
 
-        if ( FIX.equals( policySetting ) )
+        if ( FIX.equals( policySetting ) && localFile.isFileBased())
         {
-            ChecksummedFile checksum = new ChecksummedFile( localFile );
+            ChecksummedFile checksum = new ChecksummedFile( localFile.getFilePath() );
             if ( checksum.fixChecksums( algorithms ).getTotalStatus() != UpdateStatus.ERROR )
             {
                 log.debug( "Checksum policy set to FIX, checksum files have been updated." );
@@ -156,7 +157,7 @@ public class ChecksumPolicy
             {
                 throw new PolicyViolationException(
                     "Checksum policy set to FIX, " + "yet unable to update checksums for local file "
-                        + localFile.toAbsolutePath() + "." );
+                        + localFile.getPath() + "." );
             }
         }
 
index 90261737e7c13a355fe1574ffa42103b3411e8e2..28de5336b99d6900b7ee6214eb23b1d67bbefd68 100644 (file)
@@ -19,7 +19,8 @@ package org.apache.archiva.policies;
  * under the License.
  */
 
-import java.nio.file.Path;
+import org.apache.archiva.repository.content.StorageAsset;
+
 import java.util.Map;
 import java.util.Properties;
 
@@ -43,7 +44,7 @@ public interface DownloadErrorPolicy
      * @return whether to process the exception or not
      * @throws PolicyConfigurationException if the policy is improperly configured
      */
-    boolean applyPolicy( String policySetting, Properties request, Path localFile, Exception exception,
+    boolean applyPolicy( String policySetting, Properties request, StorageAsset localFile, Exception exception,
                          Map<String, Exception> previousExceptions )
         throws PolicyConfigurationException;
 }
index 8d149e619544bac2001920fe241fa0e9053cb2e6..f9a14433127214caec134365e0978d565f3973f6 100644 (file)
@@ -19,7 +19,8 @@ package org.apache.archiva.policies;
  * under the License.
  */
 
-import java.nio.file.Path;
+import org.apache.archiva.repository.content.StorageAsset;
+
 import java.util.Properties;
 
 /**
@@ -37,9 +38,9 @@ public interface DownloadPolicy
      * @param policySetting the policy setting.
      * @param request the list of request properties that the policy might use.
      * @param localFile
-     * 
+     *
      * @throws PolicyViolationException if the policy has been violated.
      */
-    void applyPolicy( String policySetting, Properties request, Path localFile )
+    void applyPolicy( String policySetting, Properties request, StorageAsset localFile )
         throws PolicyViolationException, PolicyConfigurationException;
 }
index 1fab1209a0c1107dcea9ea59674fb5699d2228a8..7a0baefe1c41288fdf82ec2cd25a9e8195476316 100644 (file)
@@ -19,12 +19,12 @@ package org.apache.archiva.policies;
  * under the License.
  */
 
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -64,7 +64,7 @@ public class PropagateErrorsDownloadPolicy
     }
 
     @Override
-    public boolean applyPolicy( String policySetting, Properties request, Path localFile, Exception exception,
+    public boolean applyPolicy( String policySetting, Properties request, StorageAsset localFile, Exception exception,
                                 Map<String, Exception> previousExceptions )
         throws PolicyConfigurationException
     {
index ec32891056631ed6cbd070481cd646947ed98011..9b22a9b23166aa2aae950206de1b05d6b11ec402 100644 (file)
@@ -19,11 +19,11 @@ package org.apache.archiva.policies;
  * under the License.
  */
 
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
 
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -55,7 +55,7 @@ public class PropagateErrorsOnUpdateDownloadPolicy
     }
 
     @Override
-    public boolean applyPolicy( String policySetting, Properties request, Path localFile, Exception exception,
+    public boolean applyPolicy( String policySetting, Properties request, StorageAsset localFile, Exception exception,
                                 Map<String, Exception> previousExceptions )
         throws PolicyConfigurationException
     {
@@ -76,7 +76,7 @@ public class PropagateErrorsOnUpdateDownloadPolicy
         if ( NOT_PRESENT.equals( policySetting ) )
         {
             // cancel the exception if the file exists
-            return !Files.exists(localFile);
+            return !localFile.exists();
         }
 
         throw new PolicyConfigurationException(
index 28e8cb9b128f1e97d61352c41fd2e4b3fc725b6c..700e4a56083079fcaaebc79051a5abdf1f15be6b 100644 (file)
@@ -20,6 +20,8 @@ package org.apache.archiva.proxy.model;
  */
 
 
+import org.apache.archiva.repository.content.StorageAsset;
+
 import java.nio.file.Path;
 
 /**
@@ -31,18 +33,18 @@ public class ProxyFetchResult
 {
 
     //The file returned
-    private Path file;
+    private StorageAsset file;
 
     //Was the local file modified by the fetch?
     private boolean modified;
 
-    public ProxyFetchResult( Path file, boolean modified )
+    public ProxyFetchResult( StorageAsset file, boolean modified )
     {
         this.file = file;
         this.modified = modified;
     }
 
-    public Path getFile()
+    public StorageAsset getFile()
     {
         return file;
     }
index eee2d86d2d83ad620ecfd55a0562a01d069863ef..f82d555140c8c8f2ddd1cf8e314aeaf1268fbe6f 100644 (file)
@@ -23,8 +23,8 @@ import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.policies.ProxyDownloadException;
 import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.content.StorageAsset;
 
-import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
 
@@ -50,7 +50,7 @@ public interface RepositoryProxyHandler
      * @return the file that was obtained, or null if no content was obtained
      * @throws ProxyDownloadException if there was a problem fetching the content from the target repositories.
      */
-    Path fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
+    StorageAsset fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
         throws ProxyDownloadException;
     
     /**
@@ -74,7 +74,7 @@ public interface RepositoryProxyHandler
      * @param path the path of the resource to fetch
      * @return the file that was obtained, or null if no content was obtained
      */
-    Path fetchFromProxies( ManagedRepositoryContent managedRepository, String path );
+    StorageAsset fetchFromProxies( ManagedRepositoryContent managedRepository, String path );
 
     /**
      * Get the List of {@link ProxyConnector} objects of the source repository.
index 5622fe5c42788be1e6e27e61b7898c73111f5df3..fac557ed43f1bb27a7502b55bd2931e8514abe88 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.archiva.proxy;
  * under the License.
  */
 
+import org.apache.archiva.checksum.ChecksumAlgorithm;
+import org.apache.archiva.checksum.ChecksumUtil;
 import org.apache.archiva.proxy.model.ProxyConnectorRuleType;
 import org.apache.archiva.common.filelock.FileLockException;
 import org.apache.archiva.common.filelock.FileLockManager;
@@ -37,6 +39,9 @@ import org.apache.archiva.redback.components.registry.Registry;
 import org.apache.archiva.redback.components.registry.RegistryListener;
 import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
 import org.apache.archiva.repository.*;
+import org.apache.archiva.repository.content.FilesystemStorage;
+import org.apache.archiva.repository.content.StorageAsset;
+import org.apache.archiva.repository.content.StorageUtil;
 import org.apache.archiva.repository.metadata.MetadataTools;
 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
@@ -94,12 +99,14 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
     private FileLockManager fileLockManager;
 
     private Map<String, NetworkProxy> networkProxyMap = new ConcurrentHashMap<>();
+    private List<ChecksumAlgorithm> checksumAlgorithms;
 
     @PostConstruct
     public void initialize()
     {
         initConnectors();
         archivaConfiguration.addChangeListener( this );
+        checksumAlgorithms = ChecksumUtil.getAlgorithms(archivaConfiguration.getConfiguration().getArchivaRuntimeConfiguration().getChecksumTypes());
 
     }
 
@@ -243,10 +250,10 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
     }
 
     @Override
-    public Path fetchFromProxies(ManagedRepositoryContent repository, ArtifactReference artifact )
+    public StorageAsset fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
         throws ProxyDownloadException
     {
-        Path localFile = toLocalFile( repository, artifact );
+        StorageAsset localFile = toLocalFile( repository, artifact );
 
         Properties requestProperties = new Properties();
         requestProperties.setProperty( "filetype", "artifact" );
@@ -275,13 +282,13 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
 
             try
             {
-                Path downloadedFile =
+                StorageAsset downloadedFile =
                     transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
                                   true );
 
-                if ( fileExists( downloadedFile ) )
+                if ( downloadedFile.exists() )
                 {
-                    log.debug( "Successfully transferred: {}", downloadedFile.toAbsolutePath() );
+                    log.debug( "Successfully transferred: {}", downloadedFile.getPath() );
                     return downloadedFile;
                 }
             }
@@ -314,12 +321,12 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
     }
 
     @Override
-    public Path fetchFromProxies( ManagedRepositoryContent repository, String path )
+    public StorageAsset fetchFromProxies( ManagedRepositoryContent repository, String path )
     {
-        Path localFile = Paths.get( repository.getRepoRoot(), path );
+        StorageAsset localFile = repository.getRepository().getAsset( path );
 
         // no update policies for these paths
-        if ( Files.exists(localFile) )
+        if ( localFile.exists() )
         {
             return null;
         }
@@ -343,13 +350,13 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
 
             try
             {
-                Path downloadedFile =
+                StorageAsset downloadedFile =
                     transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
                                   false );
 
                 if ( fileExists( downloadedFile ) )
                 {
-                    log.debug( "Successfully transferred: {}", downloadedFile.toAbsolutePath() );
+                    log.debug( "Successfully transferred: {}", downloadedFile.getPath() );
                     return downloadedFile;
                 }
             }
@@ -384,7 +391,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
     @Override
     public ProxyFetchResult fetchMetadataFromProxies(ManagedRepositoryContent repository, String logicalPath )
     {
-        Path localFile = Paths.get( repository.getRepoRoot(), logicalPath );
+        StorageAsset localFile = repository.getRepository().getAsset( logicalPath );
 
         Properties requestProperties = new Properties();
         requestProperties.setProperty( "filetype", "metadata" );
@@ -401,7 +408,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
 
             RemoteRepositoryContent targetRepository = connector.getTargetRepository();
 
-            Path localRepoFile = toLocalRepoFile( repository, targetRepository, logicalPath );
+            StorageAsset localRepoFile = toLocalRepoFile( repository, targetRepository, logicalPath );
             long originalMetadataTimestamp = getLastModified( localRepoFile );
 
             try
@@ -442,7 +449,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
             metadataNeedsUpdating = true;
         }
 
-        if ( metadataNeedsUpdating || !Files.exists(localFile))
+        if ( metadataNeedsUpdating || !localFile.exists())
         {
             try
             {
@@ -450,7 +457,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
             }
             catch ( RepositoryMetadataException e )
             {
-                log.warn( "Unable to update metadata {}:{}", localFile.toAbsolutePath(), e.getMessage(), e );
+                log.warn( "Unable to update metadata {}:{}", localFile.getPath(), e.getMessage(), e );
             }
 
         }
@@ -463,27 +470,19 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         return new ProxyFetchResult( null, false );
     }
 
-    private long getLastModified(Path file )
+    private long getLastModified(StorageAsset file )
     {
-        if ( !Files.exists(file) || !Files.isRegularFile(file) )
+        if ( !file.exists() || file.isContainer() )
         {
             return 0;
         }
 
-        try
-        {
-            return Files.getLastModifiedTime(file).toMillis();
-        }
-        catch ( IOException e )
-        {
-            log.error("Could get the modified time of file {}", file.toAbsolutePath());
-            return 0;
-        }
+        return file.getModificationTime().toEpochMilli();
     }
 
-    private boolean hasBeenUpdated(Path file, long originalLastModified )
+    private boolean hasBeenUpdated(StorageAsset file, long originalLastModified )
     {
-        if ( !Files.exists(file) || !Files.isRegularFile(file) )
+        if ( !file.exists() || file.isContainer() )
         {
             return false;
         }
@@ -492,11 +491,11 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         return ( currentLastModified > originalLastModified );
     }
 
-    private Path toLocalRepoFile(ManagedRepositoryContent repository, RemoteRepositoryContent targetRepository,
-                                 String targetPath )
+    private StorageAsset toLocalRepoFile( ManagedRepositoryContent repository, RemoteRepositoryContent targetRepository,
+                                          String targetPath )
     {
         String repoPath = metadataTools.getRepositorySpecificName( targetRepository, targetPath );
-        return Paths.get( repository.getRepoRoot(), repoPath );
+        return repository.getRepository().getAsset( repoPath );
     }
 
     /**
@@ -511,7 +510,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         }
     }
 
-    private Path toLocalFile(ManagedRepositoryContent repository, ArtifactReference artifact )
+    private StorageAsset toLocalFile(ManagedRepositoryContent repository, ArtifactReference artifact )
     {
         return repository.toFile( artifact );
     }
@@ -522,19 +521,19 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      * @param file the file to test. (may be null)
      * @return true if file exists. false if the file param is null, doesn't exist, or is not of type File.
      */
-    private boolean fileExists( Path file )
+    private boolean fileExists( StorageAsset file )
     {
         if ( file == null )
         {
             return false;
         }
 
-        if ( !Files.exists(file))
+        if ( !file.exists())
         {
             return false;
         }
 
-        return Files.isRegularFile(file);
+        return !file.isContainer();
     }
 
     /**
@@ -544,7 +543,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      * @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 resource          the local file to place the downloaded resource into
+     * @param resource          the path relative to the repository storage where the file should be downloaded to
      * @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.
@@ -553,9 +552,9 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      *                              the remote resource is not newer than the local File.
      * @throws ProxyException       if transfer was unsuccessful.
      */
-    protected Path transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
-                               ManagedRepositoryContent repository, Path resource, Properties requestProperties,
-                               boolean executeConsumers )
+    protected StorageAsset transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
+                                         ManagedRepositoryContent repository, StorageAsset resource, Properties requestProperties,
+                                         boolean executeConsumers )
         throws ProxyException, NotModifiedException
     {
         String url = remoteRepository.getURL().getUrl();
@@ -594,7 +593,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         catch ( PolicyViolationException e )
         {
             String emsg = "Transfer not attempted on " + url + " : " + e.getMessage();
-            if ( fileExists( resource ) )
+            if ( resource.exists() )
             {
                 log.debug( "{} : using already present local file.", emsg );
                 return resource;
@@ -605,15 +604,27 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         }
 
         Path workingDirectory = createWorkingDirectory( repository );
-        Path tmpResource = workingDirectory.resolve(resource.getFileName());
-        Path tmpMd5 = workingDirectory.resolve(resource.getFileName().toString() + ".md5" );
-        Path tmpSha1 = workingDirectory.resolve( resource.getFileName().toString() + ".sha1" );
+        FilesystemStorage tmpStorage = null;
+        try
+        {
+            tmpStorage = new FilesystemStorage( workingDirectory, fileLockManager );
+        }
+        catch ( IOException e )
+        {
+            throw new ProxyException( "Could not create tmp storage" );
+        }
+        StorageAsset tmpResource = tmpStorage.getAsset( resource.getName( ) );
+        StorageAsset[] tmpChecksumFiles = new StorageAsset[checksumAlgorithms.size()];
+        for(int i=0; i<checksumAlgorithms.size(); i++) {
+            ChecksumAlgorithm alg = checksumAlgorithms.get( i );
+            tmpChecksumFiles[i] = tmpStorage.getAsset( resource.getName() + "." + alg.getDefaultExtension() );
+        }
 
         try
         {
 
-            transferResources( connector, remoteRepository, tmpMd5, tmpSha1, tmpResource, url, remotePath, resource,
-                               workingDirectory, repository );
+            transferResources( connector, remoteRepository, tmpResource,tmpChecksumFiles , url, remotePath,
+                resource, workingDirectory, repository );
 
             // Handle post-download policies.
             try
@@ -632,11 +643,12 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
 
             if ( resource != null )
             {
-                synchronized ( resource.toAbsolutePath().toString().intern() )
+                synchronized ( resource.getPath().intern() )
                 {
-                    Path directory = resource.getParent();
-                    moveFileIfExists( tmpMd5, directory );
-                    moveFileIfExists( tmpSha1, directory );
+                    StorageAsset directory = resource.getParent();
+                    for (int i=0; i<tmpChecksumFiles.length; i++) {
+                        moveFileIfExists( tmpChecksumFiles[i], directory );
+                    }
                     moveFileIfExists( tmpResource, directory );
                 }
             }
@@ -656,11 +668,11 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         return resource;
     }
 
-    protected abstract void transferResources(ProxyConnector connector, RemoteRepositoryContent remoteRepository, Path tmpMd5, Path tmpSha1,
-                                              Path tmpResource, String url, String remotePath, Path resource, Path workingDirectory,
-                                              ManagedRepositoryContent repository) throws ProxyException, NotModifiedException;
+    protected abstract void transferResources( ProxyConnector connector, RemoteRepositoryContent remoteRepository,
+                                               StorageAsset tmpResource, StorageAsset[] checksumFiles, String url, String remotePath, StorageAsset resource, Path workingDirectory,
+                                               ManagedRepositoryContent repository ) throws ProxyException, NotModifiedException;
 
-    private void queueRepositoryTask(String repositoryId, Path localFile )
+    private void queueRepositoryTask(String repositoryId, StorageAsset localFile )
     {
         RepositoryTask task = new RepositoryTask();
         task.setRepositoryId( repositoryId );
@@ -675,7 +687,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         catch ( TaskQueueException e )
         {
             log.error( "Unable to queue repository task to execute consumers on resource file ['{}"
-                           + "'].", localFile.getFileName() );
+                           + "'].", localFile.getName() );
         }
     }
 
@@ -685,12 +697,12 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      * @param fileToMove this could be either the main artifact, sha1 or md5 checksum file.
      * @param directory  directory to write files to
      */
-    private void moveFileIfExists( Path fileToMove, Path directory )
+    private void moveFileIfExists( StorageAsset fileToMove, StorageAsset directory )
         throws ProxyException
     {
-        if ( fileToMove != null && Files.exists(fileToMove) )
+        if ( fileToMove != null && fileToMove.exists() )
         {
-            Path newLocation = directory.resolve(fileToMove.getFileName());
+            StorageAsset newLocation = directory.getStorage().getAsset( directory.getPath()+ "/" + fileToMove.getName());
             moveTempToTarget( fileToMove, newLocation );
         }
     }
@@ -701,13 +713,13 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      * @param policies  the map of policies to execute. (Map of String policy keys, to {@link DownloadPolicy} objects)
      * @param settings  the map of settings for the policies to execute. (Map of String policy keys, to String policy
      *                  setting)
-     * @param request   the request properties (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, Path)}
+     * @param request   the request properties (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, StorageAsset)}
      *                  )
-     * @param localFile the local file (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, Path)})
+     * @param localFile the local file (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, StorageAsset)})
      * @throws PolicyViolationException
      */
     private void validatePolicies( Map<String, ? extends DownloadPolicy> policies, Map<String, String> settings,
-                                   Properties request, Path localFile )
+                                   Properties request, StorageAsset localFile )
         throws PolicyViolationException
     {
         for ( Map.Entry<String, ? extends DownloadPolicy> entry : policies.entrySet() )
@@ -732,9 +744,9 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
         }
     }
 
-    private void validatePolicies(Map<String, DownloadErrorPolicy> policies, Map<String, String> settings,
-                                  Properties request, ArtifactReference artifact, RemoteRepositoryContent content,
-                                  Path localFile, Exception exception, Map<String, Exception> previousExceptions )
+    private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<String, String> settings,
+                                   Properties request, ArtifactReference artifact, RemoteRepositoryContent content,
+                                   StorageAsset localFile, Exception exception, Map<String, Exception> previousExceptions )
         throws ProxyDownloadException
     {
         boolean process = true;
@@ -813,61 +825,28 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
      * @param target The final location of the downloaded file
      * @throws ProxyException when the temp file cannot replace the target file
      */
-    private void moveTempToTarget( Path temp, Path target )
+    private void moveTempToTarget( StorageAsset temp, StorageAsset target )
         throws ProxyException
     {
 
-        Lock lock;
         try
         {
-            lock = fileLockManager.writeFileLock( target );
-            try {
-                Files.deleteIfExists(lock.getFile());
-            } catch (IOException e) {
-                throw new ProxyException( "Unable to overwrite existing target file: " + target.toAbsolutePath() );
-            }
-
-            try {
-                Files.createDirectories(lock.getFile().getParent());
-            } catch (IOException e) {
-                throw new ProxyException("Unable to create parent directory "+lock.getFile().getParent());
-            }
-
+            StorageUtil.moveAsset( temp, target, true );
+        }
+        catch ( IOException e )
+        {
+            log.error( "Move failed from {} to {}, trying copy.", temp, target );
             try
             {
-                Files.move(temp, lock.getFile() );
+                StorageUtil.copyAsset( temp, target, true );
+                if (temp.exists()) {
+                    temp.getStorage( ).removeAsset( temp );
+                }
             }
-            catch ( IOException e )
+            catch ( IOException ex )
             {
-                log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );
-
-                try
-                {
-                    Files.copy( temp, lock.getFile());
-                }
-                catch ( IOException e2 )
-                {
-                    if ( Files.exists(lock.getFile()) )
-                    {
-                        log.debug( "Tried to copy file {} to {} but file with this name already exists.",
-                            temp.getFileName(), lock.getFile().toAbsolutePath() );
-                    }
-                    else
-                    {
-                        throw new ProxyException(
-                            "Cannot copy tmp file " + temp.toAbsolutePath() + " to its final location", e2 );
-                    }
-                }
-                finally
-                {
-                    org.apache.archiva.common.utils.FileUtils.deleteQuietly( temp );
-                }
+                throw new ProxyException("Could not move temp file "+temp.getPath()+" to target "+target.getPath(), e);
             }
-
-        }
-        catch ( FileLockException | FileLockTimeoutException e )
-        {
-            throw new ProxyException( e.getMessage(), e );
         }
     }
 
index 1bab4a8ffe800492b44270b829cfd1ce4beb4c46..c50a89cf223f7d1c18be7826bfa84c0d604d0e34 100644 (file)
@@ -23,18 +23,9 @@ import org.apache.archiva.model.ArchivaArtifact;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.model.ProjectReference;
 import org.apache.archiva.model.VersionedReference;
-import org.apache.archiva.repository.content.RepositoryStorage;
 import org.apache.archiva.repository.content.StorageAsset;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.time.Instant;
-import java.util.List;
 import java.util.Set;
-import java.util.function.Consumer;
-import java.util.function.Function;
 
 /**
  * ManagedRepositoryContent interface for interacting with a managed repository in an abstract way,
@@ -198,7 +189,7 @@ public interface ManagedRepositoryContent extends RepositoryContent
      * @param reference the artifact reference to use.
      * @return the relative path to the artifact.
      */
-    Path toFile( ArtifactReference reference );
+    StorageAsset toFile( ArtifactReference reference );
 
     /**
      * Given an {@link ArchivaArtifact}, return the file reference to the artifact.
@@ -206,7 +197,7 @@ public interface ManagedRepositoryContent extends RepositoryContent
      * @param reference the archiva artifact to use.
      * @return the relative path to the artifact.
      */
-    Path toFile( ArchivaArtifact reference );
+    StorageAsset toFile( ArchivaArtifact reference );
 
     /**
      * Given a {@link ProjectReference}, return the path to the metadata for
index 82b40b2cef88432f71166e103d7cf03ec5059715..3dea0b2945cc6b3ee9b782b7dd74de0209d0073b 100644 (file)
@@ -21,6 +21,10 @@ package org.apache.archiva.repository.content;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.CopyOption;
 import java.util.function.Consumer;
 
 /**
@@ -47,13 +51,42 @@ public interface RepositoryStorage {
     /**
      * Consumes the data and sets a lock for the file during the operation.
      *
-     * @param asset
-     * @param consumerFunction
-     * @param readLock
+     * @param asset The asset from which the data is consumed.
+     * @param consumerFunction The consumer that reads the data
+     * @param readLock If true, a read lock is acquired on the asset.
      * @throws IOException
      */
     void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock) throws IOException;
 
+    /**
+     * Consumes the data and sets a lock for the file during the operation.
+     *
+     * @param asset The asset from which the data is consumed.
+     * @param consumerFunction The consumer that reads the data
+     * @param readLock If true, a read lock is acquired on the asset.
+     * @throws IOException
+     */
+    void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock) throws IOException;
+
+    /**
+     * Writes data to the asset using a write lock.
+     *
+     * @param asset The asset to which the data is written.
+     * @param consumerFunction The function that provides the data.
+     * @param writeLock If true, a write lock is acquired on the destination.
+     */
+    void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock) throws IOException;;
+
+    /**
+     * Writes data and sets a lock during the operation.
+     *
+     * @param asset The asset to which the data is written.
+     * @param consumerFunction The function that provides the data.
+     * @param writeLock If true, a write lock is acquired on the destination.
+     * @throws IOException
+     */
+    void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock) throws IOException;
+
     /**
      * Adds a new asset to the underlying storage.
      * @param path The path to the asset.
@@ -73,19 +106,43 @@ public interface RepositoryStorage {
     /**
      * Moves the asset to the given location and returns the asset object for the destination.
      *
-     * @param origin
-     * @param destination
-     * @return
+     * @param origin The original asset
+     * @param destination The destination path pointing to the new asset.
+     * @param copyOptions The copy options.
+     * @return The asset representation of the moved object.
+     */
+    StorageAsset moveAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException;
+
+    /**
+     * Moves the asset to the new path.
+     *
+     * @param origin The original asset
+     * @param destination The destination asset.
+     * @param copyOptions The copy options (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING}
+     * @throws IOException If it was not possible to copy the asset.
      */
-    StorageAsset moveAsset(StorageAsset origin, String destination) throws IOException;
+    void moveAsset(StorageAsset origin, StorageAsset destination, CopyOption... copyOptions) throws IOException;
 
     /**
      * Copies the given asset to the new destination.
      *
-     * @param origin
-     * @param destination
-     * @return
-     * @throws IOException
+     * @param origin The original asset
+     * @param destination The path to the new asset
+     * @param copyOptions The copy options, e.g. (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING}
+     * @return The asset representation of the copied object
+     * @throws IOException If it was not possible to copy the asset
      */
-    StorageAsset copyAsset(StorageAsset origin, String destination) throws IOException;
+    StorageAsset copyAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException;
+
+    /**
+     * Copies the given asset to the new destination.
+     *
+     * @param origin The original asset
+     * @param destination The path to the new asset
+     * @param copyOptions The copy options, e.g. (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING}
+     * @throws IOException If it was not possible to copy the asset
+     */
+    void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions) throws IOException;
+
+
 }
index 16e70859ddfda4e944122575b4af3642a0dfbeb4..38ef2a8950fa2c1685ebc2039d91fb3894ab8cc4 100644 (file)
@@ -22,6 +22,8 @@ package org.apache.archiva.repository.content;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.nio.file.Path;
 import java.time.Instant;
 import java.util.List;
@@ -39,6 +41,13 @@ import java.util.function.Consumer;
  */
 public interface StorageAsset
 {
+
+    /**
+     * Returns the storage this asset belongs to.
+     * @return
+     */
+    RepositoryStorage getStorage();
+
     /**
      * Returns the complete path relative to the repository to the given asset.
      *
@@ -68,7 +77,7 @@ public interface StorageAsset
     /**
      * List the child assets.
      *
-     * @return The list of children. If there are no children, a empty list will be returned.
+     * @return The list of children. If there are no children and if the asset is not a container, a empty list will be returned.
      */
     List<StorageAsset> list();
 
@@ -82,22 +91,41 @@ public interface StorageAsset
     /**
      * Returns the input stream of the artifact content.
      * It will throw a IOException, if the stream could not be created.
-     * Implementations should create a new stream instance for each invocation.
+     * Implementations should create a new stream instance for each invocation and make sure that the
+     * stream is proper closed after usage.
      *
      * @return The InputStream representing the content of the artifact.
      * @throws IOException
      */
-    InputStream getData() throws IOException;
+    InputStream getReadStream() throws IOException;
+
+    /**
+     * Returns a NIO representation of the data.
+     *
+     * @return A channel to the asset data.
+     * @throws IOException
+     */
+    ReadableByteChannel getReadChannel() throws IOException;
 
     /**
      *
-     * Returns an output stream where you can write data to the asset.
+     * Returns an output stream where you can write data to the asset. The operation is not locked or synchronized.
+     * User of this method have to make sure, that the stream is proper closed after usage.
      *
      * @param replace If true, the original data will be replaced, otherwise the data will be appended.
      * @return The OutputStream where the data can be written.
      * @throws IOException
      */
-    OutputStream writeData( boolean replace) throws IOException;
+    OutputStream getWriteStream( boolean replace) throws IOException;
+
+    /**
+     * Returns a NIO representation of the asset where you can write the data.
+     *
+     * @param replace True, if the content should be replaced by the data written to the stream.
+     * @return The Channel for writing the data.
+     * @throws IOException
+     */
+    WritableByteChannel getWriteChannel( boolean replace) throws IOException;
 
     /**
      * Replaces the content. The implementation may do an atomic move operation, or keep a backup. If
@@ -107,7 +135,7 @@ public interface StorageAsset
      *
      * @param newData Replaces the data by the content of the given file.
      */
-    boolean storeDataFile( Path newData) throws IOException;
+    boolean replaceDataFromFile( Path newData) throws IOException;
 
     /**
      * Returns true, if the asset exists.
@@ -123,12 +151,21 @@ public interface StorageAsset
 
     /**
      * Returns the real path to the asset, if it exist. Not all implementations may implement this method.
+     * The method throws {@link UnsupportedOperationException}, if and only if {@link #isFileBased()} returns false.
      *
      * @return The filesystem path to the asset.
-     * @throws UnsupportedOperationException
+     * @throws UnsupportedOperationException If the underlying storage is not file based.
      */
     Path getFilePath() throws UnsupportedOperationException;
 
+    /**
+     * Returns true, if the asset can return a file path for the given asset. If this is true, the  {@link #getFilePath()}
+     * will not throw a {@link UnsupportedOperationException}
+     *
+     * @return
+     */
+    boolean isFileBased();
+
     /**
      * Returns true, if there is a parent to this asset.
      * @return
index de57977f272ca16c2d4f3b739494f11b12a62450..87b5420b1b44f800acbd6e31874cc257d23b556c 100644 (file)
@@ -35,7 +35,11 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.URI;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.CopyOption;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -348,24 +352,54 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     }
 
     @Override
-    public StorageAsset moveAsset( StorageAsset origin, String destination ) throws IOException
+    public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
     {
         return storage.moveAsset(origin, destination);
     }
 
     @Override
-    public StorageAsset copyAsset( StorageAsset origin, String destination ) throws IOException
+    public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
+    {
+        storage.moveAsset( origin, destination, copyOptions );
+    }
+
+    @Override
+    public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
     {
         return storage.copyAsset(origin, destination);
     }
 
+    @Override
+    public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
+    {
+        storage.copyAsset( origin, destination, copyOptions);
+    }
+
     @Override
     public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
     {
         storage.consumeData(asset, consumerFunction, readLock);
     }
 
-    protected void setStorage(RepositoryStorage storage) {
+    @Override
+    public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
+    {
+        storage.consumeDataFromChannel( asset, consumerFunction, readLock );
+    }
+
+    @Override
+    public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
+    {
+        storage.writeData( asset, consumerFunction, writeLock );
+    }
+
+    @Override
+    public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
+    {
+        storage.writeDataToChannel( asset, consumerFunction, writeLock );
+    }
+
+    protected void setStorage( RepositoryStorage storage) {
         this.storage = storage;
     }
 
index 2b0ac684ac5f8b182c6bba85cdbc61c7dd3e0b63..e78130e33275a85d3eb90d3096c099a40a84af64 100644 (file)
@@ -26,6 +26,8 @@ import org.apache.archiva.indexer.IndexCreationFailedException;
 import org.apache.archiva.indexer.IndexManagerFactory;
 import org.apache.archiva.indexer.IndexUpdateFailedException;
 import org.apache.archiva.redback.components.registry.RegistryException;
+import org.apache.archiva.repository.content.RepositoryStorage;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.archiva.repository.features.IndexCreationEvent;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
@@ -1378,4 +1380,5 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             listener.raise(event);
         }
     }
+
 }
index 41b45dfdcd28444641e60a9a049f72d06037ba8a..e0d10f863eb14dc26ecbb9e946ae018033e166dc 100644 (file)
@@ -26,6 +26,9 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.nio.file.*;
 import java.nio.file.attribute.*;
 import java.time.Instant;
@@ -85,15 +88,20 @@ public class FilesystemAsset implements StorageAsset {
     boolean supportsAcl = false;
     boolean supportsPosix = false;
     final boolean setPermissionsForNew;
+    final RepositoryStorage storage;
 
     boolean directoryHint = false;
 
+    private static final OpenOption[] REPLACE_OPTIONS = new OpenOption[]{StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE};
+    private static final OpenOption[] APPEND_OPTIONS = new OpenOption[]{StandardOpenOption.APPEND};
 
-    FilesystemAsset(String path, Path assetPath, Path basePath) {
+
+    FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath) {
         this.assetPath = assetPath;
         this.relativePath = path;
         this.setPermissionsForNew=false;
         this.basePath = basePath;
+        this.storage = storage;
         init();
     }
 
@@ -104,11 +112,12 @@ public class FilesystemAsset implements StorageAsset {
      * @param path The logical path for the asset relative to the repository.
      * @param assetPath The asset path.
      */
-    public FilesystemAsset(String path, Path assetPath) {
+    public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath) {
         this.assetPath = assetPath;
         this.relativePath = path;
         this.setPermissionsForNew = false;
         this.basePath = null;
+        this.storage = storage;
         init();
     }
 
@@ -121,12 +130,13 @@ public class FilesystemAsset implements StorageAsset {
      * @param directory This is only relevant, if the represented file or directory does not exist yet and
      *                  is a hint.
      */
-    public FilesystemAsset(String path, Path assetPath, Path basePath, boolean directory) {
+    public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath, boolean directory) {
         this.assetPath = assetPath;
         this.relativePath = path;
         this.directoryHint = directory;
         this.setPermissionsForNew = false;
         this.basePath = basePath;
+        this.storage = storage;
         init();
     }
 
@@ -139,12 +149,13 @@ public class FilesystemAsset implements StorageAsset {
      * @param directory This is only relevant, if the represented file or directory does not exist yet and
      *                  is a hint.
      */
-    public FilesystemAsset(String path, Path assetPath, Path basePath, boolean directory, boolean setPermissionsForNew) {
+    public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath, boolean directory, boolean setPermissionsForNew) {
         this.assetPath = assetPath;
         this.relativePath = path;
         this.directoryHint = directory;
         this.setPermissionsForNew = setPermissionsForNew;
         this.basePath = basePath;
+        this.storage = storage;
         init();
     }
 
@@ -190,6 +201,12 @@ public class FilesystemAsset implements StorageAsset {
     }
 
 
+    @Override
+    public RepositoryStorage getStorage( )
+    {
+        return storage;
+    }
+
     @Override
     public String getPath() {
         return relativePath;
@@ -233,7 +250,7 @@ public class FilesystemAsset implements StorageAsset {
     @Override
     public List<StorageAsset> list() {
         try {
-            return Files.list(assetPath).map(p -> new FilesystemAsset(relativePath + "/" + p.getFileName().toString(), assetPath.resolve(p)))
+            return Files.list(assetPath).map(p -> new FilesystemAsset(storage, relativePath + "/" + p.getFileName().toString(), assetPath.resolve(p)))
                     .collect(Collectors.toList());
         } catch (IOException e) {
             return Collections.EMPTY_LIST;
@@ -262,7 +279,7 @@ public class FilesystemAsset implements StorageAsset {
      * @throws IOException
      */
     @Override
-    public InputStream getData() throws IOException {
+    public InputStream getReadStream() throws IOException {
         if (isContainer()) {
             throw new IOException("Can not create input stream for container");
         }
@@ -270,13 +287,18 @@ public class FilesystemAsset implements StorageAsset {
     }
 
     @Override
-    public OutputStream writeData(boolean replace) throws IOException {
-        OpenOption[] options;
-        if (replace) {
-            options = new OpenOption[]{StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE};
-        } else {
-            options = new OpenOption[]{StandardOpenOption.APPEND};
-        }
+    public ReadableByteChannel getReadChannel( ) throws IOException
+    {
+        return FileChannel.open( assetPath, StandardOpenOption.READ );
+    }
+
+    private OpenOption[] getOpenOptions(boolean replace) {
+        return replace ? REPLACE_OPTIONS : APPEND_OPTIONS;
+    }
+
+    @Override
+    public OutputStream getWriteStream( boolean replace) throws IOException {
+        OpenOption[] options = getOpenOptions( replace );
         if (!Files.exists( assetPath )) {
             create();
         }
@@ -284,7 +306,14 @@ public class FilesystemAsset implements StorageAsset {
     }
 
     @Override
-    public boolean storeDataFile(Path newData) throws IOException {
+    public WritableByteChannel getWriteChannel( boolean replace ) throws IOException
+    {
+        OpenOption[] options = getOpenOptions( replace );
+        return FileChannel.open( assetPath, options );
+    }
+
+    @Override
+    public boolean replaceDataFromFile( Path newData) throws IOException {
         final boolean createNew = !Files.exists(assetPath);
         Path backup = null;
         if (!createNew) {
@@ -361,6 +390,12 @@ public class FilesystemAsset implements StorageAsset {
         return assetPath;
     }
 
+    @Override
+    public boolean isFileBased( )
+    {
+        return true;
+    }
+
     @Override
     public boolean hasParent( )
     {
@@ -382,7 +417,7 @@ public class FilesystemAsset implements StorageAsset {
         }
         String relativeParent = StringUtils.substringBeforeLast( relativePath,"/");
         if (parentPath!=null) {
-            return new FilesystemAsset( relativeParent, parentPath, basePath, true, setPermissionsForNew );
+            return new FilesystemAsset(storage, relativeParent, parentPath, basePath, true, setPermissionsForNew );
         } else {
             return null;
         }
index 344ebe6336f6afe606ab69160db47447a6610d64..92044fa864407f0c1ffa88d36af052fb984db655 100644 (file)
@@ -30,9 +30,16 @@ import org.slf4j.LoggerFactory;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.CopyOption;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
 import java.util.function.Consumer;
 
 /**
@@ -100,6 +107,85 @@ public class FilesystemStorage implements RepositoryStorage {
 
     }
 
+    @Override
+    public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
+    {
+        final Path path = asset.getFilePath();
+        try {
+            if (readLock) {
+                consumeDataFromChannelLocked( path, consumerFunction );
+            } else
+            {
+                try ( FileChannel is = FileChannel.open( path, StandardOpenOption.READ ) )
+                {
+                    consumerFunction.accept( is );
+                }
+                catch ( IOException e )
+                {
+                    log.error("Could not read the input stream from file {}", path);
+                    throw e;
+                }
+            }
+        } catch (RuntimeException e)
+        {
+            log.error( "Runtime exception during data consume from artifact {}. Error: {}", path, e.getMessage() );
+            throw new IOException( e );
+        }
+    }
+
+    @Override
+    public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
+    {
+        final Path path = asset.getFilePath();
+        try {
+            if (writeLock) {
+                writeDataLocked( path, consumerFunction );
+            } else
+            {
+                try ( OutputStream is = Files.newOutputStream( path ) )
+                {
+                    consumerFunction.accept( is );
+                }
+                catch ( IOException e )
+                {
+                    log.error("Could not write the output stream to file {}", path);
+                    throw e;
+                }
+            }
+        } catch (RuntimeException e)
+        {
+            log.error( "Runtime exception during data consume from artifact {}. Error: {}", path, e.getMessage() );
+            throw new IOException( e );
+        }
+
+    }
+
+    @Override
+    public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
+    {
+        final Path path = asset.getFilePath();
+        try {
+            if (writeLock) {
+                writeDataToChannelLocked( path, consumerFunction );
+            } else
+            {
+                try ( FileChannel os = FileChannel.open( path, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE ))
+                {
+                    consumerFunction.accept( os );
+                }
+                catch ( IOException e )
+                {
+                    log.error("Could not write the data to file {}", path);
+                    throw e;
+                }
+            }
+        } catch (RuntimeException e)
+        {
+            log.error( "Runtime exception during data consume from artifact {}. Error: {}", path, e.getMessage() );
+            throw new IOException( e );
+        }
+    }
+
     private void consumeDataLocked( Path file, Consumer<InputStream> consumerFunction) throws IOException
     {
 
@@ -127,12 +213,93 @@ public class FilesystemStorage implements RepositoryStorage {
         }
     }
 
+    private void consumeDataFromChannelLocked( Path file, Consumer<ReadableByteChannel> consumerFunction) throws IOException
+    {
+
+        final Lock lock;
+        try
+        {
+            lock = fileLockManager.readFileLock( file );
+            try ( FileChannel is = FileChannel.open( lock.getFile( ), StandardOpenOption.READ ))
+            {
+                consumerFunction.accept( is );
+            }
+            catch ( IOException e )
+            {
+                log.error("Could not read the input stream from file {}", file);
+                throw e;
+            } finally
+            {
+                fileLockManager.release( lock );
+            }
+        }
+        catch ( FileLockException | FileNotFoundException | FileLockTimeoutException e)
+        {
+            log.error("Locking error on file {}", file);
+            throw new IOException(e);
+        }
+    }
+
+
+    private void writeDataLocked( Path file, Consumer<OutputStream> consumerFunction) throws IOException
+    {
+
+        final Lock lock;
+        try
+        {
+            lock = fileLockManager.writeFileLock( file );
+            try ( OutputStream is = Files.newOutputStream( lock.getFile()))
+            {
+                consumerFunction.accept( is );
+            }
+            catch ( IOException e )
+            {
+                log.error("Could not write the output stream to file {}", file);
+                throw e;
+            } finally
+            {
+                fileLockManager.release( lock );
+            }
+        }
+        catch ( FileLockException | FileNotFoundException | FileLockTimeoutException e)
+        {
+            log.error("Locking error on file {}", file);
+            throw new IOException(e);
+        }
+    }
+
+    private void writeDataToChannelLocked( Path file, Consumer<WritableByteChannel> consumerFunction) throws IOException
+    {
+
+        final Lock lock;
+        try
+        {
+            lock = fileLockManager.writeFileLock( file );
+            try ( FileChannel is = FileChannel.open( lock.getFile( ), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE ))
+            {
+                consumerFunction.accept( is );
+            }
+            catch ( IOException e )
+            {
+                log.error("Could not write to file {}", file);
+                throw e;
+            } finally
+            {
+                fileLockManager.release( lock );
+            }
+        }
+        catch ( FileLockException | FileNotFoundException | FileLockTimeoutException e)
+        {
+            log.error("Locking error on file {}", file);
+            throw new IOException(e);
+        }
+    }
 
     @Override
     public StorageAsset getAsset( String path )
     {
         try {
-            return new FilesystemAsset( path, getAssetPath(path));
+            return new FilesystemAsset(this, path, getAssetPath(path));
         } catch (IOException e) {
             throw new IllegalArgumentException("Path navigates outside of base directory "+path);
         }
@@ -142,7 +309,7 @@ public class FilesystemStorage implements RepositoryStorage {
     public StorageAsset addAsset( String path, boolean container )
     {
         try {
-            return new FilesystemAsset( path, getAssetPath(path), basePath, container);
+            return new FilesystemAsset(this, path, getAssetPath(path), basePath, container);
         } catch (IOException e) {
             throw new IllegalArgumentException("Path navigates outside of base directory "+path);
         }
@@ -155,29 +322,51 @@ public class FilesystemStorage implements RepositoryStorage {
     }
 
     @Override
-    public StorageAsset moveAsset( StorageAsset origin, String destination ) throws IOException
+    public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
     {
         boolean container = origin.isContainer();
-        FilesystemAsset newAsset = new FilesystemAsset( destination, getAssetPath(destination), basePath, container );
-        Files.move(origin.getFilePath(), newAsset.getFilePath());
+        FilesystemAsset newAsset = new FilesystemAsset(this, destination, getAssetPath(destination), basePath, container );
+        moveAsset( origin, newAsset, copyOptions );
         return newAsset;
     }
 
     @Override
-    public StorageAsset copyAsset( StorageAsset origin, String destination ) throws IOException
+    public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
+    {
+        Files.move(origin.getFilePath(), destination.getFilePath(), copyOptions);
+    }
+
+    @Override
+    public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
     {
         boolean container = origin.isContainer();
-        FilesystemAsset newAsset = new FilesystemAsset( destination, getAssetPath(destination), basePath, container );
-        if (Files.exists(newAsset.getFilePath())) {
-            throw new IOException("Destination file exists already "+ newAsset.getFilePath());
+        FilesystemAsset newAsset = new FilesystemAsset(this, destination, getAssetPath(destination), basePath, container );
+        copyAsset( origin, newAsset, copyOptions );
+        return newAsset;
+    }
+
+    @Override
+    public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
+    {
+        Path destinationPath = destination.getFilePath();
+        boolean overwrite = false;
+        for (int i=0; i<copyOptions.length; i++) {
+            if (copyOptions[i].equals( StandardCopyOption.REPLACE_EXISTING )) {
+                overwrite=true;
+            }
+        }
+        if (Files.exists(destinationPath) && !overwrite) {
+            throw new IOException("Destination file exists already "+ destinationPath);
         }
         if (Files.isDirectory( origin.getFilePath() ))
         {
-            FileUtils.copyDirectory(origin.getFilePath( ).toFile(), newAsset.getFilePath( ).toFile() );
+            FileUtils.copyDirectory(origin.getFilePath( ).toFile(), destinationPath.toFile() );
         } else if (Files.isRegularFile( origin.getFilePath() )) {
-            FileUtils.copyFile(origin.getFilePath( ).toFile(), newAsset.getFilePath( ).toFile() );
+            if (!Files.exists( destinationPath )) {
+                Files.createDirectories( destinationPath );
+            }
+            Files.copy( origin.getFilePath( ), destinationPath, copyOptions );
         }
-        return newAsset;
     }
 
     public FileLockManager getFileLockManager() {
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java
new file mode 100644 (file)
index 0000000..4b8d11b
--- /dev/null
@@ -0,0 +1,192 @@
+package org.apache.archiva.repository.content;
+
+/*
+ * 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 org.apache.archiva.common.filelock.FileLockException;
+import org.apache.archiva.common.filelock.FileLockManager;
+import org.apache.archiva.common.filelock.FileLockTimeoutException;
+import org.apache.archiva.common.filelock.Lock;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.CopyOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class StorageUtil
+{
+    private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+    /**
+     * Copies the source asset to the target. The assets may be from different RepositoryStorage instances.
+     *
+     * @param source The source asset
+     * @param target The target asset
+     * @param locked If true, a readlock is set on the source and a write lock is set on the target.
+     * @param copyOptions Copy options
+     * @throws IOException
+     */
+    public static final void copyAsset( final StorageAsset source,
+                                        final StorageAsset target,
+                                        boolean locked,
+                                        final CopyOption... copyOptions ) throws IOException
+    {
+        if (source.isFileBased() && target.isFileBased()) {
+            // Short cut for FS operations
+            final Path sourcePath = source.getFilePath();
+            final Path targetPath = target.getFilePath( );
+            if (locked) {
+                final FileLockManager lmSource = ((FilesystemStorage)source.getStorage()).getFileLockManager();
+                final FileLockManager lmTarget = ((FilesystemStorage)target.getStorage()).getFileLockManager();
+                try (Lock lockRead = lmSource.readFileLock( sourcePath ); Lock lockWrite = lmTarget.writeFileLock( targetPath ) )
+                {
+                    Files.copy( sourcePath, targetPath, copyOptions );
+                }
+                catch ( FileLockException e )
+                {
+                    throw new IOException( e );
+                }
+                catch ( FileLockTimeoutException e )
+                {
+                    throw new IOException( e );
+                }
+            } else
+            {
+                Files.copy( sourcePath, targetPath, copyOptions );
+            }
+        } else {
+            try {
+                final RepositoryStorage sourceStorage = source.getStorage();
+                final RepositoryStorage targetStorage = target.getStorage();
+                sourceStorage.consumeDataFromChannel( source, is -> wrapWriteFunction( is, targetStorage, target, locked ), locked);
+            }  catch (IOException e) {
+                throw e;
+            }  catch (Throwable e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof IOException) {
+                    throw (IOException)cause;
+                } else
+                {
+                    throw new IOException( e );
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * @param source
+     * @param target
+     * @param locked
+     * @param copyOptions
+     * @throws IOException
+     */
+    public static void moveAsset(StorageAsset source, StorageAsset target, boolean locked, CopyOption... copyOptions) throws IOException
+    {
+        if (source.isFileBased() && target.isFileBased()) {
+            // Short cut for FS operations
+            // Move is atomic operation
+            Files.move( source.getFilePath(), target.getFilePath(), copyOptions );
+        } else {
+            try {
+                final RepositoryStorage sourceStorage = source.getStorage();
+                final RepositoryStorage targetStorage = target.getStorage();
+                sourceStorage.consumeDataFromChannel( source, is -> wrapWriteFunction( is, targetStorage, target, locked ), locked);
+                sourceStorage.removeAsset( source );
+            }  catch (IOException e) {
+                throw e;
+            }  catch (Throwable e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof IOException) {
+                    throw (IOException)cause;
+                } else
+                {
+                    throw new IOException( e );
+                }
+            }
+        }
+
+    }
+
+    private static void wrapWriteFunction(ReadableByteChannel is, RepositoryStorage targetStorage, StorageAsset target, boolean locked) {
+        try {
+            targetStorage.writeDataToChannel( target, os -> copy(is, os), locked );
+        } catch (Exception e) {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    private static void copy( final ReadableByteChannel is, final WritableByteChannel os ) {
+        if (is instanceof FileChannel) {
+            copy( (FileChannel) is, os );
+        } else if (os instanceof FileChannel) {
+            copy(is, (FileChannel)os);
+        } else
+        {
+            try
+            {
+                ByteBuffer buffer = ByteBuffer.allocate( DEFAULT_BUFFER_SIZE );
+                while ( is.read( buffer ) != -1 )
+                {
+                    buffer.flip( );
+                    while ( buffer.hasRemaining( ) )
+                    {
+                        os.write( buffer );
+                    }
+                    buffer.clear( );
+                }
+            }
+            catch ( IOException e )
+            {
+                throw new RuntimeException( e );
+            }
+        }
+    }
+
+    private static void copy( final FileChannel is, final WritableByteChannel os ) {
+        try
+        {
+            is.transferTo( 0, is.size( ), os );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    private static void copy( final ReadableByteChannel is, final FileChannel os ) {
+        try
+        {
+            os.transferFrom( is, 0, Long.MAX_VALUE );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+}
index b06546a1f53ab7ba43afa7bd388081090c5236c0..8e98e59bb86496fa133beabdb6cd5aaafc9e124f 100644 (file)
@@ -25,7 +25,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.*;
-import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -124,7 +123,7 @@ public class FilesystemAssetTest {
     public void getData() throws IOException {
         FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile);
         Files.write(assetPathFile, "abcdef".getBytes("ASCII"));
-        try(InputStream is = asset.getData()) {
+        try(InputStream is = asset.getReadStream()) {
             assertEquals("abcdef", IOUtils.toString(is, "ASCII"));
         }
 
@@ -135,7 +134,7 @@ public class FilesystemAssetTest {
         FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathDir);
         Files.write(assetPathFile, "abcdef".getBytes("ASCII"));
         try {
-            InputStream is = asset.getData();
+            InputStream is = asset.getReadStream();
             assertFalse("Exception expected for data on dir", true);
         } catch (IOException e) {
             // fine
@@ -147,7 +146,7 @@ public class FilesystemAssetTest {
     public void writeData() throws IOException {
         FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile);
         Files.write(assetPathFile, "abcdef".getBytes("ASCII"));
-        try(OutputStream os  = asset.writeData(true)) {
+        try(OutputStream os  = asset.getWriteStream(true)) {
             IOUtils.write("test12345", os, "ASCII");
         }
         assertEquals("test12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII"));
@@ -157,7 +156,7 @@ public class FilesystemAssetTest {
     public void writeDataAppend() throws IOException {
         FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile);
         Files.write(assetPathFile, "abcdef".getBytes("ASCII"));
-        try(OutputStream os  = asset.writeData(false)) {
+        try(OutputStream os  = asset.getWriteStream(false)) {
             IOUtils.write("test12345", os, "ASCII");
         }
         assertEquals("abcdeftest12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII"));
@@ -168,7 +167,7 @@ public class FilesystemAssetTest {
         FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathDir);
         try {
 
-            OutputStream os = asset.writeData(true);
+            OutputStream os = asset.getWriteStream(true);
             assertTrue("Writing to a directory should throw a IOException", false);
         } catch (IOException e) {
             // Fine
@@ -182,7 +181,7 @@ public class FilesystemAssetTest {
         try(OutputStream os = Files.newOutputStream(dataFile)) {
             IOUtils.write("testkdkdkd", os, "ASCII");
         }
-        asset.storeDataFile(dataFile);
+        asset.replaceDataFromFile(dataFile);
         assertEquals("testkdkdkd", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII"));
     }
 
index 0eb574ed4f32ed2c96f6c7383361646b236dccc1..328f58a5a86544e684e004f5cd7ba1b968361e1d 100644 (file)
@@ -31,11 +31,7 @@ import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.content.StorageAsset;
 import org.springframework.stereotype.Service;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
 import java.util.Set;
-import java.util.function.Consumer;
 
 /**
  * @author Martin Stockhammer <martin_s@apache.org>
@@ -136,13 +132,13 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
     }
 
     @Override
-    public Path toFile( ArtifactReference reference )
+    public StorageAsset toFile( ArtifactReference reference )
     {
         return null;
     }
 
     @Override
-    public Path toFile( ArchivaArtifact reference )
+    public StorageAsset toFile( ArchivaArtifact reference )
     {
         return null;
     }
index e814a496c115891b5fd187a970291fa832f836b7..ade81214a292e52fbb07fbb3236655f10f99ae69 100644 (file)
@@ -27,10 +27,9 @@ import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.model.ProjectReference;
 import org.apache.archiva.model.VersionedReference;
 import org.apache.archiva.repository.*;
-import org.apache.archiva.repository.content.FilesystemStorage;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
@@ -328,13 +327,13 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
 
 
     @Override
-    public Path toFile( ArtifactReference reference )
+    public StorageAsset toFile( ArtifactReference reference )
     {
         return Paths.get(getRepoRoot(), refs.get(reference));
     }
 
     @Override
-    public Path toFile( ArchivaArtifact reference )
+    public StorageAsset toFile( ArchivaArtifact reference )
     {
         return null;
     }
index b59d9983588a07934c8b1d8737fe5a3b1fb0ad00..9c383c37d5979af073361777dd2272ec7a793382 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.archiva.proxy.ProxyException;
 import org.apache.archiva.proxy.model.NetworkProxy;
 import org.apache.archiva.proxy.model.ProxyConnector;
 import org.apache.archiva.repository.*;
+import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.wagon.ConnectionException;
 import org.apache.maven.wagon.ResourceDoesNotExistException;
@@ -101,9 +102,8 @@ public class MavenRepositoryProxyHandler extends DefaultRepositoryProxyHandler {
     /**
      * @param connector
      * @param remoteRepository
-     * @param tmpMd5
-     * @param tmpSha1
      * @param tmpResource
+     * @param checksumFiles
      * @param url
      * @param remotePath
      * @param resource
@@ -112,9 +112,9 @@ public class MavenRepositoryProxyHandler extends DefaultRepositoryProxyHandler {
      * @throws ProxyException
      * @throws NotModifiedException
      */
-    protected void transferResources(ProxyConnector connector, RemoteRepositoryContent remoteRepository, Path tmpMd5,
-                                     Path tmpSha1, Path tmpResource, String url, String remotePath, Path resource,
-                                     Path workingDirectory, ManagedRepositoryContent repository)
+    protected void transferResources( ProxyConnector connector, RemoteRepositoryContent remoteRepository,
+                                      Path tmpResource, Path[] checksumFiles, String url, String remotePath, StorageAsset resource,
+                                      Path workingDirectory, ManagedRepositoryContent repository )
             throws ProxyException, NotModifiedException {
         Wagon wagon = null;
         try {
@@ -146,16 +146,17 @@ public class MavenRepositoryProxyHandler extends DefaultRepositoryProxyHandler {
 
             boolean connected = connectToRepository(connector, wagon, remoteRepository);
             if (connected) {
-                transferArtifact(wagon, remoteRepository, remotePath, repository, resource, workingDirectory,
+                transferArtifact(wagon, remoteRepository, remotePath, repository, resource.getFilePath(), workingDirectory,
                         tmpResource);
 
                 // 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
-                transferChecksum(wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".sha1",
-                        tmpSha1);
-                transferChecksum(wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".md5",
-                        tmpMd5);
+                for (int i=0; i<checksumFiles.length; i++) {
+                    String ext = "."+StringUtils.substringAfterLast( checksumFiles[i].getFileName( ).toString( ), "." );
+                    transferChecksum(wagon, remoteRepository, remotePath, repository, resource.getFilePath(), ext,
+                        checksumFiles[i]);
+                }
             }
         } catch (NotFoundException e) {
             urlFailureCache.cacheFailure(url);
@@ -196,13 +197,12 @@ public class MavenRepositoryProxyHandler extends DefaultRepositoryProxyHandler {
      * @param remotePath       the remote path to the resource to get.
      * @param repository       the managed repository that will hold the file
      * @param resource         the local file that should contain the downloaded contents
-     * @param tmpDirectory     the temporary directory to download to
      * @param ext              the type of checksum to transfer (example: ".md5" or ".sha1")
      * @throws ProxyException if copying the downloaded file into place did not succeed.
      */
-    protected void transferChecksum(Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
-                                    ManagedRepositoryContent repository, Path resource, Path tmpDirectory, String ext,
-                                    Path destFile)
+    protected void transferChecksum( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
+                                     ManagedRepositoryContent repository, Path resource, String ext,
+                                     Path destFile )
             throws ProxyException {
         String url = remoteRepository.getURL().getUrl() + remotePath + ext;
 
index 2f10b16b51be3567067d91881dc2b86f7a2a2196..61ad3d3a0495050dc29678d9ab64a780e74e2355 100644 (file)
@@ -27,19 +27,14 @@ import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.model.ProjectReference;
 import org.apache.archiva.model.VersionedReference;
 import org.apache.archiva.repository.*;
-import org.apache.archiva.repository.content.PathParser;
 import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -334,13 +329,13 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
 
 
     @Override
-    public Path toFile( ArtifactReference reference )
+    public StorageAsset toFile( ArtifactReference reference )
     {
         return Paths.get(getRepoRoot(), refs.get(reference));
     }
 
     @Override
-    public Path toFile( ArchivaArtifact reference )
+    public StorageAsset toFile( ArchivaArtifact reference )
     {
         return null;
     }
index 01e429e6dc179516f93f5791080459a414bb95ce..9c36647d0799b850c194b048c7ef1dac73cc9f06 100644 (file)
@@ -19,10 +19,7 @@ package org.apache.archiva.repository.content.maven2;
  * under the License.
  */
 
-import org.apache.archiva.common.filelock.FileLockException;
 import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.common.filelock.FileLockTimeoutException;
-import org.apache.archiva.common.filelock.Lock;
 import org.apache.archiva.common.utils.PathUtil;
 import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
@@ -37,15 +34,10 @@ import org.apache.archiva.repository.LayoutException;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RepositoryException;
-import org.apache.archiva.repository.content.FilesystemAsset;
-import org.apache.archiva.repository.content.FilesystemStorage;
 import org.apache.archiva.repository.content.StorageAsset;
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -55,7 +47,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -202,30 +193,30 @@ public class ManagedDefaultRepositoryContent
     public Set<ArtifactReference> getRelatedArtifacts( ArtifactReference reference )
         throws ContentNotFoundException
     {
-        Path artifactFile = toFile( reference );
-        Path repoBase = PathUtil.getPathFromUri(repository.getLocation()).toAbsolutePath();
-        Path repoDir = artifactFile.getParent().toAbsolutePath();
+        StorageAsset artifactFile = toFile( reference );
+        StorageAsset repoBase = repository.getAsset( "" );
+        StorageAsset repoDir = artifactFile.getParent();
 
-        if ( !Files.exists(repoDir))
+        if ( !repoDir.exists())
         {
             throw new ContentNotFoundException(
-                "Unable to get related artifacts using a non-existant directory: " + repoDir.toAbsolutePath() );
+                "Unable to get related artifacts using a non-existant directory: " + repoDir.getPath() );
         }
 
-        if ( !Files.isDirectory( repoDir ) )
+        if ( !repoDir.isContainer() )
         {
             throw new ContentNotFoundException(
-                "Unable to get related artifacts using a non-directory: " + repoDir.toAbsolutePath() );
+                "Unable to get related artifacts using a non-directory: " + repoDir.getPath() );
         }
 
         Set<ArtifactReference> foundArtifacts;
 
         // First gather up the versions found as artifacts in the managed repository.
 
-        try (Stream<Path> stream = Files.list(repoDir)) {
-            foundArtifacts = stream.filter(Files::isRegularFile).map(path -> {
+        try (Stream<StorageAsset> stream = repoDir.list().stream() ) {
+            foundArtifacts = stream.filter(asset -> !asset.isContainer()).map(path -> {
                 try {
-                    ArtifactReference artifact = toArtifactReference(repoBase.relativize(path).toString());
+                    ArtifactReference artifact = toArtifactReference(path.getPath());
                     if( artifact.getGroupId().equals( reference.getGroupId() ) && artifact.getArtifactId().equals(
                             reference.getArtifactId() ) && artifact.getVersion().equals( reference.getVersion() )) {
                         return artifact;
@@ -237,9 +228,6 @@ public class ManagedDefaultRepositoryContent
                     return null;
                 }
             }).filter(Objects::nonNull).collect(Collectors.toSet());
-        } catch (IOException e) {
-            log.error("Could not read directory {}: {}", repoDir, e.getMessage(), e);
-            return Collections.emptySet();
         }
         return foundArtifacts;
     }
@@ -379,8 +367,8 @@ public class ManagedDefaultRepositoryContent
     @Override
     public boolean hasContent( ArtifactReference reference )
     {
-        Path artifactFile = toFile( reference );
-        return Files.exists(artifactFile) && Files.isRegularFile( artifactFile );
+        StorageAsset artifactFile = toFile( reference );
+        return artifactFile.exists() && !artifactFile.isContainer();
     }
 
     @Override
@@ -454,15 +442,15 @@ public class ManagedDefaultRepositoryContent
 
 
     @Override
-    public Path toFile( ArtifactReference reference )
+    public StorageAsset toFile( ArtifactReference reference )
     {
-        return PathUtil.getPathFromUri( repository.getLocation()).resolve( toPath( reference ) );
+        return repository.getAsset(toPath(reference));
     }
 
     @Override
-    public Path toFile( ArchivaArtifact reference )
+    public StorageAsset toFile( ArchivaArtifact reference )
     {
-        return PathUtil.getPathFromUri( repository.getLocation()).resolve( toPath( reference ) );
+        return repository.getAsset( toPath( reference ) );
     }
 
     /**
index b93fe5a759144dfb9279c0a6e91f2b489542539e..a858c1a844e0439af5c5413d3f8268efc7ac3020 100644 (file)
@@ -1,6 +1,7 @@
 package org.apache.archiva.scheduler.repository.model;
 
 import org.apache.archiva.redback.components.taskqueue.Task;
+import org.apache.archiva.repository.content.StorageAsset;
 
 import java.nio.file.Path;
 
@@ -33,7 +34,7 @@ public class RepositoryTask
 {
     private String repositoryId;
 
-    private Path resourceFile;
+    private StorageAsset resourceFile;
 
     private boolean updateRelatedArtifacts;
 
@@ -81,12 +82,12 @@ public class RepositoryTask
         return 0;
     }
 
-    public Path getResourceFile()
+    public StorageAsset getResourceFile()
     {
         return resourceFile;
     }
 
-    public void setResourceFile( Path resourceFile )
+    public void setResourceFile( StorageAsset resourceFile )
     {
         this.resourceFile = resourceFile;
     }
index c961a8df44d09f0f6b10bf456203fe7d48056fc7..ea2cb26883140c393fc95dee50d24020756af78d 100644 (file)
@@ -115,7 +115,10 @@ public class ArchivaRepositoryScanningTaskExecutor
             if ( task.getResourceFile() != null )
             {
                 log.debug( "Executing task from queue with job name: {}", task );
-                consumers.executeConsumers( arepo, task.getResourceFile(), task.isUpdateRelatedArtifacts() );
+                if (task.getResourceFile().isFileBased())
+                {
+                    consumers.executeConsumers( arepo, task.getResourceFile( ).getFilePath(), task.isUpdateRelatedArtifacts( ) );
+                }
             }
             else
             {
index 3c3cc7140d4fe3378d33eed28f74fe4e575b0716..f3dd25569c1dc1df219ef65fa541023c6cb0c63c 100644 (file)
@@ -54,6 +54,9 @@ import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryNotFoundException;
 import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.content.RepositoryStorage;
+import org.apache.archiva.repository.content.StorageAsset;
+import org.apache.archiva.repository.content.StorageUtil;
 import org.apache.archiva.repository.events.RepositoryListener;
 import org.apache.archiva.repository.metadata.MetadataTools;
 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
@@ -384,9 +387,9 @@ public class DefaultRepositoriesService
                                                        null );
             }
 
-            Path artifactFile = source.getLocalPath().resolve( artifactSourcePath );
+            StorageAsset artifactFile = source.getAsset( artifactSourcePath );
 
-            if ( !Files.exists(artifactFile) )
+            if ( !artifactFile.exists() )
             {
                 log.error( "cannot find artifact {}", artifactTransferRequest );
                 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString(),
@@ -401,18 +404,19 @@ public class DefaultRepositoriesService
             int lastIndex = artifactPath.lastIndexOf( '/' );
 
             String path = artifactPath.substring( 0, lastIndex );
-            Path targetPath = target.getLocalPath().resolve( path );
+            StorageAsset targetPath = target.getAsset( path );
 
             Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
             int newBuildNumber = 1;
             String timestamp = null;
 
-            Path versionMetadataFile = targetPath.resolve( MetadataTools.MAVEN_METADATA );
+            StorageAsset versionMetadataFile = target.getAsset(path + "/" + MetadataTools.MAVEN_METADATA );
             /* unused */ getMetadata( versionMetadataFile );
 
-            if ( !Files.exists(targetPath) )
+            if ( !targetPath.exists() )
             {
-                Files.createDirectories( targetPath );
+                targetPath = target.addAsset(targetPath.getPath(), true);
+                targetPath.create();
             }
 
             String filename = artifactPath.substring( lastIndex + 1 );
@@ -420,8 +424,8 @@ public class DefaultRepositoriesService
             boolean fixChecksums =
                 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
 
-            Path targetFile = targetPath.resolve( filename );
-            if ( Files.exists(targetFile) && target.blocksRedeployments())
+            StorageAsset targetFile = target.getAsset(targetPath + "/" + filename );
+            if ( targetFile.exists() && target.blocksRedeployments())
             {
                 throw new ArchivaRestServiceException(
                     "artifact already exists in target repo: " + artifactTransferRequest.getTargetRepositoryId()
@@ -430,7 +434,7 @@ public class DefaultRepositoriesService
             }
             else
             {
-                copyFile( artifactFile, targetPath, filename, fixChecksums );
+                copyFile( source, artifactFile, target, targetFile, fixChecksums );
                 queueRepositoryTask( target.getId(), targetFile );
             }
 
@@ -442,13 +446,14 @@ public class DefaultRepositoriesService
             }
             pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
 
-            Path pomFile = source.getLocalPath().resolve(
-                artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) )).resolve( pomFilename );
+            StorageAsset pomFile = source.getAsset(
+                artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) )+"/"+ pomFilename );
 
-            if ( pomFile != null && Files.size( pomFile ) > 0 )
+            if ( pomFile != null && pomFile.exists() )
             {
-                copyFile( pomFile, targetPath, pomFilename, fixChecksums );
-                queueRepositoryTask( target.getId(), targetPath.resolve( pomFilename ) );
+                StorageAsset targetPomFile = target.getAsset( targetPath.getPath() + "/" + pomFilename );
+                copyFile( source, pomFile, target, targetPomFile, fixChecksums );
+                queueRepositoryTask( target.getId(), targetPomFile );
 
 
             }
@@ -456,7 +461,7 @@ public class DefaultRepositoriesService
             // explicitly update only if metadata-updater consumer is not enabled!
             if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) )
             {
-                updateProjectMetadata( targetPath.toAbsolutePath().toString(), lastUpdatedTimestamp, timestamp, newBuildNumber,
+                updateProjectMetadata( target, targetPath, lastUpdatedTimestamp, timestamp, newBuildNumber,
                                        fixChecksums, artifactTransferRequest );
 
 
@@ -487,8 +492,9 @@ public class DefaultRepositoriesService
         return true;
     }
 
-    private void queueRepositoryTask( String repositoryId, Path localFile )
+    private void queueRepositoryTask( String repositoryId, StorageAsset localFile )
     {
+
         RepositoryTask task = new RepositoryTask();
         task.setRepositoryId( repositoryId );
         task.setResourceFile( localFile );
@@ -502,19 +508,19 @@ public class DefaultRepositoriesService
         catch ( TaskQueueException e )
         {
             log.error( "Unable to queue repository task to execute consumers on resource file ['{}"
-                           + "'].", localFile.getFileName());
+                           + "'].", localFile.getName());
         }
     }
 
-    private ArchivaRepositoryMetadata getMetadata( Path metadataFile )
+    private ArchivaRepositoryMetadata getMetadata( StorageAsset metadataFile )
         throws RepositoryMetadataException
     {
         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
-        if ( Files.exists(metadataFile) )
+        if ( metadataFile.exists() )
         {
             try
             {
-                metadata = MavenMetadataReader.read( metadataFile );
+                metadata = MavenMetadataReader.read( metadataFile.getFilePath() );
             }
             catch ( XMLException e )
             {
@@ -524,44 +530,49 @@ public class DefaultRepositoriesService
         return metadata;
     }
 
-    private Path getMetadata( String targetPath )
+    private StorageAsset getMetadata( RepositoryStorage storage, String targetPath )
     {
-        String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( FileSystems.getDefault().getSeparator() ));
+        return storage.getAsset( targetPath + "/" + MetadataTools.MAVEN_METADATA );
 
-        return Paths.get( artifactPath, MetadataTools.MAVEN_METADATA );
     }
 
-    private void copyFile( Path sourceFile, Path targetPath, String targetFilename, boolean fixChecksums )
+    /*
+     * Copies the asset to the new target.
+     */
+    private void copyFile( RepositoryStorage sourceStorage,  StorageAsset sourceFile, RepositoryStorage targetStorage, StorageAsset targetPath, boolean fixChecksums )
         throws IOException
     {
-        Files.copy( sourceFile, targetPath.resolve( targetFilename ), StandardCopyOption.REPLACE_EXISTING,
-                    StandardCopyOption.COPY_ATTRIBUTES );
 
+        StorageUtil.copyAsset( sourceStorage, sourceFile, targetStorage, targetPath, true );
         if ( fixChecksums )
         {
-            fixChecksums( targetPath.resolve( targetFilename ) );
+            fixChecksums( targetPath );
         }
     }
 
-    private void fixChecksums( Path file )
+    private void fixChecksums( StorageAsset file )
     {
-        ChecksummedFile checksum = new ChecksummedFile( file );
-        checksum.fixChecksums( algorithms );
+        Path destinationFile = file.getFilePath();
+        if (destinationFile!=null)
+        {
+            ChecksummedFile checksum = new ChecksummedFile( destinationFile );
+            checksum.fixChecksums( algorithms );
+        }
     }
 
-    private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
+    private void updateProjectMetadata( RepositoryStorage storage, StorageAsset targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
                                         boolean fixChecksums, ArtifactTransferRequest artifactTransferRequest )
         throws RepositoryMetadataException
     {
         List<String> availableVersions = new ArrayList<>();
         String latestVersion = artifactTransferRequest.getVersion();
 
-        Path projectDir = Paths.get( targetPath ).getParent();
-        Path projectMetadataFile = projectDir.resolve( MetadataTools.MAVEN_METADATA );
+        StorageAsset projectDir = targetPath.getParent();
+        StorageAsset projectMetadataFile = storage.getAsset( projectDir.getPath()+"/"+MetadataTools.MAVEN_METADATA );
 
         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
 
-        if ( Files.exists(projectMetadataFile) )
+        if ( projectMetadataFile.exists() )
         {
             availableVersions = projectMetadata.getAvailableVersions();
 
@@ -601,7 +612,7 @@ public class DefaultRepositoriesService
             projectMetadata.setReleasedVersion( latestVersion );
         }
 
-        RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile);
+        RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile.getFilePath());
 
         if ( fixChecksums )
         {
@@ -765,7 +776,7 @@ public class DefaultRepositoriesService
             TimeZone timezone = TimeZone.getTimeZone( "UTC" );
             DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
             fmt.setTimeZone( timezone );
-            ManagedRepository repoConfig = repositoryRegistry.getManagedRepository( repositoryId );
+            ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
 
             VersionedReference ref = new VersionedReference();
             ref.setArtifactId( artifact.getArtifactId() );
@@ -801,9 +812,9 @@ public class DefaultRepositoriesService
 
                 int index = path.lastIndexOf( '/' );
                 path = path.substring( 0, index );
-                Path targetPath = repoConfig.getLocalPath().resolve( path );
+                StorageAsset targetPath = repo.getAsset( path );
 
-                if ( !Files.exists(targetPath) )
+                if ( targetPath.exists() )
                 {
                     //throw new ContentNotFoundException(
                     //    artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() );
@@ -825,7 +836,7 @@ public class DefaultRepositoriesService
                         repository.deleteArtifact( artifactRef );
                     }
                 }
-                Path metadataFile = getMetadata( targetPath.toAbsolutePath().toString() );
+                StorageAsset metadataFile = getMetadata( repo, targetPath.getPath() );
                 ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
 
                 updateMetadata( metadata, metadataFile, lastUpdatedTimestamp, artifact );
@@ -1115,14 +1126,14 @@ public class DefaultRepositoriesService
      *
      * @param metadata
      */
-    private void updateMetadata( ArchivaRepositoryMetadata metadata, Path metadataFile, Date lastUpdatedTimestamp,
+    private void updateMetadata( ArchivaRepositoryMetadata metadata, StorageAsset metadataFile, Date lastUpdatedTimestamp,
                                  Artifact artifact )
         throws RepositoryMetadataException
     {
         List<String> availableVersions = new ArrayList<>();
         String latestVersion = "";
 
-        if ( Files.exists(metadataFile) )
+        if ( metadataFile.exists() )
         {
             if ( metadata.getAvailableVersions() != null )
             {
@@ -1166,8 +1177,8 @@ public class DefaultRepositoriesService
         metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
         metadata.setAvailableVersions( availableVersions );
 
-        RepositoryMetadataWriter.write( metadata, metadataFile);
-        ChecksummedFile checksum = new ChecksummedFile( metadataFile );
+        RepositoryMetadataWriter.write( metadata, metadataFile.getFilePath());
+        ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() );
         checksum.fixChecksums( algorithms );
     }
 
index eed07ea4f0dd101c1d8dff9c1f1bb13aa9b7da10..b3843e513f8dcaeb3419cca184685608c162272c 100644 (file)
@@ -336,7 +336,7 @@ public class ArchivaDavResource
                 }
                 StorageAsset member = repositoryStorage.addAsset( newPath, false );
                 member.create();
-                member.storeDataFile( tempFile );
+                member.replaceDataFromFile( tempFile );
             }
             catch ( IOException e )
             {
index 46c920c9a368acf68531f77a495be969bc8963aa..30e14433dc114dcccf6de7e806323722a6bc6d53 100644 (file)
@@ -24,10 +24,8 @@ import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin;
 import org.apache.archiva.audit.Auditable;
 import org.apache.archiva.checksum.ChecksumAlgorithm;
 import org.apache.archiva.checksum.ChecksumUtil;
-import org.apache.archiva.checksum.ChecksummedFile;
 import org.apache.archiva.checksum.StreamingChecksum;
 import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
 import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
 import org.apache.archiva.common.utils.PathUtil;
 import org.apache.archiva.common.utils.VersionUtil;
@@ -68,7 +66,6 @@ import org.apache.archiva.repository.RepositoryGroup;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.RepositoryRequestInfo;
 import org.apache.archiva.repository.content.FilesystemAsset;
-import org.apache.archiva.repository.content.FilesystemStorage;
 import org.apache.archiva.repository.content.StorageAsset;
 import org.apache.archiva.repository.events.AuditListener;
 import org.apache.archiva.repository.features.IndexCreationFeature;
@@ -94,7 +91,6 @@ import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.lock.LockManager;
 import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
-import org.codehaus.plexus.digest.Digester;
 import org.codehaus.plexus.digest.DigesterException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -1254,7 +1250,7 @@ public class ArchivaDavResourceFactory
         throws RepositoryMetadataException, DigesterException, IOException
     {
         StorageAsset asset = repoGroup.addAsset( outputFilename, false );
-        OutputStream stream = asset.writeData( true );
+        OutputStream stream = asset.getWriteStream( true );
         OutputStreamWriter sw = new OutputStreamWriter( stream, "UTF-8" );
         RepositoryMetadataWriter.write( mergedMetadata, sw );
 
@@ -1269,7 +1265,7 @@ public class ArchivaDavResourceFactory
             String ext = algo.getDefaultExtension( );
             try
             {
-                return repo.getAsset( path + "." + ext ).writeData( true );
+                return repo.getAsset( path + "." + ext ).getWriteStream( true );
             }
             catch ( IOException e )
             {
@@ -1279,7 +1275,7 @@ public class ArchivaDavResourceFactory
         } ).filter( Objects::nonNull ).collect( Collectors.toList( ) );
         try
         {
-            StreamingChecksum.updateChecksums( repo.getAsset(path).getData(), algorithms, outStreams );
+            StreamingChecksum.updateChecksums( repo.getAsset(path).getReadStream(), algorithms, outStreams );
         }
         catch ( IOException e )
         {