diff --git a/pom.xml b/pom.xml index fb076cdc..27a0b125 100644 --- a/pom.xml +++ b/pom.xml @@ -168,6 +168,11 @@ commons-exec 1.3 + + org.apache.maven.shared + maven-common-artifact-filters + 3.0.0 + org.apache.maven.shared diff --git a/src/main/java/org/codehaus/mojo/exec/AbstractExecMojo.java b/src/main/java/org/codehaus/mojo/exec/AbstractExecMojo.java index 0899b53b..12c2a0b4 100644 --- a/src/main/java/org/codehaus/mojo/exec/AbstractExecMojo.java +++ b/src/main/java/org/codehaus/mojo/exec/AbstractExecMojo.java @@ -20,20 +20,24 @@ */ import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.Resource; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; +import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter; import org.codehaus.plexus.util.cli.CommandLineUtils; /** @@ -140,6 +144,17 @@ public abstract class AbstractExecMojo */ @Parameter( property = "addOutputToClasspath", defaultValue = "true" ) private boolean addOutputToClasspath; + + + /** + * List of dependencies to exclude from the test classpath. Each dependency string must follow the format + * groupId:artifactId. For example: org.acme:project-a + * + * @since 1.5.1 + */ + @Parameter( property = "exec.classpathDependencyExcludes" ) + private String[] classpathDependencyExcludes; + /** * Collects the project artifacts in the specified List and the project specific classpath (build output and build @@ -192,10 +207,44 @@ else if ( "system".equals( classpathScope ) ) { throw new IllegalStateException( "Invalid classpath scope: " + classpathScope ); } - + getLog().debug( "Collected project artifacts " + artifacts ); + //filter dependency + if ( classpathDependencyExcludes != null ) + { + ArtifactFilter dependencyFilter = + new PatternIncludesArtifactFilter( Arrays.asList( classpathDependencyExcludes ) ); + List filterList = this.filterArtifacts( artifacts, dependencyFilter ); + artifacts.clear(); + artifacts.addAll(filterList); + getLog().debug( "Collected project artifacts after filter " + artifacts ); + } + + getLog().debug( "Collected project classpath " + theClasspathFiles ); } + + /** + * Return a new set containing only the artifacts accepted by the given filter. + * + * @param artifacts The unfiltered artifacts + * @param filter The filter to apply + * @return The filtered result + */ + private List filterArtifacts( List artifacts, ArtifactFilter filter ) + { + List filteredArtifacts = new ArrayList(); + + for ( Artifact artifact : artifacts ) + { + if ( !filter.include( artifact ) ) + { + filteredArtifacts.add( artifact ); + } + } + + return filteredArtifacts; + } /** * Parses the argument string given by the user. Strings are recognized as everything between STRING_WRAPPER. diff --git a/src/test/java/org/codehaus/mojo/exec/ExecJavaMojoTest.java b/src/test/java/org/codehaus/mojo/exec/ExecJavaMojoTest.java index 33389de6..1c26ae2c 100644 --- a/src/test/java/org/codehaus/mojo/exec/ExecJavaMojoTest.java +++ b/src/test/java/org/codehaus/mojo/exec/ExecJavaMojoTest.java @@ -18,6 +18,8 @@ import java.io.File; import java.io.PrintStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.DefaultArtifactRepository; @@ -135,6 +137,32 @@ public void testWaitNoDaemonThreads() assertEquals( MainWithThreads.ALL_EXITED, output.trim() ); } + + + + public void testClasspathDependencyExcludes() + throws Exception + { + File pom = new File( getBasedir(), "src/test/projects/project15/pom.xml" ); + String output = executeDebug( pom, "java" ); + String expectedExcludeDependency = "commons-logging:commons-logging"; + + Pattern pattern = Pattern.compile(".*?Collected project artifacts \\[(.*?)\\].*"); + Matcher matcher = pattern.matcher(output.trim()); + String result = expectedExcludeDependency; + //check it present in project dependency + if(matcher.find()){ + pattern = Pattern.compile(".*?Collected project artifacts after filter \\[(.*?)\\].*"); + matcher = pattern.matcher(output.trim()); + //check it present after filter + if(matcher.find()){ + result = matcher.group(0); + } + } + + assertFalse(result.contains(expectedExcludeDependency) ); + } + /** * For cases where the Java code spawns Threads and main returns soon, but code contains non interruptible threads. @@ -235,6 +263,52 @@ private String execute( File pom, String goal ) return stringOutputStream.toString(); } + + + /** + * @return output from System.out during mojo execution + */ + private String executeDebug( File pom, String goal ) + throws Exception + { + + ExecJavaMojo mojo; + mojo = (ExecJavaMojo) lookupMojo( goal, pom ); + + setUpProject( pom, mojo ); + + MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" ); + + // why isn't this set up by the harness based on the default-value? TODO get to bottom of this! + setVariableValueToObject( mojo, "includeProjectDependencies", Boolean.TRUE ); + setVariableValueToObject( mojo, "killAfter", (long) -1 ); + setVariableValueToObject( mojo, "cleanupDaemonThreads", Boolean.TRUE ); + setVariableValueToObject( mojo, "classpathScope", "compile" ); + + assertNotNull( mojo ); + assertNotNull( project ); + + // trap System.out + PrintStream out = System.out; + StringOutputStream stringOutputStream = new StringOutputStream(); + System.setOut( new PrintStream( stringOutputStream ) ); + // ensure we don't log unnecessary stuff which would interfere with assessing success of tests + mojo.setLog( new DefaultLog( new ConsoleLogger( Logger.LEVEL_DEBUG, "exec:java" ) ) ); + + try + { + mojo.execute(); + } + finally + { + // see testUncooperativeThread() for explaination + Thread.sleep( 300 ); // time seems about right + System.setOut( out ); + } + + return stringOutputStream.toString(); + } + private void setUpProject( File pomFile, AbstractMojo mojo ) throws Exception diff --git a/src/test/projects/project15/pom.xml b/src/test/projects/project15/pom.xml new file mode 100644 index 00000000..2c421706 --- /dev/null +++ b/src/test/projects/project15/pom.xml @@ -0,0 +1,88 @@ + + 4.0.0 + org.cb.maven.plugins.exec + project15 + 0.1 + jar + Maven Exec Plugin + Test that one can force adding the test-classpath for the java mojo + + 2005 + + + Apache License 2 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + Jerome Lacoste + jerome + jerome@coffeebreaks.org + CoffeeBreaks + http://www.coffeebreaks.org + + Java Developer + + +1 + + + + + + commons-io + commons-io + 1.1 + + + commons-logging + commons-logging + 1.0.4 + + + junit + junit + 3.8.1 + test + + + + + + + + org.codehaus.mojo + exec-maven-plugin + + + test + + java + + + + + true + + commons-logging:commons-logging + + org.codehaus.mojo.exec.DummyMain + -X + + -X + + + + + + + +