From c5a945fe3c7f09577a7b3ad96953f2a09a8da824 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Tue, 21 Jul 2009 08:52:12 +0000 Subject: [PATCH] Allow users to specify a classpath when using a custom adapter in javac, rmic, javah or native2ascii. PR 11143 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@796188 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 5 ++ docs/manual/CoreTasks/javac.html | 8 +++ docs/manual/CoreTasks/rmic.html | 7 ++ docs/manual/OptionalTasks/javah.html | 7 ++ docs/manual/OptionalTasks/native2ascii.html | 7 ++ .../org/apache/tools/ant/taskdefs/Javac.java | 13 +++- .../org/apache/tools/ant/taskdefs/Rmic.java | 13 +++- .../compilers/CompilerAdapterFactory.java | 43 +++++++++++- .../tools/ant/taskdefs/optional/Javah.java | 13 +++- .../ant/taskdefs/optional/Native2Ascii.java | 14 +++- .../optional/javah/JavahAdapterFactory.java | 30 +++++++- .../Native2AsciiAdapterFactory.java | 32 ++++++++- .../ant/taskdefs/rmic/RmicAdapterFactory.java | 38 +++++++++- .../ant/util/facade/FacadeTaskHelper.java | 21 ++++++ src/tests/antunit/taskdefs/javac-test.xml | 36 ++++++++++ .../antunit/taskdefs/optional/javah-test.xml | 55 +++++++++++++++ .../taskdefs/optional/native2ascci-test.xml | 56 +++++++++++++++ src/tests/antunit/taskdefs/rmic-test.xml | 69 +++++++++++++++++++ 18 files changed, 454 insertions(+), 13 deletions(-) create mode 100644 src/tests/antunit/taskdefs/optional/javah-test.xml create mode 100644 src/tests/antunit/taskdefs/optional/native2ascci-test.xml create mode 100644 src/tests/antunit/taskdefs/rmic-test.xml diff --git a/WHATSNEW b/WHATSNEW index 332910beb..63ba8bc67 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -784,6 +784,11 @@ Other changes: different executable. Bugzilla Report 42132. + * , , and now provide a nested + element to specify a classpath that will be used when loading the + task's (compiler) adapter class. + Bugzilla Issue 11143. + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= diff --git a/docs/manual/CoreTasks/javac.html b/docs/manual/CoreTasks/javac.html index 328031e3c..6c3736a1b 100644 --- a/docs/manual/CoreTasks/javac.html +++ b/docs/manual/CoreTasks/javac.html @@ -509,6 +509,14 @@ used.

+

compilerclasspath since Ant 1.8.0

+ +

A PATH like structure holding the + classpath to use when loading the compiler implementation if a + custom class has been specified. Doesn't have any effect when + using one of the built-in compilers.

+ +

Examples

  <javac srcdir="${src}"
          destdir="${build}"
diff --git a/docs/manual/CoreTasks/rmic.html b/docs/manual/CoreTasks/rmic.html
index 817f22848..2f1926668 100644
--- a/docs/manual/CoreTasks/rmic.html
+++ b/docs/manual/CoreTasks/rmic.html
@@ -276,6 +276,13 @@ used.

+

compilerclasspath since Ant 1.8.0

+ +

A PATH like structure holding the + classpath to use when loading the compiler implementation if a + custom class has been specified. Doesn't have any effect when + using one of the built-in compilers.

+

Examples

  <rmic classname="com.xyz.FooBar" base="${build}/classes"/>

runs the rmic compiler for the class com.xyz.FooBar. The diff --git a/docs/manual/OptionalTasks/javah.html b/docs/manual/OptionalTasks/javah.html index abbefea25..7e2f3729f 100644 --- a/docs/manual/OptionalTasks/javah.html +++ b/docs/manual/OptionalTasks/javah.html @@ -170,6 +170,13 @@ only if a given compiler implementation will be used.

+

implementationclasspath since Ant 1.8.0

