All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bluestemsoftware.open.eoa.plugin.compile.AbstractCompilerMojo Maven / Gradle / Ivy

Go to download

Defines goals for building, testing and installing your alakai extension projects.

The newest version!
/**
 * Copyright 2008 Bluestem Software LLC.  All Rights Reserved.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */

package org.bluestemsoftware.open.eoa.plugin.compile;

/*
 * Adapted from org.apache.maven.plugin.CompilerMojo which was released under the following
 * license:
 * 

* 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 java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.maven.plugin.MojoExecutionException; import org.bluestemsoftware.open.eoa.plugin.AbstractDeploymentMojo; import org.bluestemsoftware.open.eoa.plugin.util.FileFilterImpl; import org.codehaus.plexus.compiler.Compiler; import org.codehaus.plexus.compiler.CompilerConfiguration; import org.codehaus.plexus.compiler.CompilerError; 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.StringUtils; public abstract class AbstractCompilerMojo extends AbstractDeploymentMojo { /** * Indicates whether the build will continue even if there are compilation errors; defaults * to true. * * @parameter expression="${maven.compiler.failOnError}" default-value="true" */ protected boolean failOnError = true; /** * Set to true to include debugging information in the compiled class files. * * @parameter expression="${maven.compiler.debug}" default-value="true" */ protected boolean debug = true; /** * Set to true to show messages about what the compiler is doing. * * @parameter expression="${maven.compiler.verbose}" default-value="false" */ protected boolean verbose; /** * Sets whether to show source locations where deprecated APIs are used. * * @parameter expression="${maven.compiler.showDeprecation}" default-value="false" */ protected boolean showDeprecation; /** * Set to true to optimize the compiled code using the compiler's optimization methods. * * @parameter expression="${maven.compiler.optimize}" default-value="false" */ protected boolean optimize; /** * Set to true to show compilation warnings. * * @parameter expression="${maven.compiler.showWarnings}" default-value="false" */ protected boolean showWarnings; /** * The -source argument for the Java compiler. * * @parameter expression="${maven.compiler.source}" default-value="1.5" */ protected String source; /** * The -target argument for the Java compiler. * * @parameter expression="${maven.compiler.target}" default-value="1.5" */ protected String target; /** * The -encoding argument for the Java compiler. * * @parameter expression="${maven.compiler.encoding}" */ protected 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" */ protected int staleMillis; /** * The compiler id of the compiler to use. See this guide for more information. * * @parameter expression="${maven.compiler.compilerId}" default-value="javac" */ protected String compilerId; /** * Version of the compiler to use, ex. "1.3", "1.5", if fork is set to true. * * @parameter expression="${maven.compiler.compilerVersion}" */ protected String compilerVersion; /** * Allows running the compiler in a separate process. If "false" it uses the built in * compiler, while if "true" it will use an executable. * * @parameter default-value="false" */ protected boolean fork; /** * Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m" if fork is * set to true. * * @parameter expression="${maven.compiler.meminitial}" */ protected String meminitial; /** * Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m" if * fork is set to true. * * @parameter expression="${maven.compiler.maxmem}" */ protected String maxmem; /** * Sets the executable of the compiler to use when fork is true. * * @parameter expression="${maven.compiler.executable}" */ protected String executable; /** *

* Sets the arguments to be passed to the compiler (prepending a dash) if fork is set to * true. *

*

* This is because the list of valid arguments passed to a Java compiler varies based on * the compiler version. *

* * @parameter */ protected Map compilerArguments; /** *

* Sets the unformatted argument string to be passed to the compiler if fork is set to * true. *

*

* This is because the list of valid arguments passed to a Java compiler varies based on * the compiler version. *

* * @parameter */ protected String compilerArgument; /** * Sets the name of the output file when compiling a set of sources to a single file. * * @parameter expression="${project.build.finalName}" */ protected String outputFileName; /** * Plexus compiler manager. * * @component */ protected CompilerManager compilerManager; /** * Project test classpath. * * @parameter expression="${project.testClasspathElements}" * @required * @readonly */ protected List testClasspathElements; /** * A list of inclusion filters for the compiler. * * @parameter */ protected Set testIncludes = new HashSet(); /** * A list of exclusion filters for the compiler. * * @parameter */ protected Set testExcludes = new HashSet(); @SuppressWarnings("unchecked") public void execute() throws MojoExecutionException, CompilationFailureException { // ---------------------------------------------------------------------- // Look up the compiler. This is done before other code than can // cause the mojo to return before the lookup is done possibly resulting // in misconfigured POMs still building. // ---------------------------------------------------------------------- Compiler compiler; getLog().debug("Using compiler '" + compilerId + "'."); try { compiler = compilerManager.getCompiler(compilerId); } catch (NoSuchCompilerException e) { throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'."); } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- List compileSourceRoots = removeEmptyCompileSourceRoots(getCompileSourceRoots()); if (compileSourceRoots.isEmpty()) { getLog().info("No sources to compile"); return; } // ---------------------------------------------------------------------- // Create the compiler configuration // ---------------------------------------------------------------------- CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); compilerConfiguration.setOutputLocation(getOutputDirectory().getAbsolutePath()); compilerConfiguration.setClasspathEntries(getClasspathElements()); compilerConfiguration.setSourceLocations(compileSourceRoots); compilerConfiguration.setOptimize(optimize); compilerConfiguration.setDebug(debug); compilerConfiguration.setVerbose(verbose); compilerConfiguration.setShowWarnings(showWarnings); compilerConfiguration.setShowDeprecation(showDeprecation); compilerConfiguration.setSourceVersion(source); compilerConfiguration.setTargetVersion(target); compilerConfiguration.setSourceEncoding(encoding); if ((compilerArguments != null) || (compilerArgument != null)) { LinkedHashMap cplrArgsCopy = new LinkedHashMap(); if (compilerArguments != null) { for (Iterator i = compilerArguments.entrySet().iterator(); i.hasNext();) { Map.Entry me = (Map.Entry)i.next(); String key = (String)me.getKey(); String value = (String)me.getValue(); if (!key.startsWith("-")) { key = "-" + key; } cplrArgsCopy.put(key, value); } } if (!StringUtils.isEmpty(compilerArgument)) { cplrArgsCopy.put(compilerArgument, null); } compilerConfiguration.setCustomCompilerArguments(cplrArgsCopy); } compilerConfiguration.setFork(fork); if (fork) { if (!StringUtils.isEmpty(meminitial)) { String value = getMemoryValue(meminitial); if (value != null) { compilerConfiguration.setMeminitial(value); } else { getLog().info("Invalid value for meminitial '" + meminitial + "'. Ignoring this option."); } } if (!StringUtils.isEmpty(maxmem)) { String value = getMemoryValue(maxmem); if (value != null) { compilerConfiguration.setMaxmem(value); } else { getLog().info("Invalid value for maxmem '" + maxmem + "'. Ignoring this option."); } } } compilerConfiguration.setExecutable(executable); compilerConfiguration.setWorkingDirectory(basedir); compilerConfiguration.setCompilerVersion(compilerVersion); compilerConfiguration.setBuildDirectory(buildDirectory); compilerConfiguration.setOutputFileName(outputFileName); // TODO: have an option to always compile (without need to clean) Set staleSources; boolean canUpdateTarget; try { staleSources = computeStaleSources(compilerConfiguration, compiler, getSourceInclusionScanner(staleMillis)); 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)); compilerConfiguration.setSourceFiles(sources); } else { compilerConfiguration.setSourceFiles(staleSources); } } catch (CompilerException e) { throw new MojoExecutionException("Error while computing stale sources.", e); } if (staleSources.isEmpty()) { getLog().info("Nothing to compile - all classes are up to date"); return; } // ---------------------------------------------------------------------- // Compile! // ---------------------------------------------------------------------- List messages; try { messages = compiler.compile(compilerConfiguration); } catch (Exception e) { // TODO: don't catch Exception throw new MojoExecutionException("Fatal error compiling", e); } boolean compilationError = false; for (Iterator i = messages.iterator(); i.hasNext();) { CompilerError message = (CompilerError)i.next(); if (message.isError()) { compilationError = true; break; } } if (compilationError && failOnError) { throw new CompilationFailureException(messages); } else { for (Iterator i = messages.iterator(); i.hasNext();) { CompilerError message = (CompilerError)i.next(); getLog().warn(message.toString()); } } } protected abstract List getCompileSourceRoots(); protected abstract File getOutputDirectory(); protected abstract List getClasspathElements() throws MojoExecutionException; protected SourceInclusionScanner getSourceInclusionScanner(int staleMillis) { SourceInclusionScanner scanner = null; if (testIncludes.isEmpty() && testExcludes.isEmpty()) { scanner = new StaleSourceScanner(staleMillis); } else { if (testIncludes.isEmpty()) { testIncludes.add("**/*.java"); } scanner = new StaleSourceScanner(staleMillis, testIncludes, testExcludes); } return scanner; } protected SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding) { SourceInclusionScanner scanner = null; if (testIncludes.isEmpty() && testExcludes.isEmpty()) { testIncludes = Collections.singleton("**/*." + inputFileEnding); scanner = new SimpleSourceInclusionScanner(testIncludes, Collections.EMPTY_SET); } else { if (testIncludes.isEmpty()) { testIncludes.add("**/*." + inputFileEnding); } scanner = new SimpleSourceInclusionScanner(testIncludes, testExcludes); } return scanner; } protected File copyDir(File source, File target) throws MojoExecutionException { target.mkdirs(); File[] entries = source.listFiles(new FileFilterImpl()); for (int i = 0; i < entries.length; i++) { File entry = entries[i]; File file = new File(target, File.separator + entry.getName()); if (entry.isDirectory()) { copyDir(entry, file); } else { InputStream in = null; OutputStream out = null; try { in = new FileInputStream(entry); out = new BufferedOutputStream(new FileOutputStream(file)); byte[] buffer = new byte[4096]; for (int length = 0; length >= 0; length = in.read(buffer)) { out.write(buffer, 0, length); } } catch (Exception ex) { throw new MojoExecutionException("Error copying test resources. " + ex); } finally { if (in != null) { try { in.close(); } catch (IOException ignore) { } } if (out != null) { try { out.close(); } catch (IOException ignore) { } } } } } return target; } private String getMemoryValue(String setting) { String value = null; // Allow '128' or '128m' if (isDigits(setting)) { value = setting + "m"; } else { if ((isDigits(setting.substring(0, setting.length() - 1))) && (setting.toLowerCase().endsWith("m"))) { value = setting; } } return value; } private boolean isDigits(String string) { for (int i = 0; i < string.length(); i++) { if (!Character.isDigit(string.charAt(i))) { return false; } } return true; } private Set computeStaleSources(CompilerConfiguration compilerConfiguration, Compiler compiler, SourceInclusionScanner scanner) 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 = getOutputDirectory(); } 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 = getCompileSourceRoots().iterator(); it.hasNext();) { String sourceRoot = (String)it.next(); File rootFile = new File(sourceRoot); if (!rootFile.isDirectory()) { continue; } try { Iterator itr = scanner.getIncludedSources(rootFile, outputDirectory).iterator(); while (itr.hasNext()) { staleSources.add((File)itr.next()); } } 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; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy