Author: jsdelfino
Date: Mon Jan 28 23:27:34 2008
New Revision: 616190
URL: http://svn.apache.org/viewvc?rev=616190&view=rev
Log:
Simplified the incremental build plugin and made it more reliable. Removed all
the complicated code that was trying to detect stale sources. Handle the case
where an IDE has compiled the Java sources but the output archive is outdated.
Keep track of failed tests using a .test marker file and re-execute the tests
on subsequent builds.
Removed:
incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/AbstractBuildMojo.java
Modified:
incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java
Modified:
incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java
URL:
http://svn.apache.org/viewvc/incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java?rev=616190&r1=616189&r2=616190&view=diff
==============================================================================
---
incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java
(original)
+++
incubator/tuscany/java/sca/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java
Mon Jan 28 23:27:34 2008
@@ -19,13 +19,16 @@
package org.apache.tuscany.sca.tools.incremental.build.plugin;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
@@ -33,7 +36,7 @@
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.MavenInvocationException;
-import org.codehaus.plexus.compiler.Compiler;
+import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.cli.CommandLineException;
/**
@@ -43,38 +46,22 @@
* @requiresDependencyResolution test
* @description Incrementally build project modules that depend on modified
modules.
*/
-public class IncrementalBuildMojo extends AbstractBuildMojo {
+public class IncrementalBuildMojo extends AbstractMojo {
+
/**
* Keep track of modified projects.
*/
private static Set<String> modifiedProjectIDs = new HashSet<String>();
/**
- * Returns the qualified id of an artifact .
- * @param p a Maven artifact
- * @return a qualified id
- */
- private static String id(Artifact a) {
- return a.getGroupId() + ':' + a.getArtifactId();
- }
-
- /**
- * Returns the qualified id of a project.
- * @param p a Maven project
- * @return a qualified id
- */
- private static String id(MavenProject p) {
- return p.getGroupId() + ':' + p.getArtifactId();
- }
-
- /**
* The current user system settings for use in Maven.
*
* @parameter expression="${settings}"
* @required
* @readonly
*/
- // private Settings settings;
+ private Settings settings;
+
/**
* Used to invoke Maven builds.
*
@@ -83,60 +70,69 @@
private Invoker invoker;
/**
- * The local repository where the artifacts are located
+ * The target directory of the compiler if fork is true.
*
- * @parameter expression="${localRepository}"
+ * @parameter expression="${project.build.directory}"
* @required
+ * @readonly
*/
- private ArtifactRepository localRepository;
+ private File buildDirectory;
/**
- * @parameter expression="${settings}"
+ * The project to create a build for.
+ *
+ * @parameter expression="${project}"
* @required
* @readonly
*/
- protected Settings settings;
+ private MavenProject project;
+
+ private File outputFile;
public void execute() throws MojoExecutionException {
- getLog().info("Building " + project.getName() + " [" + project.getId()
+ "]");
+ String projectID = id(project);
+ outputFile = getOutputFile();
+
+ File testMarkerFile = new File(project.getBasedir().getPath() +
"/.test");
+
List<String> goals = new ArrayList<String>();
String type = project.getArtifact().getType();
if ("pom".equals(type)) {
+
+ // Always install pom modules
goals.add("install");
+
} else {
- String projectID = id(project);
- Compiler compiler = getCompiler();
+ // Check if anything has changed in the project
boolean changed = false;
boolean testChanged = false;
- String marker = project.getBasedir().getPath() + "/.modified";
- if (new File(marker).exists()) {
- getLog().info("Project: " + projectID + " has been modified.");
+ boolean testFailed = false;
+ if (new File(project.getBasedir().getPath() +
"/.modified").exists()) {
+ getLog().info("Found .modified marker file.");
changed = true;
} else {
- changed = isSourceChanged(compiler) || isResourceChanged() ||
isPOMChanged();
+ changed = areSourcesStale() || areResourcesStale() ||
isPOMStale();
}
if (changed) {
modifiedProjectIDs.add(projectID);
} else {
- testChanged = isTestSourceChanged(compiler) ||
isTestResourceChanged();
+ testChanged = areTestSourcesStale() || areTestResourcesStale();
}
-
+
// Check if a project has compile dependencies on the modified
projects
// and will need to be recompiled, or has runtime or test
dependencies
// on the modified projects and needs to be retested
-
if (changed) {
goals.add("clean");
goals.add("install");
+ getLog().info("Project " + projectID + " has changed and will
be recompiled.");
+
} else {
for (Artifact artifact :
(List<Artifact>)project.getCompileArtifacts()) {
String artifactID = id(artifact);
if (modifiedProjectIDs.contains(artifactID)) {
- getLog().info("Project " + projectID
- + " depends on modified project "
- + artifactID
- + " and will be recompiled.");
+ getLog().info("Project " + projectID + " depends on
modified project " + artifactID + " and will be recompiled.");
goals.add("clean");
goals.add("install");
break;
@@ -150,10 +146,7 @@
for (Artifact artifact : artifacts) {
String artifactID = id(artifact);
if (modifiedProjectIDs.contains(artifactID)) {
- getLog().info("Project " + projectID
- + " depends on modified project "
- + artifactID
- + " and will be retested.");
+ getLog().info("Project " + projectID + " depends
on modified project " + artifactID + " and will be retested.");
goals.add("test");
break;
}
@@ -162,8 +155,17 @@
}
if (testChanged && goals.isEmpty()) {
+ getLog().info("Project " + projectID + " has changed and will
be retested.");
goals.add("test");
}
+
+ if (goals.isEmpty()) {
+ if (testMarkerFile.exists()) {
+ testFailed = true;
+ getLog().info("Project " + projectID + " contains failed
tests and will be retested.");
+ goals.add("test");
+ }
+ }
}
// Invoke Maven with the necessary goals
@@ -180,25 +182,229 @@
request.setBaseDirectory(project.getBasedir());
request.setPomFile(project.getFile());
+ boolean success = false;
try {
- InvocationResult result = invoker.execute(request);
-
- CommandLineException cle = result.getExecutionException();
- if (cle != null) {
- throw new MojoExecutionException(cle.getMessage(), cle);
+ try {
+ InvocationResult result = invoker.execute(request);
+
+ CommandLineException cle = result.getExecutionException();
+ if (cle != null) {
+ throw new MojoExecutionException(cle.getMessage(),
cle);
+ }
+
+ int ec = result.getExitCode();
+ if (ec != 0) {
+ throw new MojoExecutionException("Maven invocation
exit code: " + ec);
+ }
+
+ success = true;
+
+
+
+ } catch (MavenInvocationException e) {
+ throw new MojoExecutionException(e.getMessage(), e);
}
-
- int ec = result.getExitCode();
- if (ec != 0) {
- throw new MojoExecutionException("Maven invocation exit
code: " + ec);
+ } finally {
+
+ // Create or delete a .test marker file to keep track of the
latest
+ // test result status and trigger testing again next time the
build
+ // is run
+ if (!success) {
+ try {
+ if (!testMarkerFile.exists()) {
+ testMarkerFile.createNewFile();
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+ } else {
+ if (testMarkerFile.exists()) {
+ testMarkerFile.delete();
+ }
}
- } catch (MavenInvocationException e) {
- e.printStackTrace();
- throw new MojoExecutionException(e.getMessage(), e);
}
} else {
getLog().info("The project is up-to-date. No build is required.");
}
}
+ private File getOutputFile() {
+ File basedir = buildDirectory;
+ String finalName = project.getBuild().getFinalName();
+ String classifier = project.getArtifact().getClassifier();
+ if (classifier == null) {
+ classifier = "";
+ } else if (classifier.trim().length() > 0 &&
!classifier.startsWith("-")) {
+ classifier = "-" + classifier;
+ }
+
+ String pkg = project.getPackaging();
+ if ("maven-plugin".equals(pkg)) {
+ pkg = "jar";
+ }
+ return new File(basedir, finalName + classifier + "." + pkg);
+ }
+
+ /**
+ * Test if any of the resources are stale
+ * @param resources
+ * @param outputDirectory
+ * @return
+ * @throws MojoExecutionException
+ */
+ private boolean areStale(List<Resource> resources, String outputDirectory)
throws MojoExecutionException {
+
+ for (Resource resource: resources) {
+
+ File resourceDirectory = new File(resource.getDirectory());
+ if (!resourceDirectory.exists()) {
+ continue;
+ }
+
+ DirectoryScanner scanner = new DirectoryScanner();
+
+ scanner.setBasedir(resource.getDirectory());
+ if (resource.getIncludes() != null &&
!resource.getIncludes().isEmpty()) {
+
scanner.setIncludes((String[])resource.getIncludes().toArray(new String[]{}));
+ } else {
+ scanner.setIncludes(new String[]{"**/**"});
+ }
+ if (resource.getExcludes() != null &&
!resource.getExcludes().isEmpty()) {
+
scanner.setExcludes((String[])resource.getExcludes().toArray(new String[]{}));
+ }
+
+ scanner.addDefaultExcludes();
+ scanner.scan();
+
+ List<String> includedFiles =
Arrays.asList(scanner.getIncludedFiles());
+ String targetPath = resource.getTargetPath();
+ for (String source: includedFiles) {
+ String target;
+ if (source.endsWith(".java")) {
+ target = source.substring(0, source.length() - 5) +
".class";
+ } else {
+ target = source;
+ }
+
+ String destination;
+ if (targetPath != null) {
+ destination = targetPath + "/" + target;
+ } else {
+ destination = target;
+ }
+
+ File sourceFile = new File(resource.getDirectory(), source);
+ File destinationFile = new File(outputDirectory, destination);
+
+ if (!destinationFile.exists()) {
+ getLog().info("Target file " + destinationFile + " could
not be found.");
+ return true;
+ } else {
+ if (sourceFile.lastModified() >
destinationFile.lastModified()) {
+ getLog().info("Target file " + destinationFile + " is
stale.");
+ return true;
+ } else if (sourceFile.lastModified() >
outputFile.lastModified()) {
+ getLog().info("Target build output file " + outputFile
+ " is stale.");
+ return true;
+ } else if (outputFile.lastModified() == 0) {
+ getLog().info("Target build output file " + outputFile
+ " could not be found.");
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if the POM resource is stale.
+ *
+ * @return
+ */
+ private boolean isPOMStale() {
+ File pom = project.getFile();
+ if (pom.lastModified() > outputFile.lastModified()) {
+ getLog().info("File " + pom + " is stale.");
+ return true;
+ } else if (outputFile.lastModified() == 0) {
+ getLog().info("Target build output file " + outputFile + " could
not be found.");
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Test if the project resources are stale.
+ *
+ * @return
+ * @throws MojoExecutionException
+ */
+ private boolean areResourcesStale() throws MojoExecutionException {
+ return areStale(project.getResources(),
project.getBuild().getOutputDirectory());
+ }
+
+ /**
+ * Test if the project sources are stale.
+ *
+ * @return
+ * @throws MojoExecutionException
+ */
+ private boolean areSourcesStale() throws MojoExecutionException {
+ List<Resource> resources = new ArrayList<Resource>();
+ for (String root: (List<String>)project.getCompileSourceRoots()) {
+ if (new File(root).exists()) {
+ Resource resource = new Resource();
+ resource.setDirectory(root);
+ resources.add(resource);
+ }
+ }
+ return areStale(resources, project.getBuild().getOutputDirectory());
+ }
+
+ /**
+ * Tests if the project test resources are stale.
+ *
+ * @return
+ * @throws MojoExecutionException
+ */
+ private boolean areTestResourcesStale() throws MojoExecutionException {
+ return areStale(project.getTestResources(),
project.getBuild().getTestOutputDirectory());
+ }
+
+ /**
+ * Tests if the project test sources are stale.
+ *
+ * @return
+ * @throws MojoExecutionException
+ */
+ private boolean areTestSourcesStale() throws MojoExecutionException {
+ List<Resource> resources = new ArrayList<Resource>();
+ for (String root: (List<String>)project.getTestCompileSourceRoots()) {
+ if (new File(root).exists()) {
+ Resource resource = new Resource();
+ resource.setDirectory(root);
+ resources.add(resource);
+ }
+ }
+ return areStale(resources,
project.getBuild().getTestOutputDirectory());
+ }
+
+ /**
+ * Returns the qualified id of a Maven artifact .
+ * @param p a Maven artifact
+ * @return a qualified id
+ */
+ private static String id(Artifact a) {
+ return a.getGroupId() + ':' + a.getArtifactId();
+ }
+
+ /**
+ * Returns the qualified id of a Maven project.
+ * @param p a Maven project
+ * @return a qualified id
+ */
+ private static String id(MavenProject p) {
+ return p.getGroupId() + ':' + p.getArtifactId();
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]