From ba24e76bd9fed7c4ab410e495601e37053f4677a Mon Sep 17 00:00:00 2001 From: adammurdoch Date: Tue, 26 Mar 2002 02:19:53 +0000 Subject: [PATCH] Started moving across the task to the java antlib: * Added 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-ffa450edef68 --- .../antlib/java/ExternalCompilerAdaptor.java | 92 +++++++ .../antlib/java/JavaCompilerAdaptor.java | 247 ++++++++++++++++++ .../org/apache/antlib/java/JavacAdaptor.java | 114 ++++++++ .../org/apache/antlib/java/JavacTask.java | 54 ++++ .../org/apache/antlib/java/JikesAdaptor.java | 83 ++++++ .../myrmidon/src/manifest/java-manifest.mf | 4 + 6 files changed, 594 insertions(+) create mode 100644 proposal/myrmidon/src/java/org/apache/antlib/java/ExternalCompilerAdaptor.java create mode 100644 proposal/myrmidon/src/java/org/apache/antlib/java/JavaCompilerAdaptor.java create mode 100644 proposal/myrmidon/src/java/org/apache/antlib/java/JavacAdaptor.java create mode 100644 proposal/myrmidon/src/java/org/apache/antlib/java/JavacTask.java create mode 100644 proposal/myrmidon/src/java/org/apache/antlib/java/JikesAdaptor.java create mode 100644 proposal/myrmidon/src/manifest/java-manifest.mf diff --git a/proposal/myrmidon/src/java/org/apache/antlib/java/ExternalCompilerAdaptor.java b/proposal/myrmidon/src/java/org/apache/antlib/java/ExternalCompilerAdaptor.java new file mode 100644 index 000000000..e58b154aa --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/antlib/java/ExternalCompilerAdaptor.java @@ -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 Adam Murdoch + * @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 ); + } + } + +} diff --git a/proposal/myrmidon/src/java/org/apache/antlib/java/JavaCompilerAdaptor.java b/proposal/myrmidon/src/java/org/apache/antlib/java/JavaCompilerAdaptor.java new file mode 100644 index 000000000..7a2a17370 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/antlib/java/JavaCompilerAdaptor.java @@ -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 duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * + * @author Stefan Bodewig + * @author J D Glanville + * @author Adam Murdoch + * @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 ); + } + } + } +} diff --git a/proposal/myrmidon/src/java/org/apache/antlib/java/JavacAdaptor.java b/proposal/myrmidon/src/java/org/apache/antlib/java/JavacAdaptor.java new file mode 100644 index 000000000..cb9a8bbc5 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/antlib/java/JavacAdaptor.java @@ -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 Adam Murdoch + * @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 ); + } + } +} diff --git a/proposal/myrmidon/src/java/org/apache/antlib/java/JavacTask.java b/proposal/myrmidon/src/java/org/apache/antlib/java/JavacTask.java new file mode 100644 index 000000000..7a9fb9e1f --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/antlib/java/JavacTask.java @@ -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 duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + * @author Adam Murdoch + * @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; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/antlib/java/JikesAdaptor.java b/proposal/myrmidon/src/java/org/apache/antlib/java/JikesAdaptor.java new file mode 100644 index 000000000..d40c56b84 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/antlib/java/JikesAdaptor.java @@ -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 duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * + * @author Stefan Bodewig + * @author J D Glanville + * @author skanthak@muehlheim.de + * @author Adam Murdoch + * @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() ); + } +} diff --git a/proposal/myrmidon/src/manifest/java-manifest.mf b/proposal/myrmidon/src/manifest/java-manifest.mf new file mode 100644 index 000000000..95698a2a7 --- /dev/null +++ b/proposal/myrmidon/src/manifest/java-manifest.mf @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Extension-List: tools +tools-Extension-Name: com.sun.tools +tools-Specification-Version: 1.0