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]

Reply via email to