From 13b07b313fdc7ab2620f71517ab16698be496f24 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Fri, 4 Feb 2005 08:08:07 +0000 Subject: [PATCH] Make javah a facade task, support kaffeh git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277590 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 16 +- docs/manual/OptionalTasks/javah.html | 62 +++- .../taskdefs/optional/javah/build.xml | 47 +++ .../optional/javah/input/org/example/Foo.java | 25 ++ .../tools/ant/taskdefs/optional/Javah.java | 315 +++++++++--------- .../ant/taskdefs/optional/Native2Ascii.java | 2 +- .../taskdefs/optional/javah/JavahAdapter.java | 34 ++ .../optional/javah/JavahAdapterFactory.java | 96 ++++++ .../ant/taskdefs/optional/javah/Kaffeh.java | 90 +++++ .../ant/taskdefs/optional/javah/SunJavah.java | 120 +++++++ .../ant/taskdefs/optional/JavahTest.java | 44 +++ 11 files changed, 684 insertions(+), 167 deletions(-) create mode 100644 src/etc/testcases/taskdefs/optional/javah/build.xml create mode 100644 src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/optional/JavahTest.java diff --git a/WHATSNEW b/WHATSNEW index 2d40a462b..de828fb0e 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -144,7 +144,7 @@ Other changes: * Added nested elements to and to allow specification of multiple sub-build targets, which are executed with a single dependency analysis. - + * Refactored Target invocation into org.apache.tools.ant.Executor implementations. Bugzilla Reports 21421, 29248. @@ -203,7 +203,7 @@ Other changes: * Added length task to get strings' and files' lengths. -* now also supports Kaffe's version. +* and now also support Kaffe's versions. * Recursive token expansion in a filterset can now be disabled by setting its recurse attribute to false. @@ -1291,6 +1291,18 @@ Other changes: clashes of custom tasks +* and now support , which let you enable + and disable Java1.4 assertions on a package or class basis. These + only work when fork=true, currently. + +* .NET tasks expanded with VB support and J#, via , + and . supports nested types, + for (potentially conditional) definitions, + filesets for references. The executable attribute lets you switch to + mono or other implementations - has been tested with Mono on + Linux and OSX. + + Changes from Ant 1.5.3 to Ant 1.5.4 =================================== diff --git a/docs/manual/OptionalTasks/javah.html b/docs/manual/OptionalTasks/javah.html index 8d06e7f06..0fb005b76 100644 --- a/docs/manual/OptionalTasks/javah.html +++ b/docs/manual/OptionalTasks/javah.html @@ -15,6 +15,16 @@ are needed to implement native methods. JNI operates differently depending on whether JDK1.2 (or later) or pre-JDK1.2 systems are used.

+ +

It is possible to use different compilers. This can be selected +with the implementation attribute. Here are the choices:

+
    +
  • default - the default compiler (kaffeh or sun) for the platform.
  • +
  • sun (the standard compiler of the JDK)
  • +
  • kaffeh (the native standard compiler of Kaffe)
  • +
+

Parameters

@@ -74,8 +84,58 @@ systems are used.

+ + + + +
location of installed extensions. No
implementationThe compiler implementation to use. If this + attribute is not set, the default compiler for the current VM + will be used. (See the above list of valid compilers.)No

Either outputFile or destdir must be supplied, but not both. 

+ +

Parameters specified as nested elements

+ +

arg

+ +

You can specify additional command line arguments for the compiler +with nested <arg> elements. These elements are +specified like Command-line Arguments +but have an additional attribute that can be used to enable arguments +only if a given compiler implementation will be used.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
valueSee + Command-line Arguments.Exactly one of these.
line
file
path
implementationOnly pass the specified argument if the chosen compiler + implementation matches the value of this attribute. Legal values + are the same as those in the above list of valid compilers.)No
+

Examples

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

