diff --git a/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java b/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java index e4501ab51..6971cfc68 100644 --- a/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java +++ b/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java @@ -34,6 +34,7 @@ import org.codehaus.plexus.components.io.fileselectors.FileSelector; import org.codehaus.plexus.components.io.resources.PlexusIoResource; import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection; +import org.codehaus.plexus.components.io.resources.ResourceFactory; import org.codehaus.plexus.logging.Logger; import javax.annotation.Nonnull; @@ -784,7 +785,15 @@ private boolean acceptFile( final File inputFile ) { if ( selectors != null ) { - final FileInfo fileInfo = new DefaultFileInfo( inputFile ); + final FileInfo fileInfo; + try + { + fileInfo = ResourceFactory.createResource( inputFile ); + } + catch ( final IOException e ) + { + throw new ArchiverException( "Error processing file: " + inputFile, e ); + } for ( final FileSelector selector : selectors ) { diff --git a/src/main/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandler.java b/src/main/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandler.java index 12f101200..3783a4247 100644 --- a/src/main/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandler.java +++ b/src/main/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandler.java @@ -25,6 +25,7 @@ import org.codehaus.plexus.archiver.ResourceIterator; import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.components.io.fileselectors.FileInfo; +import org.codehaus.plexus.components.io.resources.PlexusIoResource; import javax.annotation.Nonnull; import java.io.BufferedReader; @@ -38,11 +39,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import static java.lang.Math.max; abstract class AbstractLineAggregatingHandler implements ContainerDescriptorHandler { + private Map catalogLastModified = new HashMap<>(); + private Map> catalog = new HashMap<>(); private boolean excludeOverride = false; @@ -93,6 +99,12 @@ void addToArchive( final Archiver archiver ) writer.println( line ); } } + + final AtomicLong lastModified = catalogLastModified.get( name ); + if ( lastModified != null && lastModified.get() > 0 ) + { + f.setLastModified( lastModified.get() ); + } } catch ( final IOException e ) { @@ -133,6 +145,22 @@ public boolean isSelected( @Nonnull final FileInfo fileInfo ) { name = getOutputPathPrefix( fileInfo ) + new File( name ).getName(); + if ( fileInfo instanceof PlexusIoResource ) + { + final PlexusIoResource resource = (PlexusIoResource) fileInfo; + final long lastModified = resource.getLastModified(); + + if ( catalogLastModified.containsKey( name ) ) + { + final AtomicLong latestLastModified = catalogLastModified.get( name ); + latestLastModified.set( max( latestLastModified.get(), lastModified ) ); + } + else + { + catalogLastModified.put( name, new AtomicLong( lastModified ) ); + } + } + List lines = catalog.get( name ); if ( lines == null ) { diff --git a/src/main/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilter.java b/src/main/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilter.java index 813da5f34..443aa0076 100644 --- a/src/main/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilter.java +++ b/src/main/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilter.java @@ -27,13 +27,13 @@ import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.components.io.fileselectors.FileInfo; +import org.codehaus.plexus.components.io.resources.PlexusIoResource; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.Xpp3DomWriter; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import javax.annotation.Nonnull; - import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -45,6 +45,8 @@ import java.util.List; import java.util.Map; +import static java.lang.Math.max; + /** * Components XML file filter. * @@ -64,6 +66,8 @@ public class ComponentsXmlArchiverFileFilter private boolean excludeOverride = false; + private long lastModified = 0L; + void addComponentsXml( final Reader componentsReader ) throws XmlPullParserException, IOException { @@ -121,6 +125,11 @@ private void addToArchive( final Archiver archiver ) Xpp3DomWriter.write( fileWriter, dom ); } + if ( lastModified > 0 ) + { + f.setLastModified( lastModified ); + } + excludeOverride = true; archiver.addFile( f, COMPONENTS_XML_PATH ); @@ -183,6 +192,12 @@ public boolean isSelected( @Nonnull final FileInfo fileInfo ) if ( ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH.equals( entry ) ) { + if ( fileInfo instanceof PlexusIoResource ) + { + final PlexusIoResource resource = (PlexusIoResource) fileInfo; + lastModified = max( lastModified, resource.getLastModified() ); + } + try ( Reader reader = new BufferedReader( ReaderFactory.newXmlReader( fileInfo.getContents() ) ) ) { addComponentsXml( reader ); diff --git a/src/main/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandler.java b/src/main/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandler.java index 2fa737305..4b0658ddc 100644 --- a/src/main/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandler.java +++ b/src/main/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandler.java @@ -25,6 +25,7 @@ import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.components.io.fileselectors.FileInfo; +import org.codehaus.plexus.components.io.resources.PlexusIoResource; import org.codehaus.plexus.logging.LogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.console.ConsoleLogger; @@ -46,6 +47,8 @@ import java.util.Date; import java.util.List; +import static java.lang.Math.max; + /** * */ @@ -65,6 +68,8 @@ public class SimpleAggregatingDescriptorHandler // calculated, temporary values. + private long lastModified = 0L; + private String filePattern; private String outputPath; @@ -94,6 +99,11 @@ public void finalizeArchiveCreation( final Archiver archiver ) final File temp = writePropertiesFile(); + if ( lastModified > 0 ) + { + temp.setLastModified( lastModified ); + } + overrideFilterAction = true; archiver.addFile( temp, outputPath ); @@ -172,6 +182,12 @@ public boolean isSelected( @Nonnull final FileInfo fileInfo ) readProperties( fileInfo ); filenames.add( name ); + if ( fileInfo instanceof PlexusIoResource ) + { + final PlexusIoResource resource = (PlexusIoResource) fileInfo; + lastModified = max( lastModified, resource.getLastModified() ); + } + return false; } diff --git a/src/test/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandlerTest.java b/src/test/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandlerTest.java new file mode 100644 index 000000000..4ee75d42a --- /dev/null +++ b/src/test/java/org/apache/maven/plugins/assembly/filter/AbstractLineAggregatingHandlerTest.java @@ -0,0 +1,114 @@ +package org.apache.maven.plugins.assembly.filter; + +/* + * 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.codehaus.plexus.archiver.ArchiveEntry; +import org.codehaus.plexus.archiver.Archiver; +import org.codehaus.plexus.archiver.ResourceIterator; +import org.codehaus.plexus.archiver.dir.DirectoryArchiver; +import org.codehaus.plexus.components.io.fileselectors.FileInfo; +import org.codehaus.plexus.components.io.resources.PlexusIoResource; +import org.codehaus.plexus.util.FileUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; + +import static org.codehaus.plexus.components.io.resources.ResourceFactory.createResource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class AbstractLineAggregatingHandlerTest +{ + /** A time today, rounded down to the previous minute */ + static long MODIFIED_TODAY = (System.currentTimeMillis() / TimeUnit.MINUTES.toMillis( 1 )) * TimeUnit.MINUTES.toMillis( 1 ); + + /** A time yesterday, rounded down to the previous minute */ + static long MODIFIED_YESTERDAY = MODIFIED_TODAY - TimeUnit.DAYS.toMillis( 1 ); + + /** A time last week, rounded down to the previous minute */ + static long MODIFIED_LAST_WEEK = MODIFIED_TODAY - TimeUnit.DAYS.toMillis( 7 ); + + private final AbstractLineAggregatingHandler handler = new AbstractLineAggregatingHandler() + { + @Override + protected String getOutputPathPrefix( final FileInfo fileInfo ) { + return ""; + } + + @Override + protected boolean fileMatches( final FileInfo fileInfo ) { + return true; + } + }; + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void testHandlerMergesMatchingFiles() + throws Exception + { + // Arrange + final Archiver archiver = new DirectoryArchiver(); + final FileInfo resource1 = resource( "merged.txt", "text1", MODIFIED_YESTERDAY ); + final FileInfo resource2 = resource( "merged.txt", "text2", MODIFIED_LAST_WEEK ); + + // Act + handler.isSelected( resource1 ); + handler.isSelected( resource2 ); + handler.finalizeArchiveCreation( archiver ); + + // Assert + + final ResourceIterator resources = archiver.getResources(); + assertTrue( "Expected at least one resource", resources.hasNext() ); + + final ArchiveEntry resource = resources.next(); + assertFalse( "Expected at most one resource", resources.hasNext() ); + + try(final BufferedReader in = + new BufferedReader( new InputStreamReader( resource.getInputStream() ) ) ) + { + assertEquals( "text1", in.readLine()); + assertEquals( "text2", in.readLine()); + assertNull( in.readLine() ); + } + + assertTrue( + "Merging old resources should result in old merge", + resource.getResource().getLastModified() < MODIFIED_TODAY + ); + } + + private PlexusIoResource resource( final String name, final String text, final long modified ) throws IOException { + final File file = temporaryFolder.newFile(); + FileUtils.fileWrite( file, text ); + file.setLastModified( modified ); + return createResource( file, name ); + } +} diff --git a/src/test/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilterTest.java b/src/test/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilterTest.java index ea8ea0780..bee064da7 100644 --- a/src/test/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilterTest.java +++ b/src/test/java/org/apache/maven/plugins/assembly/filter/ComponentsXmlArchiverFileFilterTest.java @@ -27,9 +27,12 @@ import org.codehaus.plexus.archiver.FileSet; import org.codehaus.plexus.archiver.ResourceIterator; import org.codehaus.plexus.archiver.diags.NoOpArchiver; +import org.codehaus.plexus.archiver.dir.DirectoryArchiver; import org.codehaus.plexus.archiver.zip.ZipArchiver; +import org.codehaus.plexus.components.io.fileselectors.FileInfo; import org.codehaus.plexus.components.io.resources.PlexusIoResource; import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection; +import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.jdom.Document; @@ -42,14 +45,10 @@ import org.junit.rules.TemporaryFolder; import javax.annotation.Nonnull; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; @@ -63,6 +62,16 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static org.apache.maven.plugins.assembly.filter.AbstractLineAggregatingHandlerTest.MODIFIED_TODAY; +import static org.apache.maven.plugins.assembly.filter.AbstractLineAggregatingHandlerTest.MODIFIED_YESTERDAY; +import static org.apache.maven.plugins.assembly.filter.ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH; +import static org.codehaus.plexus.components.io.resources.ResourceFactory.createResource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + public class ComponentsXmlArchiverFileFilterTest { @@ -154,7 +163,7 @@ public void testAddToArchive_ShouldWriteComponentWithoutHintToFile() filter.finalizeArchiveCreation( fca ); - assertEquals( ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName() ); + assertEquals( COMPONENTS_XML_PATH, fca.getDestFileName() ); final SAXBuilder builder = new SAXBuilder( false ); @@ -182,7 +191,7 @@ public void testAddToArchive_ShouldWriteComponentWithHintToFile() filter.finalizeArchiveCreation( fca ); - assertEquals( ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName() ); + assertEquals( COMPONENTS_XML_PATH, fca.getDestFileName() ); final SAXBuilder builder = new SAXBuilder( false ); @@ -215,7 +224,7 @@ public void testAddToArchive_ShouldWriteTwoComponentToFile() filter.finalizeArchiveCreation( fca ); - assertEquals( ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName() ); + assertEquals( COMPONENTS_XML_PATH, fca.getDestFileName() ); final SAXBuilder builder = new SAXBuilder( false ); @@ -267,7 +276,7 @@ public void testAddToArchive_ShouldWriteTwoComponentToArchivedFile() try ( ZipFile zf = new ZipFile( archiveFile ) ) { - final ZipEntry ze = zf.getEntry( ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH ); + final ZipEntry ze = zf.getEntry( COMPONENTS_XML_PATH ); assertNotNull( ze ); @@ -293,7 +302,53 @@ public void testAddToArchive_ShouldWriteTwoComponentToArchivedFile() assertEquals( "role", ( (Text) role2.selectSingleNode( doc ) ).getText() ); assertEquals( "hint2", ( (Text) hint2.selectSingleNode( doc ) ).getText() ); assertEquals( "impl", ( (Text) implementation2.selectSingleNode( doc ) ).getText() ); + } + + @Test + public void testHandlerMergesMatchingFiles() + throws Exception + { + // Arrange + + final String minimalValidXml = "" + + "\n" + + " \n" + + " a-role\n" + + " \n" + + ""; + + final Archiver archiver = new DirectoryArchiver(); + final FileInfo file = resource( COMPONENTS_XML_PATH, minimalValidXml, MODIFIED_YESTERDAY ); + + // Act + filter.isSelected( file ); + filter.finalizeArchiveCreation( archiver ); + + // Assert + + final ResourceIterator resources = archiver.getResources(); + assertTrue( "Expected at least one resource", resources.hasNext() ); + + final ArchiveEntry resource = resources.next(); + assertFalse( "Expected at most one resource", resources.hasNext() ); + + try(final BufferedReader in = + new BufferedReader( new InputStreamReader( resource.getInputStream() ) ) ) + { + assertEquals( "", in.readLine()); + } + + assertTrue( + "Merging old resources should result in old merge", + resource.getResource().getLastModified() < MODIFIED_TODAY + ); + } + private PlexusIoResource resource( final String name, final String text, final long modified ) throws IOException { + final File file = temporaryFolder.newFile(); + FileUtils.fileWrite( file, text ); + file.setLastModified( modified ); + return createResource( file, name ); } private Xpp3Dom createComponentDom( final ComponentDef def ) diff --git a/src/test/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandlerTest.java b/src/test/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandlerTest.java new file mode 100644 index 000000000..a20abb684 --- /dev/null +++ b/src/test/java/org/apache/maven/plugins/assembly/filter/SimpleAggregatingDescriptorHandlerTest.java @@ -0,0 +1,99 @@ +package org.apache.maven.plugins.assembly.filter; + +/* + * 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.codehaus.plexus.archiver.ArchiveEntry; +import org.codehaus.plexus.archiver.Archiver; +import org.codehaus.plexus.archiver.ResourceIterator; +import org.codehaus.plexus.archiver.dir.DirectoryArchiver; +import org.codehaus.plexus.components.io.fileselectors.FileInfo; +import org.codehaus.plexus.components.io.resources.PlexusIoResource; +import org.codehaus.plexus.util.FileUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +import static org.apache.maven.plugins.assembly.filter.AbstractLineAggregatingHandlerTest.MODIFIED_LAST_WEEK; +import static org.apache.maven.plugins.assembly.filter.AbstractLineAggregatingHandlerTest.MODIFIED_TODAY; +import static org.apache.maven.plugins.assembly.filter.AbstractLineAggregatingHandlerTest.MODIFIED_YESTERDAY; +import static org.codehaus.plexus.components.io.resources.ResourceFactory.createResource; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class SimpleAggregatingDescriptorHandlerTest +{ + private final SimpleAggregatingDescriptorHandler handler = new SimpleAggregatingDescriptorHandler(); + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void testHandlerMergesMatchingFiles() + throws Exception + { + // Arrange + final Archiver archiver = new DirectoryArchiver(); + final FileInfo resource1 = resource( "input1.txt", "text1", MODIFIED_YESTERDAY ); + final FileInfo resource2 = resource( "input2.txt", "text2", MODIFIED_LAST_WEEK ); + + handler.setFilePattern( "input.*\\.txt" ); + handler.setOutputPath( "merged.txt" ); + + // Act + handler.isSelected( resource1 ); + handler.isSelected( resource2 ); + handler.finalizeArchiveCreation( archiver ); + + // Assert + final ResourceIterator resources = archiver.getResources(); + assertTrue( "Expected at least one resource", resources.hasNext() ); + + final ArchiveEntry resource = resources.next(); + assertFalse( "Expected at most one resource", resources.hasNext() ); + + try(final BufferedReader in = + new BufferedReader( new InputStreamReader( resource.getInputStream() ) ) ) + { + assertThat( in.readLine(), startsWith("# Aggregated on ") ); + assertThat( in.readLine(), equalTo("# input1.txt") ); + assertThat( in.readLine(), equalTo("# input2.txt") ); + } + + assertTrue( + "Merging old resources should result in old merge", + resource.getResource().getLastModified() < MODIFIED_TODAY + ); + } + + private PlexusIoResource resource( final String name, final String text, final long modified ) throws IOException { + final File file = temporaryFolder.newFile(); + FileUtils.fileWrite( file, text ); + file.setLastModified( modified ); + return createResource( file, name ); + } +}