* Added <javac> task, which extends AbstractFacadeTask. * Added JavaCompilerAdaptor and ExternalCompilerAdaptor abstract adaptors. Currently only handle classpath, debug and deprecation args. * Added basic jikes and javac (modern) compilers. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272035 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,92 @@ | |||
| /* | |||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||
| * | |||
| * This software is published under the terms of the Apache Software License | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.antlib.java; | |||
| import java.io.File; | |||
| import java.io.FileWriter; | |||
| import java.io.PrintWriter; | |||
| import java.io.IOException; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.Execute; | |||
| /** | |||
| * An abstract compiler adaptor, that forks an external compiler. | |||
| * | |||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
| * @version $Revision$ $Date$ | |||
| */ | |||
| public abstract class ExternalCompilerAdaptor | |||
| extends JavaCompilerAdaptor | |||
| { | |||
| /** | |||
| * Compiles a set of files. | |||
| */ | |||
| protected void compile( final File[] files ) | |||
| throws TaskException | |||
| { | |||
| // Write the file names to a temp file | |||
| final File tempFile = createTempFile( files ); | |||
| try | |||
| { | |||
| final Execute exe = new Execute(); | |||
| // Build the command line | |||
| buildCommandLine( exe, tempFile ); | |||
| // Execute | |||
| exe.execute( getContext() ); | |||
| } | |||
| finally | |||
| { | |||
| tempFile.delete(); | |||
| } | |||
| } | |||
| /** | |||
| * Builds the command-line to execute the compiler. | |||
| */ | |||
| protected abstract void buildCommandLine( final Execute exe, final File tempFile ) | |||
| throws TaskException; | |||
| /** | |||
| * Writes the temporary file containing the names of the files to compile. | |||
| */ | |||
| private File createTempFile( final File[] files ) | |||
| throws TaskException | |||
| { | |||
| try | |||
| { | |||
| // Build the temp file name | |||
| final File tmpFile = File.createTempFile( "javac", "", getContext().getBaseDirectory() ); | |||
| // Write file names to the temp file | |||
| final FileWriter writer = new FileWriter( tmpFile ); | |||
| try | |||
| { | |||
| final PrintWriter pwriter = new PrintWriter( writer, false ); | |||
| for( int i = 0; i < files.length; i++ ) | |||
| { | |||
| File file = files[ i ]; | |||
| pwriter.println( file.getAbsolutePath() ); | |||
| } | |||
| pwriter.close(); | |||
| } | |||
| finally | |||
| { | |||
| writer.close(); | |||
| } | |||
| return tmpFile; | |||
| } | |||
| catch( final IOException e ) | |||
| { | |||
| throw new TaskException( "Cannot write file list", e ); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,247 @@ | |||
| /* | |||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||
| * | |||
| * This software is published under the terms of the Apache Software License | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.antlib.java; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import org.apache.myrmidon.api.TaskContext; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.FileSet; | |||
| import org.apache.myrmidon.framework.file.FileList; | |||
| import org.apache.myrmidon.framework.file.Path; | |||
| import org.apache.tools.todo.types.DirectoryScanner; | |||
| import org.apache.tools.todo.types.ScannerUtil; | |||
| import org.apache.tools.todo.types.SourceFileScanner; | |||
| import org.apache.tools.todo.util.mappers.GlobPatternMapper; | |||
| /** | |||
| * An abstract Java compiler. | |||
| * | |||
| * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
| * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
| * </a> | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
| * @version $Revision$ $Date$ | |||
| * | |||
| * @ant.role shorthand="java-compiler" | |||
| */ | |||
| public abstract class JavaCompilerAdaptor | |||
| { | |||
| private TaskContext m_context; | |||
| private Path m_classPath = new Path(); | |||
| private ArrayList m_sourceFilesets = new ArrayList(); | |||
| private boolean m_debug; | |||
| private boolean m_deprecation; | |||
| private File m_destDir; | |||
| /** | |||
| * Sets the context for this adaptor. | |||
| */ | |||
| public void setContext( final TaskContext context ) | |||
| { | |||
| m_context = context; | |||
| } | |||
| /** | |||
| * Returns the context for this adaptor. | |||
| */ | |||
| protected TaskContext getContext() | |||
| { | |||
| return m_context; | |||
| } | |||
| /** | |||
| * Enables debug in the compiled classes. | |||
| */ | |||
| public void setDebug( final boolean debug ) | |||
| { | |||
| m_debug = debug; | |||
| } | |||
| /** | |||
| * Returns the 'debug' flag. | |||
| */ | |||
| protected boolean isDebug() | |||
| { | |||
| return m_debug; | |||
| } | |||
| /** | |||
| * Sets the destination directory. | |||
| */ | |||
| public void setDestDir( final File destDir ) | |||
| { | |||
| m_destDir = destDir; | |||
| } | |||
| /** | |||
| * Returns the destination directory. | |||
| */ | |||
| protected File getDestDir() | |||
| { | |||
| return m_destDir; | |||
| } | |||
| /** | |||
| * Enables deprecation info. | |||
| */ | |||
| public void setDeprecation( final boolean deprecation ) | |||
| { | |||
| m_deprecation = deprecation; | |||
| } | |||
| /** | |||
| * Returns the 'deprecation' flag. | |||
| */ | |||
| protected boolean isDeprecation() | |||
| { | |||
| return m_deprecation; | |||
| } | |||
| /** | |||
| * Adds a source fileset. | |||
| */ | |||
| public void addSrc( final FileSet fileset ) | |||
| { | |||
| m_sourceFilesets.add( fileset ); | |||
| } | |||
| /** | |||
| * Adds a class-path element. | |||
| */ | |||
| public void addClasspath( final Path path ) | |||
| { | |||
| m_classPath.add( path ); | |||
| } | |||
| /** | |||
| * Returns the classpath | |||
| */ | |||
| protected FileList getClassPath() | |||
| { | |||
| return m_classPath; | |||
| } | |||
| /** | |||
| * Invokes the compiler. | |||
| */ | |||
| public void execute() | |||
| throws TaskException | |||
| { | |||
| validate(); | |||
| // Build the list of files to compile | |||
| final File[] compileList = getCompileList(); | |||
| logFiles( compileList ); | |||
| if( compileList.length == 0 ) | |||
| { | |||
| return; | |||
| } | |||
| // Compile | |||
| compile( compileList ); | |||
| } | |||
| /** | |||
| * Compiles a set of files. | |||
| */ | |||
| protected abstract void compile( final File[] files ) | |||
| throws TaskException; | |||
| /** | |||
| * Logs the details of what is going to be compiled. | |||
| */ | |||
| private void logFiles( final File[] compileList ) | |||
| { | |||
| // Log | |||
| final String message = "Compiling " + compileList.length + " source files to " + m_destDir; | |||
| getContext().info( message ); | |||
| if( getContext().isVerboseEnabled() ) | |||
| { | |||
| getContext().verbose( "Compiling the following files:" ); | |||
| for( int i = 0; i < compileList.length; i++ ) | |||
| { | |||
| final File file = compileList[ i ]; | |||
| getContext().verbose( file.getAbsolutePath() ); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Builds the set of file to compile. | |||
| */ | |||
| private File[] getCompileList() | |||
| throws TaskException | |||
| { | |||
| final ArrayList allFiles = new ArrayList(); | |||
| for( int i = 0; i < m_sourceFilesets.size(); i++ ) | |||
| { | |||
| final FileSet fileSet = (FileSet)m_sourceFilesets.get( i ); | |||
| final DirectoryScanner scanner = ScannerUtil.getDirectoryScanner( fileSet ); | |||
| final String[] files = scanner.getIncludedFiles(); | |||
| restrictFiles( fileSet.getDir(), files, allFiles ); | |||
| } | |||
| return (File[])allFiles.toArray( new File[ allFiles.size() ] ); | |||
| } | |||
| /** | |||
| * Restricts a set of source files to those that are out-of-date WRT | |||
| * their class file. | |||
| */ | |||
| private void restrictFiles( final File srcDir, | |||
| final String files[], | |||
| final List acceptedFiles ) | |||
| throws TaskException | |||
| { | |||
| final GlobPatternMapper mapper = new GlobPatternMapper(); | |||
| mapper.setFrom( "*.java" ); | |||
| mapper.setTo( "*.class" ); | |||
| final SourceFileScanner sfs = new SourceFileScanner(); | |||
| final File[] newFiles = sfs.restrictAsFiles( files, | |||
| srcDir, | |||
| m_destDir, | |||
| mapper, | |||
| getContext() ); | |||
| for( int i = 0; i < newFiles.length; i++ ) | |||
| { | |||
| final File file = newFiles[i ]; | |||
| acceptedFiles.add( file ); | |||
| } | |||
| } | |||
| /** | |||
| * Validates the compiler settings. | |||
| */ | |||
| private void validate() throws TaskException | |||
| { | |||
| // Validate the destination directory | |||
| if( m_destDir == null ) | |||
| { | |||
| throw new TaskException( "No destination directory specified." ); | |||
| } | |||
| if( m_destDir.exists() ) | |||
| { | |||
| if( !m_destDir.isDirectory() ) | |||
| { | |||
| throw new TaskException( "Destination " + m_destDir + " is not a directory." ); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| if( !m_destDir.mkdirs() ) | |||
| { | |||
| throw new TaskException( "Cannot create destination directory " + m_destDir ); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,114 @@ | |||
| /* | |||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||
| * | |||
| * This software is published under the terms of the Apache Software License | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.antlib.java; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.file.Path; | |||
| import org.apache.tools.todo.types.Commandline; | |||
| import org.apache.tools.todo.types.PathUtil; | |||
| import java.io.File; | |||
| import java.lang.reflect.Method; | |||
| /** | |||
| * An adaptor for the in-process Javac compiler. | |||
| * | |||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
| * @version $Revision$ $Date$ | |||
| * | |||
| * @ant.type type="java-compiler" name="javac" | |||
| */ | |||
| public class JavacAdaptor | |||
| extends JavaCompilerAdaptor | |||
| { | |||
| /** | |||
| * Compiles as set of files. | |||
| */ | |||
| protected void compile( final File[] compileList ) | |||
| throws TaskException | |||
| { | |||
| final Commandline cmd = new Commandline(); | |||
| setupModernJavacCommand( cmd, compileList ); | |||
| final String[] args = cmd.getArguments(); | |||
| // Use reflection to be able to build on all JDKs >= 1.2: | |||
| final Class compilerClass; | |||
| try | |||
| { | |||
| compilerClass = Class.forName( "com.sun.tools.javac.Main" ); | |||
| } | |||
| catch( ClassNotFoundException exc ) | |||
| { | |||
| throw new TaskException( "Could not find the javac compiler.", exc ); | |||
| } | |||
| try | |||
| { | |||
| final Object compiler = compilerClass.newInstance(); | |||
| final Class[] paramTypes = new Class[] { args.getClass() }; | |||
| final Method compile = compilerClass.getMethod( "compile", paramTypes ); | |||
| final Object[] params = new Object[]{ args }; | |||
| final Integer result = (Integer)compile.invoke( compiler, params ); | |||
| if( result.intValue() != 0 ) | |||
| { | |||
| throw new TaskException( "Javac finished with non-zero return code." ); | |||
| } | |||
| } | |||
| catch( final TaskException exc ) | |||
| { | |||
| throw exc; | |||
| } | |||
| catch( final Exception exc ) | |||
| { | |||
| throw new TaskException( "Could not start javac compiler", exc ); | |||
| } | |||
| } | |||
| /** | |||
| * Builds the command-line to invoke the compiler with. | |||
| */ | |||
| private void setupModernJavacCommand( final Commandline cmd, | |||
| final File[] files ) | |||
| throws TaskException | |||
| { | |||
| // Build the classpath | |||
| Path classpath = new Path(); | |||
| classpath.addLocation( getDestDir() ); | |||
| classpath.add( getClassPath() ); | |||
| cmd.addArgument( "-classpath" ); | |||
| cmd.addArgument( PathUtil.formatPath( classpath, getContext() ) ); | |||
| if( isDeprecation() ) | |||
| { | |||
| cmd.addArgument( "-deprecation" ); | |||
| } | |||
| cmd.addArgument( "-d" ); | |||
| cmd.addArgument( getDestDir() ); | |||
| if( isDebug() ) | |||
| { | |||
| cmd.addArgument( "-g" ); | |||
| } | |||
| else | |||
| { | |||
| cmd.addArgument( "-g:none" ); | |||
| } | |||
| // Add the files to compile | |||
| for( int i = 0; i < files.length; i++ ) | |||
| { | |||
| final File file = files[i ]; | |||
| cmd.addArgument( file ); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,54 @@ | |||
| /* | |||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||
| * | |||
| * This software is published under the terms of the Apache Software License | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.antlib.java; | |||
| import org.apache.myrmidon.framework.AbstractFacadeTask; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| /** | |||
| * A task that compiles Java source files. | |||
| * | |||
| * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
| * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com</a> | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
| * @version $Revision$ $Date$ | |||
| * | |||
| * @ant.task name="javac" | |||
| */ | |||
| public class JavacTask | |||
| extends AbstractFacadeTask | |||
| { | |||
| public JavacTask() | |||
| { | |||
| super( "compiler", JavaCompilerAdaptor.class, "javac" ); | |||
| } | |||
| /** | |||
| * Execute this task. | |||
| */ | |||
| public void execute() | |||
| throws TaskException | |||
| { | |||
| getContext().verbose( "Using " + getImplementation() + " compiler." ); | |||
| final JavaCompilerAdaptor adaptor = (JavaCompilerAdaptor)prepareFacade(); | |||
| adaptor.execute(); | |||
| } | |||
| /** | |||
| * Create the instance of the facade. | |||
| */ | |||
| protected Object createFacade() | |||
| throws TaskException | |||
| { | |||
| JavaCompilerAdaptor adaptor = (JavaCompilerAdaptor)super.createFacade(); | |||
| adaptor.setContext( getContext() ); | |||
| return adaptor; | |||
| } | |||
| } | |||
| @@ -0,0 +1,83 @@ | |||
| /* | |||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||
| * | |||
| * This software is published under the terms of the Apache Software License | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.antlib.java; | |||
| import java.io.File; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.Execute; | |||
| import org.apache.myrmidon.framework.file.Path; | |||
| import org.apache.tools.todo.types.Commandline; | |||
| import org.apache.tools.todo.types.PathUtil; | |||
| /** | |||
| * An adaptor for the jikes compiler. | |||
| * | |||
| * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
| * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
| * </a> | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
| * @author skanthak@muehlheim.de | |||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
| * @version $Revision$ $Date$ | |||
| * | |||
| * @ant.type type="java-compiler" name="jikes" | |||
| */ | |||
| public class JikesAdaptor | |||
| extends ExternalCompilerAdaptor | |||
| { | |||
| /** | |||
| * Builds the command-line to execute the compiler. | |||
| */ | |||
| protected void buildCommandLine( final Execute exe, final File tempFile ) | |||
| throws TaskException | |||
| { | |||
| Path classpath = new Path(); | |||
| // Add the destination directory | |||
| classpath.addLocation( getDestDir() ); | |||
| // Add the compile classpath | |||
| classpath.add( getClassPath() ); | |||
| // If the user has set JIKESPATH we should add the contents as well | |||
| String jikesPath = System.getProperty( "jikes.class.path" ); | |||
| if( jikesPath != null ) | |||
| { | |||
| classpath.add( jikesPath ); | |||
| } | |||
| // Add the runtime | |||
| PathUtil.addJavaRuntime( classpath ); | |||
| // Build the command line | |||
| final Commandline cmd = exe.getCommandline(); | |||
| cmd.setExecutable( "jikes" ); | |||
| if( isDeprecation() ) | |||
| { | |||
| cmd.addArgument( "-deprecation" ); | |||
| } | |||
| if( isDebug() ) | |||
| { | |||
| cmd.addArgument( "-g" ); | |||
| } | |||
| cmd.addArgument( "-d" ); | |||
| cmd.addArgument( getDestDir() ); | |||
| cmd.addArgument( "-classpath" ); | |||
| cmd.addArgument( PathUtil.formatPath( classpath, getContext() ) ); | |||
| // TODO - make this configurable | |||
| cmd.addArgument( "+E" ); | |||
| cmd.addArgument( "@" + tempFile.getAbsolutePath() ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| Manifest-Version: 1.0 | |||
| Extension-List: tools | |||
| tools-Extension-Name: com.sun.tools | |||
| tools-Specification-Version: 1.0 | |||