makes a JNI header of the named class, using the JDK1.2 JNI model. Assuming @@ -110,7 +170,7 @@ writes the corresponding .c stubs. The verbose option will cause Javah to describe its progress.


-

Copyright © 2001-2002,2004 The Apache Software Foundation. All rights +

Copyright © 2001-2002,2004-2005 The Apache Software Foundation. All rights Reserved.

diff --git a/src/etc/testcases/taskdefs/optional/javah/build.xml b/src/etc/testcases/taskdefs/optional/javah/build.xml new file mode 100644 index 000000000..e54f218f6 --- /dev/null +++ b/src/etc/testcases/taskdefs/optional/javah/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + For tests only + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java b/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java new file mode 100644 index 000000000..e0e4f0535 --- /dev/null +++ b/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java @@ -0,0 +1,25 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.example; + +public class Foo { + + public Foo() {} + + public native String bar(Object baz); + +} 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 48b866543..a68f1f445 100755 --- a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java @@ -18,18 +18,21 @@ package org.apache.tools.ant.taskdefs.optional; import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.optional.javah.JavahAdapter; +import org.apache.tools.ant.taskdefs.optional.javah.JavahAdapterFactory; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.util.JavaEnvUtils; +import org.apache.tools.ant.util.facade.FacadeTaskHelper; +import org.apache.tools.ant.util.facade.ImplementationSpecificArgument; /** * Generates JNI header files using javah. @@ -76,6 +79,11 @@ public class Javah extends Task { private Path bootclasspath; //private Path extdirs; private static String lSep = System.getProperty("line.separator"); + private FacadeTaskHelper facade = null; + + public Javah() { + facade = new FacadeTaskHelper(JavahAdapterFactory.getDefault()); + } /** * the fully-qualified name of the class (or classes, separated by commas). @@ -101,7 +109,6 @@ public class Javah extends Task { public void setName(String name) { this.name = name; - log("ClassArgument.name=" + name); } public String getName() { @@ -109,6 +116,28 @@ public class Javah extends Task { } } + /** + * Names of the classes to process. + * + * @since Ant 1.6.3 + */ + public String[] getClasses() { + ArrayList al = new ArrayList(); + if (cls != null) { + StringTokenizer tok = new StringTokenizer(cls, ",", false); + while (tok.hasMoreTokens()) { + al.add(tok.nextToken().trim()); + } + } + + Enumeration e = classes.elements(); + while (e.hasMoreElements()) { + ClassArgument arg = (ClassArgument) e.nextElement(); + al.add(arg.getName()); + } + return (String[]) al.toArray(new String[0]); + } + /** * Set the destination directory into which the Java source * files should be compiled. @@ -117,6 +146,15 @@ public class Javah extends Task { this.destDir = destDir; } + /** + * The destination directory, if any. + * + * @since Ant 1.6.3 + */ + public File getDestdir() { + return destDir; + } + /** * the classpath to use. */ @@ -146,6 +184,15 @@ public class Javah extends Task { createClasspath().setRefid(r); } + /** + * The classpath to use. + * + * @since Ant 1.6.3 + */ + public Path getClasspath() { + return classpath; + } + /** * location of bootstrap class files. */ @@ -175,27 +222,14 @@ public class Javah extends Task { createBootclasspath().setRefid(r); } - ///** - // * Sets the extension directories that will be used during the - // * compilation. - // */ - //public void setExtdirs(Path extdirs) { - // if (this.extdirs == null) { - // this.extdirs = extdirs; - // } else { - // this.extdirs.append(extdirs); - // } - //} - - ///** - // * Maybe creates a nested classpath element. - // */ - //public Path createExtdirs() { - // if (extdirs == null) { - // extdirs = new Path(project); - // } - // return extdirs.createPath(); - //} + /** + * The bootclasspath to use. + * + * @since Ant 1.6.3 + */ + public Path getBootclasspath() { + return bootclasspath; + } /** * Concatenates the resulting header or source files for all @@ -205,6 +239,15 @@ public class Javah extends Task { this.outputFile = outputFile; } + /** + * The destination file, if any. + * + * @since Ant 1.6.3 + */ + public File getOutputfile() { + return outputFile; + } + /** * If true, output files should always be written (JDK1.2 only). */ @@ -212,6 +255,15 @@ public class Javah extends Task { this.force = force; } + /** + * Whether output files should always be written. + * + * @since Ant 1.6.3 + */ + public boolean getForce() { + return force; + } + /** * If true, specifies that old JDK1.0-style header files should be * generated. @@ -221,6 +273,15 @@ public class Javah extends Task { this.old = old; } + /** + * Whether old JDK1.0-style header files should be generated. + * + * @since Ant 1.6.3 + */ + public boolean getOld() { + return old; + } + /** * If true, generate C declarations from the Java object file (used with old). */ @@ -228,6 +289,15 @@ public class Javah extends Task { this.stubs = stubs; } + /** + * Whether C declarations from the Java object file should be generated. + * + * @since Ant 1.6.3 + */ + public boolean getStubs() { + return stubs; + } + /** * If true, causes Javah to print a message concerning * the status of the generated files. @@ -236,6 +306,51 @@ public class Javah extends Task { this.verbose = verbose; } + /** + * Whether verbose output should get generated. + * + * @since Ant 1.6.3 + */ + public boolean getVerbose() { + return verbose; + } + + /** + * Choose the implementation for this particular task. + * @param impl the name of the implemenation + * @since Ant 1.6.3 + */ + public void setImplementation(String impl) { + if ("default".equals(impl)) { + facade.setImplementation(JavahAdapterFactory.getDefault()); + } else { + facade.setImplementation(impl); + } + } + + /** + * Adds an implementation specific command-line argument. + * @return a ImplementationSpecificArgument to be configured + * + * @since Ant 1.6.3 + */ + public ImplementationSpecificArgument createArg() { + ImplementationSpecificArgument arg = + new ImplementationSpecificArgument(); + facade.addImplementationArgument(arg); + return arg; + } + + /** + * Returns the (implementation specific) settings given as nested + * arg elements. + * + * @since Ant 1.6.3 + */ + public String[] getCurrentArgs() { + return facade.getArgs(); + } + /** * Execute the task * @@ -271,132 +386,20 @@ public class Javah extends Task { classpath = classpath.concatSystemClasspath("ignore"); } - /* unused. - TODO: If anyone cannot come up with a reason for this, lets delete it - - String compiler = getProject().getProperty("build.compiler"); - if (compiler == null) { - if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1) - && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)) { - compiler = "modern"; - } else { - compiler = "classic"; - } + JavahAdapter ad = + JavahAdapterFactory.getAdapter(facade.getImplementation(), + this); + if (!ad.compile(this)) { + throw new BuildException("compilation failed"); } - */ - doClassicCompile(); } - // XXX - // we need a way to not use the current classpath. - /** - * Performs a compile using the classic compiler that shipped with - * JDK 1.1 and 1.2. - */ - - private void doClassicCompile() throws BuildException { - Commandline cmd = setupJavahCommand(); - - // Use reflection to be able to build on all JDKs - /* - // provide the compiler a different message sink - namely our own - sun.tools.javac.Main compiler = - new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac"); - - if (!compiler.compile(cmd.getArguments())) { - throw new BuildException("Compile failed"); - } - */ - - - try { - Class javahMainClass = null; - try { - // first search for the "old" javah class in 1.4.2 tools.jar - javahMainClass = Class.forName("com.sun.tools.javah.oldjavah.Main"); - } catch (ClassNotFoundException cnfe) { - // assume older than 1.4.2 tools.jar - javahMainClass = Class.forName("com.sun.tools.javah.Main"); - } - - // now search for the constructor that takes in String[] arguments. - Class[] strings = new Class[] {String[].class}; - Constructor constructor = javahMainClass.getConstructor(strings); - - // construct the javah Main instance - Object javahMain = constructor.newInstance(new Object[] {cmd.getArguments()}); - - // find the run method - Method runMethod = javahMainClass.getMethod("run", new Class[0]); - - runMethod.invoke(javahMain, new Object[0]); - } catch (Exception ex) { - if (ex instanceof BuildException) { - throw (BuildException) ex; - } else { - throw new BuildException("Error starting javah: " + ex, ex, getLocation()); - } - } - } - - /** - * Does the command line argument processing common to classic and - * modern. + * Logs the compilation parameters, adds the files to compile and logs the + * "niceSourceList" */ - private Commandline setupJavahCommand() { - Commandline cmd = new Commandline(); - - if (destDir != null) { - cmd.createArgument().setValue("-d"); - cmd.createArgument().setFile(destDir); - } - - if (outputFile != null) { - cmd.createArgument().setValue("-o"); - cmd.createArgument().setFile(outputFile); - } - - if (classpath != null) { - cmd.createArgument().setValue("-classpath"); - cmd.createArgument().setPath(classpath); - } - - // JDK1.1 is rather simpler than JDK1.2 - if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { - if (verbose) { - cmd.createArgument().setValue("-v"); - } - } else { - if (verbose) { - cmd.createArgument().setValue("-verbose"); - } - if (old) { - cmd.createArgument().setValue("-old"); - } - if (force) { - cmd.createArgument().setValue("-force"); - } - } - - if (stubs) { - if (!old) { - throw new BuildException("stubs only available in old mode.", getLocation()); - } - cmd.createArgument().setValue("-stubs"); - } - Path bcp = new Path(getProject()); - if (bootclasspath != null) { - bcp.append(bootclasspath); - } - bcp = bcp.concatSystemBootClasspath("ignore"); - if (bcp.size() > 0) { - cmd.createArgument().setValue("-bootclasspath"); - cmd.createArgument().setPath(bcp); - } - + public void logAndAddFiles(Commandline cmd) { logAndAddFilesToCompile(cmd); - return cmd; } /** @@ -404,32 +407,18 @@ public class Javah extends Task { * "niceSourceList" */ protected void logAndAddFilesToCompile(Commandline cmd) { - int n = 0; log("Compilation " + cmd.describeArguments(), Project.MSG_VERBOSE); StringBuffer niceClassList = new StringBuffer(); - if (cls != null) { - StringTokenizer tok = new StringTokenizer(cls, ",", false); - while (tok.hasMoreTokens()) { - String aClass = tok.nextToken().trim(); - cmd.createArgument().setValue(aClass); - niceClassList.append(" " + aClass + lSep); - n++; - } - } - - Enumeration e = classes.elements(); - while (e.hasMoreElements()) { - ClassArgument arg = (ClassArgument) e.nextElement(); - String aClass = arg.getName(); - cmd.createArgument().setValue(aClass); - niceClassList.append(" " + aClass + lSep); - n++; + String[] c = getClasses(); + for (int i = 0; i < c.length; i++) { + cmd.createArgument().setValue(c[i]); + niceClassList.append(" " + c[i] + lSep); } StringBuffer prefix = new StringBuffer("Class"); - if (n > 1) { + if (c.length > 1) { prefix.append("es"); } prefix.append(" to be compiled:"); 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 8ed26974e..35de85408 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java @@ -123,7 +123,7 @@ public class Native2Ascii extends MatchingTask { /** * Choose the implementation for this particular task. - * @param compiler the name of the compiler + * @param impl the name of the implemenation * @since Ant 1.6.3 */ public void setImplementation(String impl) { diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java new file mode 100644 index 000000000..4891eb80c --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java @@ -0,0 +1,34 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tools.ant.taskdefs.optional.javah; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.optional.Javah; + +/** + * Interface for different backend implementations of the Javah task. + * + * @since Ant 1.6.3 + */ +public interface JavahAdapter { + /** + * Performs the actual compilation. + * + * @since Ant 1.6.3 + */ + boolean compile(Javah javah) throws BuildException; +} \ No newline at end of file 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 new file mode 100644 index 000000000..9f3dff458 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +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.util.JavaEnvUtils; + +/** + * Creates the JavahAdapter based on the user choice and + * potentially the VM vendor. + * + * @since Ant 1.6.3 + */ +public class JavahAdapterFactory { + + /** + * Determines the default choice of adapter based on the VM + * vendor. + * + * @return the default choice of adapter based on the VM + * vendor + */ + public static String getDefault() { + if (JavaEnvUtils.isKaffe()) { + return Kaffeh.IMPLEMENTATION_NAME; + } + return SunJavah.IMPLEMENTATION_NAME; + } + + /** + * 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. + * @return The adapter to use. + */ + public static JavahAdapter getAdapter(String choice, + ProjectComponent log) + 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); + } + + // This default has been good enough until Ant 1.6.3, so stick + // with it + return new SunJavah(); + } + + /** + * Tries to resolve the given classname into a native2ascii adapter. + * Throws a fit if it can't. + * + * @param className The fully qualified classname to be created. + * @throws BuildException This is the fit that is thrown if className + * isn't an instance of JavahAdapter. + */ + private static JavahAdapter resolveClassName(String className) + throws BuildException { + try { + Class c = Class.forName(className); + Object o = c.newInstance(); + return (JavahAdapter) o; + } catch (ClassNotFoundException cnfe) { + throw new BuildException("Can't load " + className, cnfe); + } catch (ClassCastException cce) { + throw new BuildException(className + + " is not a Javah adapter", cce); + } catch (Throwable t) { + // for all other possibilities + throw new BuildException(className + " caused an interesting " + + "exception.", t); + } + } +} \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java new file mode 100644 index 000000000..5ed3d3c73 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java @@ -0,0 +1,90 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.optional.javah; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.optional.Javah; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.JavaEnvUtils; + +/** + * Adapter to the native kaffeh compiler. + * + * @since Ant 1.6.3 + */ +public class Kaffeh implements JavahAdapter { + + public static final String IMPLEMENTATION_NAME = "kaffeh"; + + /** + * Performs the actual compilation. + * + * @since Ant 1.6.3 + */ + public boolean compile(Javah javah) throws BuildException { + Commandline cmd = setupKaffehCommand(javah); + try { + Execute.runCommand(javah, cmd.getCommandline()); + return true; + } catch (BuildException e) { + if (e.getMessage().indexOf("failed with return code") == -1) { + throw e; + } + } + return false; + } + + private Commandline setupKaffehCommand(Javah javah) { + Commandline cmd = new Commandline(); + cmd.setExecutable(JavaEnvUtils.getJdkExecutable("kaffeh")); + + if (javah.getDestdir() != null) { + cmd.createArgument().setValue("-d"); + cmd.createArgument().setFile(javah.getDestdir()); + } + + if (javah.getOutputfile() != null) { + cmd.createArgument().setValue("-o"); + cmd.createArgument().setFile(javah.getOutputfile()); + } + + Path cp = new Path(javah.getProject()); + if (javah.getBootclasspath() != null) { + cp.append(javah.getBootclasspath()); + } + cp = cp.concatSystemBootClasspath("ignore"); + if (javah.getClasspath() != null) { + cp.append(javah.getClasspath()); + } + if (cp.size() > 0) { + cmd.createArgument().setValue("-classpath"); + cmd.createArgument().setPath(cp); + } + + if (!javah.getOld()) { + cmd.createArgument().setValue("-jni"); + } + + cmd.addArguments(javah.getCurrentArgs()); + + javah.logAndAddFiles(cmd); + return cmd; + } + +} \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java new file mode 100644 index 000000000..b6faf36af --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java @@ -0,0 +1,120 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.optional.javah; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.ExecuteJava; +import org.apache.tools.ant.taskdefs.optional.Javah; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.JavaEnvUtils; + +/** + * Adapter to com.sun.tools.javah.oldjavah.Main or com.sun.tools.javah.Main. + * + * @since Ant 1.6.3 + */ +public class SunJavah implements JavahAdapter { + + public static final String IMPLEMENTATION_NAME = "sun"; + + /** + * Performs the actual compilation. + * + * @since Ant 1.6.3 + */ + public boolean compile(Javah javah) throws BuildException { + Commandline cmd = setupJavahCommand(javah); + ExecuteJava ej = new ExecuteJava(); + + try { + try { + // first search for the "old" javah class in 1.4.2 tools.jar + Class.forName("com.sun.tools.javah.oldjavah.Main"); + cmd.setExecutable("com.sun.tools.javah.oldjavah.Main"); + } catch (ClassNotFoundException cnfe) { + // assume older than 1.4.2 tools.jar + Class.forName("com.sun.tools.javah.Main"); + cmd.setExecutable("com.sun.tools.javah.Main"); + } + } catch (ClassNotFoundException ex) { + throw new BuildException("Can't load javah", ex, + javah.getLocation()); + } + ej.setJavaCommand(cmd); + return ej.fork(javah) == 0; + } + + private Commandline setupJavahCommand(Javah javah) { + Commandline cmd = new Commandline(); + + if (javah.getDestdir() != null) { + cmd.createArgument().setValue("-d"); + cmd.createArgument().setFile(javah.getDestdir()); + } + + if (javah.getOutputfile() != null) { + cmd.createArgument().setValue("-o"); + cmd.createArgument().setFile(javah.getOutputfile()); + } + + if (javah.getClasspath() != null) { + cmd.createArgument().setValue("-classpath"); + cmd.createArgument().setPath(javah.getClasspath()); + } + + // JDK1.1 is rather simpler than JDK1.2 + if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) { + if (javah.getVerbose()) { + cmd.createArgument().setValue("-v"); + } + } else { + if (javah.getVerbose()) { + cmd.createArgument().setValue("-verbose"); + } + if (javah.getOld()) { + cmd.createArgument().setValue("-old"); + } + if (javah.getForce()) { + cmd.createArgument().setValue("-force"); + } + if (javah.getStubs() && !javah.getOld()) { + throw new BuildException("stubs only available in old mode.", + javah.getLocation()); + } + } + + if (javah.getStubs()) { + cmd.createArgument().setValue("-stubs"); + } + Path bcp = new Path(javah.getProject()); + if (javah.getBootclasspath() != null) { + bcp.append(javah.getBootclasspath()); + } + bcp = bcp.concatSystemBootClasspath("ignore"); + if (bcp.size() > 0) { + cmd.createArgument().setValue("-bootclasspath"); + cmd.createArgument().setPath(bcp); + } + + cmd.addArguments(javah.getCurrentArgs()); + + javah.logAndAddFiles(cmd); + return cmd; + } + +} \ No newline at end of file diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/JavahTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/JavahTest.java new file mode 100644 index 000000000..8148e9123 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/JavahTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.optional; + +import org.apache.tools.ant.BuildFileTest; + +public class JavahTest extends BuildFileTest { + + private final static String BUILD_XML = + "src/etc/testcases/taskdefs/optional/javah/build.xml"; + + public JavahTest(String name) { + super(name); + } + + public void setUp() { + configureProject(BUILD_XML); + } + + public void tearDown() { + executeTarget("tearDown"); + } + + public void testSimpleCompile() { + executeTarget("simple-compile"); + assertTrue(getProject().resolveFile("output/org_example_Foo.h") + .exists()); + } + +} \ No newline at end of file