diff options
Diffstat (limited to 'sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build')
6 files changed, 982 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/DISCLAIMER b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software
+Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is
+required of all newly accepted projects until a further review indicates that
+the infrastructure, communications, and decision making process have stabilized
+in a manner consistent with other successful ASF projects. While incubation
+status is not necessarily a reflection of the completeness or stability of the
+code, it does indicate that the project has yet to be fully endorsed by the ASF.
+
diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/LICENSE b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/NOTICE b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/pom.xml b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/pom.xml new file mode 100644 index 0000000000..a4bb5d55ea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/pom.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-maven-tools</artifactId> + <version>1.1-incubating-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-maven-incremental-build</artifactId> + <packaging>maven-plugin</packaging> + <name>Apache Tuscany SCA Incremental Build Generator Maven Plugin</name> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-settings</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>2.0.5</version> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-invoker</artifactId> + <version>2.0.7</version> + </dependency> + + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-api</artifactId> + <version>1.5.3</version> + </dependency> + + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-manager</artifactId> + <version>1.5.3</version> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-javac</artifactId> + <version>1.5.3</version> + <scope>runtime</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>LATEST</version> + <configuration> + <goalPrefix>incremental</goalPrefix> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/AbstractBuildMojo.java b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/AbstractBuildMojo.java new file mode 100644 index 0000000000..576fd47d96 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/AbstractBuildMojo.java @@ -0,0 +1,459 @@ +package org.apache.tuscany.sca.tools.incremental.build.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +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.codehaus.plexus.compiler.Compiler; +import org.codehaus.plexus.compiler.CompilerConfiguration; +import org.codehaus.plexus.compiler.CompilerException; +import org.codehaus.plexus.compiler.CompilerOutputStyle; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.codehaus.plexus.compiler.manager.NoSuchCompilerException; +import org.codehaus.plexus.compiler.util.scan.InclusionScanException; +import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner; +import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner; +import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner; +import org.codehaus.plexus.compiler.util.scan.mapping.SingleTargetSourceMapping; +import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping; +import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping; +import org.codehaus.plexus.util.DirectoryScanner; + +/** + * @version $Id: StaleSourceScannerTest.java 2393 2005-08-08 22:32:59Z kenney $ + */ +public abstract class AbstractBuildMojo extends AbstractMojo { + // ---------------------------------------------------------------------- + // Configurables + // ---------------------------------------------------------------------- + + /** + * The -source argument for the Java compiler. + * + * @parameter expression="${maven.compiler.source}" + * @readonly + */ + private String source; + + /** + * The -target argument for the Java compiler. + * + * @parameter expression="${maven.compiler.target}" + * @readonly + */ + private String target; + + /** + * The -encoding argument for the Java compiler. + * + * @parameter expression="${maven.compiler.encoding}" + * @readonly + */ + private String encoding; + + /** + * Sets the granularity in milliseconds of the last modification + * date for testing whether a source needs recompilation. + * + * @parameter expression="${lastModGranularityMs}" default-value="0" + * + */ + private int staleMillis; + + /** + * The compiler id of the compiler to use. See this + * <a href="non-javac-compilers.html">guide</a> for more information. + * + * @parameter expression="${maven.compiler.compilerId}" default-value="javac" + * @readonly + */ + private String compilerId; + + /** + * Version of the compiler to use, ex. "1.3", "1.5", if fork is set to true. + * + * @parameter expression="${maven.compiler.compilerVersion}" + * @readonly + */ + private String compilerVersion; + + /** + * Sets the executable of the compiler to use when fork is true. + * + * @parameter expression="${maven.compiler.executable}" + * @readonly + */ + private String executable; + + /** + * The directory to run the compiler from if fork is true. + * + * @parameter expression="${basedir}" + * @required + * @readonly + */ + protected File basedir; + + /** + * The target directory of the compiler if fork is true. + * + * @parameter expression="${project.build.directory}" + * @required + * @readonly + */ + private File buildDirectory; + + /** + * Plexus compiler manager. + * + * @component + * @readonly + */ + private CompilerManager compilerManager; + + /** + * The project to create a build for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + protected MavenProject project; + + protected SourceInclusionScanner getSourceInclusionScanner(int staleMillis) { + return new StaleSourceScanner(staleMillis); + } + + protected SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding) { + Set includes = Collections.singleton("**/*." + inputFileEnding); + return new SimpleSourceInclusionScanner(includes, Collections.EMPTY_SET); + } + + protected boolean isPOMChanged() { + File pom = project.getFile(); + File out = getOutputFile(); + return pom.lastModified() > out.lastModified(); + } + + protected 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 the resources have been changed + * @return + * @throws MojoExecutionException + */ + protected boolean isResourceChanged() throws MojoExecutionException { + return isChanged(project.getResources(), project.getBuild().getOutputDirectory()); + } + + protected boolean isTestResourceChanged() throws MojoExecutionException { + return isChanged(project.getTestResources(), project.getBuild().getTestOutputDirectory()); + } + + private static final String[] EMPTY_STRING_ARRAY = {}; + + private static final String[] DEFAULT_INCLUDES = {"**/**"}; + + /** + * Test if any of the resources have been changed + * @param resources + * @param outputDirectory + * @return + * @throws MojoExecutionException + */ + protected boolean isChanged(List resources, String outputDirectory) throws MojoExecutionException { + + for (Iterator i = resources.iterator(); i.hasNext();) { + Resource resource = (Resource)i.next(); + + String targetPath = resource.getTargetPath(); + + File resourceDirectory = new File(resource.getDirectory()); + + if (!resourceDirectory.exists()) { + continue; + } + + // this part is required in case the user specified "../something" as destination + // see MNG-1345 + File outputDir = new File(outputDirectory); + if (!outputDir.exists()) { + return true; + } + + DirectoryScanner scanner = new DirectoryScanner(); + + scanner.setBasedir(resource.getDirectory()); + if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) { + scanner.setIncludes((String[])resource.getIncludes().toArray(EMPTY_STRING_ARRAY)); + } else { + scanner.setIncludes(DEFAULT_INCLUDES); + } + if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) { + scanner.setExcludes((String[])resource.getExcludes().toArray(EMPTY_STRING_ARRAY)); + } + + scanner.addDefaultExcludes(); + scanner.scan(); + + List includedFiles = Arrays.asList(scanner.getIncludedFiles()); + for (Iterator j = includedFiles.iterator(); j.hasNext();) { + String name = (String)j.next(); + + String destination = name; + + if (targetPath != null) { + destination = targetPath + "/" + name; + } + + File source = new File(resource.getDirectory(), name); + + File destinationFile = new File(outputDirectory, destination); + + if (!destinationFile.exists()) { + return true; + } else { + if (source.lastModified() > destinationFile.lastModified()) { + return true; + } + } + } + } + return false; + } + + protected boolean isSourceChanged(Compiler compiler) throws MojoExecutionException { + try { + List sourceRoots = project.getCompileSourceRoots(); + File outputDir = new File(project.getBuild().getOutputDirectory()); + List classPathEntries = project.getCompileClasspathElements(); + return isChanged(compiler, sourceRoots, classPathEntries, outputDir); + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + protected boolean isTestSourceChanged(Compiler compiler) throws MojoExecutionException { + try { + List sourceRoots = project.getTestCompileSourceRoots(); + File outputDir = new File(project.getBuild().getTestOutputDirectory()); + List classPathEntries = project.getTestClasspathElements(); + return isChanged(compiler, sourceRoots, classPathEntries, outputDir); + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + public boolean isChanged(Compiler compiler, List sourceRoots, List classPathEntries, File outputDir) + throws MojoExecutionException { + List compileSourceRoots = removeEmptyCompileSourceRoots(sourceRoots); + + if (compileSourceRoots.isEmpty()) { + // getLog().info("No sources to compile"); + return false; + } + + // ---------------------------------------------------------------------- + // Create the compiler configuration + // ---------------------------------------------------------------------- + + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + + compilerConfiguration.setOutputLocation(outputDir.getAbsolutePath()); + + compilerConfiguration.setClasspathEntries(classPathEntries); + + compilerConfiguration.setSourceLocations(compileSourceRoots); + + compilerConfiguration.setOptimize(false); + + compilerConfiguration.setDebug(true); + + compilerConfiguration.setVerbose(false); + + compilerConfiguration.setShowWarnings(false); + + compilerConfiguration.setShowDeprecation(true); + + compilerConfiguration.setSourceVersion(source); + + compilerConfiguration.setTargetVersion(target); + + compilerConfiguration.setSourceEncoding(encoding); + + compilerConfiguration.setExecutable(executable); + + compilerConfiguration.setWorkingDirectory(basedir); + + compilerConfiguration.setCompilerVersion(compilerVersion); + + compilerConfiguration.setBuildDirectory(buildDirectory); + + compilerConfiguration.setOutputFileName(project.getBuild().getFinalName()); + + // TODO: have an option to always compile (without need to clean) + Set staleSources; + + boolean canUpdateTarget; + + try { + staleSources = + computeStaleSources(compilerConfiguration, + compiler, + getSourceInclusionScanner(staleMillis), + sourceRoots, + outputDir); + + canUpdateTarget = compiler.canUpdateTarget(compilerConfiguration); + + if (compiler.getCompilerOutputStyle().equals(CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES) && !canUpdateTarget) { + getLog().info("RESCANNING!"); + // TODO: This second scan for source files is sub-optimal + String inputFileEnding = compiler.getInputFileEnding(compilerConfiguration); + + Set sources = + computeStaleSources(compilerConfiguration, + compiler, + getSourceInclusionScanner(inputFileEnding), + sourceRoots, + outputDir); + + compilerConfiguration.setSourceFiles(sources); + } else { + compilerConfiguration.setSourceFiles(staleSources); + } + } catch (CompilerException e) { + throw new MojoExecutionException("Error while computing stale sources.", e); + } + + return !staleSources.isEmpty(); + + } + + protected Compiler getCompiler() throws MojoExecutionException { + Compiler compiler; + + getLog().debug("Using compiler '" + compilerId + "'."); + + try { + compiler = compilerManager.getCompiler(compilerId); + } catch (NoSuchCompilerException e) { + throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'."); + } + return compiler; + } + + protected Set computeStaleSources(CompilerConfiguration compilerConfiguration, + Compiler compiler, + SourceInclusionScanner scanner, + List sourceRoots, + File outputDir) throws MojoExecutionException, CompilerException { + CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle(); + + SourceMapping mapping; + + File outputDirectory; + + if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE) { + mapping = + new SuffixMapping(compiler.getInputFileEnding(compilerConfiguration), compiler + .getOutputFileEnding(compilerConfiguration)); + + outputDirectory = outputDir; + } else if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES) { + mapping = + new SingleTargetSourceMapping(compiler.getInputFileEnding(compilerConfiguration), compiler + .getOutputFile(compilerConfiguration)); + + outputDirectory = buildDirectory; + } else { + throw new MojoExecutionException("Unknown compiler output style: '" + outputStyle + "'."); + } + + scanner.addSourceMapping(mapping); + + Set staleSources = new HashSet(); + + for (Iterator it = sourceRoots.iterator(); it.hasNext();) { + String sourceRoot = (String)it.next(); + + File rootFile = new File(sourceRoot); + + if (!rootFile.isDirectory()) { + continue; + } + + try { + Set changed = scanner.getIncludedSources(rootFile, outputDirectory); + staleSources.addAll(changed); + } catch (InclusionScanException e) { + throw new MojoExecutionException("Error scanning source root: \'" + sourceRoot + + "\' " + + "for stale files to recompile.", e); + } + } + + return staleSources; + } + + /** + * @todo also in ant plugin. This should be resolved at some point so that it does not need to + * be calculated continuously - or should the plugins accept empty source roots as is? + */ + private static List removeEmptyCompileSourceRoots(List compileSourceRootsList) { + List newCompileSourceRootsList = new ArrayList(); + if (compileSourceRootsList != null) { + // copy as I may be modifying it + for (Iterator i = compileSourceRootsList.iterator(); i.hasNext();) { + String srcDir = (String)i.next(); + if (!newCompileSourceRootsList.contains(srcDir) && new File(srcDir).exists()) { + newCompileSourceRootsList.add(srcDir); + } + } + } + return newCompileSourceRootsList; + } +} diff --git a/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java new file mode 100644 index 0000000000..17fe2dfddb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.tools.incremental.build.plugin; + +import java.util.ArrayList; +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.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; +import org.apache.maven.shared.invoker.DefaultInvocationRequest; +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.cli.CommandLineException; + +/** + * @version $Rev$ $Date$ + * @goal build + * @phase validate + * @requiresDependencyResolution test + * @description Incrementally build project modules that depend on modified modules. + */ +public class IncrementalBuildMojo extends AbstractBuildMojo { + /** + * 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; + /** + * Used to invoke Maven builds. + * + * @component + */ + private Invoker invoker; + + /** + * The local repository where the artifacts are located + * + * @parameter expression="${localRepository}" + * @required + */ + private ArtifactRepository localRepository; + + /** + * @parameter expression="${settings}" + * @required + * @readonly + */ + protected Settings settings; + + public void execute() throws MojoExecutionException { + getLog().info("Building " + project.getName() + " [" + project.getId() + "]"); + List<String> goals = new ArrayList<String>(); + String type = project.getArtifact().getType(); + if ("pom".equals(type)) { + goals.add("install"); + } else { + String projectID = id(project); + + Compiler compiler = getCompiler(); + boolean changed = isSourceChanged(compiler) || isResourceChanged() || isPOMChanged(); + boolean testChanged = false; + if (changed) { + modifiedProjectIDs.add(projectID); + } else { + testChanged = isTestSourceChanged(compiler) || isTestResourceChanged(); + } + + // 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"); + } 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."); + goals.add("clean"); + goals.add("install"); + break; + } + } + + if (goals.isEmpty()) { + List<Artifact> artifacts = new ArrayList<Artifact>(); + artifacts.addAll(project.getRuntimeArtifacts()); + artifacts.addAll(project.getTestArtifacts()); + 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."); + goals.add("test"); + break; + } + } + } + } + + if (testChanged && goals.isEmpty()) { + goals.add("test"); + } + } + + // Invoke Maven with the necessary goals + if (!goals.isEmpty()) { + DefaultInvocationRequest request = new DefaultInvocationRequest(); + request.setGoals(goals); + // FIXME: The maven invoker doesn't handle the directory names with spaces + // request.setLocalRepositoryDirectory(new File(localRepository.getBasedir())); + request.setInteractive(false); + request.setShowErrors(true); + request.setRecursive(false); + // request.setDebug(true); + request.setOffline(settings.isOffline()); + request.setBaseDirectory(project.getBasedir()); + request.setPomFile(project.getFile()); + + 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); + } + } catch (MavenInvocationException e) { + e.printStackTrace(); + throw new MojoExecutionException(e.getMessage(), e); + } + } else { + getLog().info("The project is up-to-date. No build is required."); + } + } + +} |