diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java index a80b3a0e4..d838d76d0 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java @@ -33,6 +33,8 @@ import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.internal.impl.DefaultArtifactResolver; import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider; +import org.eclipse.aether.internal.impl.DefaultTrackingFileManager; +import org.eclipse.aether.internal.impl.TrackingFileManager; import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector; import org.eclipse.aether.internal.impl.DefaultDeployer; import org.eclipse.aether.internal.impl.DefaultFileProcessor; @@ -217,6 +219,7 @@ public DefaultServiceLocator() addService( LocalRepositoryManagerFactory.class, SimpleLocalRepositoryManagerFactory.class ); addService( LocalRepositoryManagerFactory.class, EnhancedLocalRepositoryManagerFactory.class ); addService( LoggerFactory.class, Slf4jLoggerFactory.class ); + addService( TrackingFileManager.class, DefaultTrackingFileManager.class ); } private Entry getEntry( Class type, boolean create ) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java index 0558f2874..0c9f6a5b4 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java @@ -40,6 +40,8 @@ import org.eclipse.aether.impl.RemoteRepositoryManager; import org.eclipse.aether.impl.RepositoryConnectorProvider; import org.eclipse.aether.impl.RepositoryEventDispatcher; +import org.eclipse.aether.internal.impl.DefaultTrackingFileManager; +import org.eclipse.aether.internal.impl.TrackingFileManager; import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory; import org.eclipse.aether.internal.impl.synccontext.GlobalSyncContextFactory; import org.eclipse.aether.internal.impl.synccontext.NamedSyncContextFactory; @@ -158,6 +160,7 @@ protected void configure() .to( SimpleLocalRepositoryManagerFactory.class ).in( Singleton.class ); bind( LocalRepositoryManagerFactory.class ).annotatedWith( Names.named( "enhanced" ) ) // .to( EnhancedLocalRepositoryManagerFactory.class ).in( Singleton.class ); + bind( TrackingFileManager.class ).to( DefaultTrackingFileManager.class ).in( Singleton.class ); bind( SyncContextFactoryDelegate.class ).annotatedWith( Names.named( NoLockSyncContextFactory.NAME ) ) .to( NoLockSyncContextFactory.class ).in( Singleton.class ); diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManager.java new file mode 100644 index 000000000..e6e2e653a --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManager.java @@ -0,0 +1,155 @@ +package org.eclipse.aether.internal.impl; + +/* + * 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 java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.Properties; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manages access to a properties file. + */ +@Singleton +@Named +public final class DefaultTrackingFileManager + implements TrackingFileManager +{ + private static final Logger LOGGER = LoggerFactory.getLogger( DefaultTrackingFileManager.class ); + + @Override + public Properties read( File file ) + { + FileInputStream stream = null; + try + { + if ( !file.exists() ) + { + return null; + } + + stream = new FileInputStream( file ); + + Properties props = new Properties(); + props.load( stream ); + + return props; + } + catch ( IOException e ) + { + LOGGER.warn( "Failed to read tracking file {}", file, e ); + } + finally + { + close( stream, file ); + } + + return null; + } + + @Override + public Properties update( File file, Map updates ) + { + Properties props = new Properties(); + + File directory = file.getParentFile(); + if ( !directory.mkdirs() && !directory.exists() ) + { + LOGGER.warn( "Failed to create parent directories for tracking file {}", file ); + return props; + } + + RandomAccessFile raf = null; + try + { + raf = new RandomAccessFile( file, "rw" ); + + if ( file.canRead() ) + { + byte[] buffer = new byte[(int) raf.length()]; + + raf.readFully( buffer ); + + ByteArrayInputStream stream = new ByteArrayInputStream( buffer ); + + props.load( stream ); + } + + for ( Map.Entry update : updates.entrySet() ) + { + if ( update.getValue() == null ) + { + props.remove( update.getKey() ); + } + else + { + props.setProperty( update.getKey(), update.getValue() ); + } + } + + ByteArrayOutputStream stream = new ByteArrayOutputStream( 1024 * 2 ); + + LOGGER.debug( "Writing tracking file {}", file ); + props.store( stream, "NOTE: This is a Maven Resolver internal implementation file" + + ", its format can be changed without prior notice." ); + + raf.seek( 0 ); + raf.write( stream.toByteArray() ); + raf.setLength( raf.getFilePointer() ); + } + catch ( IOException e ) + { + LOGGER.warn( "Failed to write tracking file {}", file, e ); + } + finally + { + close( raf, file ); + } + + return props; + } + + private void close( Closeable closeable, File file ) + { + if ( closeable != null ) + { + try + { + closeable.close(); + } + catch ( IOException e ) + { + LOGGER.warn( "Error closing tracking file {}", file, e ); + } + } + } + +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java index 8d1bb20ea..e4aba8345 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java @@ -64,7 +64,7 @@ public class DefaultUpdateCheckManager private static final Logger LOGGER = LoggerFactory.getLogger( DefaultUpdatePolicyAnalyzer.class ); - private final TrackingFileManager trackingFileManager; + private TrackingFileManager trackingFileManager; private UpdatePolicyAnalyzer updatePolicyAnalyzer; @@ -86,21 +86,28 @@ public class DefaultUpdateCheckManager public DefaultUpdateCheckManager() { - trackingFileManager = new TrackingFileManager(); + // default ctor for ServiceLocator } @Inject - DefaultUpdateCheckManager( UpdatePolicyAnalyzer updatePolicyAnalyzer ) + DefaultUpdateCheckManager( TrackingFileManager trackingFileManager, UpdatePolicyAnalyzer updatePolicyAnalyzer ) { - this(); + setTrackingFileManager( trackingFileManager ); setUpdatePolicyAnalyzer( updatePolicyAnalyzer ); } public void initService( ServiceLocator locator ) { + setTrackingFileManager( locator.getService( TrackingFileManager.class ) ); setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) ); } + public DefaultUpdateCheckManager setTrackingFileManager( TrackingFileManager trackingFileManager ) + { + this.trackingFileManager = requireNonNull( trackingFileManager ); + return this; + } + public DefaultUpdateCheckManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer ) { this.updatePolicyAnalyzer = requireNonNull( updatePolicyAnalyzer, "update policy analyzer cannot be null" ); diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java index 9ba089083..677406eff 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java @@ -26,6 +26,8 @@ import java.util.HashSet; import java.util.Map; import static java.util.Objects.requireNonNull; + +import java.util.Objects; import java.util.Properties; import org.eclipse.aether.RepositorySystemSession; @@ -65,7 +67,9 @@ class EnhancedLocalRepositoryManager private final TrackingFileManager trackingFileManager; - EnhancedLocalRepositoryManager( File basedir, RepositorySystemSession session ) + EnhancedLocalRepositoryManager( File basedir, + RepositorySystemSession session, + TrackingFileManager trackingFileManager ) { super( basedir, "enhanced" ); String filename = ConfigUtils.getString( session, "", "aether.enhancedLocalRepository.trackingFilename" ); @@ -74,8 +78,8 @@ class EnhancedLocalRepositoryManager { filename = "_remote.repositories"; } - trackingFilename = filename; - trackingFileManager = new TrackingFileManager(); + this.trackingFilename = filename; + this.trackingFileManager = Objects.requireNonNull( trackingFileManager ); } @Override diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java index 622331507..fb33ed501 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java @@ -19,6 +19,9 @@ * under the License. */ +import java.util.Objects; + +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -27,6 +30,8 @@ import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.NoLocalRepositoryManagerException; import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory; +import org.eclipse.aether.spi.locator.Service; +import org.eclipse.aether.spi.locator.ServiceLocator; /** * Creates enhanced local repository managers for repository types {@code "default"} or {@code "" (automatic)}. Enhanced @@ -38,13 +43,27 @@ @Singleton @Named( "enhanced" ) public class EnhancedLocalRepositoryManagerFactory - implements LocalRepositoryManagerFactory + implements LocalRepositoryManagerFactory, Service { private float priority = 10.0f; + private TrackingFileManager trackingFileManager; + public EnhancedLocalRepositoryManagerFactory() { - // enable no-arg constructor + // no arg ctor for ServiceLocator + } + + @Inject + public EnhancedLocalRepositoryManagerFactory( final TrackingFileManager trackingFileManager ) + { + this.trackingFileManager = Objects.requireNonNull( trackingFileManager ); + } + + @Override + public void initService( final ServiceLocator locator ) + { + this.trackingFileManager = Objects.requireNonNull( locator.getService( TrackingFileManager.class ) ); } public LocalRepositoryManager newInstance( RepositorySystemSession session, LocalRepository repository ) @@ -52,7 +71,7 @@ public LocalRepositoryManager newInstance( RepositorySystemSession session, Loca { if ( "".equals( repository.getContentType() ) || "default".equals( repository.getContentType() ) ) { - return new EnhancedLocalRepositoryManager( repository.getBasedir(), session ); + return new EnhancedLocalRepositoryManager( repository.getBasedir(), session, trackingFileManager ); } else { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java index e31f0969c..1bc5b3e72 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java @@ -19,130 +19,16 @@ * under the License. */ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.RandomAccessFile; import java.util.Map; import java.util.Properties; /** * Manages access to a properties file. */ -class TrackingFileManager +public interface TrackingFileManager { + Properties read( File file ); - private static final Logger LOGGER = LoggerFactory.getLogger( TrackingFileManager.class ); - - public Properties read( File file ) - { - FileInputStream stream = null; - try - { - if ( !file.exists() ) - { - return null; - } - - stream = new FileInputStream( file ); - - Properties props = new Properties(); - props.load( stream ); - - return props; - } - catch ( IOException e ) - { - LOGGER.warn( "Failed to read tracking file {}", file, e ); - } - finally - { - close( stream, file ); - } - - return null; - } - - public Properties update( File file, Map updates ) - { - Properties props = new Properties(); - - File directory = file.getParentFile(); - if ( !directory.mkdirs() && !directory.exists() ) - { - LOGGER.warn( "Failed to create parent directories for tracking file {}", file ); - return props; - } - - RandomAccessFile raf = null; - try - { - raf = new RandomAccessFile( file, "rw" ); - - if ( file.canRead() ) - { - byte[] buffer = new byte[(int) raf.length()]; - - raf.readFully( buffer ); - - ByteArrayInputStream stream = new ByteArrayInputStream( buffer ); - - props.load( stream ); - } - - for ( Map.Entry update : updates.entrySet() ) - { - if ( update.getValue() == null ) - { - props.remove( update.getKey() ); - } - else - { - props.setProperty( update.getKey(), update.getValue() ); - } - } - - ByteArrayOutputStream stream = new ByteArrayOutputStream( 1024 * 2 ); - - LOGGER.debug( "Writing tracking file {}", file ); - props.store( stream, "NOTE: This is a Maven Resolver internal implementation file" - + ", its format can be changed without prior notice." ); - - raf.seek( 0 ); - raf.write( stream.toByteArray() ); - raf.setLength( raf.getFilePointer() ); - } - catch ( IOException e ) - { - LOGGER.warn( "Failed to write tracking file {}", file, e ); - } - finally - { - close( raf, file ); - } - - return props; - } - - private void close( Closeable closeable, File file ) - { - if ( closeable != null ) - { - try - { - closeable.close(); - } - catch ( IOException e ) - { - LOGGER.warn( "Error closing tracking file {}", file, e ); - } - } - } - + Properties update( File file, Map updates ); } diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultArtifactResolverTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultArtifactResolverTest.java index 3710a6912..3c27f9854 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultArtifactResolverTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultArtifactResolverTest.java @@ -272,7 +272,10 @@ public void get( Collection artifactDownloads, }; repositoryConnectorProvider.setConnector( connector ); - resolver.setUpdateCheckManager( new DefaultUpdateCheckManager().setUpdatePolicyAnalyzer( new DefaultUpdatePolicyAnalyzer() ) ); + resolver.setUpdateCheckManager( new DefaultUpdateCheckManager() + .setUpdatePolicyAnalyzer( new DefaultUpdatePolicyAnalyzer() ) + .setTrackingFileManager( new DefaultTrackingFileManager() ) + ); session.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy( true, false ) ); session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER ); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/TrackingFileManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManagerTest.java similarity index 91% rename from maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/TrackingFileManagerTest.java rename to maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManagerTest.java index 1593fa435..e3745aa68 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/TrackingFileManagerTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManagerTest.java @@ -36,14 +36,14 @@ /** */ -public class TrackingFileManagerTest +public class DefaultTrackingFileManagerTest { @Test public void testRead() throws Exception { - TrackingFileManager tfm = new TrackingFileManager(); + TrackingFileManager tfm = new DefaultTrackingFileManager(); File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" ); Properties props = tfm.read( propFile ); @@ -63,7 +63,7 @@ public void testRead() public void testReadNoFileLeak() throws Exception { - TrackingFileManager tfm = new TrackingFileManager(); + TrackingFileManager tfm = new DefaultTrackingFileManager(); for ( int i = 0; i < 1000; i++ ) { @@ -77,7 +77,7 @@ public void testReadNoFileLeak() public void testUpdate() throws Exception { - TrackingFileManager tfm = new TrackingFileManager(); + TrackingFileManager tfm = new DefaultTrackingFileManager(); // NOTE: The excessive repetitions are to check the update properly truncates the file File propFile = TestFileUtils.createTempFile( "key1=value1\nkey2 : value2\n".getBytes( StandardCharsets.UTF_8 ), 1000 ); @@ -100,7 +100,7 @@ public void testUpdate() public void testUpdateNoFileLeak() throws Exception { - TrackingFileManager tfm = new TrackingFileManager(); + TrackingFileManager tfm = new DefaultTrackingFileManager(); Map updates = new HashMap<>(); updates.put( "k", "v" ); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java index 3b38e8b81..111aca754 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java @@ -80,7 +80,9 @@ public void setup() session = TestUtils.newSession(); repository = new RemoteRepository.Builder( "id", "default", TestFileUtils.createTempDir().toURI().toURL().toString() ).build(); - manager = new DefaultUpdateCheckManager().setUpdatePolicyAnalyzer( new DefaultUpdatePolicyAnalyzer() ); + manager = new DefaultUpdateCheckManager() + .setUpdatePolicyAnalyzer( new DefaultUpdatePolicyAnalyzer() ) + .setTrackingFileManager( new DefaultTrackingFileManager() ); metadata = new DefaultMetadata( "gid", "aid", "ver", "maven-metadata.xml", Metadata.Nature.RELEASE_OR_SNAPSHOT, metadataFile ); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java index 32a422259..1dae78941 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java @@ -64,6 +64,8 @@ public class EnhancedLocalRepositoryManagerTest private String testContext = "project/compile"; + private TrackingFileManager trackingFileManager; + private RepositorySystemSession session; private Metadata metadata; @@ -96,7 +98,8 @@ public void setup() basedir = TestFileUtils.createTempDir( "enhanced-repo" ); session = TestUtils.newSession(); - manager = new EnhancedLocalRepositoryManager( basedir, session ); + trackingFileManager = new DefaultTrackingFileManager(); + manager = new EnhancedLocalRepositoryManager( basedir, session, trackingFileManager ); artifactFile = new File( basedir, manager.getPathForLocalArtifact( artifact ) ); }