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

org.codehaus.groovy.ant.Groovyc Maven / Gradle / Ivy

There is a newer version: 1.5.8
Show newest version
/*
 * Copyright 2003-2007 the original author or authors.
 *
 * 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.
 */
package org.codehaus.groovy.ant;

import groovy.lang.GroovyClassLoader;
import org.apache.commons.cli.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.listener.AnsiColorLogger;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.GlobPatternMapper;
import org.apache.tools.ant.util.SourceFileScanner;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.tools.ErrorReporter;
import org.codehaus.groovy.tools.StringHelper;
import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
import org.codehaus.groovy.tools.javac.JavaCompiler;
import org.codehaus.groovy.tools.javac.JavaCompilerFactory;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * Compiles Groovy source files. This task can take the following
 * arguments:
 * 
    *
  • srcdir *
  • destdir *
  • classpath *
  • stacktrace *
  • jointCompilation *
  • verbose *
  • encoding *
  • failonerror *
* Of these arguments, the srcdir and destdir are required. *

* When this task executes, it will recursively scan srcdir and * destdir looking for Groovy source files to compile. This task makes its * compile decision based on timestamp. * * Based heavily on the Javac implementation in Ant * * @author James Strachan * @author Hein Meling * @version $Revision: 9536 $ */ public class Groovyc extends MatchingTask { private final LoggingHelper log = new LoggingHelper(this); private Path compileClasspath; private Path compileSourcepath; private String encoding; private Javac javac; protected File destDir; protected Path src; protected CompilerConfiguration configuration = new CompilerConfiguration(); protected boolean failOnError = true; protected boolean listFiles = false; protected File[] compileList = new File[0]; private boolean jointCompilation; public static void main(String[] args) { Project project = new Project(); DefaultLogger logger = new AnsiColorLogger(); logger.setMessageOutputLevel(Project.MSG_INFO); project.addBuildListener(logger); // project.init(); Groovyc compiler = new Groovyc(); compiler.setProject(project); args = compiler.evalCompilerFlags(args); String dest = "."; String src = "."; boolean listFiles = false; if (args.length > 0) { dest = args[0]; } if (args.length > 1) { src = args[1]; } if (args.length > 2) { String flag = args[2]; if (flag.equalsIgnoreCase("true")) { listFiles = true; } } compiler.setSrcdir(new Path(project, src)); compiler.setDestdir(project.resolveFile(dest)); compiler.setListfiles(listFiles); compiler.execute(); } private String[] evalCompilerFlags(String[] args) { // // Parse the command line Options options = new Options(); options.addOption( OptionBuilder.withArgName( "property=value" ) .withValueSeparator('=') .hasArgs(2) .create( "J" )); options.addOption( OptionBuilder.withArgName( "property=value" ) .hasArg() .create( "F" )); options.addOption(OptionBuilder.withLongOpt("jointCompilation").create('j')); PosixParser cliParser = new PosixParser(); CommandLine cli; try { cli = cliParser.parse(options, args); } catch (ParseException e) { throw new BuildException(e); } jointCompilation = cli.hasOption('j'); if (jointCompilation) { Map compilerOptions = new HashMap(); String[] opts = cli.getOptionValues("J"); compilerOptions.put("namedValues", opts); opts = cli.getOptionValues("F"); compilerOptions.put("flags", opts); compilerOptions.put("stubDir", createTempDir()); configuration.setJointCompilationOptions(compilerOptions); } return cli.getArgs(); } public Groovyc() { } /** * Adds a path for source compilation. * * @return a nested src element. */ public Path createSrc() { if (src == null) { src = new Path(getProject()); } return src.createPath(); } /** * Recreate src. * * @return a nested src element. */ protected Path recreateSrc() { src = null; return createSrc(); } /** * Set the source directories to find the source Java files. * @param srcDir the source directories as a path */ public void setSrcdir(Path srcDir) { if (src == null) { src = srcDir; } else { src.append(srcDir); } } /** * Gets the source dirs to find the source java files. * @return the source directorys as a path */ public Path getSrcdir() { return src; } /** * Set the destination directory into which the Java source * files should be compiled. * @param destDir the destination director */ public void setDestdir(File destDir) { this.destDir = destDir; } /** * Enable verbose compiling which will display which files * are being compiled */ public void setVerbose(boolean verbose) { configuration.setVerbose( verbose ); } /** * Enable compiler to report stack trace information if a problem occurs * during compilation. */ public void setStacktrace(boolean stacktrace) { configuration.setDebug(stacktrace); } /** * Gets the destination directory into which the java source files * should be compiled. * @return the destination directory */ public File getDestdir() { return destDir; } /** * Set the sourcepath to be used for this compilation. * @param sourcepath the source path */ public void setSourcepath(Path sourcepath) { if (compileSourcepath == null) { compileSourcepath = sourcepath; } else { compileSourcepath.append(sourcepath); } } /** * Gets the sourcepath to be used for this compilation. * @return the source path */ public Path getSourcepath() { return compileSourcepath; } /** * Adds a path to sourcepath. * @return a sourcepath to be configured */ public Path createSourcepath() { if (compileSourcepath == null) { compileSourcepath = new Path(getProject()); } return compileSourcepath.createPath(); } /** * Adds a reference to a source path defined elsewhere. * @param r a reference to a source path */ public void setSourcepathRef(Reference r) { createSourcepath().setRefid(r); } /** * Set the classpath to be used for this compilation. * * @param classpath an Ant Path object containing the compilation classpath. */ public void setClasspath(Path classpath) { if (compileClasspath == null) { compileClasspath = classpath; } else { compileClasspath.append(classpath); } } /** * Gets the classpath to be used for this compilation. * @return the class path */ public Path getClasspath() { return compileClasspath; } /** * Adds a path to the classpath. * @return a class path to be configured */ public Path createClasspath() { if (compileClasspath == null) { compileClasspath = new Path(getProject()); } return compileClasspath.createPath(); } /** * Adds a reference to a classpath defined elsewhere. * @param r a reference to a classpath */ public void setClasspathRef(Reference r) { createClasspath().setRefid(r); } /** * Returns the encoding to be used when creating files.
* If no encoding value has been set it will default to * System.properties("file.encoding") * * @return the file encoding to use */ public String createEncoding() { if (encoding == null) { encoding = System.getProperty("file.encoding"); } return encoding; } /** * Sets the file encoding for generated files. * @param encoding the file encoding to be used */ public void setEncoding(String encoding) { this.encoding = encoding; } /** * Returns the encoding to be used when creating files. * @return the file encoding to use */ public String getEncoding() { return encoding; } /** * If true, list the source files being handed off to the compiler. * @param list if true list the source files */ public void setListfiles(boolean list) { listFiles = list; } /** * Get the listfiles flag. * @return the listfiles flag */ public boolean getListfiles() { return listFiles; } /** * Indicates whether the build will continue * even if there are compilation errors; defaults to true. * @param fail if true halt the build on failure */ public void setFailonerror(boolean fail) { failOnError = fail; } /** * @param proceed inverse of failonerror */ public void setProceed(boolean proceed) { failOnError = !proceed; } /** * Gets the failonerror flag. * @return the failonerror flag */ public boolean getFailonerror() { return failOnError; } /** * Executes the task. * @exception BuildException if an error occurs */ public void execute() throws BuildException { checkParameters(); resetFileLists(); if (javac!=null) jointCompilation=true; // scan source directories and dest directory to build up // compile lists String[] list = src.list(); for (int i = 0; i < list.length; i++) { File srcDir = getProject().resolveFile(list[i]); if (!srcDir.exists()) { throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", getLocation()); } DirectoryScanner ds = this.getDirectoryScanner(srcDir); String[] files = ds.getIncludedFiles(); scanDir(srcDir, destDir != null ? destDir : srcDir, files); } compile(); } /** * Clear the list of files to be compiled and copied.. */ protected void resetFileLists() { compileList = new File[0]; } /** * Scans the directory looking for source files to be compiled. * The results are returned in the class variable compileList * * @param srcDir The source directory * @param destDir The destination directory * @param files An array of filenames */ protected void scanDir(File srcDir, File destDir, String[] files) { GlobPatternMapper m = new GlobPatternMapper(); m.setFrom("*.groovy"); m.setTo("*.class"); SourceFileScanner sfs = new SourceFileScanner(this); File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); addToCompileList(newFiles); if (jointCompilation) { m.setFrom("*.java"); m.setTo("*.class"); newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); addToCompileList(newFiles); } } protected void addToCompileList(File[] newFiles) { if (newFiles.length > 0) { File[] newCompileList = new File[compileList.length + newFiles.length]; System.arraycopy(compileList, 0, newCompileList, 0, compileList.length); System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length); compileList = newCompileList; } } /** * Gets the list of files to be compiled. * @return the list of files as an array */ public File[] getFileList() { return compileList; } protected void checkParameters() throws BuildException { if (src == null) { throw new BuildException("srcdir attribute must be set!", getLocation()); } if (src.size() == 0) { throw new BuildException("srcdir attribute must be set!", getLocation()); } if (destDir != null && !destDir.isDirectory()) { throw new BuildException( "destination directory \"" + destDir + "\" does not exist or is not a directory", getLocation()); } if (encoding != null && !Charset.isSupported(encoding)) { throw new BuildException("encoding \"\" not supported"); } } protected void compile() { if (compileList.length == 0) { log.info("No sources to compile"); return; } log.info("Compiling " + compileList.length + " source file" + (compileList.length == 1 ? "" : "s") + " to " + destDir); if (listFiles) { for (int i = 0; i < compileList.length; i++) { String filename = compileList[i].getAbsolutePath(); log.info(" " + filename); } } try { Path classpath = getClasspath(); if (classpath != null) { configuration.setClasspath(classpath.toString()); } configuration.setTargetDirectory(destDir); if (encoding != null) { configuration.setSourceEncoding(encoding); } CompilationUnit unit = makeCompileUnit(); unit.addSources(compileList); unit.compile(); } catch (Exception e) { StringWriter writer = new StringWriter(); new ErrorReporter( e, false ).write( new PrintWriter(writer) ); String message = writer.toString(); if (failOnError) { throw new BuildException(message, e, getLocation()); } else { log(message, Project.MSG_ERR); } } } protected CompilationUnit makeCompileUnit() { if (javac!=null) { Map compilerOptions = new HashMap(); compilerOptions.put("stubDir", createTempDir()); configuration.setJointCompilationOptions(compilerOptions); jointCompilation = true; } if (jointCompilation) { JavaAwareCompilationUnit unit = new JavaAwareCompilationUnit(configuration, buildClassLoaderFor()); if (javac!=null) { final JavaCompiler compiler = new JavaCompiler() { public void compile(List files, CompilationUnit cu) { // forward options if (javac.getClasspath()==null) { javac.setClasspath(compileClasspath); } if (javac.getSourcepath()==null && compileSourcepath!=null) { javac.createSourcepath().add(compileSourcepath); } if (javac.getEncoding()==null) { javac.setEncoding(encoding); } javac.setDestdir(destDir); Path p = javac.createSrc(); p.add(src); Path tmpDir = new Path(getProject()); File dir = (File) cu.getConfiguration().getJointCompilationOptions().get("stubDir"); tmpDir.setLocation(dir); p.add(tmpDir); javac.execute(); } }; unit.setCompilerFactory(new JavaCompilerFactory() { public JavaCompiler createCompiler(CompilerConfiguration config) { return compiler; } }); } return unit; } else { return new CompilationUnit(configuration, null, buildClassLoaderFor()); } } protected File createTempDir() { File tempFile; try { tempFile = File.createTempFile("generated-", "java-source"); tempFile.delete(); tempFile.mkdirs(); } catch (IOException e) { throw new BuildException(e); } return tempFile; } protected GroovyClassLoader buildClassLoaderFor() { ClassLoader parent = this.getClass().getClassLoader(); if (parent instanceof AntClassLoader) { AntClassLoader antLoader = (AntClassLoader) parent; String[] pathElm = antLoader.getClasspath().split(File.pathSeparator); List classpath = configuration.getClasspath(); /* * Iterate over the classpath provided to groovyc, and add any missing path * entries to the AntClassLoader. This is a workaround, since for some reason * 'directory' classpath entries were not added to the AntClassLoader' classpath. */ for (Iterator iter = classpath.iterator(); iter.hasNext();) { String cpEntry = (String) iter.next(); boolean found = false; for (int i = 0; i < pathElm.length; i++) { if (cpEntry.equals(pathElm[i])) { found = true; break; } } /* * fix for GROOVY-2284 * seems like AntClassLoader doesn't check if the file * may not exist in the classpath yet */ if (!found && new File(cpEntry).exists()) antLoader.addPathElement(cpEntry); } } return new GroovyClassLoader(parent, configuration); } public void setJointCompilationOptions(String options) { String[] args = StringHelper.tokenizeUnquoted(options); evalCompilerFlags(args); } public Javac createJavac() { if (javac!=null) throw new BuildException("nested javac element allowed only once"); javac = new Javac(); return javac; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy