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