import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.beans.ManagedRepository;
-import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.archiva.consumers.RepositoryContentConsumer;
import org.apache.commons.collections.CollectionUtils;
-import org.codehaus.plexus.util.DirectoryWalker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
+import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
/**
* DefaultRepositoryScanner
public class DefaultRepositoryScanner
implements RepositoryScanner
{
+
+ private static final Logger log = LoggerFactory.getLogger(DefaultRepositoryScanner.class);
+
@Inject
private FileTypes filetypes;
throw new IllegalArgumentException( "Unable to operate on a null repository." );
}
- File repositoryBase = new File( repository.getLocation() );
+ Path repositoryBase = Paths.get( repository.getLocation() );
//MRM-1342 Repository statistics report doesn't appear to be working correctly
//create the repo if not existing to have an empty stats
- if ( !repositoryBase.exists() && !repositoryBase.mkdirs() )
+ if ( !Files.exists(repositoryBase))
{
- throw new UnsupportedOperationException(
- "Unable to scan a repository, directory " + repositoryBase.getPath() + " does not exist." );
+ try {
+ Files.createDirectories(repositoryBase);
+ } catch (IOException e) {
+ throw new UnsupportedOperationException("Unable to scan a repository, directory " + repositoryBase + " does not exist." );
+ }
}
- if ( !repositoryBase.isDirectory() )
+ if ( !Files.isDirectory(repositoryBase) )
{
throw new UnsupportedOperationException(
- "Unable to scan a repository, path " + repositoryBase.getPath() + " is not a directory." );
+ "Unable to scan a repository, path " + repositoryBase+ " is not a directory." );
}
// Setup Includes / Excludes.
// Scan All Content. (intentional)
allIncludes.add( "**/*" );
- // Setup Directory Walker
- DirectoryWalker dirWalker = new DirectoryWalker();
-
- dirWalker.setBaseDir( repositoryBase );
-
- dirWalker.setIncludes( allIncludes );
- dirWalker.setExcludes( allExcludes );
-
// Setup the Scan Instance
RepositoryScannerInstance scannerInstance =
new RepositoryScannerInstance( repository, knownContentConsumers, invalidContentConsumers, changesSince );
+ scannerInstance.setFileNameIncludePattern(allIncludes);
+ scannerInstance.setFileNameExcludePattern(allExcludes);
inProgressScans.add( scannerInstance );
- RepositoryScanStatistics stats;
+ RepositoryScanStatistics stats = null;
try
{
- dirWalker.addDirectoryWalkListener( scannerInstance );
-
- // Execute scan.
- dirWalker.scan();
+ Files.walkFileTree(repositoryBase, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, scannerInstance);
stats = scannerInstance.getStatistics();
stats.setKnownConsumers( gatherIds( knownContentConsumers ) );
stats.setInvalidConsumers( gatherIds( invalidContentConsumers ) );
- }
- finally
+ } catch (IOException e) {
+ log.error("Could not scan directory {}", repositoryBase);
+ } finally
{
inProgressScans.remove( scannerInstance );
}
import org.springframework.stereotype.Service;
import javax.inject.Inject;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.nio.file.Path;
+import java.util.*;
/**
* RepositoryContentConsumerUtil
* @param localFile the local file to execute the consumers against.
* @param updateRelatedArtifacts TODO
*/
- public void executeConsumers( ManagedRepository repository, File localFile, boolean updateRelatedArtifacts )
+ public void executeConsumers(ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
throws RepositoryAdminException
{
List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
// yuck. In case you can't read this, it says
// "process the file if the consumer has it in the includes list, and not in the excludes list"
- BaseFile baseFile = new BaseFile( repository.getLocation(), localFile );
+ BaseFile baseFile = new BaseFile( repository.getLocation(), localFile.toFile() );
ConsumerWantsFilePredicate predicate = new ConsumerWantsFilePredicate( repository );
predicate.setBasefile( baseFile );
predicate.setCaseSensitive( false );
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.functors.IfClosure;
import org.apache.commons.lang.SystemUtils;
-import org.codehaus.plexus.util.DirectoryWalkListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* RepositoryScannerInstance
*/
public class RepositoryScannerInstance
- implements DirectoryWalkListener
+ implements FileVisitor<Path>
{
private Logger log = LoggerFactory.getLogger( RepositoryScannerInstance.class );
private Map<String, Long> consumerCounts;
+
+ private List<String> fileNameIncludePattern = new ArrayList<>();
+ private List<String> fileNameExcludePattern = new ArrayList<>();
+
+ private List<PathMatcher> includeMatcher = new ArrayList<>();
+ private List<PathMatcher> excludeMatcher = new ArrayList<>();
+
+ private boolean isRunning = false;
+
+ Path basePath = null;
+
public RepositoryScannerInstance( ManagedRepository repository,
List<KnownRepositoryContentConsumer> knownConsumerList,
List<InvalidRepositoryContentConsumer> invalidConsumerList )
this.knownConsumers = knownConsumerList;
this.invalidConsumers = invalidConsumerList;
+ addFileNameIncludePattern("**/*");
+
consumerTimings = new HashMap<>();
consumerCounts = new HashMap<>();
return consumerCounts;
}
- @Override
- public void directoryWalkStarting( File basedir )
+ public ManagedRepository getRepository()
{
- log.info( "Walk Started: [{}] {}", this.repository.getId(), this.repository.getLocation() );
- stats.triggerStart();
+ return repository;
}
- @Override
- public void directoryWalkStep( int percentage, File file )
+ public RepositoryScanStatistics getStats()
+ {
+ return stats;
+ }
+
+ public long getChangesSince()
{
- log.debug( "Walk Step: {}, {}", percentage, file );
+ return changesSince;
+ }
- stats.increaseFileCount();
+ public List<String> getFileNameIncludePattern() {
+ return fileNameIncludePattern;
+ }
- // consume files regardless - the predicate will check the timestamp
- BaseFile basefile = new BaseFile( repository.getLocation(), file );
+ public void setFileNameIncludePattern(List<String> fileNamePattern) {
+ this.fileNameIncludePattern = fileNamePattern;
+ FileSystem sys = FileSystems.getDefault();
+ this.includeMatcher = fileNamePattern.stream().map(ts ->sys
+ .getPathMatcher("glob:" + ts)).collect(Collectors.toList());
+ }
- // Timestamp finished points to the last successful scan, not this current one.
- if ( file.lastModified() >= changesSince )
- {
- stats.increaseNewFileCount();
+ public void addFileNameIncludePattern(String fileNamePattern) {
+ if (! this.fileNameIncludePattern.contains(fileNamePattern)) {
+ this.fileNameIncludePattern.add(fileNamePattern);
+ this.includeMatcher.add(FileSystems.getDefault().getPathMatcher("glob:" + fileNamePattern));
}
+ }
- consumerProcessFile.setBasefile( basefile );
- consumerWantsFile.setBasefile( basefile );
+ public List<String> getFileNameExcludePattern() {
+ return fileNameExcludePattern;
+ }
- Closure processIfWanted = IfClosure.getInstance( consumerWantsFile, consumerProcessFile );
- CollectionUtils.forAllDo( this.knownConsumers, processIfWanted );
+ public void setFileNameExcludePattern(List<String> fileNamePattern) {
+ this.fileNameExcludePattern = fileNamePattern;
+ FileSystem sys = FileSystems.getDefault();
+ this.excludeMatcher = fileNamePattern.stream().map(ts ->sys
+ .getPathMatcher("glob:" + ts)).collect(Collectors.toList());
+ }
- if ( consumerWantsFile.getWantedFileCount() <= 0 )
- {
- // Nothing known processed this file. It is invalid!
- CollectionUtils.forAllDo( this.invalidConsumers, consumerProcessFile );
+ public void addFileNameExcludePattern(String fileNamePattern) {
+ if (! this.fileNameExcludePattern.contains(fileNamePattern)) {
+ this.fileNameExcludePattern.add(fileNamePattern);
+ this.excludeMatcher.add(FileSystems.getDefault().getPathMatcher("glob:" + fileNamePattern));
}
}
+
@Override
- public void directoryWalkFinished()
- {
- TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, true );
- CollectionUtils.forAllDo( knownConsumers, scanCompletedClosure );
- CollectionUtils.forAllDo( invalidConsumers, scanCompletedClosure );
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ if (!isRunning) {
+ isRunning = true;
+ this.basePath = dir;
+ log.info( "Walk Started: [{}] {}", this.repository.getId(), this.repository.getLocation() );
+ stats.triggerStart();
+ }
+ return FileVisitResult.CONTINUE;
+ }
- stats.setConsumerTimings( consumerTimings );
- stats.setConsumerCounts( consumerCounts );
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (excludeMatcher.stream().noneMatch(m -> m.matches(file)) && includeMatcher.stream().allMatch(m -> m.matches(file))) {
+ log.debug( "Walk Step: {}, {}", file );
- log.info( "Walk Finished: [{}] {}", this.repository.getId(), this.repository.getLocation() );
- stats.triggerFinished();
+ stats.increaseFileCount();
+
+ // consume files regardless - the predicate will check the timestamp
+ BaseFile basefile = new BaseFile( repository.getLocation(), file.toFile() );
+
+ // Timestamp finished points to the last successful scan, not this current one.
+ if ( Files.getLastModifiedTime(file).toMillis() >= changesSince )
+ {
+ stats.increaseNewFileCount();
+ }
+
+ consumerProcessFile.setBasefile( basefile );
+ consumerWantsFile.setBasefile( basefile );
+
+ Closure processIfWanted = IfClosure.getInstance( consumerWantsFile, consumerProcessFile );
+ CollectionUtils.forAllDo( this.knownConsumers, processIfWanted );
+
+ if ( consumerWantsFile.getWantedFileCount() <= 0 )
+ {
+ // Nothing known processed this file. It is invalid!
+ CollectionUtils.forAllDo( this.invalidConsumers, consumerProcessFile );
+ }
+
+ }
+ return FileVisitResult.CONTINUE;
}
- /**
- * Debug method from DirectoryWalker.
- */
@Override
- public void debug( String message )
- {
- log.debug( "Repository Scanner: {}", message );
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ log.error("Error occured at {}: {}", file, exc.getMessage(), exc);
+ if (basePath!=null && Files.isSameFile(file, basePath)) {
+ finishWalk();
+ }
+ return FileVisitResult.CONTINUE;
}
- public ManagedRepository getRepository()
- {
- return repository;
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ if (Files.isSameFile(dir, basePath)) {
+ finishWalk();
+ }
+ return FileVisitResult.CONTINUE;
}
- public RepositoryScanStatistics getStats()
- {
- return stats;
- }
+ private void finishWalk() {
+ this.isRunning = false;
+ TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, true );
+ CollectionUtils.forAllDo( knownConsumers, scanCompletedClosure );
+ CollectionUtils.forAllDo( invalidConsumers, scanCompletedClosure );
- public long getChangesSince()
- {
- return changesSince;
+ stats.setConsumerTimings( consumerTimings );
+ stats.setConsumerCounts( consumerCounts );
+
+ log.info( "Walk Finished: [{}] {}", this.repository.getId(), this.repository.getLocation() );
+ stats.triggerFinished();
+ this.basePath = null;
}
}
import org.springframework.test.context.ContextConfiguration;
import javax.inject.Inject;
-import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
@Inject
ApplicationContext applicationContext;
- protected ManagedRepository createRepository( String id, String name, File location )
+ protected ManagedRepository createRepository( String id, String name, Path location )
{
ManagedRepository repo = new ManagedRepository();
repo.setId( id );
repo.setName( name );
- repo.setLocation( location.getAbsolutePath() );
+ repo.setLocation( location.toAbsolutePath().toString() );
return repo;
}
consumers.setSelectedInvalidConsumers( Collections.singletonList( selectedInvalidConsumer ) );
- ManagedRepository repo = createRepository( "id", "name", new File( "target/test-repo" ) );
- File testFile = new File( "target/test-repo/path/to/test-file.txt" );
+ ManagedRepository repo = createRepository( "id", "name", Paths.get( "target/test-repo" ) );
+ Path testFile = Paths.get( "target/test-repo/path/to/test-file.txt" );
Date startTime = new Date( System.currentTimeMillis() );
startTime.setTime( 12345678 );
knownControl.reset();
invalidControl.reset();
- File notIncludedTestFile = new File( "target/test-repo/path/to/test-file.xml" );
+ Path notIncludedTestFile = Paths.get( "target/test-repo/path/to/test-file.xml" );
selectedKnownConsumer.beginScan( repo, startTime, false );
expect( selectedKnownConsumer.getExcludes() ).andReturn( Collections.<String>emptyList() );
knownControl.reset();
invalidControl.reset();
- File excludedTestFile = new File( "target/test-repo/path/to/test-file.txt" );
+ Path excludedTestFile = Paths.get( "target/test-repo/path/to/test-file.txt" );
selectedKnownConsumer.beginScan( repo, startTime, false );
expect( selectedKnownConsumer.getExcludes() ).andReturn( Collections.singletonList( "**/test-file.txt" ) );
import org.springframework.test.context.ContextConfiguration;
import javax.inject.Inject;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.attribute.FileTime;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@Inject
ApplicationContext applicationContext;
- protected ManagedRepository createRepository( String id, String name, File location )
+ protected ManagedRepository createRepository( String id, String name, Path location )
{
ManagedRepository repo = new ManagedRepository();
repo.setId( id );
repo.setName( name );
- repo.setLocation( location.getAbsolutePath() );
+ repo.setLocation( location.toAbsolutePath().toString());
return repo;
}
private ManagedRepository createDefaultRepository()
{
- File repoDir =
- Paths.get( System.getProperty( "basedir" ), "src/test/repositories/default-repository" ).toFile();
+ Path repoDir =
+ Paths.get( System.getProperty( "basedir" ), "src/test/repositories/default-repository" );
- assertTrue( "Default Test Repository should exist.", repoDir.exists() && repoDir.isDirectory() );
+ assertTrue( "Default Test Repository should exist.", Files.exists(repoDir) && Files.isDirectory(repoDir) );
return createRepository( "testDefaultRepo", "Test Default Repository", repoDir );
}
private ManagedRepository createSimpleRepository()
throws IOException, ParseException
{
- File srcDir = Paths.get( System.getProperty( "basedir" ), "src/test/repositories/simple-repository" ).toFile();
+ Path srcDir = Paths.get( System.getProperty( "basedir" ), "src/test/repositories/simple-repository" );
- File repoDir = Paths.get( System.getProperty( "basedir" ), "target/test-repos/simple-repository" ).toFile();
+ Path repoDir = Paths.get( System.getProperty( "basedir" ), "target/test-repos/simple-repository" );
- FileUtils.deleteDirectory( repoDir );
+ org.apache.archiva.common.utils.FileUtils.deleteDirectory( repoDir );
- FileUtils.copyDirectory( srcDir, repoDir );
+ FileUtils.copyDirectory( srcDir.toFile(), repoDir.toFile() );
- File repoFile = new File( repoDir,
+ Path repoFile = repoDir.resolve(
"groupId/snapshot-artifact/1.0-alpha-1-SNAPSHOT/snapshot-artifact-1.0-alpha-1-20050611.202024-1.pom" );
- repoFile.setLastModified( getTimestampAsMillis( "20050611.202024" ) );
+ Files.setLastModifiedTime(repoFile, FileTime.fromMillis(getTimestampAsMillis( "20050611.202024" ) ));
- assertTrue( "Simple Test Repository should exist.", repoDir.exists() && repoDir.isDirectory() );
+ assertTrue( "Simple Test Repository should exist.", Files.exists(repoDir) && Files.isDirectory(repoDir) );
return createRepository( "testSimpleRepo", "Test Simple Repository", repoDir );
}
private ManagedRepository createLegacyRepository()
{
- File repoDir = Paths.get( System.getProperty( "basedir" ), "src/test/repositories/legacy-repository" ).toFile();
+ Path repoDir = Paths.get( System.getProperty( "basedir" ), "src/test/repositories/legacy-repository" );
- assertTrue( "Legacy Test Repository should exist.", repoDir.exists() && repoDir.isDirectory() );
+ assertTrue( "Legacy Test Repository should exist.", Files.exists(repoDir) && Files.isDirectory(repoDir) );
ManagedRepository repo = createRepository( "testLegacyRepo", "Test Legacy Repository", repoDir );
repo.setLayout( "legacy" );
if ( task.getResourceFile() != null )
{
log.debug( "Executing task from queue with job name: {}", task );
- consumers.executeConsumers( arepo, task.getResourceFile(), task.isUpdateRelatedArtifacts() );
+ consumers.executeConsumers( arepo, task.getResourceFile().toPath(), task.isUpdateRelatedArtifacts() );
}
else
{