+ +

A PATH like structure holding the + classpath to use when loading the compiler implementation if a + custom class has been specified. Doesn't have any effect when + using one of the built-in compilers.

+

Examples

  <javah destdir="c" class="org.foo.bar.Wibble"/>

makes a JNI header of the named class, using the JDK1.2 JNI model. Assuming diff --git a/docs/manual/OptionalTasks/native2ascii.html b/docs/manual/OptionalTasks/native2ascii.html index 2cefeca36..3b3ce5c61 100644 --- a/docs/manual/OptionalTasks/native2ascii.html +++ b/docs/manual/OptionalTasks/native2ascii.html @@ -183,6 +183,13 @@ only if a given converter implementation will be used.

+

implementationclasspath since Ant 1.8.0

+ +

A PATH like structure holding the + classpath to use when loading the converter implementation if a + custom class has been specified. Doesn't have any effect when + using one of the built-in converters.

+

Examples

diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java
index 3b2be7de5..6ddcefd04 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Javac.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java
@@ -859,6 +859,16 @@ public class Javac extends MatchingTask {
         return taskSuccess;
     }
 
+    /**
+     * The classpath to use when loading the compiler implementation
+     * if it is not a built-in one.
+     *
+     * @since Ant 1.8.0
+     */
+    public Path createCompilerClasspath() {
+        return facade.getImplementationClasspath(getProject());
+    }
+
     /**
      * Executes the task.
      * @exception BuildException if an error occurs
@@ -1067,7 +1077,8 @@ public class Javac extends MatchingTask {
             }
 
             CompilerAdapter adapter =
-                CompilerAdapterFactory.getCompiler(compilerImpl, this);
+                CompilerAdapterFactory.getCompiler(compilerImpl, this,
+                                                   createCompilerClasspath());
 
             // now we need to populate the compiler adapter
             adapter.setJavac(this);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Rmic.java b/src/main/org/apache/tools/ant/taskdefs/Rmic.java
index a69f87360..fcc9e6d46 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Rmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Rmic.java
@@ -509,6 +509,16 @@ public class Rmic extends MatchingTask {
         return executable;
     }
 
+    /**
+     * The classpath to use when loading the compiler implementation
+     * if it is not a built-in one.
+     *
+     * @since Ant 1.8.0
+     */
+    public Path createCompilerClasspath() {
+        return facade.getImplementationClasspath(getProject());
+    }
+
     /**
      * execute by creating an instance of an implementation
      * class and getting to do the work
@@ -528,7 +538,8 @@ public class Rmic extends MatchingTask {
         if (verify) {
             log("Verify has been turned on.", Project.MSG_VERBOSE);
         }
-        RmicAdapter adapter = RmicAdapterFactory.getRmic(getCompiler(), this);
+        RmicAdapter adapter = RmicAdapterFactory.getRmic(getCompiler(), this,
+                                                         createCompilerClasspath());
 
         // now we need to populate the compiler adapter
         adapter.setRmic(this);
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
index 8cf2bb43e..38ebb1120 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
@@ -21,6 +21,7 @@ package org.apache.tools.ant.taskdefs.compilers;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.ClasspathUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
 
@@ -62,6 +63,40 @@ public final class CompilerAdapterFactory {
      * a compiler adapter.
      */
     public static CompilerAdapter getCompiler(String compilerType, Task task)
