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