aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Stockhammer <martin_s@apache.org>2019-07-19 19:29:01 +0200
committerMartin Stockhammer <martin_s@apache.org>2019-07-19 19:29:01 +0200
commit8e4acdc82a875ca32e39eb216b879c002d228de3 (patch)
tree0c255f334dd886636ae1d1343430c89b7f1e630a
parentd599b89e3d259266373717897f8b7fd24fc7fb8e (diff)
downloadarchiva-8e4acdc82a875ca32e39eb216b879c002d228de3.tar.gz
archiva-8e4acdc82a875ca32e39eb216b879c002d228de3.zip
Migrating to storage API
-rw-r--r--archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java1
-rw-r--r--archiva-modules/archiva-base/archiva-configuration/pom.xml4
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java4
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java26
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java4
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java21
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java5
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java7
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java4
-rw-r--r--archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java6
-rw-r--r--archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java8
-rw-r--r--archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java6
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java193
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java13
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java81
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java51
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java40
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java3
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java65
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java213
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java192
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java13
-rw-r--r--archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java8
-rw-r--r--archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java7
-rw-r--r--archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java28
-rw-r--r--archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java9
-rw-r--r--archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java44
-rw-r--r--archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java7
-rw-r--r--archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java5
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java97
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java2
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java10
32 files changed, 834 insertions, 343 deletions
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
index 5a11b910f..bb6a710ae 100644
--- a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
@@ -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());
}
+
}
diff --git a/archiva-modules/archiva-base/archiva-configuration/pom.xml b/archiva-modules/archiva-base/archiva-configuration/pom.xml
index 75690291a..fd4565cce 100644
--- a/archiva-modules/archiva-base/archiva-configuration/pom.xml
+++ b/archiva-modules/archiva-base/archiva-configuration/pom.xml
@@ -136,10 +136,6 @@
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
- <artifactId>archiva-policies</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.archiva</groupId>
<artifactId>archiva-test-utils</artifactId>
<version>${project.version}</version>
<scope>test</scope>
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
index ab10d7404..f8e4e4603 100644
--- a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
@@ -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;
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java
index 1fbbfece5..cf1c0da4a 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/AbstractUpdatePolicy.java
@@ -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 ) )
{
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java
index e92858fe8..ac20dbc8e 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/CachedFailuresPolicy.java
@@ -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 ) )
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
index 82d4d3da4..8f6885a6b 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
@@ -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() + "." );
}
}
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java
index 90261737e..28de5336b 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadErrorPolicy.java
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java
index 8d149e619..f9a144331 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/DownloadPolicy.java
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java
index 1fab1209a..7a0baefe1 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsDownloadPolicy.java
@@ -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
{
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java
index ec3289105..9b22a9b23 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java
@@ -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(
diff --git a/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java b/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java
index 28e8cb9b1..700e4a560 100644
--- a/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java
+++ b/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/ProxyFetchResult.java
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java b/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java
index eee2d86d2..f82d55514 100644
--- a/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java
+++ b/archiva-modules/archiva-base/archiva-proxy-api/src/main/java/org/apache/archiva/proxy/model/RepositoryProxyHandler.java
@@ -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.
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java
index 5622fe5c4..fac557ed4 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java
@@ -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 );
}
}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
index 1bab4a8ff..c50a89cf2 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
@@ -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
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java
index 82b40b2ce..3dea0b294 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/RepositoryStorage.java
@@ -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,14 +51,43 @@ 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.
* @param container True, if the asset should be a container, false, if it is a file.
@@ -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;
+
+
}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java
index 16e70859d..38ef2a895 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/StorageAsset.java
@@ -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,13 +151,22 @@ 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
*/
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
index de57977f2..87b5420b1 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
index 2b0ac684a..e78130e33 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
@@ -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);
}
}
+
}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java
index 41b45dfdc..e0d10f863 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemAsset.java
@@ -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();
}
@@ -191,6 +202,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) {
@@ -362,6 +391,12 @@ public class FilesystemAsset implements StorageAsset {
}
@Override
+ public boolean isFileBased( )
+ {
+ return true;
+ }
+
+ @Override
public boolean hasParent( )
{
if (basePath!=null && assetPath.equals(basePath)) {
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java
index 344ebe633..92044fa86 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/FilesystemStorage.java
@@ -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
index 000000000..4b8d11b39
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java
@@ -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 );
+ }
+ }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java
index b06546a1f..8e98e59bb 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java
@@ -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"));
}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
index 0eb574ed4..328f58a5a 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
@@ -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;
}
diff --git a/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java b/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java
index e814a496c..ade81214a 100644
--- a/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java
+++ b/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java
@@ -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;
}
diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java
index b59d99835..9c383c37d 100644
--- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java
+++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/main/java/org/apache/archiva/proxy/maven/MavenRepositoryProxyHandler.java
@@ -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;
diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
index 2f10b16b5..61ad3d3a0 100644
--- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
+++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
@@ -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;
}
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java
index 01e429e6d..9c36647d0 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java
@@ -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 ) );
}
/**
diff --git a/archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java b/archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java
index b93fe5a75..a858c1a84 100644
--- a/archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java
+++ b/archiva-modules/archiva-scheduler/archiva-scheduler-repository-api/src/main/java/org/apache/archiva/scheduler/repository/model/RepositoryTask.java
@@ -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;
}
diff --git a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java
index c961a8df4..ea2cb2688 100644
--- a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java
+++ b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/main/java/org/apache/archiva/scheduler/repository/ArchivaRepositoryScanningTaskExecutor.java
@@ -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
{
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java
index 3c3cc7140..f3dd25569 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java
@@ -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 );
}
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
index eed07ea4f..b3843e513 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
@@ -336,7 +336,7 @@ public class ArchivaDavResource
}
StorageAsset member = repositoryStorage.addAsset( newPath, false );
member.create();
- member.storeDataFile( tempFile );
+ member.replaceDataFromFile( tempFile );
}
catch ( IOException e )
{
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java
index 46c920c9a..30e14433d 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResourceFactory.java
@@ -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 )
{