* 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 | |||||