Author: jdcasey Date: Tue Sep 21 20:41:59 2010 New Revision: 999628 URL: http://svn.apache.org/viewvc?rev=999628&view=rev Log: [MASSEMBLY-187] Prevent infinite recursion by excluding location patterns matching the assembly working directory (which is a temp workspace for archive creation).
Modified: maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiver.java maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiver.java maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/PrefixedFileSet.java maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiverTest.java maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiverTest.java Modified: maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiver.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiver.java?rev=999628&r1=999627&r2=999628&view=diff ============================================================================== --- maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiver.java (original) +++ maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiver.java Tue Sep 21 20:41:59 2010 @@ -318,7 +318,7 @@ public class DefaultAssemblyArchiver archiver = new AssemblyProxyArchiver( prefix, archiver, containerHandlers, extraSelectors, extraFinalizers, - getLogger(), configSource.isDryRun() ); + configSource.getWorkingDirectory(), getLogger(), configSource.isDryRun() ); return archiver; } Modified: maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiver.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiver.java?rev=999628&r1=999627&r2=999628&view=diff ============================================================================== --- maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiver.java (original) +++ maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiver.java Tue Sep 21 20:41:59 2010 @@ -40,6 +40,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -61,6 +62,8 @@ public class AssemblyProxyArchiver implements Archiver { + private static final String[] STR_TEMPLATE = new String[0]; + private final Archiver delegate; private String rootPrefix; @@ -75,14 +78,20 @@ public class AssemblyProxyArchiver private final Set<String> seenPaths = new HashSet<String>(); + private final String assemblyWorkPath; + public AssemblyProxyArchiver( final String rootPrefix, final Archiver delegate, final List<ContainerDescriptorHandler> containerDescriptorHandlers, final List<FileSelector> extraSelectors, - final List<ArchiveFinalizer> extraFinalizers, final Logger logger, - final boolean dryRun ) + final List<ArchiveFinalizer> extraFinalizers, final File assemblyWorkDir, + final Logger logger, final boolean dryRun ) { this.rootPrefix = rootPrefix; this.delegate = delegate; + + assemblyWorkPath = assemblyWorkDir.getAbsolutePath() + .replace( '\\', '/' ); + this.logger = logger; this.dryRun = dryRun; @@ -330,7 +339,7 @@ public class AssemblyProxyArchiver } else { - delegate.addFileSet( fs ); + doAddFileSet( fs ); } } finally @@ -359,7 +368,7 @@ public class AssemblyProxyArchiver } else { - delegate.addFileSet( fs ); + doAddFileSet( fs ); } } finally @@ -390,7 +399,7 @@ public class AssemblyProxyArchiver } else { - delegate.addFileSet( fs ); + doAddFileSet( fs ); } } finally @@ -419,7 +428,7 @@ public class AssemblyProxyArchiver } else { - delegate.addFileSet( fs ); + doAddFileSet( fs ); } } finally @@ -712,7 +721,7 @@ public class AssemblyProxyArchiver } else { - delegate.addFileSet( fs ); + doAddFileSet( fs ); } } finally @@ -721,6 +730,64 @@ public class AssemblyProxyArchiver } } + private void doAddFileSet( final FileSet fs ) + throws ArchiverException + { + final String fsPath = fs.getDirectory() + .getAbsolutePath() + .replace( '\\', '/' ); + + if ( fsPath.equals( assemblyWorkPath ) ) + { + logger.debug( "SKIPPING fileset with source directory matching assembly working-directory: " + fsPath ); + return; + } + else if ( assemblyWorkPath.startsWith( fsPath ) ) + { + final List<String> newEx = new ArrayList<String>(); + if ( fs.getExcludes() != null ) + { + newEx.addAll( Arrays.asList( fs.getExcludes() ) ); + } + + final String workDirExclude = assemblyWorkPath.substring( fsPath.length() + 1 ); + + logger.debug( "Adding exclude for assembly working-directory: " + workDirExclude + + "\nFile-Set source directory: " + fsPath ); + + newEx.add( workDirExclude ); + + final List<String> newIn = new ArrayList<String>(); + if ( fs.getIncludes() != null ) + { + for ( final String include : fs.getIncludes() ) + { + if ( !include.startsWith( workDirExclude ) ) + { + newIn.add( include ); + } + } + } + + final DefaultFileSet dfs = new DefaultFileSet(); + + dfs.setCaseSensitive( fs.isCaseSensitive() ); + dfs.setDirectory( fs.getDirectory() ); + dfs.setExcludes( newEx.toArray( STR_TEMPLATE ) ); + dfs.setFileSelectors( fs.getFileSelectors() ); + dfs.setIncludes( newIn.toArray( STR_TEMPLATE ) ); + dfs.setIncludingEmptyDirectories( fs.isIncludingEmptyDirectories() ); + dfs.setPrefix( fs.getPrefix() ); + dfs.setUsingDefaultExcludes( fs.isUsingDefaultExcludes() ); + + delegate.addFileSet( dfs ); + } + else + { + delegate.addFileSet( fs ); + } + } + private String getMethodName() { final NullPointerException npe = new NullPointerException(); Modified: maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/PrefixedFileSet.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/PrefixedFileSet.java?rev=999628&r1=999627&r2=999628&view=diff ============================================================================== --- maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/PrefixedFileSet.java (original) +++ maven/plugins/trunk/maven-assembly-plugin/src/main/java/org/apache/maven/plugin/assembly/archive/archiver/PrefixedFileSet.java Tue Sep 21 20:41:59 2010 @@ -32,15 +32,17 @@ public class PrefixedFileSet { private final String rootPrefix; + private final FileSet fileSet; + private final FileSelector[] selectors; - public PrefixedFileSet( FileSet fileSet, String rootPrefix, FileSelector[] selectors ) + public PrefixedFileSet( final FileSet fileSet, final String rootPrefix, final FileSelector[] selectors ) { this.fileSet = fileSet; this.selectors = selectors; - if ( rootPrefix.length() > 0 && ! rootPrefix.endsWith( "/" ) ) + if ( rootPrefix.length() > 0 && !rootPrefix.endsWith( "/" ) ) { this.rootPrefix = rootPrefix + "/"; } @@ -60,7 +62,7 @@ public class PrefixedFileSet FileSelector[] sel = fileSet.getFileSelectors(); if ( ( sel != null ) && ( selectors != null ) ) { - FileSelector[] temp = new FileSelector[ sel.length + selectors.length ]; + final FileSelector[] temp = new FileSelector[sel.length + selectors.length]; System.arraycopy( sel, 0, temp, 0, sel.length ); System.arraycopy( selectors, 0, temp, sel.length, selectors.length ); @@ -83,6 +85,11 @@ public class PrefixedFileSet public String getPrefix() { String prefix = fileSet.getPrefix(); + if ( prefix == null ) + { + return rootPrefix; + } + if ( prefix.startsWith( "/" ) ) { if ( prefix.length() > 1 ) Modified: maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiverTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiverTest.java?rev=999628&r1=999627&r2=999628&view=diff ============================================================================== --- maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiverTest.java (original) +++ maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/DefaultAssemblyArchiverTest.java Tue Sep 21 20:41:59 2010 @@ -137,6 +137,9 @@ public class DefaultAssemblyArchiverTest configSource.getArchiverConfig(); csControl.setReturnValue( null, MockControl.ZERO_OR_MORE ); + configSource.getWorkingDirectory(); + csControl.setReturnValue( new File( "." ), MockControl.ZERO_OR_MORE ); + final Assembly assembly = new Assembly(); final AssemblyContext context = new DefaultAssemblyContext(); @@ -190,6 +193,9 @@ public class DefaultAssemblyArchiverTest configSource.isDryRun(); configCtl.setReturnValue( false, MockControl.ZERO_OR_MORE ); + configSource.getWorkingDirectory(); + configCtl.setReturnValue( new File( "." ), MockControl.ZERO_OR_MORE ); + mm.add( configCtl ); mm.replayAll(); @@ -233,6 +239,9 @@ public class DefaultAssemblyArchiverTest configSource.getJarArchiveConfiguration(); configCtl.setReturnValue( null, MockControl.ZERO_OR_MORE ); + configSource.getWorkingDirectory(); + configCtl.setReturnValue( new File( "." ), MockControl.ZERO_OR_MORE ); + mm.add( configCtl ); mm.replayAll(); @@ -274,6 +283,9 @@ public class DefaultAssemblyArchiverTest configSource.getJarArchiveConfiguration(); configCtl.setReturnValue( null, MockControl.ZERO_OR_MORE ); + configSource.getWorkingDirectory(); + configCtl.setReturnValue( new File( "." ), MockControl.ZERO_OR_MORE ); + mm.add( configCtl ); mm.replayAll(); @@ -306,6 +318,9 @@ public class DefaultAssemblyArchiverTest configSource.getArchiverConfig(); configCtl.setReturnValue( null, MockControl.ZERO_OR_MORE ); + configSource.getWorkingDirectory(); + configCtl.setReturnValue( new File( "." ), MockControl.ZERO_OR_MORE ); + mm.add( configCtl ); mm.replayAll(); Modified: maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiverTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiverTest.java?rev=999628&r1=999627&r2=999628&view=diff ============================================================================== --- maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiverTest.java (original) +++ maven/plugins/trunk/maven-assembly-plugin/src/test/java/org/apache/maven/plugin/assembly/archive/archiver/AssemblyProxyArchiverTest.java Tue Sep 21 20:41:59 2010 @@ -19,37 +19,90 @@ package org.apache.maven.plugin.assembly * under the License. */ +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import org.apache.maven.plugin.assembly.testutils.TestFileManager; +import org.apache.maven.plugin.assembly.testutils.TrackingArchiverStub; +import org.apache.maven.plugin.assembly.testutils.TrackingArchiverStub.Addition; import org.codehaus.plexus.archiver.Archiver; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.JarArchiver; +import org.codehaus.plexus.archiver.util.DefaultFileSet; import org.codehaus.plexus.components.io.fileselectors.FileInfo; import org.codehaus.plexus.components.io.fileselectors.FileSelector; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.console.ConsoleLogger; import org.easymock.MockControl; +import org.junit.AfterClass; +import org.junit.Test; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - public class AssemblyProxyArchiverTest - extends TestCase { - private final TestFileManager fileManager = new TestFileManager( "massembly-proxyArchiver", "" ); + private static final TestFileManager fileManager = new TestFileManager( "massembly-proxyArchiver", "" ); + + private static final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ); - @Override - public void tearDown() - throws Exception + @AfterClass + public static void cleanupFiles() { fileManager.cleanUp(); } - public void testAddFile_NoPerms_CallAcceptFilesOnlyOnce() + @Test( timeout = 5000 ) + public void addFileSet_SkipWhenSourceIsAssemblyWorkDir() + throws IOException, ArchiverException + { + final File sources = fileManager.createTempDir(); + + final File workdir = new File( sources, "workdir" ); + + final TrackingArchiverStub tracker = new TrackingArchiverStub(); + final AssemblyProxyArchiver archiver = + new AssemblyProxyArchiver( "", tracker, null, null, null, workdir, logger, false ); + + final DefaultFileSet fs = new DefaultFileSet(); + fs.setDirectory( workdir ); + + archiver.addFileSet( fs ); + + assertTrue( tracker.added.isEmpty() ); + } + + @Test( timeout = 5000 ) + public void addFileSet_addExcludeWhenSourceContainsAssemblyWorkDir() + throws IOException, ArchiverException + { + final File sources = fileManager.createTempDir(); + + final File workdir = new File( sources, "workdir" ); + + final TrackingArchiverStub tracker = new TrackingArchiverStub(); + final AssemblyProxyArchiver archiver = + new AssemblyProxyArchiver( "", tracker, null, null, null, workdir, logger, false ); + + final DefaultFileSet fs = new DefaultFileSet(); + fs.setDirectory( sources ); + + archiver.addFileSet( fs ); + + assertEquals( 1, tracker.added.size() ); + + final Addition addition = tracker.added.get( 0 ); + assertNotNull( addition.excludes ); + assertEquals( 1, addition.excludes.length ); + assertEquals( workdir.getName(), addition.excludes[0] ); + } + + @Test + public void addFile_NoPerms_CallAcceptFilesOnlyOnce() throws IOException, ArchiverException { final MockControl delegateControl = MockControl.createControl( Archiver.class ); @@ -66,8 +119,8 @@ public class AssemblyProxyArchiverTest delegateControl.replay(); final AssemblyProxyArchiver archiver = - new AssemblyProxyArchiver( "", delegate, null, selectors, null, new ConsoleLogger( Logger.LEVEL_DEBUG, - "test" ), false ); + new AssemblyProxyArchiver( "", delegate, null, selectors, null, new File( "." ), + new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), false ); final File inputFile = fileManager.createTempFile(); @@ -78,7 +131,8 @@ public class AssemblyProxyArchiverTest delegateControl.verify(); } - public void testAddDirectory_NoPerms_CallAcceptFilesOnlyOnce() + @Test + public void addDirectory_NoPerms_CallAcceptFilesOnlyOnce() throws IOException, ArchiverException { final Archiver delegate = new JarArchiver(); @@ -91,8 +145,8 @@ public class AssemblyProxyArchiverTest selectors.add( counter ); final AssemblyProxyArchiver archiver = - new AssemblyProxyArchiver( "", delegate, null, selectors, null, new ConsoleLogger( Logger.LEVEL_DEBUG, - "test" ), false ); + new AssemblyProxyArchiver( "", delegate, null, selectors, null, new File( "." ), + new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), false ); final File dir = fileManager.createTempDir(); fileManager.createFile( dir, "file.txt", "This is a test." );