diff options
Diffstat (limited to 'archiva-modules/archiva-base')
63 files changed, 1044 insertions, 687 deletions
diff --git a/archiva-modules/archiva-base/archiva-configuration/pom.xml b/archiva-modules/archiva-base/archiva-configuration/pom.xml index fd4565cce..5961fd259 100644 --- a/archiva-modules/archiva-base/archiva-configuration/pom.xml +++ b/archiva-modules/archiva-base/archiva-configuration/pom.xml @@ -34,6 +34,10 @@ <dependencies> <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-policies</artifactId> + </dependency> + <dependency> <groupId>org.apache.archiva.redback.components.registry</groupId> <artifactId>spring-registry-api</artifactId> <exclusions> diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurge.java index 44b7daa19..6354e3a2a 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurge.java @@ -31,6 +31,8 @@ import org.apache.archiva.model.ArtifactReference; import org.apache.archiva.repository.ContentNotFoundException; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.events.RepositoryListener; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.archiva.repository.storage.StorageUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -211,22 +213,22 @@ public abstract class AbstractRepositoryPurge log.error( "Error during metadata retrieval {}: {}", metaBaseId, e.getMessage( ) ); } } - Path artifactFile = repository.toFile( reference ); + StorageAsset artifactFile = repository.toFile( reference ); for ( RepositoryListener listener : listeners ) { listener.deleteArtifact( metadataRepository, repository.getId( ), reference.getGroupId( ), reference.getArtifactId( ), reference.getVersion( ), - artifactFile.getFileName( ).toString( ) ); + artifactFile.getName( )); } try { - Files.delete( artifactFile ); - log.debug( "File deleted: {}", artifactFile.toAbsolutePath( ) ); + artifactFile.getStorage().removeAsset(artifactFile); + log.debug( "File deleted: {}", artifactFile ); } catch ( IOException e ) { - log.error( "Could not delete file {}: {}", artifactFile.toAbsolutePath( ), e.getMessage( ), e ); + log.error( "Could not delete file {}: {}", artifactFile.toString(), e.getMessage( ), e ); continue; } try @@ -364,11 +366,11 @@ public abstract class AbstractRepositoryPurge } } - private void deleteSilently( Path path ) + private void deleteSilently( StorageAsset path ) { try { - Files.deleteIfExists( path ); + path.getStorage().removeAsset(path); triggerAuditEvent( repository.getRepository( ).getId( ), path.toString( ), AuditEvent.PURGE_FILE ); } catch ( IOException e ) @@ -387,22 +389,23 @@ public abstract class AbstractRepositoryPurge * * @param artifactFile the file to base off of. */ - private void purgeSupportFiles( Path artifactFile ) + private void purgeSupportFiles( StorageAsset artifactFile ) { - Path parentDir = artifactFile.getParent( ); + StorageAsset parentDir = artifactFile.getParent( ); - if ( !Files.exists( parentDir ) ) + if ( !parentDir.exists() ) { return; } - final String artifactName = artifactFile.getFileName( ).toString( ); + final String artifactName = artifactFile.getName( ); try { - Files.find( parentDir, 3, - ( path, basicFileAttributes ) -> path.getFileName( ).toString( ).startsWith( artifactName ) - && Files.isRegularFile( path ) ).forEach( this::deleteSilently ); + + StorageUtil.recurse(parentDir, a -> { + if (!artifactFile.isContainer() && artifactFile.getName().startsWith(artifactName)) deleteSilently(a); + }, true, 3 ); } catch ( IOException e ) { diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/DaysOldRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/DaysOldRepositoryPurge.java index 6c6607d2d..9ff31ec60 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/DaysOldRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/repository/DaysOldRepositoryPurge.java @@ -28,6 +28,7 @@ import org.apache.archiva.repository.ContentNotFoundException; import org.apache.archiva.repository.LayoutException; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.events.RepositoryListener; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.time.DateUtils; import java.io.IOException; @@ -115,12 +116,12 @@ public class DaysOldRepositoryPurge artifactFile.toAbsolutePath( ).toString() ); newArtifactReference.setVersion( version ); - Path newArtifactFile = repository.toFile( newArtifactReference ); + StorageAsset newArtifactFile = repository.toFile( newArtifactReference ); // Is this a generic snapshot "1.0-SNAPSHOT" ? if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion( ) ) ) { - if ( Files.getLastModifiedTime( newArtifactFile ).toMillis() < olderThanThisDate.getTimeInMillis( ) ) + if ( newArtifactFile.getModificationTime().toEpochMilli() < olderThanThisDate.getTimeInMillis( ) ) { artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) ); } @@ -138,7 +139,7 @@ public class DaysOldRepositoryPurge } purge( artifactsToDelete ); } - catch ( ContentNotFoundException | IOException e ) + catch ( ContentNotFoundException e ) { throw new RepositoryPurgeException( e.getMessage( ), e ); } diff --git a/archiva-modules/archiva-base/archiva-policies/pom.xml b/archiva-modules/archiva-base/archiva-policies/pom.xml index 63acd6750..ab5f64081 100644 --- a/archiva-modules/archiva-base/archiva-policies/pom.xml +++ b/archiva-modules/archiva-base/archiva-policies/pom.xml @@ -40,6 +40,10 @@ </dependency> <dependency> <groupId>org.apache.archiva</groupId> + <artifactId>archiva-storage-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> <artifactId>archiva-checksum</artifactId> </dependency> <dependency> @@ -83,6 +87,11 @@ </dependency> <dependency> <groupId>org.apache.archiva</groupId> + <artifactId>archiva-storage-fs</artifactId> + <scope>test</scope> + </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-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 cf1c0da4a..394917cdd 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,16 +20,13 @@ package org.apache.archiva.policies; */ import org.apache.archiva.common.utils.VersionUtil; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.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.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.List; import java.util.Properties; 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 ac20dbc8e..7cd1294d0 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,7 +20,7 @@ package org.apache.archiva.policies; */ import org.apache.archiva.policies.urlcache.UrlFailureCache; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 8f6885a6b..99c5ddab4 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,7 +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.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 28de5336b..43ae03e0f 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,7 @@ package org.apache.archiva.policies; * under the License. */ -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import java.util.Map; import java.util.Properties; 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 f9a144331..1ee2713db 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,7 @@ package org.apache.archiva.policies; * under the License. */ -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import java.util.Properties; 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 7a0baefe1..7726ebb86 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,7 +19,7 @@ package org.apache.archiva.policies; * under the License. */ -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 9b22a9b23..a50c1b9e0 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,10 @@ package org.apache.archiva.policies; * under the License. */ -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/CachedFailuresPolicyTest.java b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/CachedFailuresPolicyTest.java index 2c9995c0b..d27c392be 100644 --- a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/CachedFailuresPolicyTest.java +++ b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/CachedFailuresPolicyTest.java @@ -20,7 +20,10 @@ package org.apache.archiva.policies; */ import junit.framework.TestCase; +import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.policies.urlcache.UrlFailureCache; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.junit.Test; import org.junit.runner.RunWith; @@ -28,6 +31,7 @@ import org.springframework.test.context.ContextConfiguration; import javax.inject.Inject; import javax.inject.Named; +import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; @@ -47,6 +51,8 @@ public class CachedFailuresPolicyTest @Inject private UrlFailureCache urlFailureCache; + private FilesystemStorage filesystemStorage; + @Inject @Named( value = "preDownloadPolicy#cache-failures" ) DownloadPolicy downloadPolicy; @@ -57,9 +63,11 @@ public class CachedFailuresPolicyTest return downloadPolicy; } - private Path getFile() - { - return Paths.get( "target/cache-failures/" + getName() + ".txt" ); + private StorageAsset getFile() throws IOException { + if (filesystemStorage==null) { + filesystemStorage = new FilesystemStorage(Paths.get("target/cache-failures"), new DefaultFileLockManager()); + } + return filesystemStorage.getAsset( getName() + ".txt" ); } private Properties createRequest() @@ -74,7 +82,7 @@ public class CachedFailuresPolicyTest throws Exception { DownloadPolicy policy = lookupPolicy(); - Path localFile = getFile(); + StorageAsset localFile = getFile(); Properties request = createRequest(); request.setProperty( "url", "http://a.bad.hostname.maven.org/path/to/resource.txt" ); @@ -88,7 +96,7 @@ public class CachedFailuresPolicyTest { DownloadPolicy policy = lookupPolicy(); - Path localFile = getFile(); + StorageAsset localFile = getFile(); Properties request = createRequest(); // make unique name String url = "http://a.bad.hostname.maven.org/path/to/resource"+ System.currentTimeMillis() +".txt"; diff --git a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ChecksumPolicyTest.java b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ChecksumPolicyTest.java index 3faad0b97..4a8c6cb81 100644 --- a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ChecksumPolicyTest.java +++ b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ChecksumPolicyTest.java @@ -19,6 +19,9 @@ package org.apache.archiva.policies; * under the License. */ +import org.apache.archiva.common.filelock.DefaultFileLockManager; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.io.FileUtils; import org.junit.Rule; @@ -31,6 +34,7 @@ import javax.inject.Inject; import javax.inject.Named; import java.io.BufferedReader; import java.io.FileReader; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -51,6 +55,8 @@ public class ChecksumPolicyTest private static final String BAD = "bad"; + private static FilesystemStorage filesystemStorage; + @Inject @Named( value = "postDownloadPolicy#checksum" ) PostDownloadPolicy downloadPolicy; @@ -195,7 +201,7 @@ public class ChecksumPolicyTest throws Exception { PostDownloadPolicy policy = lookupPolicy(); - Path localFile = createTestableFiles( null, null ); + StorageAsset localFile = createTestableFiles( null, null ); Properties request = createRequest(); policy.applyPolicy( ChecksumPolicy.IGNORE, request, localFile ); @@ -205,7 +211,7 @@ public class ChecksumPolicyTest throws Exception { PostDownloadPolicy policy = lookupPolicy(); - Path localFile = createTestableFiles( md5State, sha1State ); + StorageAsset localFile = createTestableFiles( md5State, sha1State ); Properties request = createRequest(); boolean actualResult; @@ -220,9 +226,9 @@ public class ChecksumPolicyTest actualResult = false; String msg = createMessage( ChecksumPolicy.FAIL, md5State, sha1State ); - assertFalse( msg + " local file should not exist:", Files.exists(localFile) ); - Path md5File = localFile.toAbsolutePath().resolveSibling( localFile.getFileName() + ".sha1" ); - Path sha1File = localFile.toAbsolutePath().resolveSibling( localFile.getFileName() + ".md5" ); + assertFalse( msg + " local file should not exist:", localFile.exists() ); + Path md5File = localFile.getFilePath().toAbsolutePath().resolveSibling( localFile.getName() + ".sha1" ); + Path sha1File = localFile.getFilePath().toAbsolutePath().resolveSibling( localFile.getName() + ".md5" ); assertFalse( msg + " local md5 file should not exist:", Files.exists(md5File) ); assertFalse( msg + " local sha1 file should not exist:", Files.exists(sha1File) ); } @@ -234,7 +240,7 @@ public class ChecksumPolicyTest throws Exception { PostDownloadPolicy policy = lookupPolicy(); - Path localFile = createTestableFiles( md5State, sha1State ); + StorageAsset localFile = createTestableFiles( md5State, sha1State ); Properties request = createRequest(); boolean actualResult; @@ -252,8 +258,8 @@ public class ChecksumPolicyTest assertEquals( createMessage( ChecksumPolicy.FIX, md5State, sha1State ), expectedResult, actualResult ); // End result should be legitimate SHA1 and MD5 files. - Path md5File = localFile.toAbsolutePath().resolveSibling( localFile.getFileName() + ".md5" ); - Path sha1File = localFile.toAbsolutePath().resolveSibling( localFile.getFileName() + ".sha1" ); + Path md5File = localFile.getFilePath().toAbsolutePath().resolveSibling( localFile.getName() + ".md5" ); + Path sha1File = localFile.getFilePath().toAbsolutePath().resolveSibling( localFile.getName() + ".sha1" ); assertTrue( "ChecksumPolicy.apply(FIX) md5 should exist.", Files.exists(md5File) && Files.isRegularFile(md5File) ); assertTrue( "ChecksumPolicy.apply(FIX) sha1 should exist.", Files.exists(sha1File) && Files.isRegularFile(sha1File) ); @@ -336,37 +342,41 @@ public class ChecksumPolicyTest return request; } - private Path createTestableFiles( String md5State, String sha1State ) + private StorageAsset createTestableFiles(String md5State, String sha1State ) throws Exception { - Path sourceDir = getTestFile( "src/test/resources/checksums/" ); - Path destDir = getTestFile( "target/checksum-tests/" + name.getMethodName() + "/" ); + FilesystemStorage fs = new FilesystemStorage(Paths.get("target/checksum-tests"), new DefaultFileLockManager()); + StorageAsset sourceDir = getTestFile( "src/test/resources/checksums/" ); + StorageAsset destDir = getTestFile( "target/checksum-tests/" + name.getMethodName() + "/" ); - FileUtils.copyFileToDirectory( sourceDir.resolve("artifact.jar" ).toFile(), destDir.toFile() ); + FileUtils.copyFileToDirectory( sourceDir.getFilePath().resolve("artifact.jar" ).toFile(), destDir.getFilePath().toFile() ); if ( md5State != null ) { - Path md5File = sourceDir.resolve("artifact.jar.md5-" + md5State ); + Path md5File = sourceDir.getFilePath().resolve("artifact.jar.md5-" + md5State ); assertTrue( "Testable file exists: " + md5File.getFileName() + ":", Files.exists(md5File) && Files.isRegularFile(md5File) ); - Path destFile = destDir.resolve("artifact.jar.md5" ); + Path destFile = destDir.getFilePath().resolve("artifact.jar.md5" ); FileUtils.copyFile( md5File.toFile(), destFile.toFile() ); } if ( sha1State != null ) { - Path sha1File = sourceDir.resolve("artifact.jar.sha1-" + sha1State ); + Path sha1File = sourceDir.getFilePath().resolve("artifact.jar.sha1-" + sha1State ); assertTrue( "Testable file exists: " + sha1File.getFileName() + ":", Files.exists(sha1File) && Files.isRegularFile(sha1File) ); - Path destFile = destDir.resolve("artifact.jar.sha1" ); + Path destFile = destDir.getFilePath().resolve("artifact.jar.sha1" ); FileUtils.copyFile( sha1File.toFile(), destFile.toFile() ); } - Path localFile = destDir.resolve("artifact.jar" ); - return localFile; + + StorageAsset localAsset = fs.getAsset("artifact.jar"); + return localAsset; } - public static Path getTestFile( String path ) - { - return Paths.get( org.apache.archiva.common.utils.FileUtils.getBasedir(), path ); + public static StorageAsset getTestFile( String path ) throws IOException { + if (filesystemStorage==null) { + filesystemStorage = new FilesystemStorage(Paths.get(org.apache.archiva.common.utils.FileUtils.getBasedir()), new DefaultFileLockManager()); + } + return filesystemStorage.getAsset( path ); } } diff --git a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ReleasePolicyTest.java b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ReleasePolicyTest.java index adf341b29..3c5bae066 100644 --- a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ReleasePolicyTest.java +++ b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/ReleasePolicyTest.java @@ -20,6 +20,7 @@ package org.apache.archiva.policies; */ import junit.framework.TestCase; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.junit.Before; import org.junit.Test; @@ -338,17 +339,17 @@ public class ReleasePolicyTest request.setProperty( "version", "2.0" ); } - Path targetDir = ChecksumPolicyTest.getTestFile( "target/test-policy/" ); - Path localFile = targetDir.resolve( path ); + StorageAsset targetDir = ChecksumPolicyTest.getTestFile( "target/test-policy/" ); + StorageAsset localFile = targetDir.resolve( path ); - Files.deleteIfExists( localFile ); + Files.deleteIfExists( localFile.getFilePath() ); if ( createLocalFile ) { - Files.createDirectories( localFile.getParent()); - org.apache.archiva.common.utils.FileUtils.writeStringToFile( localFile, FILE_ENCODING, "random-junk" ); - Files.setLastModifiedTime( localFile, - FileTime.fromMillis(Files.getLastModifiedTime(localFile).toMillis() - generatedLocalFileUpdateDelta)); + Files.createDirectories( localFile.getParent().getFilePath()); + org.apache.archiva.common.utils.FileUtils.writeStringToFile( localFile.getFilePath(), FILE_ENCODING, "random-junk" ); + Files.setLastModifiedTime( localFile.getFilePath(), + FileTime.fromMillis(Files.getLastModifiedTime(localFile.getFilePath()).toMillis() - generatedLocalFileUpdateDelta)); } policy.applyPolicy( setting, request, localFile ); diff --git a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/SnapshotsPolicyTest.java b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/SnapshotsPolicyTest.java index 5272777fe..a68ae8dd9 100644 --- a/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/SnapshotsPolicyTest.java +++ b/archiva-modules/archiva-base/archiva-policies/src/test/java/org/apache/archiva/policies/SnapshotsPolicyTest.java @@ -20,6 +20,8 @@ package org.apache.archiva.policies; */ import junit.framework.TestCase; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.junit.Before; import org.junit.Test; @@ -80,6 +82,8 @@ public class SnapshotsPolicyTest @Inject @Named(value="preDownloadPolicy#snapshots") PreDownloadPolicy policy; + private FilesystemStorage filesystemStorage; + private PreDownloadPolicy lookupPolicy() throws Exception { @@ -337,17 +341,17 @@ public class SnapshotsPolicyTest request.setProperty( "version", "2.0" ); } - Path targetDir = ChecksumPolicyTest.getTestFile( "target/test-policy/" ); - Path localFile = targetDir.resolve( path ); + StorageAsset targetDir = ChecksumPolicyTest.getTestFile( "target/test-policy/" ); + StorageAsset localFile = targetDir.resolve( path ); - Files.deleteIfExists( localFile ); + Files.deleteIfExists( localFile.getFilePath() ); if ( createLocalFile ) { - Files.createDirectories( localFile.getParent()); - org.apache.archiva.common.utils.FileUtils.writeStringToFile( localFile, FILE_ENCODING, "random-junk" ); - Files.setLastModifiedTime( localFile, - FileTime.fromMillis( Files.getLastModifiedTime( localFile ).toMillis() - generatedLocalFileUpdateDelta )); + Files.createDirectories( localFile.getParent().getFilePath() ); + org.apache.archiva.common.utils.FileUtils.writeStringToFile( localFile.getFilePath(), FILE_ENCODING, "random-junk" ); + Files.setLastModifiedTime( localFile.getFilePath(), + FileTime.fromMillis( Files.getLastModifiedTime( localFile.getFilePath() ).toMillis() - generatedLocalFileUpdateDelta )); } policy.applyPolicy( setting, request, localFile ); 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 700e4a560..b4faf2da7 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,9 +20,7 @@ package org.apache.archiva.proxy.model; */ -import org.apache.archiva.repository.content.StorageAsset; - -import java.nio.file.Path; +import org.apache.archiva.repository.storage.StorageAsset; /** * A result from a proxy fetch operation. 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 f82d55514..efcd901f0 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,7 +23,7 @@ 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 org.apache.archiva.repository.storage.StorageAsset; import java.util.List; import java.util.Map; 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 fac557ed4..d5f6f94a9 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 @@ -22,10 +22,7 @@ package org.apache.archiva.proxy; 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; -import org.apache.archiva.common.filelock.FileLockTimeoutException; -import org.apache.archiva.common.filelock.Lock; import org.apache.archiva.configuration.*; import org.apache.archiva.model.ArtifactReference; import org.apache.archiva.model.Keys; @@ -39,9 +36,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.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.archiva.repository.storage.StorageUtil; import org.apache.archiva.repository.metadata.MetadataTools; import org.apache.archiva.repository.metadata.RepositoryMetadataException; import org.apache.archiva.scheduler.ArchivaTaskScheduler; @@ -61,7 +58,6 @@ import javax.inject.Named; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java index 8cef4f30b..e98e8321a 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java @@ -21,8 +21,8 @@ package org.apache.archiva.admin.model.group; import org.apache.archiva.admin.model.AuditInformation; import org.apache.archiva.admin.model.RepositoryAdminException; import org.apache.archiva.admin.model.beans.RepositoryGroup; +import org.apache.archiva.repository.storage.StorageAsset; -import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -75,5 +75,5 @@ public interface RepositoryGroupAdmin Map<String, List<String>> getRepositoryToGroupMap() throws RepositoryAdminException; - Path getMergedIndexDirectory(String repositoryGroupId ); + StorageAsset getMergedIndexDirectory(String repositoryGroupId ); } diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java index 757aa12a8..39919a88e 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java @@ -29,11 +29,11 @@ import org.apache.archiva.configuration.Configuration; import org.apache.archiva.configuration.RepositoryGroupConfiguration; import org.apache.archiva.metadata.model.facets.AuditEvent; import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler; -import org.apache.archiva.repository.EditableRepository; import org.apache.archiva.repository.EditableRepositoryGroup; import org.apache.archiva.repository.RepositoryException; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.repository.features.IndexCreationFeature; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,9 +47,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -112,9 +109,14 @@ public class DefaultRepositoryGroupAdmin @Override - public Path getMergedIndexDirectory( String repositoryGroupId ) + public StorageAsset getMergedIndexDirectory(String repositoryGroupId ) { - return groupsDirectory.resolve( repositoryGroupId ); + org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup(repositoryGroupId); + if (group!=null) { + return group.getFeature(IndexCreationFeature.class).get().getLocalIndexPath(); + } else { + return null; + } } @Override diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java index 064045de9..1bd7e4c10 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java @@ -19,7 +19,7 @@ package org.apache.archiva.admin.mock; * under the License. */ -import org.apache.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.common.utils.FileUtils; import org.apache.archiva.common.utils.PathUtil; import org.apache.archiva.configuration.ArchivaConfiguration; @@ -40,10 +40,12 @@ import org.apache.archiva.repository.RemoteRepository; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.UnsupportedRepositoryTypeException; -import org.apache.archiva.repository.content.FilesystemAsset; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.FilesystemAsset; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.features.RemoteIndexFeature; +import org.apache.archiva.repository.storage.StorageUtil; import org.apache.commons.lang.StringUtils; import org.apache.maven.index.ArtifactContext; import org.apache.maven.index.ArtifactContextProducer; @@ -143,7 +145,7 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { private Path getIndexPath( ArchivaIndexingContext ctx ) { - return PathUtil.getPathFromUri( ctx.getPath( ) ); + return ctx.getPath( ).getFilePath(); } @FunctionalInterface @@ -378,9 +380,9 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { @Override public void addArtifactsToIndex( final ArchivaIndexingContext context, final Collection<URI> artifactReference ) throws IndexUpdateFailedException { - final URI ctxUri = context.getPath(); + final StorageAsset ctxUri = context.getPath(); executeUpdateFunction(context, indexingContext -> { - Collection<ArtifactContext> artifacts = artifactReference.stream().map(r -> artifactContextProducer.getArtifactContext(indexingContext, Paths.get(ctxUri.resolve(r)).toFile())).collect(Collectors.toList()); + Collection<ArtifactContext> artifacts = artifactReference.stream().map(r -> artifactContextProducer.getArtifactContext(indexingContext, Paths.get(ctxUri.getFilePath().toUri().resolve(r)).toFile())).collect(Collectors.toList()); try { indexer.addArtifactsToIndex(artifacts, indexingContext); } catch (IOException e) { @@ -394,9 +396,9 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { @Override public void removeArtifactsFromIndex( ArchivaIndexingContext context, Collection<URI> artifactReference ) throws IndexUpdateFailedException { - final URI ctxUri = context.getPath(); + final StorageAsset ctxUri = context.getPath(); executeUpdateFunction(context, indexingContext -> { - Collection<ArtifactContext> artifacts = artifactReference.stream().map(r -> artifactContextProducer.getArtifactContext(indexingContext, Paths.get(ctxUri.resolve(r)).toFile())).collect(Collectors.toList()); + Collection<ArtifactContext> artifacts = artifactReference.stream().map(r -> artifactContextProducer.getArtifactContext(indexingContext, Paths.get(ctxUri.getFilePath().toUri().resolve(r)).toFile())).collect(Collectors.toList()); try { indexer.deleteArtifactsFromIndex(artifacts, indexingContext); } catch (IOException e) { @@ -455,7 +457,7 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { log.warn("Index close failed"); } try { - FileUtils.deleteDirectory(Paths.get(context.getPath())); + StorageUtil.deleteRecursively(context.getPath()); } catch (IOException e) { throw new IndexUpdateFailedException("Could not delete index files"); } @@ -530,6 +532,7 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { URI indexDir = icf.getIndexPath(); String indexPath = indexDir.getPath(); Path indexDirectory = null; + FilesystemStorage filesystemStorage = (FilesystemStorage) repo.getAsset("").getStorage(); if ( ! StringUtils.isEmpty(indexDir.toString( ) ) ) { @@ -538,6 +541,7 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { if ( indexDirectory.isAbsolute( ) ) { indexPath = indexDirectory.getFileName().toString(); + filesystemStorage = new FilesystemStorage(indexDirectory.getParent(), new DefaultFileLockManager()); } else { @@ -554,7 +558,7 @@ public class ArchivaIndexManagerMock implements ArchivaIndexManager { { Files.createDirectories( indexDirectory ); } - return new FilesystemAsset( indexPath, indexDirectory); + return new FilesystemAsset( filesystemStorage, indexPath, indexDirectory); } private IndexingContext createRemoteContext(RemoteRepository remoteRepository ) throws IOException diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java index 3bed60293..4b4528bc8 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java @@ -19,8 +19,12 @@ package org.apache.archiva.admin.mock; * under the License. */ +import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.storage.FilesystemAsset; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.maven.index.context.IndexingContext; import java.io.IOException; @@ -38,10 +42,16 @@ public class MavenIndexContextMock implements ArchivaIndexingContext { private IndexingContext delegate; private Repository repository; + private FilesystemStorage filesystemStorage; MavenIndexContextMock(Repository repository, IndexingContext delegate) { this.delegate = delegate; this.repository = repository; + try { + this.filesystemStorage = new FilesystemStorage(delegate.getIndexDirectoryFile().toPath(), new DefaultFileLockManager()); + } catch (IOException e) { + e.printStackTrace(); + } } @@ -56,8 +66,9 @@ public class MavenIndexContextMock implements ArchivaIndexingContext { } @Override - public URI getPath() { - return delegate.getIndexDirectoryFile().toURI(); + public StorageAsset getPath() { + return + new FilesystemAsset(filesystemStorage, "", delegate.getIndexDirectoryFile().toPath()); } @Override diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockMergedRemoteIndexesScheduler.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockMergedRemoteIndexesScheduler.java index 4cb8ca78d..6222e7c51 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockMergedRemoteIndexesScheduler.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockMergedRemoteIndexesScheduler.java @@ -21,10 +21,9 @@ package org.apache.archiva.admin.mock; import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler; import org.apache.archiva.repository.RepositoryGroup; +import org.apache.archiva.repository.storage.StorageAsset; import org.springframework.stereotype.Service; -import java.nio.file.Path; - /** * @author Olivier Lamy */ @@ -34,7 +33,7 @@ public class MockMergedRemoteIndexesScheduler { @Override - public void schedule( RepositoryGroup repositoryGroup, Path directory ) + public void schedule(RepositoryGroup repositoryGroup, StorageAsset directory ) { // no op } diff --git a/archiva-modules/archiva-base/archiva-repository-api/pom.xml b/archiva-modules/archiva-base/archiva-repository-api/pom.xml index b5f10a7db..7251ab2a6 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-api/pom.xml @@ -38,6 +38,10 @@ <groupId>org.apache.archiva</groupId> <artifactId>archiva-common</artifactId> </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-storage-api</artifactId> + </dependency> <dependency> <groupId>commons-lang</groupId> diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java index 5eb57705f..8e38b829a 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java @@ -21,10 +21,8 @@ package org.apache.archiva.indexer; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryType; -import org.apache.archiva.repository.content.StorageAsset; import java.net.URI; -import java.nio.file.Path; import java.util.Collection; import java.util.List; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java index 795354598..2dee4412d 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java @@ -20,6 +20,7 @@ package org.apache.archiva.indexer; */ import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.storage.StorageAsset; import java.io.IOException; import java.net.URI; @@ -48,7 +49,7 @@ public interface ArchivaIndexingContext { * The path where the index is stored. * @return */ - URI getPath(); + StorageAsset getPath(); /** * Returns true, if the index has no entries or is not initialized. diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/IndexMergerRequest.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/IndexMergerRequest.java index 787e02d5b..9a8bae159 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/IndexMergerRequest.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/IndexMergerRequest.java @@ -18,6 +18,8 @@ package org.apache.archiva.indexer.merger; * under the License. */ +import org.apache.archiva.repository.storage.StorageAsset; + import java.nio.file.Path; import java.util.Collection; @@ -47,7 +49,7 @@ public class IndexMergerRequest private int mergedIndexTtl; - private Path mergedIndexDirectory; + private StorageAsset mergedIndexDirectory; private boolean temporary; @@ -121,17 +123,17 @@ public class IndexMergerRequest this.mergedIndexTtl = mergedIndexTtl; } - public Path getMergedIndexDirectory() + public StorageAsset getMergedIndexDirectory() { return mergedIndexDirectory; } - public void setMergedIndexDirectory( Path mergedIndexDirectory ) + public void setMergedIndexDirectory( StorageAsset mergedIndexDirectory ) { this.mergedIndexDirectory = mergedIndexDirectory; } - public IndexMergerRequest mergedIndexDirectory( Path mergedIndexDirectory ) + public IndexMergerRequest mergedIndexDirectory( StorageAsset mergedIndexDirectory ) { this.mergedIndexDirectory = mergedIndexDirectory; return this; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/MergedRemoteIndexesScheduler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/MergedRemoteIndexesScheduler.java index 8125610b6..79eaaac3a 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/MergedRemoteIndexesScheduler.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/MergedRemoteIndexesScheduler.java @@ -21,8 +21,7 @@ package org.apache.archiva.indexer.merger; import org.apache.archiva.repository.RepositoryGroup; - -import java.nio.file.Path; +import org.apache.archiva.repository.storage.StorageAsset; /** * @author Olivier Lamy @@ -35,8 +34,9 @@ public interface MergedRemoteIndexesScheduler * will check if this repository group need to a schedule a cron to download/merge * remote indexes * @param repositoryGroup + * @param directory */ - void schedule(RepositoryGroup repositoryGroup, Path directory ); + void schedule(RepositoryGroup repositoryGroup, StorageAsset directory ); void unschedule( RepositoryGroup repositoryGroup ); diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/TemporaryGroupIndex.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/TemporaryGroupIndex.java index d0b576b74..8f5588893 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/TemporaryGroupIndex.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/merger/TemporaryGroupIndex.java @@ -18,6 +18,8 @@ package org.apache.archiva.indexer.merger; * under the License. */ +import org.apache.archiva.repository.storage.StorageAsset; + import java.io.Serializable; import java.nio.file.Path; import java.util.Date; @@ -30,7 +32,7 @@ public class TemporaryGroupIndex { private long creationTime = new Date().getTime(); - private Path directory; + private StorageAsset directory; private String indexId; @@ -38,7 +40,7 @@ public class TemporaryGroupIndex private int mergedIndexTtl; - public TemporaryGroupIndex(Path directory, String indexId, String groupId, int mergedIndexTtl) + public TemporaryGroupIndex(StorageAsset directory, String indexId, String groupId, int mergedIndexTtl) { this.directory = directory; this.indexId = indexId; @@ -57,12 +59,12 @@ public class TemporaryGroupIndex return this; } - public Path getDirectory() + public StorageAsset getDirectory() { return directory; } - public TemporaryGroupIndex setDirectory( Path directory ) + public TemporaryGroupIndex setDirectory( StorageAsset directory ) { this.directory = directory; return this; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java index 2c77cadc5..3acd16198 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java @@ -20,8 +20,6 @@ package org.apache.archiva.repository; */ -import org.apache.archiva.repository.content.RepositoryStorage; - import java.util.Set; /** 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 c50a89cf2..5cabc3f6a 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,7 +23,7 @@ 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.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import java.util.Set; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java index 453badc2d..d6c38a04d 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java @@ -20,7 +20,7 @@ package org.apache.archiva.repository; */ import org.apache.archiva.indexer.ArchivaIndexingContext; -import org.apache.archiva.repository.content.RepositoryStorage; +import org.apache.archiva.repository.storage.RepositoryStorage; import org.apache.archiva.repository.features.RepositoryFeature; import java.net.URI; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryGroup.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryGroup.java index 8386c5838..5b50dc0a7 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryGroup.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryGroup.java @@ -19,8 +19,7 @@ package org.apache.archiva.repository; * under the License. */ -import org.apache.archiva.repository.content.RepositoryStorage; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.RepositoryStorage; import java.util.List; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java index 636e2cb40..ff10b2d39 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java @@ -22,12 +22,11 @@ package org.apache.archiva.repository.features; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryEventListener; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import java.net.URI; import java.net.URISyntaxException; -import java.nio.file.Path; import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_PACKED_INDEX_PATH; diff --git a/archiva-modules/archiva-base/archiva-repository-layer/pom.xml b/archiva-modules/archiva-base/archiva-repository-layer/pom.xml index 7d2c1a667..3e9335650 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-layer/pom.xml @@ -43,6 +43,10 @@ </dependency> <dependency> <groupId>org.apache.archiva</groupId> + <artifactId>archiva-storage-fs</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> <artifactId>archiva-checksum</artifactId> </dependency> <dependency> diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultIndexMerger.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultIndexMerger.java index 293b73b71..b04005fa6 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultIndexMerger.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultIndexMerger.java @@ -28,6 +28,8 @@ import org.apache.archiva.indexer.merger.IndexMergerRequest; import org.apache.archiva.indexer.merger.TemporaryGroupIndex; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.archiva.repository.storage.StorageUtil; import org.apache.commons.lang.time.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,7 +89,7 @@ public class DefaultIndexMerger stopWatch.reset(); stopWatch.start(); - Path mergedIndexDirectory = indexMergerRequest.getMergedIndexDirectory(); + StorageAsset mergedIndexDirectory = indexMergerRequest.getMergedIndexDirectory(); Repository destinationRepository = repositoryRegistry.getRepository(indexMergerRequest.getGroupId()); ArchivaIndexManager idxManager = repositoryRegistry.getIndexManager(destinationRepository.getType()); @@ -131,10 +133,10 @@ public class DefaultIndexMerger ctx.close(true); temporaryGroupIndexes.remove( temporaryGroupIndex ); temporaryContextes.remove( ctx ); - Path directory = temporaryGroupIndex.getDirectory(); - if ( directory != null && Files.exists(directory) ) + StorageAsset directory = temporaryGroupIndex.getDirectory(); + if ( directory != null && directory.exists() ) { - FileUtils.deleteDirectory( directory ); + StorageUtil.deleteRecursively( directory ); } } } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultMergedRemoteIndexesScheduler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultMergedRemoteIndexesScheduler.java index b2be61184..93dbaeaad 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultMergedRemoteIndexesScheduler.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/indexer/merger/DefaultMergedRemoteIndexesScheduler.java @@ -22,6 +22,7 @@ package org.apache.archiva.indexer.merger; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.RepositoryGroup; import org.apache.archiva.repository.features.IndexCreationFeature; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +60,7 @@ public class DefaultMergedRemoteIndexesScheduler private Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>(); @Override - public void schedule(RepositoryGroup repositoryGroup, Path directory ) + public void schedule(RepositoryGroup repositoryGroup, StorageAsset directory ) { if ( StringUtils.isEmpty( repositoryGroup.getSchedulingDefinition() ) ) { diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractManagedRepository.java index 41d703ab2..45d95ade3 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractManagedRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractManagedRepository.java @@ -20,17 +20,12 @@ package org.apache.archiva.repository; */ -import org.apache.archiva.repository.content.RepositoryStorage; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.RepositoryStorage; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Set; -import java.util.function.Consumer; /** * Simple implementation of a managed repository. diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRemoteRepository.java index ff2ac062a..048ad227a 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRemoteRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRemoteRepository.java @@ -20,7 +20,7 @@ package org.apache.archiva.repository; */ -import org.apache.archiva.repository.content.RepositoryStorage; +import org.apache.archiva.repository.storage.RepositoryStorage; import java.nio.file.Path; import java.time.Duration; 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 87b5420b1..c9fc92660 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 @@ -23,10 +23,9 @@ import com.cronutils.model.CronType; import com.cronutils.model.definition.CronDefinition; import com.cronutils.model.definition.CronDefinitionBuilder; import com.cronutils.parser.CronParser; -import org.apache.archiva.common.utils.PathUtil; import org.apache.archiva.indexer.ArchivaIndexingContext; -import org.apache.archiva.repository.content.RepositoryStorage; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.RepositoryStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.repository.features.RepositoryFeature; import org.apache.archiva.repository.features.StagingRepositoryFeature; import org.apache.commons.lang.StringUtils; diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepositoryGroup.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepositoryGroup.java index 2011d4a5c..2f78b7bf5 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepositoryGroup.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepositoryGroup.java @@ -19,18 +19,13 @@ package org.apache.archiva.repository; * under the License. */ -import org.apache.archiva.repository.content.RepositoryStorage; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.RepositoryStorage; import org.apache.commons.collections4.map.ListOrderedMap; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; import java.util.List; import java.util.Locale; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Consumer; /** * Abstract repository group implementation. diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicManagedRepository.java index a16630b4a..8f65cb4d3 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicManagedRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicManagedRepository.java @@ -21,9 +21,8 @@ package org.apache.archiva.repository; import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.common.filelock.FileLockManager; -import org.apache.archiva.repository.content.FilesystemStorage; -import org.apache.archiva.repository.content.RepositoryStorage; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.RepositoryStorage; import org.apache.archiva.repository.features.ArtifactCleanupFeature; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.features.StagingRepositoryFeature; @@ -31,10 +30,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Path; import java.util.Locale; -import java.util.function.Consumer; /** * diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicRemoteRepository.java index acca83a76..0675402a0 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicRemoteRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/BasicRemoteRepository.java @@ -21,8 +21,8 @@ package org.apache.archiva.repository; import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.common.filelock.FileLockManager; -import org.apache.archiva.repository.content.FilesystemStorage; -import org.apache.archiva.repository.content.RepositoryStorage; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.RepositoryStorage; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.features.RemoteIndexFeature; import org.slf4j.Logger; 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 e78130e33..e0e61c54a 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,8 +26,6 @@ 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; @@ -44,11 +42,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import java.util.stream.Stream; diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/ArtifactUtil.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/ArtifactUtil.java index 7755b53d7..8bcfa97d6 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/ArtifactUtil.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/ArtifactUtil.java @@ -23,6 +23,7 @@ import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.RepositoryContentFactory; import org.apache.archiva.repository.RepositoryException; +import org.apache.archiva.repository.storage.StorageAsset; import org.springframework.stereotype.Service; import javax.inject.Inject; @@ -53,4 +54,19 @@ public class ArtifactUtil { return Paths.get(repository.getLocation()).resolve(artifactPath); } + /** + * Returns the physical location of a given artifact in the repository. There is no check for the + * existence of the returned file. + * + * @param repository The repository, where the artifact is stored. + * @param artifactReference The artifact reference. + * @return The asset representation of the artifact. + * @throws RepositoryException + */ + public StorageAsset getArtifactAsset(ManagedRepository repository, ArtifactReference artifactReference) throws RepositoryException { + final ManagedRepositoryContent content = repositoryContentFactory.getManagedRepositoryContent(repository); + final String artifactPath = content.toPath( artifactReference ); + return repository.getAsset(artifactPath); + } + } 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 deleted file mode 100644 index 4b8d11b39..000000000 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/StorageUtil.java +++ /dev/null @@ -1,192 +0,0 @@ -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/main/java/org/apache/archiva/repository/metadata/MetadataTools.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/MetadataTools.java index 9df3f49c6..57cc2c331 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/MetadataTools.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/MetadataTools.java @@ -42,6 +42,7 @@ import org.apache.archiva.repository.ContentNotFoundException; import org.apache.archiva.repository.LayoutException; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.RemoteRepositoryContent; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.xml.XMLException; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; @@ -369,9 +370,9 @@ public class MetadataTools ProjectReference reference, String proxyId ) { String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) ); - Path metadataFile = Paths.get( managedRepository.getRepoRoot(), metadataPath ); + StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath ); - if ( !Files.exists(metadataFile) || !Files.isRegularFile( metadataFile )) + if ( !metadataFile.exists() || metadataFile.isContainer()) { // Nothing to do. return null. return null; @@ -381,11 +382,11 @@ public class MetadataTools { return MavenMetadataReader.read( metadataFile ); } - catch ( XMLException e ) + catch (XMLException | IOException e ) { // TODO: [monitor] consider a monitor for this event. // TODO: consider a read-redo on monitor return code? - log.warn( "Unable to read metadata: {}", metadataFile.toAbsolutePath(), e ); + log.warn( "Unable to read metadata: {}", metadataFile.getPath(), e ); return null; } } @@ -394,9 +395,9 @@ public class MetadataTools String logicalResource, String proxyId ) { String metadataPath = getRepositorySpecificName( proxyId, logicalResource ); - Path metadataFile = Paths.get( managedRepository.getRepoRoot(), metadataPath ); + StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath ); - if ( !Files.exists(metadataFile) || !Files.isRegularFile( metadataFile)) + if ( !metadataFile.exists() || metadataFile.isContainer()) { // Nothing to do. return null. return null; @@ -406,11 +407,11 @@ public class MetadataTools { return MavenMetadataReader.read( metadataFile ); } - catch ( XMLException e ) + catch (XMLException | IOException e ) { // TODO: [monitor] consider a monitor for this event. // TODO: consider a read-redo on monitor return code? - log.warn( "Unable to read metadata: {}", metadataFile.toAbsolutePath(), e ); + log.warn( "Unable to read metadata: {}", metadataFile.getPath(), e ); return null; } } @@ -419,9 +420,9 @@ public class MetadataTools VersionedReference reference, String proxyId ) { String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) ); - Path metadataFile = Paths.get( managedRepository.getRepoRoot(), metadataPath ); + StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath ); - if ( !Files.exists(metadataFile) || !Files.isRegularFile(metadataFile)) + if ( !metadataFile.exists() || metadataFile.isContainer()) { // Nothing to do. return null. return null; @@ -431,11 +432,11 @@ public class MetadataTools { return MavenMetadataReader.read( metadataFile ); } - catch ( XMLException e ) + catch (XMLException | IOException e ) { // TODO: [monitor] consider a monitor for this event. // TODO: consider a read-redo on monitor return code? - log.warn( "Unable to read metadata: {}", metadataFile.toAbsolutePath(), e ); + log.warn( "Unable to read metadata: {}", metadataFile.getPath(), e ); return null; } } @@ -443,7 +444,7 @@ public class MetadataTools public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource ) throws RepositoryMetadataException { - final Path metadataFile = Paths.get( managedRepository.getRepoRoot(), logicalResource ); + final StorageAsset metadataFile = managedRepository.getRepository().getAsset( logicalResource ); ArchivaRepositoryMetadata metadata = null; //Gather and merge all metadata available @@ -480,7 +481,7 @@ public class MetadataTools RepositoryMetadataWriter.write( metadata, metadataFile ); - ChecksummedFile checksum = new ChecksummedFile( metadataFile ); + ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() ); checksum.fixChecksums( algorithms ); } @@ -491,30 +492,17 @@ public class MetadataTools * @param metadataParentDirectory * @return origional set plus newly found versions */ - private Set<String> findPossibleVersions( Set<String> versions, Path metadataParentDirectory ) + private Set<String> findPossibleVersions( Set<String> versions, StorageAsset metadataParentDirectory ) { Set<String> result = new HashSet<String>( versions ); - try (Stream<Path> stream = Files.list( metadataParentDirectory )) { - stream.filter( Files::isDirectory ).filter( - p -> - { - try(Stream<Path> substream = Files.list(p)) - { - return substream.anyMatch( f -> Files.isRegularFile( f ) && f.toString().endsWith( ".pom" )); - } - catch ( IOException e ) - { - return false; - } + metadataParentDirectory.list().stream().filter(asset -> + asset.isContainer()).filter(asset -> { + return asset.list().stream().anyMatch(f -> !f.isContainer() && f.getName().endsWith(".pom")); } - ).forEach( - p -> result.add(p.getFileName().toString()) - ); - } catch (IOException e) { - // - } + ).forEach( p -> result.add(p.getName())); + return result; } @@ -522,8 +510,9 @@ public class MetadataTools ManagedRepositoryContent managedRepository, String logicalResource ) { List<ArchivaRepositoryMetadata> metadatas = new ArrayList<>(); - Path file = Paths.get( managedRepository.getRepoRoot(), logicalResource ); - if ( Files.exists(file) ) + StorageAsset file = managedRepository.getRepository().getAsset( logicalResource ); + + if ( file.exists() ) { try { @@ -533,10 +522,14 @@ public class MetadataTools metadatas.add( existingMetadata ); } } - catch ( XMLException e ) + catch (XMLException | IOException e ) { - log.debug( "Could not read metadata at {}. Metadata will be removed.", file.toAbsolutePath() ); - FileUtils.deleteQuietly( file ); + log.debug( "Could not read metadata at {}. Metadata will be removed.", file.getPath() ); + try { + file.getStorage().removeAsset(file); + } catch (IOException ex) { + log.error("Could not remove asset {}", file.getPath()); + } } } @@ -578,7 +571,8 @@ public class MetadataTools public void updateMetadata( ManagedRepositoryContent managedRepository, ProjectReference reference ) throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException { - Path metadataFile = Paths.get( managedRepository.getRepoRoot(), toPath( reference ) ); + + StorageAsset metadataFile = managedRepository.getRepository().getAsset( toPath( reference ) ); long lastUpdated = getExistingLastUpdated( metadataFile ); @@ -593,7 +587,7 @@ public class MetadataTools // TODO: do we know this information instead? // Set<Plugin> allPlugins = managedRepository.getPlugins( reference ); Set<Plugin> allPlugins; - if ( Files.exists(metadataFile)) + if ( metadataFile.exists()) { try { @@ -653,7 +647,7 @@ public class MetadataTools // Save the metadata model to disk. RepositoryMetadataWriter.write( metadata, metadataFile ); - ChecksummedFile checksum = new ChecksummedFile( metadataFile ); + ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() ); checksum.fixChecksums( algorithms ); } @@ -748,9 +742,9 @@ public class MetadataTools } } - private long getExistingLastUpdated( Path metadataFile ) + private long getExistingLastUpdated( StorageAsset metadataFile ) { - if ( !Files.exists(metadataFile) ) + if ( !metadataFile.exists() ) { // Doesn't exist. return 0; @@ -762,7 +756,7 @@ public class MetadataTools return getLastUpdated( metadata ); } - catch ( XMLException e ) + catch (XMLException | IOException e ) { // Error. return 0; @@ -788,7 +782,7 @@ public class MetadataTools public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference ) throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException { - Path metadataFile = Paths.get( managedRepository.getRepoRoot(), toPath( reference ) ); + StorageAsset metadataFile = managedRepository.getRepository().getAsset( toPath( reference ) ); long lastUpdated = getExistingLastUpdated( metadataFile ); @@ -893,7 +887,7 @@ public class MetadataTools // Save the metadata model to disk. RepositoryMetadataWriter.write( metadata, metadataFile ); - ChecksummedFile checksum = new ChecksummedFile( metadataFile ); + ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() ); checksum.fixChecksums( algorithms ); } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java index 4585d59ff..6f6bf6608 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java @@ -22,6 +22,7 @@ package org.apache.archiva.repository.metadata; import org.apache.archiva.common.utils.FileUtils; import org.apache.archiva.model.ArchivaRepositoryMetadata; import org.apache.archiva.model.Plugin; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.xml.XMLException; import org.apache.archiva.xml.XMLWriter; import org.apache.commons.collections4.CollectionUtils; @@ -29,9 +30,12 @@ import org.apache.commons.lang.StringUtils; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.FileWriter; import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.file.Path; import java.util.Collections; @@ -44,11 +48,13 @@ import java.util.List; */ public class RepositoryMetadataWriter { - public static void write( ArchivaRepositoryMetadata metadata, Path outputFile ) + private static final Logger log = LoggerFactory.getLogger(RepositoryMetadataWriter.class); + + public static void write( ArchivaRepositoryMetadata metadata, StorageAsset outputFile ) throws RepositoryMetadataException { boolean thrown = false; - try (FileWriter writer = new FileWriter( outputFile.toFile() )) + try (OutputStreamWriter writer = new OutputStreamWriter( outputFile.getWriteStream(true))) { write( metadata, writer ); writer.flush(); @@ -57,13 +63,17 @@ public class RepositoryMetadataWriter { thrown = true; throw new RepositoryMetadataException( - "Unable to write metadata file: " + outputFile.toAbsolutePath() + " - " + e.getMessage(), e ); + "Unable to write metadata file: " + outputFile.getPath() + " - " + e.getMessage(), e ); } finally { if ( thrown ) { - FileUtils.deleteQuietly( outputFile ); + try { + outputFile.getStorage().removeAsset(outputFile); + } catch (IOException e) { + log.error("Could not remove asset {}", outputFile); + } } } } 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 deleted file mode 100644 index 8e98e59bb..000000000 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemAssetTest.java +++ /dev/null @@ -1,202 +0,0 @@ -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.commons.io.IOUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.Instant; - -import static org.junit.Assert.*; - -public class FilesystemAssetTest { - - Path assetPathFile; - Path assetPathDir; - - @Before - public void init() throws IOException { - assetPathFile = Files.createTempFile("assetFile", "dat"); - assetPathDir = Files.createTempDirectory("assetDir"); - } - - @After - public void cleanup() { - - try { - Files.deleteIfExists(assetPathFile); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Files.deleteIfExists(assetPathDir); - } catch (IOException e) { - e.printStackTrace(); - } - } - - - @Test - public void getPath() { - FilesystemAsset asset = new FilesystemAsset("/"+assetPathFile.getFileName().toString(), assetPathFile); - assertEquals("/"+assetPathFile.getFileName().toString(), asset.getPath()); - } - - @Test - public void getName() { - FilesystemAsset asset = new FilesystemAsset("/"+assetPathFile.getFileName().toString(), assetPathFile); - assertEquals(assetPathFile.getFileName().toString(), asset.getName()); - - } - - @Test - public void getModificationTime() throws IOException { - Instant modTime = Files.getLastModifiedTime(assetPathFile).toInstant(); - FilesystemAsset asset = new FilesystemAsset("/test123", assetPathFile); - assertTrue(modTime.equals(asset.getModificationTime())); - } - - @Test - public void isContainer() { - FilesystemAsset asset = new FilesystemAsset("/test1323", assetPathFile); - assertFalse(asset.isContainer()); - FilesystemAsset asset2 = new FilesystemAsset("/test1234", assetPathDir); - assertTrue(asset2.isContainer()); - } - - @Test - public void list() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - assertEquals(0, asset.list().size()); - - FilesystemAsset asset2 = new FilesystemAsset("/test1235", assetPathDir); - assertEquals(0, asset2.list().size()); - Path f1 = Files.createTempFile(assetPathDir, "testfile", "dat"); - Path f2 = Files.createTempFile(assetPathDir, "testfile", "dat"); - Path d1 = Files.createTempDirectory(assetPathDir, "testdir"); - assertEquals(3, asset2.list().size()); - assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(f1.getFileName().toString()))); - assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(f2.getFileName().toString()))); - assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(d1.getFileName().toString()))); - Files.deleteIfExists(f1); - Files.deleteIfExists(f2); - Files.deleteIfExists(d1); - - - } - - @Test - public void getSize() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - assertEquals(0, asset.getSize()); - - Files.write(assetPathFile, new String("abcdef").getBytes("ASCII")); - assertTrue(asset.getSize()>=6); - - - } - - @Test - public void getData() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - Files.write(assetPathFile, "abcdef".getBytes("ASCII")); - try(InputStream is = asset.getReadStream()) { - assertEquals("abcdef", IOUtils.toString(is, "ASCII")); - } - - } - - @Test - public void getDataExceptionOnDir() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathDir); - Files.write(assetPathFile, "abcdef".getBytes("ASCII")); - try { - InputStream is = asset.getReadStream(); - assertFalse("Exception expected for data on dir", true); - } catch (IOException e) { - // fine - } - - } - - @Test - public void writeData() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - Files.write(assetPathFile, "abcdef".getBytes("ASCII")); - try(OutputStream os = asset.getWriteStream(true)) { - IOUtils.write("test12345", os, "ASCII"); - } - assertEquals("test12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); - } - - @Test - public void writeDataAppend() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - Files.write(assetPathFile, "abcdef".getBytes("ASCII")); - try(OutputStream os = asset.getWriteStream(false)) { - IOUtils.write("test12345", os, "ASCII"); - } - assertEquals("abcdeftest12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); - } - - @Test - public void writeDataExceptionOnDir() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathDir); - try { - - OutputStream os = asset.getWriteStream(true); - assertTrue("Writing to a directory should throw a IOException", false); - } catch (IOException e) { - // Fine - } - } - - @Test - public void storeDataFile() throws IOException { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - Path dataFile = Files.createTempFile("testdata", "dat"); - try(OutputStream os = Files.newOutputStream(dataFile)) { - IOUtils.write("testkdkdkd", os, "ASCII"); - } - asset.replaceDataFromFile(dataFile); - assertEquals("testkdkdkd", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); - } - - @Test - public void exists() { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - assertTrue(asset.exists()); - FilesystemAsset asset2 = new FilesystemAsset("/test1234", Paths.get("abcdefgkdkdk")); - assertFalse(asset2.exists()); - - } - - @Test - public void getFilePath() { - FilesystemAsset asset = new FilesystemAsset("/test1234", assetPathFile); - assertEquals(assetPathFile, asset.getFilePath()); - } -}
\ No newline at end of file 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 328f58a5a..27b1e1f45 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 @@ -28,7 +28,7 @@ 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.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.springframework.stereotype.Service; import java.util.Set; diff --git a/archiva-modules/archiva-base/archiva-repository-scanner/src/main/java/org/apache/archiva/repository/scanner/DefaultRepositoryScanner.java b/archiva-modules/archiva-base/archiva-repository-scanner/src/main/java/org/apache/archiva/repository/scanner/DefaultRepositoryScanner.java index b26bea9bd..30abcb437 100644 --- a/archiva-modules/archiva-base/archiva-repository-scanner/src/main/java/org/apache/archiva/repository/scanner/DefaultRepositoryScanner.java +++ b/archiva-modules/archiva-base/archiva-repository-scanner/src/main/java/org/apache/archiva/repository/scanner/DefaultRepositoryScanner.java @@ -25,7 +25,7 @@ import org.apache.archiva.consumers.InvalidRepositoryContentConsumer; import org.apache.archiva.consumers.KnownRepositoryContentConsumer; import org.apache.archiva.consumers.RepositoryContentConsumer; import org.apache.archiva.repository.ManagedRepository; -import org.apache.archiva.repository.content.StorageAsset; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryScannerTest.java b/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryScannerTest.java index 5f6f7e0d5..dec4e8dc9 100644 --- a/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryScannerTest.java +++ b/archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryScannerTest.java @@ -29,7 +29,7 @@ import org.apache.archiva.repository.BasicRemoteRepository; import org.apache.archiva.repository.EditableManagedRepository; import org.apache.archiva.repository.EditableRemoteRepository; import org.apache.archiva.repository.ManagedRepository; -import org.apache.archiva.repository.content.FilesystemStorage; +import org.apache.archiva.repository.storage.FilesystemStorage; import org.apache.archiva.repository.scanner.mock.ManagedRepositoryContentMock; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.io.FileUtils; 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 ade81214a..dadf98a35 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 @@ -19,6 +19,7 @@ package org.apache.archiva.repository.scanner.mock; * under the License. */ +import org.apache.archiva.common.filelock.DefaultFileLockManager; import org.apache.archiva.common.utils.VersionUtil; import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet; @@ -27,9 +28,11 @@ 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.StorageAsset; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang.StringUtils; +import java.io.IOException; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -48,6 +51,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent private ManagedRepository repository; + private FilesystemStorage fsStorage; public ManagedRepositoryContentMock(ManagedRepository repo) { this.repository = repo; @@ -92,7 +96,18 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent @Override public String getRepoRoot( ) { - return Paths.get("", "target", "test-repository", "managed").toString(); + return getRepoRootAsset().getFilePath().toString(); + } + + private StorageAsset getRepoRootAsset() { + if (fsStorage==null) { + try { + fsStorage = new FilesystemStorage(Paths.get("", "target", "test-repository", "managed"), new DefaultFileLockManager()); + } catch (IOException e) { + e.printStackTrace(); + } + } + return fsStorage.getAsset(""); } @Override @@ -329,7 +344,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent @Override public StorageAsset toFile( ArtifactReference reference ) { - return Paths.get(getRepoRoot(), refs.get(reference)); + return getRepoRootAsset().resolve(refs.get(reference)); } @Override diff --git a/archiva-modules/archiva-base/archiva-storage-api/pom.xml b/archiva-modules/archiva-base/archiva-storage-api/pom.xml new file mode 100644 index 000000000..06c853dda --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-api/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>archiva-base</artifactId> + <groupId>org.apache.archiva</groupId> + <version>3.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>archiva-storage-api</artifactId> + + <name>Archiva Base :: Repository API</name> + + <properties> + <site.staging.base>${project.parent.parent.basedir}</site.staging.base> + </properties> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <basedir>${basedir}</basedir> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + +</project>
\ No newline at end of file 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-storage-api/src/main/java/org/apache/archiva/repository/storage/RepositoryStorage.java index 3dea0b294..68ad39b81 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-storage-api/src/main/java/org/apache/archiva/repository/storage/RepositoryStorage.java @@ -1,4 +1,4 @@ -package org.apache.archiva.repository.content; +package org.apache.archiva.repository.storage; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -28,15 +28,20 @@ import java.nio.file.CopyOption; import java.util.function.Consumer; /** - * Repository storage gives access to the files and directories on the storage. - * The storage may be on a filesystem but can be any other storage system. * - * This API is low level repository access. If you use this API you must - * either have knowledge about the specific repository layout or use the structure + * This is the low level API to access artifacts in a repository. Each artifact is represented + * by one storage asset. Each asset can be accessed by a path that is independent on the underlying storage + * implementation. Paths always use '/' as path separator. The path is local to the repository and + * is unique for each asset. + * The storage API knows nothing about the repository layout or repository specific metadata. + * If you use this API you must either have knowledge about the specific repository layout or use the structure * as it is, e.g. for browsing. * - * It is the decision of the implementation, if this API provides access to all elements, or - * just a selected view. + * The base implementation for the storage uses a directory structure on the local filesystem. + * + * + * It is the decision of the repository type specific implementation, if this API provides access to all elements, that + * is really stored or just a selected view. * * Checking access is not part of this API. */ @@ -104,7 +109,9 @@ public interface RepositoryStorage { void removeAsset(StorageAsset asset) throws IOException; /** - * Moves the asset to the given location and returns the asset object for the destination. + * Moves the asset to the given location and returns the asset object for the destination. Moves only assets that + * belong to the same storage instance. It will throw a IOException if the assets are from differents storage + * instances. * * @param origin The original asset * @param destination The destination path pointing to the new asset. @@ -114,17 +121,20 @@ public interface RepositoryStorage { StorageAsset moveAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException; /** - * Moves the asset to the new path. - * + * Moves the asset to the given location and returns the asset object for the destination. Moves only assets that + * belong to the same storage instance. It will throw a IOException if the assets are from differents storage + * instances. + * * * @param origin The original asset - * @param destination The destination asset. + * @param destination The destination path. * @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. */ void moveAsset(StorageAsset origin, StorageAsset destination, CopyOption... copyOptions) throws IOException; /** - * Copies the given asset to the new destination. + * Copies the given asset to the new destination. Copies only assets that belong to the same storage instance. + * It will throw a IOException if the assets are from differents storage instances. * * @param origin The original asset * @param destination The path to the new asset @@ -135,7 +145,8 @@ public interface RepositoryStorage { StorageAsset copyAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException; /** - * Copies the given asset to the new destination. + * Copies the given asset to the new destination. Copies only assets that belong to the same storage instance. + * It will throw a IOException if the assets are from differents storage instances. * * @param origin The original asset * @param destination The path to the new asset 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-storage-api/src/main/java/org/apache/archiva/repository/storage/StorageAsset.java index 38ef2a895..5e6b52987 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-storage-api/src/main/java/org/apache/archiva/repository/storage/StorageAsset.java @@ -1,4 +1,4 @@ -package org.apache.archiva.repository.content; +package org.apache.archiva.repository.storage; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -27,10 +27,9 @@ import java.nio.channels.WritableByteChannel; import java.nio.file.Path; import java.time.Instant; import java.util.List; -import java.util.function.Consumer; /** - * A instance of this interface represents information about an specific asset in a repository. + * A instance of this interface represents information about a specific asset in a repository. * The asset may be an real artifact, a directory, or a virtual asset. * * Each asset has a unique path relative to the repository. @@ -177,4 +176,11 @@ public interface StorageAsset * @return The asset, or <code>null</code>, if it does not exist. */ StorageAsset getParent(); + + /** + * Returns the asset relative to the given path + * @param toPath + * @return + */ + StorageAsset resolve(String toPath); } diff --git a/archiva-modules/archiva-base/archiva-storage-fs/pom.xml b/archiva-modules/archiva-base/archiva-storage-fs/pom.xml new file mode 100644 index 000000000..d128bed2b --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-fs/pom.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>archiva-base</artifactId> + <groupId>org.apache.archiva</groupId> + <version>3.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>archiva-storage-fs</artifactId> + + <name>Archiva Base :: Storage Filesystem Based</name> + + <properties> + <site.staging.base>${project.parent.parent.basedir}</site.staging.base> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-storage-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-filelock</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <basedir>${basedir}</basedir> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + +</project>
\ No newline at end of file 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-storage-fs/src/main/java/org/apache/archiva/repository/storage/FilesystemAsset.java index e0d10f863..b343c7b0e 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-storage-fs/src/main/java/org/apache/archiva/repository/storage/FilesystemAsset.java @@ -1,4 +1,4 @@ -package org.apache.archiva.repository.content; +package org.apache.archiva.repository.storage; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -98,7 +98,7 @@ public class FilesystemAsset implements StorageAsset { FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath) { this.assetPath = assetPath; - this.relativePath = path; + this.relativePath = normalizePath(path); this.setPermissionsForNew=false; this.basePath = basePath; this.storage = storage; @@ -114,7 +114,7 @@ public class FilesystemAsset implements StorageAsset { */ public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath) { this.assetPath = assetPath; - this.relativePath = path; + this.relativePath = normalizePath(path); this.setPermissionsForNew = false; this.basePath = null; this.storage = storage; @@ -132,7 +132,7 @@ public class FilesystemAsset implements StorageAsset { */ public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath, boolean directory) { this.assetPath = assetPath; - this.relativePath = path; + this.relativePath = normalizePath(path); this.directoryHint = directory; this.setPermissionsForNew = false; this.basePath = basePath; @@ -151,7 +151,7 @@ public class FilesystemAsset implements StorageAsset { */ public FilesystemAsset(RepositoryStorage storage, String path, Path assetPath, Path basePath, boolean directory, boolean setPermissionsForNew) { this.assetPath = assetPath; - this.relativePath = path; + this.relativePath = normalizePath(path); this.directoryHint = directory; this.setPermissionsForNew = setPermissionsForNew; this.basePath = basePath; @@ -159,6 +159,14 @@ public class FilesystemAsset implements StorageAsset { init(); } + private String normalizePath(String path) { + if (!path.startsWith("/")) { + return "/"+path; + } else { + return path; + } + } + private void init() { if (setPermissionsForNew) { @@ -423,6 +431,11 @@ public class FilesystemAsset implements StorageAsset { } } + @Override + public StorageAsset resolve(String toPath) { + return storage.getAsset(this.getPath()+"/"+toPath); + } + public void setDefaultFileAcls(List<AclEntry> acl) { defaultFileAcls = acl; 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-storage-fs/src/main/java/org/apache/archiva/repository/storage/FilesystemStorage.java index 92044fa86..860a7e9d7 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-storage-fs/src/main/java/org/apache/archiva/repository/storage/FilesystemStorage.java @@ -1,4 +1,4 @@ -package org.apache.archiva.repository.content; +package org.apache.archiva.repository.storage; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -81,7 +81,7 @@ public class FilesystemStorage implements RepositoryStorage { } @Override - public void consumeData( StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException + public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException { final Path path = asset.getFilePath(); try { @@ -333,6 +333,12 @@ public class FilesystemStorage implements RepositoryStorage { @Override public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException { + if (origin.getStorage()!=this) { + throw new IOException("The origin asset does not belong to this storage instance. Cannot copy between different storage instances."); + } + if (destination.getStorage()!=this) { + throw new IOException("The destination asset does not belong to this storage instance. Cannot copy between different storage instances."); + } Files.move(origin.getFilePath(), destination.getFilePath(), copyOptions); } @@ -348,6 +354,12 @@ public class FilesystemStorage implements RepositoryStorage { @Override public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException { + if (origin.getStorage()!=this) { + throw new IOException("The origin asset does not belong to this storage instance. Cannot copy between different storage instances."); + } + if (destination.getStorage()!=this) { + throw new IOException("The destination asset does not belong to this storage instance. Cannot copy between different storage instances."); + } Path destinationPath = destination.getFilePath(); boolean overwrite = false; for (int i=0; i<copyOptions.length; i++) { diff --git a/archiva-modules/archiva-base/archiva-storage-fs/src/main/java/org/apache/archiva/repository/storage/StorageUtil.java b/archiva-modules/archiva-base/archiva-storage-fs/src/main/java/org/apache/archiva/repository/storage/StorageUtil.java new file mode 100644 index 000000000..a90068044 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-fs/src/main/java/org/apache/archiva/repository/storage/StorageUtil.java @@ -0,0 +1,346 @@ +package org.apache.archiva.repository.storage; + +/* + * 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 org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.*; +import java.util.HashSet; +import java.util.function.Consumer; + +/** + * + * Utility class for assets. Allows to copy, move between different storage instances and + * recursively consume the tree. + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +public class StorageUtil +{ + private static final int DEFAULT_BUFFER_SIZE = 4096; + private static final Logger log = LoggerFactory.getLogger(StorageUtil.class); + + /** + * Copies the source asset to the target. The assets may be from different RepositoryStorage instances. + * If you know that source and asset are from the same storage instance, the copy method of the storage + * instance may be faster. + * + * @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 ); + } + } + } + } + + /** + * Moves a asset between different storage instances. + * If you know that source and asset are from the same storage instance, the move method of the storage + * instance may be faster. + * + * @param source The source asset + * @param target The target asset + * @param locked If true, a lock is used for the move operation. + * @param copyOptions Options for copying + * @throws IOException If the move fails + */ + public static final 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 final 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 final 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 final void copy( final FileChannel is, final WritableByteChannel os ) { + try + { + is.transferTo( 0, is.size( ), os ); + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + private static final void copy( final ReadableByteChannel is, final FileChannel os ) { + try + { + os.transferFrom( is, 0, Long.MAX_VALUE ); + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + /** + * Runs the consumer function recursively on each asset found starting at the base path + * @param baseAsset The base path where to start search + * @param consumer The consumer function applied to each found asset + * @param depthFirst If true, the deepest elements are consumed first. + * @param maxDepth The maximum depth to recurse into. 0 means, only the baseAsset is consumed, 1 the base asset and its children and so forth. + */ + public static final void recurse(final StorageAsset baseAsset, final Consumer<StorageAsset> consumer, final boolean depthFirst, final int maxDepth) throws IOException { + recurse(baseAsset, consumer, depthFirst, maxDepth, 0); + } + + /** + * Runs the consumer function recursively on each asset found starting at the base path. The function descends into + * maximum depth. + * + * @param baseAsset The base path where to start search + * @param consumer The consumer function applied to each found asset + * @param depthFirst If true, the deepest elements are consumed first. + */ + public static final void recurse(final StorageAsset baseAsset, final Consumer<StorageAsset> consumer, final boolean depthFirst) throws IOException { + recurse(baseAsset, consumer, depthFirst, Integer.MAX_VALUE, 0); + } + + /** + * Runs the consumer function recursively on each asset found starting at the base path. It does not recurse with + * depth first and stops only if there are no more children available. + * + * @param baseAsset The base path where to start search + * @param consumer The consumer function applied to each found asset + */ + public static final void recurse(final StorageAsset baseAsset, final Consumer<StorageAsset> consumer) throws IOException { + recurse(baseAsset, consumer, false, Integer.MAX_VALUE, 0); + } + + private static final void recurse(final StorageAsset baseAsset, final Consumer<StorageAsset> consumer, final boolean depthFirst, final int maxDepth, final int currentDepth) + throws IOException { + if (!depthFirst) { + consumer.accept(baseAsset); + } + if (currentDepth<maxDepth && baseAsset.isContainer()) { + for(StorageAsset asset : baseAsset.list() ) { + recurse(asset, consumer, depthFirst, maxDepth, currentDepth+1); + } + } + if (depthFirst) { + consumer.accept(baseAsset); + } + } + + /** + * Deletes the given asset and all child assets recursively. + * @param baseDir The base asset to remove. + * @throws IOException + */ + public static final void deleteRecursively(StorageAsset baseDir) throws IOException { + recurse(baseDir, a -> { + try { + a.getStorage().removeAsset(a); + } catch (IOException e) { + log.error("Could not delete asset {}", a.getPath()); + } + },true); + } + + /** + * Returns the extension of the name of a given asset. Extension is the substring after the last occurence of '.' in the + * string. If no '.' is found, the empty string is returned. + * + * @param asset The asset from which to return the extension string. + * @return The extension. + */ + public static final String getExtension(StorageAsset asset) { + return StringUtils.substringAfterLast(asset.getName(),"."); + } + + public static final void copyToLocalFile(StorageAsset asset, Path destination, CopyOption... copyOptions) throws IOException { + if (asset.isFileBased()) { + Files.copy(asset.getFilePath(), destination, copyOptions); + } else { + try { + + HashSet<OpenOption> openOptions = new HashSet<>(); + for (CopyOption option : copyOptions) { + if (option == StandardCopyOption.REPLACE_EXISTING) { + openOptions.add(StandardOpenOption.CREATE); + openOptions.add(StandardOpenOption.TRUNCATE_EXISTING); + openOptions.add(StandardOpenOption.WRITE); + } else { + openOptions.add(StandardOpenOption.WRITE); + openOptions.add(StandardOpenOption.CREATE_NEW); + } + } + asset.getStorage().consumeDataFromChannel(asset, channel -> { + try { + FileChannel.open(destination, openOptions).transferFrom(channel, 0, Long.MAX_VALUE); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, false); + } catch (Throwable e) { + if (e.getCause() instanceof IOException) { + throw (IOException)e.getCause(); + } else { + throw new IOException(e); + } + } + } + } + + public static class PathInformation { + final Path path ; + final boolean tmpFile; + + PathInformation(Path path, boolean tmpFile) { + this.path = path; + this.tmpFile = tmpFile; + } + + public Path getPath() { + return path; + } + + public boolean isTmpFile() { + return tmpFile; + } + + } + + public static final PathInformation getAssetDataAsPath(StorageAsset asset) throws IOException { + if (!asset.exists()) { + throw new IOException("Asset does not exist"); + } + if (asset.isFileBased()) { + return new PathInformation(asset.getFilePath(), false); + } else { + Path tmpFile = Files.createTempFile(asset.getName(), getExtension(asset)); + copyToLocalFile(asset, tmpFile, StandardCopyOption.REPLACE_EXISTING); + return new PathInformation(tmpFile, true); + } + } + +} diff --git a/archiva-modules/archiva-base/archiva-storage-fs/src/test/java/org/apache/archiva/repository/storage/FilesystemAssetTest.java b/archiva-modules/archiva-base/archiva-storage-fs/src/test/java/org/apache/archiva/repository/storage/FilesystemAssetTest.java new file mode 100644 index 000000000..566c0cb5d --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-fs/src/test/java/org/apache/archiva/repository/storage/FilesystemAssetTest.java @@ -0,0 +1,203 @@ +package org.apache.archiva.repository.storage; + +/* + * 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.DefaultFileLockManager; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; + +public class FilesystemAssetTest { + + Path assetPathFile; + Path assetPathDir; + FilesystemStorage filesystemStorage; + + @Before + public void init() throws IOException { + assetPathDir = Files.createTempDirectory("assetDir"); + assetPathFile = Files.createTempFile(assetPathDir,"assetFile", "dat"); + filesystemStorage = new FilesystemStorage(assetPathDir, new DefaultFileLockManager()); + } + + @After + public void cleanup() { + + try { + Files.deleteIfExists(assetPathFile); + } catch (IOException e) { + e.printStackTrace(); + } + FileUtils.deleteQuietly(assetPathDir.toFile()); + } + + + @Test + public void getPath() { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, assetPathFile.getFileName().toString(), assetPathFile); + Assert.assertEquals("/"+assetPathFile.getFileName().toString(), asset.getPath()); + } + + @Test + public void getName() { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/"+assetPathFile.getFileName().toString(), assetPathFile); + Assert.assertEquals(assetPathFile.getFileName().toString(), asset.getName()); + + } + + @Test + public void getModificationTime() throws IOException { + Instant modTime = Files.getLastModifiedTime(assetPathFile).toInstant(); + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test123", assetPathFile); + Assert.assertTrue(modTime.equals(asset.getModificationTime())); + } + + @Test + public void isContainer() { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1323", assetPathFile); + Assert.assertFalse(asset.isContainer()); + FilesystemAsset asset2 = new FilesystemAsset(filesystemStorage, "/test1234", assetPathDir); + Assert.assertTrue(asset2.isContainer()); + } + + @Test + public void list() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Assert.assertEquals(0, asset.list().size()); + + FilesystemAsset asset2 = new FilesystemAsset(filesystemStorage, "/test1235", assetPathDir); + Assert.assertEquals(1, asset2.list().size()); + Path f1 = Files.createTempFile(assetPathDir, "testfile", "dat"); + Path f2 = Files.createTempFile(assetPathDir, "testfile", "dat"); + Path d1 = Files.createTempDirectory(assetPathDir, "testdir"); + Assert.assertEquals(4, asset2.list().size()); + Assert.assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(f1.getFileName().toString()))); + Assert.assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(f2.getFileName().toString()))); + Assert.assertTrue(asset2.list().stream().anyMatch(p -> p.getName().equals(d1.getFileName().toString()))); + Files.deleteIfExists(f1); + Files.deleteIfExists(f2); + Files.deleteIfExists(d1); + + + } + + @Test + public void getSize() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Assert.assertEquals(0, asset.getSize()); + + Files.write(assetPathFile, new String("abcdef").getBytes("ASCII")); + Assert.assertTrue(asset.getSize()>=6); + + + } + + @Test + public void getData() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Files.write(assetPathFile, "abcdef".getBytes("ASCII")); + try(InputStream is = asset.getReadStream()) { + Assert.assertEquals("abcdef", IOUtils.toString(is, "ASCII")); + } + + } + + @Test + public void getDataExceptionOnDir() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathDir); + Files.write(assetPathFile, "abcdef".getBytes("ASCII")); + try { + InputStream is = asset.getReadStream(); + Assert.assertFalse("Exception expected for data on dir", true); + } catch (IOException e) { + // fine + } + + } + + @Test + public void writeData() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Files.write(assetPathFile, "abcdef".getBytes("ASCII")); + try(OutputStream os = asset.getWriteStream(true)) { + IOUtils.write("test12345", os, "ASCII"); + } + Assert.assertEquals("test12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); + } + + @Test + public void writeDataAppend() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Files.write(assetPathFile, "abcdef".getBytes("ASCII")); + try(OutputStream os = asset.getWriteStream(false)) { + IOUtils.write("test12345", os, "ASCII"); + } + Assert.assertEquals("abcdeftest12345", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); + } + + @Test + public void writeDataExceptionOnDir() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathDir); + try { + + OutputStream os = asset.getWriteStream(true); + Assert.assertTrue("Writing to a directory should throw a IOException", false); + } catch (IOException e) { + // Fine + } + } + + @Test + public void storeDataFile() throws IOException { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Path dataFile = Files.createTempFile("testdata", "dat"); + try(OutputStream os = Files.newOutputStream(dataFile)) { + IOUtils.write("testkdkdkd", os, "ASCII"); + } + asset.replaceDataFromFile(dataFile); + Assert.assertEquals("testkdkdkd", IOUtils.toString(assetPathFile.toUri().toURL(), "ASCII")); + } + + @Test + public void exists() { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Assert.assertTrue(asset.exists()); + FilesystemAsset asset2 = new FilesystemAsset(filesystemStorage, "/test1234", Paths.get("abcdefgkdkdk")); + Assert.assertFalse(asset2.exists()); + + } + + @Test + public void getFilePath() { + FilesystemAsset asset = new FilesystemAsset(filesystemStorage, "/test1234", assetPathFile); + Assert.assertEquals(assetPathFile, asset.getFilePath()); + } +}
\ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemStorageTest.java b/archiva-modules/archiva-base/archiva-storage-fs/src/test/java/org/apache/archiva/repository/storage/FilesystemStorageTest.java index 309c755e6..ebbc6a5a6 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/content/FilesystemStorageTest.java +++ b/archiva-modules/archiva-base/archiva-storage-fs/src/test/java/org/apache/archiva/repository/storage/FilesystemStorageTest.java @@ -1,4 +1,4 @@ -package org.apache.archiva.repository.content; +package org.apache.archiva.repository.storage; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,13 @@ package org.apache.archiva.repository.content; */ import org.apache.archiva.common.filelock.DefaultFileLockManager; +import org.apache.archiva.repository.storage.FilesystemAsset; +import org.apache.archiva.repository.storage.FilesystemStorage; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -30,6 +35,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import static org.junit.Assert.*; @@ -51,8 +57,8 @@ public class FilesystemStorageTest { Files.createDirectories(baseDir.resolve("dir2")); file1 = Files.createFile(baseDir.resolve("dir1/testfile1.dat")); dir1 = Files.createDirectories(baseDir.resolve("dir1/testdir")); - file1Asset = new FilesystemAsset("/dir1/testfile1.dat", file1); - dir1Asset = new FilesystemAsset("/dir1/testdir", dir1); + file1Asset = new FilesystemAsset(fsStorage, "/dir1/testfile1.dat", file1); + dir1Asset = new FilesystemAsset(fsStorage, "/dir1/testdir", dir1); } private class StringResult { @@ -70,31 +76,11 @@ public class FilesystemStorageTest { @After public void cleanup() { - try { - Files.deleteIfExists(file1); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Files.deleteIfExists(dir1); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Files.deleteIfExists(baseDir.resolve("dir1")); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Files.deleteIfExists(baseDir.resolve("dir2")); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Files.deleteIfExists(baseDir); - } catch (IOException e) { - e.printStackTrace(); - } + FileUtils.deleteQuietly(file1.toFile()); + FileUtils.deleteQuietly(dir1.toFile()); + FileUtils.deleteQuietly(baseDir.resolve("dir1").toFile()); + FileUtils.deleteQuietly(baseDir.resolve("dir2").toFile()); + FileUtils.deleteQuietly(baseDir.toFile()); } @@ -107,7 +93,7 @@ public class FilesystemStorageTest { } StringResult result = new StringResult(); fsStorage.consumeData(file1Asset, is -> consume(is, result), false ); - assertEquals("abcdefghijkl" ,result.getData()); + Assert.assertEquals("abcdefghijkl" ,result.getData()); } private void consume(InputStream is, StringResult result) { @@ -122,31 +108,31 @@ public class FilesystemStorageTest { @Test public void getAsset() { StorageAsset asset = fsStorage.getAsset("/dir1/testfile1.dat"); - assertEquals(file1, asset.getFilePath()); + Assert.assertEquals(file1, asset.getFilePath()); } @Test public void addAsset() { StorageAsset newAsset = fsStorage.addAsset("dir2/test", false); - assertNotNull(newAsset); - assertFalse(newAsset.isContainer()); - assertFalse(newAsset.exists()); + Assert.assertNotNull(newAsset); + Assert.assertFalse(newAsset.isContainer()); + Assert.assertFalse(newAsset.exists()); StorageAsset newDirAsset = fsStorage.addAsset("/dir2/testdir2", true); - assertNotNull(newDirAsset); - assertTrue(newDirAsset.isContainer()); - assertFalse(newDirAsset.exists()); + Assert.assertNotNull(newDirAsset); + Assert.assertTrue(newDirAsset.isContainer()); + Assert.assertFalse(newDirAsset.exists()); } @Test public void removeAsset() throws IOException { - assertTrue(Files.exists(file1)); + Assert.assertTrue(Files.exists(file1)); fsStorage.removeAsset(file1Asset); - assertFalse(Files.exists(file1)); + Assert.assertFalse(Files.exists(file1)); - assertTrue(Files.exists(dir1)); + Assert.assertTrue(Files.exists(dir1)); fsStorage.removeAsset(dir1Asset); - assertFalse(Files.exists(dir1)); + Assert.assertFalse(Files.exists(dir1)); } @Test @@ -154,23 +140,23 @@ public class FilesystemStorageTest { Path newFile=null; Path newDir=null; try { - assertTrue(Files.exists(file1)); + Assert.assertTrue(Files.exists(file1)); try (OutputStream os = Files.newOutputStream(file1)) { IOUtils.write("testakdkkdkdkdk", os, "ASCII"); } long fileSize = Files.size(file1); fsStorage.moveAsset(file1Asset, "/dir2/testfile2.dat"); - assertFalse(Files.exists(file1)); + Assert.assertFalse(Files.exists(file1)); newFile = baseDir.resolve("dir2/testfile2.dat"); - assertTrue(Files.exists(newFile)); - assertEquals(fileSize, Files.size(newFile)); + Assert.assertTrue(Files.exists(newFile)); + Assert.assertEquals(fileSize, Files.size(newFile)); - assertTrue(Files.exists(dir1)); + Assert.assertTrue(Files.exists(dir1)); newDir = baseDir.resolve("dir2/testdir2"); fsStorage.moveAsset(dir1Asset, "dir2/testdir2"); - assertFalse(Files.exists(dir1)); - assertTrue(Files.exists(newDir)); + Assert.assertFalse(Files.exists(dir1)); + Assert.assertTrue(Files.exists(newDir)); } finally { if (newFile!=null) Files.deleteIfExists(newFile); if (newDir!=null) Files.deleteIfExists(newDir); @@ -182,27 +168,33 @@ public class FilesystemStorageTest { Path newFile=null; Path newDir=null; try { - assertTrue(Files.exists(file1)); + Assert.assertTrue(Files.exists(file1)); try (OutputStream os = Files.newOutputStream(file1)) { IOUtils.write("testakdkkdkdkdk", os, "ASCII"); } long fileSize = Files.size(file1); - fsStorage.copyAsset(file1Asset, "/dir2/testfile2.dat"); - assertTrue(Files.exists(file1)); - assertEquals(fileSize, Files.size(file1)); + fsStorage.copyAsset(file1Asset, "/dir2/testfile2.dat", StandardCopyOption.REPLACE_EXISTING); + Assert.assertTrue(Files.exists(file1)); + Assert.assertEquals(fileSize, Files.size(file1)); newFile = baseDir.resolve("dir2/testfile2.dat"); - assertTrue(Files.exists(newFile)); - assertEquals(fileSize, Files.size(newFile)); - + Assert.assertTrue(Files.exists(newFile)); + Assert.assertEquals(fileSize, Files.size(newFile)); + + try { + fsStorage.copyAsset(file1Asset, "/dir2/testfile2.dat"); + Assert.assertTrue("IOException should be thrown (File exists)", false); + } catch (IOException ex) { + Assert.assertTrue("Exception must contain 'file exists'", ex.getMessage().contains("file exists")); + } - assertTrue(Files.exists(dir1)); + Assert.assertTrue(Files.exists(dir1)); newDir = baseDir.resolve("dir2/testdir2"); fsStorage.copyAsset(dir1Asset, "dir2/testdir2"); - assertTrue(Files.exists(dir1)); - assertTrue(Files.exists(newDir)); + Assert.assertTrue(Files.exists(dir1)); + Assert.assertTrue(Files.exists(newDir)); } finally { if (newFile!=null) Files.deleteIfExists(newFile); - if (newDir!=null) Files.deleteIfExists(newDir); + if (newDir!=null) FileUtils.deleteQuietly(newDir.toFile()); } } }
\ No newline at end of file diff --git a/archiva-modules/archiva-base/pom.xml b/archiva-modules/archiva-base/pom.xml index a687a9564..a580e84a8 100644 --- a/archiva-modules/archiva-base/pom.xml +++ b/archiva-modules/archiva-base/pom.xml @@ -52,5 +52,7 @@ <module>archiva-repository-scanner</module> <module>archiva-repository-admin</module> <module>archiva-security-common</module> + <module>archiva-storage-api</module> + <module>archiva-storage-fs</module> </modules> </project> |