+        throws BuildException {
+        return getCompiler(compilerType, task, null);
+    }
+
+    /**
+     * Based on the parameter passed in, this method creates the necessary
+     * factory desired.
+     *
+     * The current mapping for compiler names are as follows:
+     * 
  • jikes = jikes compiler + *
  • classic, javac1.1, javac1.2 = the standard compiler from JDK + * 1.1/1.2 + *
  • modern, javac1.3, javac1.4, javac1.5 = the compiler of JDK 1.3+ + *
  • jvc, microsoft = the command line compiler from Microsoft's SDK + * for Java / Visual J++ + *
  • kjc = the kopi compiler
  • + *
  • gcj = the gcj compiler from gcc
  • + *
  • sj, symantec = the Symantec Java compiler
  • + *
  • a fully qualified classname = the name of a compiler + * adapter + *
+ * + * @param compilerType either the name of the desired compiler, or the + * full classname of the compiler's adapter. + * @param task a task to log through. + * @param classpath the classpath to use when looking up an + * adapter class + * @return the compiler adapter + * @throws BuildException if the compiler type could not be resolved into + * a compiler adapter. + * @since Ant 1.8.0 + */ + public static CompilerAdapter getCompiler(String compilerType, Task task, + Path classpath) throws BuildException { boolean isClassicCompilerSupported = true; //as new versions of java come out, add them to this test @@ -133,7 +168,8 @@ public final class CompilerAdapterFactory { || compilerType.equalsIgnoreCase("symantec")) { return new Sj(); } - return resolveClassName(compilerType); + return resolveClassName(compilerType, + task.getProject().createClassLoader(classpath)); } /** @@ -163,12 +199,15 @@ public final class CompilerAdapterFactory { * Throws a fit if it can't. * * @param className The fully qualified classname to be created. + * @param loader the classloader to use * @throws BuildException This is the fit that is thrown if className * isn't an instance of CompilerAdapter. */ - private static CompilerAdapter resolveClassName(String className) + private static CompilerAdapter resolveClassName(String className, + ClassLoader loader) throws BuildException { return (CompilerAdapter) ClasspathUtils.newInstance(className, + loader != null ? loader : CompilerAdapterFactory.class.getClassLoader(), CompilerAdapter.class); } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java index bd5e3de9f..704636c42 100755 --- a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java @@ -406,6 +406,16 @@ public class Javah extends Task { return facade.getArgs(); } + /** + * The classpath to use when loading the javah implementation + * if it is not a built-in one. + * + * @since Ant 1.8.0 + */ + public Path createImplementationClasspath() { + return facade.getImplementationClasspath(getProject()); + } + /** * Execute the task * @@ -443,7 +453,8 @@ public class Javah extends Task { JavahAdapter ad = JavahAdapterFactory.getAdapter(facade.getImplementation(), - this); + this, + createImplementationClasspath()); if (!ad.compile(this)) { throw new BuildException("compilation failed"); } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java index 1282cebe6..e2eb06be2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java @@ -26,6 +26,7 @@ import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapter; import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapterFactory; import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.IdentityMapper; import org.apache.tools.ant.util.SourceFileScanner; @@ -173,6 +174,16 @@ public class Native2Ascii extends MatchingTask { return arg; } + /** + * The classpath to use when loading the native2ascii + * implementation if it is not a built-in one. + * + * @since Ant 1.8.0 + */ + public Path createImplementationClasspath() { + return facade.getImplementationClasspath(getProject()); + } + /** * Execute the task * @@ -264,7 +275,8 @@ public class Native2Ascii extends MatchingTask { log("converting " + srcName, Project.MSG_VERBOSE); Native2AsciiAdapter ad = Native2AsciiAdapterFactory.getAdapter(facade.getImplementation(), - this); + this, + createImplementationClasspath()); if (!ad.convert(this, srcFile, destFile)) { throw new BuildException("conversion failed"); } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java index ad3aa87b4..8fc55f0f4 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java @@ -19,6 +19,7 @@ package org.apache.tools.ant.taskdefs.optional.javah; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.JavaEnvUtils; @@ -58,13 +59,35 @@ public class JavahAdapterFactory { public static JavahAdapter getAdapter(String choice, ProjectComponent log) throws BuildException { + return getAdapter(choice, log, null); + } + + /** + * Creates the JavahAdapter based on the user choice and + * potentially the VM vendor. + * + * @param choice the user choice (if any). + * @param log a ProjectComponent instance used to access Ant's + * logging system. + * @param classpath the classpath to use when looking up an + * adapter class + * @return The adapter to use. + * @throws BuildException if there is an error. + * @since Ant 1.8.0 + */ + public static JavahAdapter getAdapter(String choice, + ProjectComponent log, + Path classpath) + throws BuildException { if ((JavaEnvUtils.isKaffe() && choice == null) || Kaffeh.IMPLEMENTATION_NAME.equals(choice)) { return new Kaffeh(); } else if (SunJavah.IMPLEMENTATION_NAME.equals(choice)) { return new SunJavah(); } else if (choice != null) { - return resolveClassName(choice); + return resolveClassName(choice, + log.getProject() + .createClassLoader(classpath)); } // This default has been good enough until Ant 1.6.3, so stick @@ -77,12 +100,15 @@ public class JavahAdapterFactory { * Throws a fit if it can't. * * @param className The fully qualified classname to be created. + * @param loader the classloader to use * @throws BuildException This is the fit that is thrown if className * isn't an instance of JavahAdapter. */ - private static JavahAdapter resolveClassName(String className) + private static JavahAdapter resolveClassName(String className, + ClassLoader loader) throws BuildException { return (JavahAdapter) ClasspathUtils.newInstance(className, + loader != null ? loader : JavahAdapterFactory.class.getClassLoader(), JavahAdapter.class); } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java index abbaec61d..e19ce7f36 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java @@ -19,6 +19,7 @@ package org.apache.tools.ant.taskdefs.optional.native2ascii; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.JavaEnvUtils; @@ -46,7 +47,7 @@ public class Native2AsciiAdapterFactory { } /** - * Creates the Native2AsciiAdapter based on the user choice and * + * Creates the Native2AsciiAdapter based on the user choice and * potentially the VM vendor. * * @param choice the user choice (if any). @@ -58,13 +59,35 @@ public class Native2AsciiAdapterFactory { public static Native2AsciiAdapter getAdapter(String choice, ProjectComponent log) throws BuildException { + return getAdapter(choice, log, null); + } + + /** + * Creates the Native2AsciiAdapter based on the user choice and + * potentially the VM vendor. + * + * @param choice the user choice (if any). + * @param log a ProjectComponent instance used to access Ant's + * logging system. + * @param classpath the classpath to use when looking up an + * adapter class + * @return The adapter to use. + * @throws BuildException if there was a problem. + * @since Ant 1.8.0 + */ + public static Native2AsciiAdapter getAdapter(String choice, + ProjectComponent log, + Path classpath) + throws BuildException { if ((JavaEnvUtils.isKaffe() && choice == null) || KaffeNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { return new KaffeNative2Ascii(); } else if (SunNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { return new SunNative2Ascii(); } else if (choice != null) { - return resolveClassName(choice); + return resolveClassName(choice, + log.getProject() + .createClassLoader(classpath)); } // This default has been good enough until Ant 1.6.3, so stick @@ -77,12 +100,15 @@ public class Native2AsciiAdapterFactory { * Throws a fit if it can't. * * @param className The fully qualified classname to be created. + * @param loader the classloader to use * @throws BuildException This is the fit that is thrown if className * isn't an instance of Native2AsciiAdapter. */ - private static Native2AsciiAdapter resolveClassName(String className) + private static Native2AsciiAdapter resolveClassName(String className, + ClassLoader loader) throws BuildException { return (Native2AsciiAdapter) ClasspathUtils.newInstance(className, + loader != null ? loader : Native2AsciiAdapterFactory.class.getClassLoader(), Native2AsciiAdapter.class); } diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java index 275b916d5..fc625b70f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java @@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs.rmic; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.ClasspathUtils; import java.util.Locale; @@ -66,6 +67,35 @@ public final class RmicAdapterFactory { */ public static RmicAdapter getRmic(String rmicType, Task task) throws BuildException { + return getRmic(rmicType, task, null); + } + + /** + * Based on the parameter passed in, this method creates the necessary + * factory desired. + * + *

The current mapping for rmic names are as follows:

+ *
  • sun = SUN's rmic + *
  • kaffe = Kaffe's rmic + *
  • a fully qualified classname = the name of a rmic + * adapter + *
  • weblogic = weblogic compiler + *
  • forking = Sun's RMIC by forking a new JVM + *
+ * + * @param rmicType either the name of the desired rmic, or the + * full classname of the rmic's adapter. + * @param task a task to log through. + * @param classpath the classpath to use when looking up an + * adapter class + * @return the compiler adapter + * @throws BuildException if the rmic type could not be resolved into + * a rmic adapter. + * @since Ant 1.8.0 + */ + public static RmicAdapter getRmic(String rmicType, Task task, + Path classpath) + throws BuildException { //convert to lower case in the English locale, String compiler = rmicType.toLowerCase(Locale.ENGLISH); @@ -87,7 +117,8 @@ public final class RmicAdapterFactory { return new XNewRmic(); } //no match? ask for the non-lower-cased type - return resolveClassName(rmicType); + return resolveClassName(rmicType, + task.getProject().createClassLoader(classpath)); } /** @@ -95,12 +126,15 @@ public final class RmicAdapterFactory { * Throws a fit if it can't. * * @param className The fully qualified classname to be created. + * @param loader the classloader to use * @throws BuildException This is the fit that is thrown if className * isn't an instance of RmicAdapter. */ - private static RmicAdapter resolveClassName(String className) + private static RmicAdapter resolveClassName(String className, + ClassLoader loader) throws BuildException { return (RmicAdapter) ClasspathUtils.newInstance(className, + loader != null ? loader : RmicAdapterFactory.class.getClassLoader(), RmicAdapter.class); } } diff --git a/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java b/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java index 6f3bd60c6..55a3f18a3 100644 --- a/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java +++ b/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java @@ -21,6 +21,8 @@ package org.apache.tools.ant.util.facade; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.Path; /** * Helper class for facade implementations - encapsulates treatment of @@ -52,6 +54,11 @@ public class FacadeTaskHelper { */ private String defaultValue; + /** + * User specified path used as classpath when loading the implementation. + */ + private Path implementationClasspath; + /** * @param defaultValue The default value for the implementation. * Must not be null. @@ -141,4 +148,18 @@ public class FacadeTaskHelper { public boolean hasBeenSet() { return userChoice != null || magicValue != null; } + + /** + * The classpath to use when loading the implementation. + * + * @param project the current project + * @return a Path instance that may be appended to + * @since Ant 1.8.0 + */ + public Path getImplementationClasspath(Project project) { + if (implementationClasspath == null) { + implementationClasspath = new Path(project); + } + return implementationClasspath; + } } diff --git a/src/tests/antunit/taskdefs/javac-test.xml b/src/tests/antunit/taskdefs/javac-test.xml index 3180dcb72..55e794be6 100644 --- a/src/tests/antunit/taskdefs/javac-test.xml +++ b/src/tests/antunit/taskdefs/javac-test.xml @@ -119,4 +119,40 @@ updatedProperty="third-pass"/> + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/antunit/taskdefs/optional/javah-test.xml b/src/tests/antunit/taskdefs/optional/javah-test.xml new file mode 100644 index 000000000..9779ea4bc --- /dev/null +++ b/src/tests/antunit/taskdefs/optional/javah-test.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/antunit/taskdefs/optional/native2ascci-test.xml b/src/tests/antunit/taskdefs/optional/native2ascci-test.xml new file mode 100644 index 000000000..1bd192169 --- /dev/null +++ b/src/tests/antunit/taskdefs/optional/native2ascci-test.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/antunit/taskdefs/rmic-test.xml b/src/tests/antunit/taskdefs/rmic-test.xml new file mode 100644 index 000000000..f0cc36440 --- /dev/null +++ b/src/tests/antunit/taskdefs/rmic-test.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +