This is an automated email from the ASF dual-hosted git repository. hboutemy pushed a commit to annotated tag maven-invoker-plugin-1.0 in repository https://gitbox.apache.org/repos/asf/maven-invoker-plugin.git
commit 840fd36a7fe127153be03e9df68baa6cc4d6128e Author: John Dennis Casey <jdca...@apache.org> AuthorDate: Tue Aug 8 15:23:32 2006 +0000 Initial pass at a maven-forking plugin...uses the maven-invoker API from maven/shared. git-svn-id: https://svn.apache.org/repos/asf/maven/sandbox/plugins/maven-invoker-plugin@429687 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 59 +++ .../apache/maven/plugin/invoker/FileLogger.java | 64 +++ .../apache/maven/plugin/invoker/InvokerMojo.java | 583 +++++++++++++++++++++ test-with-goals-file/pom.xml | 29 + test-with-goals-file/src/it/test1/goals.txt | 1 + test-with-goals-file/src/it/test1/pom.xml | 6 + 6 files changed, 742 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d71967b --- /dev/null +++ b/pom.xml @@ -0,0 +1,59 @@ +<project + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" +> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>maven-plugin-parent</artifactId> + <groupId>org.apache.maven.plugins</groupId> + <version>2.0.1</version> + </parent> + <artifactId>maven-invoker-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>maven-plugin</packaging> + <name>Maven Invoker Plugin</name> + <dependencies> + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-invoker</artifactId> + <version>2.0.5-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>2.0</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <version>2.0</version> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>file-management</artifactId> + <version>1.1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-shared-io</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.beanshell</groupId> + <artifactId>bsh</artifactId> + <version>2.0b4</version> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/maven/plugin/invoker/FileLogger.java b/src/main/java/org/apache/maven/plugin/invoker/FileLogger.java new file mode 100644 index 0000000..40ae2f4 --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/invoker/FileLogger.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugin.invoker; + +import org.apache.maven.shared.invoker.InvocationOutputHandler; +import org.codehaus.plexus.util.IOUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +public class FileLogger + implements InvocationOutputHandler +{ + + private PrintStream stream; + + private boolean shouldFinalize = true; + + public FileLogger( File outputFile ) + throws IOException + { + stream = new PrintStream( new FileOutputStream( outputFile ) ); + + Runnable finalizer = new Runnable() + { + public void run() + { + try + { + finalize(); + } + catch ( Throwable e ) + { + } + } + }; + + Runtime.getRuntime().addShutdownHook( new Thread( finalizer ) ); + } + + public PrintStream getPrintStream() + { + return stream; + } + + public void consumeLine( String line ) + { + stream.println( line ); + stream.flush(); + } + + public void close() + { + IOUtil.close( stream ); + } + + public void finalize() + { + if ( shouldFinalize ) + { + close(); + } + } +} diff --git a/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java b/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java new file mode 100644 index 0000000..91656ce --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java @@ -0,0 +1,583 @@ +package org.apache.maven.plugin.invoker; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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 bsh.EvalError; +import bsh.Interpreter; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.shared.invoker.DefaultInvocationRequest; +import org.apache.maven.shared.invoker.InvocationRequest; +import org.apache.maven.shared.invoker.InvocationResult; +import org.apache.maven.shared.invoker.Invoker; +import org.apache.maven.shared.invoker.MavenInvocationException; +import org.apache.maven.shared.model.fileset.FileSet; +import org.apache.maven.shared.model.fileset.util.FileSetManager; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.cli.CommandLineException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.StringTokenizer; + +/** + * Searches for integration test Maven projects, and executes each, collecting a log in the project directory, and + * outputting the results to the screen. + * + * @goal run + * + * @author <a href="mailto:ken...@apache.org">Kenney Westerhof</a> + * @author <a href="mailto:jdca...@apache.org">John Casey</a> + */ +public class InvokerMojo + extends AbstractMojo +{ + /** + * The local repository for caching artifacts. + * + * @parameter expression="${invoker.localRepositoryPath}" + */ + private String localRepositoryPath; + + /** + * Directory to search for integration tests. + * + * @parameter expression="${invoker.projectsDirectory}" default-value="${basedir}/src/projects/" + */ + private File projectsDirectory; + + /** + * Includes for searching the integration test directory. This parameter is meant to be set from the POM. + * + * @parameter + */ + private List pomIncludes = Collections.singletonList( "*/pom.xml" ); + + /** + * Excludes for searching the integration test directory. This parameter is meant to be set from the POM. + * + * @parameter + */ + private List pomExcludes = Collections.EMPTY_LIST; + + /** + * The comma-separated list of goals to execute on each project. Default is 'package'. + * + * @parameter + */ + private List goals = Collections.singletonList( "package" ); + + /** + * The name of the project-specific file that contains the enumeration of goals to execute for that test. + * + * @parameter expression="${invoker.goalsFile}" default-value="goals.txt" + */ + private String goalsFile; + + /** + * @component + */ + private Invoker invoker; + + /** + * relative path of a pre-build hook beanshell script to run prior to executing the build. + * + * @parameter expression="${invoker.preBuildHookScript}" default-value="prebuild.bsh" + */ + private String preBuildHookScript; + + /** + * relative path of a verification beanshell script to run after executing the build. + * + * @parameter expression="${invoker.verificationScript}" default-value="verify.bsh" + */ + private String verificationScript; + + /** + * Location of a properties file that defines CLI properties for the test. + * + * @parameter expression="${invoker.testPropertiesFile}" default-value="test.properties" + */ + private String testPropertiesFile; + + /** + * Whether to show errors in the build output. + * + * @parameter expression="${invoker.showErrors}" default-value="false" + */ + private boolean showErrors; + + /** + * Whether to show debug statements in the build output. + * + * @parameter expression="${invoker.debug}" default-value="false" + */ + private boolean debug; + + /** + * Suppress logging to the build.log file. + * + * @parameter expression="${invoker.noLog}" default-value="false" + */ + private boolean noLog; + + public void execute() + throws MojoExecutionException, MojoFailureException + { + String[] includedPoms; + try + { + includedPoms = getPoms(); + } + catch ( final IOException e ) + { + throw new MojoExecutionException( "Error retrieving POM list from includes, excludes, " + + "and IT directory. Reason: " + e.getMessage(), e ); + } + + if ( includedPoms == null || includedPoms.length < 1 ) + { + getLog().info( "No test-projects were selected for execution." ); + return; + } + + final List failures = new ArrayList(); + + for ( int i = 0; i < includedPoms.length; i++ ) + { + final String pom = includedPoms[i]; + + runBuild( pom, failures ); + } + + final StringBuffer summary = new StringBuffer(); + summary.append( "\n\n" ); + summary.append( "---------------------------------------\n" ); + summary.append( "Execution Summary:\n" ); + summary.append( "Builds Passing: " ).append( includedPoms.length - failures.size() ).append( "\n" ); + summary.append( "Builds Failing: " ).append( failures.size() ).append( "\n" ); + summary.append( "---------------------------------------\n" ); + + if ( !failures.isEmpty() ) + { + summary.append( "\nThe following builds failed:\n" ); + + for ( final Iterator it = failures.iterator(); it.hasNext(); ) + { + final String pom = ( String ) it.next(); + summary.append( "\n* " ).append( pom ); + } + + summary.append( "\n" ); + } + + getLog().info( summary.toString() ); + + if ( !failures.isEmpty() ) + { + throw new MojoFailureException( this, "One or more builds failed.", failures.size() + " builds failed." ); + } + } + + private void runBuild( final String pom, final List failures ) + throws MojoExecutionException + { + final File pomFile = new File( projectsDirectory, pom ); + final File basedir = pomFile.getParentFile(); + + getLog().info( "Building: " + basedir ); + + final File outputLog = new File( basedir, "target/build.log" ); + + FileLogger logger = null; + + try + { + if ( !noLog ) + { + outputLog.getParentFile().mkdirs(); + + try + { + logger = new FileLogger( outputLog ); + + getLog().debug( "build log initialized in: " + outputLog ); + } + catch ( final IOException e ) + { + getLog().debug( "Error initializing build logfile in: " + outputLog, e ); + getLog().info( "...FAILED[could not initialize logfile in: " + outputLog ); + + failures.add( pom ); + + return; + } + } + + if ( !prebuild( basedir, pom, failures, logger ) ) + { + getLog().info( "...FAILED[pre-build script returned false]" ); + + failures.add( pom ); + + return; + } + + final List invocationGoals = getGoals( basedir ); + + final InvocationRequest request = new DefaultInvocationRequest(); + + if ( invocationGoals.size() == 1 && "_default".equals( invocationGoals.get( 0 ) ) ) + { + getLog().debug( "Executing default goal for project in: " + pom ); + } + else + { + getLog().debug( "Executing goals: " + invocationGoals + " for project in: " + pom ); + + request.setGoals( invocationGoals ); + } + + try + { + final Properties testProperties = loadTestProperties( basedir ); + + request.setProperties( testProperties ); + } + catch ( final IOException e ) + { + getLog().debug( "Error reading test-properties file in: " + testPropertiesFile, e ); + getLog().info( "...FAILED[error reading test properties in: " + testPropertiesFile ); + + failures.add( pom ); + + return; + } + + if ( localRepositoryPath != null ) + { + File localRepoDir = new File( localRepositoryPath ); + + if ( !localRepoDir.isAbsolute() ) + { + localRepoDir = new File( basedir, localRepositoryPath ); + } + + getLog().debug( "Using local repository: " + localRepoDir ); + + request.setLocalRepositoryDirectory( localRepoDir ); + } + + request.setInteractive( false ); + + request.setShowErrors( showErrors ); + + request.setDebug( debug ); + + request.setBaseDirectory( basedir ); + + if ( !noLog ) + { + request.setErrorHandler( logger ); + + request.setOutputHandler( logger ); + } + + request.setPomFile( pomFile ); + + InvocationResult result = null; + + try + { + result = invoker.execute( request ); + } + catch ( final MavenInvocationException e ) + { + getLog().debug( "Error invoking Maven: " + e.getMessage(), e ); + getLog().info( "...FAILED[error invoking Maven]" ); + + failures.add( pom ); + } + + final CommandLineException executionException = result.getExecutionException(); + + if ( executionException != null ) + { + getLog().info( "...FAILED. See " + outputLog.getAbsolutePath() + " for details." ); + failures.add( pom ); + } + else if ( result.getExitCode() != 0 ) + { + getLog().info( + "...FAILED[code=" + result.getExitCode() + "]. See " + outputLog.getAbsolutePath() + + " for details." ); + + failures.add( pom ); + } + else if ( !verify( basedir, pom, failures, logger ) ) + { + getLog().info( "...FAILED[verify script returned false]." ); + + failures.add( pom ); + } + else + { + getLog().info( "...SUCCESS." ); + } + } + finally + { + if ( logger != null ) + { + logger.close(); + } + } + } + + private Properties loadTestProperties( final File basedir ) + throws IOException + { + final File testProperties = new File( basedir, testPropertiesFile ); + + final Properties testProps = new Properties(); + + if ( testProperties.exists() ) + { + FileInputStream fin = null; + try + { + fin = new FileInputStream( testProperties ); + + testProps.load( fin ); + } + finally + { + IOUtil.close( fin ); + } + } + + return testProps; + } + + private boolean verify( final File basedir, final String pom, final List failures, final FileLogger logger ) + { + boolean result = true; + + if ( verificationScript != null ) + { + try + { + result = runScript( "verification script", basedir, verificationScript, logger ); + } + catch ( final IOException e ) + { + result = false; + failures.add( pom ); + } + catch ( final EvalError e ) + { + result = false; + failures.add( pom ); + } + } + + return result; + } + + private boolean runScript( final String scriptDescription, final File basedir, final String relativeScriptPath, + final FileLogger logger ) + throws IOException, EvalError + { + final File script = new File( basedir, relativeScriptPath ); + + boolean scriptResult = false; + + if ( script.exists() ) + { + final Interpreter engine = new Interpreter(); + + if ( !noLog ) + { + logger.consumeLine( "Running " + scriptDescription + " in: " + script ); + + engine.setErr( logger.getPrintStream() ); + engine.setOut( logger.getPrintStream() ); + } + + FileReader reader = null; + try + { + engine.set( "basedir", basedir ); + + reader = new FileReader( script ); + + final Object result = engine.eval( reader ); + + scriptResult = Boolean.TRUE.equals( result ) || "true".equals( result ); + } + finally + { + IOUtil.close( reader ); + } + + if ( !noLog ) + { + logger.consumeLine( "Finished " + scriptDescription + " in: " + script ); + } + } + else + { + scriptResult = true; + } + + return scriptResult; + } + + private boolean prebuild( final File basedir, final String pom, final List failures, final FileLogger logger ) + { + boolean result = true; + + if ( preBuildHookScript != null ) + { + try + { + result = runScript( "pre-build script", basedir, preBuildHookScript, logger ); + } + catch ( final IOException e ) + { + result = false; + failures.add( pom ); + } + catch ( final EvalError e ) + { + result = false; + failures.add( pom ); + } + } + + return result; + } + + private List getGoals( final File basedir ) + { + List invocationGoals = goals; + + if ( goalsFile != null ) + { + final File projectGoalList = new File( basedir, goalsFile ); + + if ( projectGoalList.exists() ) + { + final List goals = readFromFile( projectGoalList ); + + if ( goals != null && !goals.isEmpty() ) + { + getLog().info( "Using goals specified in file: " + projectGoalList ); + invocationGoals = goals; + } + } + } + + return invocationGoals; + } + + private String[] getPoms() + throws IOException + { + final FileSet fs = new FileSet(); + + fs.setIncludes( pomIncludes ); + fs.setExcludes( pomExcludes ); + fs.setDirectory( projectsDirectory.getCanonicalPath() ); + fs.setFollowSymlinks( false ); + fs.setUseDefaultExcludes( false ); + + final FileSetManager fsm = new FileSetManager( getLog() ); + + return fsm.getIncludedFiles( fs ); + } + + private List readFromFile( final File projectGoalList ) + { + BufferedReader reader = null; + + List result = null; + + try + { + reader = new BufferedReader( new FileReader( projectGoalList ) ); + + result = new ArrayList(); + + String line = null; + while ( ( line = reader.readLine() ) != null ) + { + result.addAll( collectListFromCSV( line ) ); + } + } + catch ( final IOException e ) + { + getLog().warn( + "Failed to load goal list from file: " + projectGoalList + + ". Using 'goal' parameter configured on this plugin instead." ); + getLog().debug( "Error reading goals file: " + projectGoalList, e ); + } + finally + { + if ( reader != null ) + { + try + { + reader.close(); + } + catch ( final IOException e ) + { + } + } + } + + return result; + } + + private List collectListFromCSV( final String csv ) + { + final List result = new ArrayList(); + + if ( csv != null && csv.trim().length() > 0 ) + { + final StringTokenizer st = new StringTokenizer( csv, "," ); + + while ( st.hasMoreTokens() ) + { + result.add( st.nextToken().trim() ); + } + } + + return result; + } + +} diff --git a/test-with-goals-file/pom.xml b/test-with-goals-file/pom.xml new file mode 100644 index 0000000..de078fd --- /dev/null +++ b/test-with-goals-file/pom.xml @@ -0,0 +1,29 @@ +<model + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" +> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven</groupId> + <artifactId>it-plugin-test</artifactId> + <version>1.0-alpha-1-SNAPSHOT</version> + + <build> + <plugins> + <plugin> + <artifactId>maven-invoker-plugin</artifactId> + <configuration> + <projectsDirectory>src/it</projectsDirectory> + </configuration> + <executions> + <execution> + <phase>integration-test</phase> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</model> diff --git a/test-with-goals-file/src/it/test1/goals.txt b/test-with-goals-file/src/it/test1/goals.txt new file mode 100644 index 0000000..582d972 --- /dev/null +++ b/test-with-goals-file/src/it/test1/goals.txt @@ -0,0 +1 @@ +compile diff --git a/test-with-goals-file/src/it/test1/pom.xml b/test-with-goals-file/src/it/test1/pom.xml new file mode 100644 index 0000000..47ec380 --- /dev/null +++ b/test-with-goals-file/src/it/test1/pom.xml @@ -0,0 +1,6 @@ +<project> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven.plugins.it.tests</groupId> + <artifactId>test1</artifactId> + <version>1.0</version> +</project> -- To stop receiving notification emails like this one, please contact "commits@maven.apache.org" <commits@maven.apache.org>.