@@ -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:");