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