diff --git a/build.xml b/build.xml
index 7357672f0..199b3b8f5 100644
--- a/build.xml
+++ b/build.xml
@@ -29,6 +29,7 @@
When this task executes, it will recursively scan the srcdir + * looking for NetRexx source files to compile. This task makes its + * compile decision based on timestamp. + *
Before files are compiled they and any other file in the + * srcdir will be copied to the destdir allowing support files to be + * located properly in the classpath. The reason for copying the source files + * before the compile is that NetRexxC has only two destinations for classfiles: + *
aStringVar.getBytes
+ * vs. aStringVar.getBytes()
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setStrictargs(String strictargs) {
+ this.strictargs = Project.toBoolean(strictargs);
+ }
+
+ /**
+ * Tells the NetRexx compile that assignments must match exactly on type
+ */
+ public void setStrictassign(String strictassign) {
+ this.strictassign = Project.toBoolean(strictassign);
+ }
+
+ /**
+ * Specifies whether the NetRexx compiler should be case sensitive or not
+ */
+ public void setStrictcase(String strictcase) {
+ this.strictcase = Project.toBoolean(strictcase);
+ }
+
+ /**
+ * Sets whether classes need to be imported explicitly using an
+ * import
statement. By default the NetRexx compiler will import
+ * certain packages automatically
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setStrictimport(String strictimport) {
+ this.strictimport = Project.toBoolean(strictimport);
+ }
+
+ /**
+ * Sets whether local properties need to be qualified explicitly using this
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setStrictprops(String strictprops) {
+ this.strictprops = Project.toBoolean(strictprops);
+ }
+
+
+ /**
+ * Whether the compiler should force catching of exceptions by explicitly named types
+ */
+ public void setStrictsignal(String strictsignal) {
+ this.strictsignal = Project.toBoolean(strictsignal);
+ }
+
+ /**
+ * Sets whether debug symbols should be generated into the class file
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setSymbols(String symbols) {
+ this.symbols = Project.toBoolean(symbols);
+ }
+
+ /**
+ * Asks the NetRexx compiler to print compilation times to the console
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setTime(String time) {
+ this.time = Project.toBoolean(time);
+ }
+
+ /**
+ * Turns on or off tracing and directs the resultant trace output
+ * Valid values are: "trace", "trace1", "trace2" and "notrace".
+ * "trace" and "trace2"
+ */
+ public void setTrace(String trace) {
+ if (trace.equalsIgnoreCase("trace")
+ || trace.equalsIgnoreCase("trace1")
+ || trace.equalsIgnoreCase("trace2")
+ || trace.equalsIgnoreCase("notrace")) {
+ this.trace = trace;
+ } else {
+ throw new BuildException("Unknown trace value specified: '" + trace + "'");
+ }
+ }
+
+ /**
+ * Tells the NetRexx compiler that the source is in UTF8
+ * Valid true values are "on" or "true". Anything else sets the flag to false.
+ * The default value is false.
+ */
+ public void setUtf8(String utf8) {
+ this.utf8 = Project.toBoolean(utf8);
+ }
+
+ /**
+ * Whether lots of warnings and error messages should be generated
+ */
+ public void setVerbose(String verbose) {
+ this.verbose = verbose;
+ }
+
+ /**
+ * Executes the task, i.e. does the actual compiler call
+ */
+ public void execute() throws BuildException {
+
+ // first off, make sure that we've got a srcdir and destdir
+ if (srcDir == null || destDir == null ) {
+ throw new BuildException("srcDir and destDir attributes must be set!");
+ }
+
+ // scan source and dest dirs to build up both copy lists and
+ // compile lists
+ // scanDir(srcDir, destDir);
+ DirectoryScanner ds = getDirectoryScanner(srcDir);
+
+ String[] files = ds.getIncludedFiles();
+
+ scanDir(srcDir, destDir, files);
+
+ // copy the source and support files
+ copyFilesToDestination();
+
+ // compile the source files
+ if (compileList.size() > 0) {
+ project.log("Compiling " + compileList.size() + " source files to " + destDir);
+ doNetRexxCompile();
+ }
+ }
+
+ /**
+ * Scans the directory looking for source files to be compiled and
+ * support files to be copied.
+ */
+ private void scanDir(File srcDir, File destDir, String[] files) {
+ for (int i = 0; i < files.length; i++) {
+ File srcFile = new File(srcDir, files[i]);
+ File destFile = new File(destDir, files[i]);
+ String filename = files[i];
+ // if it's a non source file, copy it if a later date than the
+ // dest
+ // if it's a source file, see if the destination class file
+ // needs to be recreated via compilation
+ if (filename.toLowerCase().endsWith(".nrx")) {
+ File classFile = new File(destDir, filename.substring(0, filename.lastIndexOf('.')) + ".class");
+ if (!compile || srcFile.lastModified() > classFile.lastModified()) {
+ filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
+ compileList.addElement(destFile.getAbsolutePath());
+ }
+ } else {
+ if (srcFile.lastModified() > destFile.lastModified()) {
+ filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy eligible files from the srcDir to destDir
+ */
+ private void copyFilesToDestination() {
+ if (filecopyList.size() > 0) {
+ project.log("Copying " + filecopyList.size() + " files to " + destDir.getAbsolutePath());
+ Enumeration enum = filecopyList.keys();
+ while (enum.hasMoreElements()) {
+ String fromFile = (String)enum.nextElement();
+ String toFile = (String)filecopyList.get(fromFile);
+ try {
+ project.copyFile(fromFile, toFile);
+ } catch (IOException ioe) {
+ String msg = "Failed to copy " + fromFile + " to " + toFile
+ + " due to " + ioe.getMessage();
+ throw new BuildException(msg, ioe);
+ }
+ }
+ }
+ }
+
+ /**
+ * Peforms a copmile using the NetRexx 1.1.x compiler
+ */
+ private void doNetRexxCompile() throws BuildException {
+ project.log("Using NetRexx compiler", project.MSG_VERBOSE);
+ String classpath = getCompileClasspath();
+ StringBuffer compileOptions = new StringBuffer();
+ StringBuffer fileList = new StringBuffer();
+
+ // create an array of strings for input to the compiler: one array
+ // comes from the compile options, the other from the compileList
+ String[] compileOptionsArray = getCompileOptionsAsArray();
+ String[] fileListArray = new String[compileList.size()];
+ Enumeration e = compileList.elements();
+ int j = 0;
+ while (e.hasMoreElements()) {
+ fileListArray[j] = (String)e.nextElement();
+ j++;
+ }
+ // create a single array of arguments for the compiler
+ String compileArgs[] = new String[compileOptionsArray.length + fileListArray.length];
+ for (int i = 0; i < compileOptionsArray.length; i++) {
+ compileArgs[i] = compileOptionsArray[i];
+ }
+ for (int i = 0; i < fileListArray.length; i++) {
+ compileArgs[i+compileOptionsArray.length] = fileListArray[i];
+ }
+
+ // print nice output about what we are doing for the log
+ compileOptions.append("Compilation args: ");
+ for (int i = 0; i < compileOptionsArray.length; i++) {
+ compileOptions.append(compileOptionsArray[i]);
+ compileOptions.append(" ");
+ }
+ project.log(compileOptions.toString(), project.MSG_VERBOSE);
+
+ String eol = System.getProperty("line.separator");
+ StringBuffer niceSourceList = new StringBuffer("Files to be compiled:" + eol);
+
+ for (int i = 0; i < compileList.size(); i++) {
+ niceSourceList.append(" ");
+ niceSourceList.append(compileList.elementAt(i).toString());
+ niceSourceList.append(eol);
+ }
+
+ project.log(niceSourceList.toString(), project.MSG_VERBOSE);
+
+ // need to set java.class.path property and restore it later
+ // since the NetRexx compiler has no option for the classpath
+ String currentClassPath = System.getProperty("java.class.path");
+ Properties currentProperties = System.getProperties();
+ currentProperties.put("java.class.path", classpath);
+
+ try {
+ int rc = COM.ibm.netrexx.process.NetRexxC.main(
+ new Rexx(compileArgs), new PrintWriter(project.getOutput()));
+
+ if (rc > 1) { // 1 is warnings from real NetRexxC
+ String msg = "Compile failed, messages should have been provided.";
+ throw new BuildException(msg);
+ }
+ } finally {
+ // need to reset java.class.path property
+ // since the NetRexx compiler has no option for the classpath
+ currentProperties = System.getProperties();
+ currentProperties.put("java.class.path", currentClassPath);
+ }
+ }
+
+ /**
+ * Builds the compilation classpath.
+ */
+ private String getCompileClasspath() {
+ StringBuffer classpath = new StringBuffer();
+
+ // add dest dir to classpath so that previously compiled and
+ // untouched classes are on classpath
+ classpath.append(destDir.getAbsolutePath());
+
+ // add our classpath to the mix
+ if (this.classpath != null) {
+ addExistingToClasspath(classpath, this.classpath);
+ }
+
+ // add the system classpath
+ // addExistingToClasspath(classpath,System.getProperty("java.class.path"));
+ return classpath.toString();
+ }
+
+ /**
+ * This
+ */
+ private String[] getCompileOptionsAsArray() {
+ Vector options = new Vector();
+ options.addElement(binary ? "-binary" : "-nobinary");
+ options.addElement(comments ? "-comments" : "-nocomments");
+ options.addElement(compile ? "-compile" : "-nocompile");
+ options.addElement(compact ? "-compact" : "-nocompact");
+ options.addElement(console ? "-console" : "-noconsole");
+ options.addElement(crossref ? "-crossref" : "-nocrossref");
+ options.addElement(decimal ? "-decimal" : "-nodecimal");
+ options.addElement(diag ? "-diag" : "-nodiag");
+ options.addElement(explicit ? "-explicit": "-noexplicit");
+ options.addElement(format ? "-format" : "-noformat");
+ options.addElement(keep ? "-keep" : "-nokeep");
+ options.addElement(logo ? "-logo" : "-nologo");
+ options.addElement(replace ? "-replace" : "-noreplace");
+ options.addElement(savelog ? "-savelog" : "-nosavelog");
+ options.addElement(sourcedir ? "-sourcedir" : "-nosourcedir");
+ options.addElement(strictargs ? "-strictargs" : "-nostrictargs");
+ options.addElement(strictassign ? "-strictassign" : "-nostrictassign");
+ options.addElement(strictcase ? "-strictcase": "-nostrictcase");
+ options.addElement(strictimport ? "-strictimport" : "-nostrictimport");
+ options.addElement(strictprops ? "-strictprops" : "-nostrictprops");
+ options.addElement(strictsignal ? "-strictsignal" : "-nostrictsignal");
+ options.addElement(symbols ? "-symbols" : "-nosymbols");
+ options.addElement(time ? "-time" : "-notime");
+ options.addElement("-" + trace);
+ options.addElement(utf8 ? "-utf8" : "-noutf8");
+ options.addElement("-" + verbose);
+ String[] results = new String[options.size()];
+ options.copyInto(results);
+ return results;
+ }
+ /**
+ * Takes a classpath-like string, and adds each element of
+ * this string to a new classpath, if the components exist.
+ * Components that don't exist, aren't added.
+ * We do this, because jikes issues warnings for non-existant
+ * files/dirs in his classpath, and these warnings are pretty
+ * annoying.
+ * @param target - target classpath
+ * @param source - source classpath
+ * to get file objects.
+ */
+ private void addExistingToClasspath(StringBuffer target,String source) {
+ StringTokenizer tok = new StringTokenizer(source,
+ System.getProperty("path.separator"), false);
+ while (tok.hasMoreTokens()) {
+ File f = project.resolveFile(tok.nextToken());
+
+ if (f.exists()) {
+ target.append(File.pathSeparator);
+ target.append(f.getAbsolutePath());
+ } else {
+ project.log("Dropping from classpath: "+
+ f.getAbsolutePath(),project.MSG_VERBOSE);
+ }
+ }
+
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java b/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java
new file mode 100644
index 000000000..5eea03003
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java
@@ -0,0 +1,105 @@
+/*
+ * RenameExtensions.java
+ *
+ * Created on 16 March 2000, 23:14
+ */
+
+package org.apache.tools.ant.taskdefs.optional;
+
+import java.io.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.*;
+
+/**
+ *
+ * @author dion
+ * @version
+ */
+public class RenameExtensions extends MatchingTask {
+
+ private String fromExtension = "";
+ private String toExtension = "";
+ private boolean replace = false;
+ private File srcDir;
+
+
+ /** Creates new RenameExtensions */
+ public RenameExtensions() {
+ super();
+ }
+
+ /** store fromExtension **/
+ public void setFromExtension(String from) {
+ fromExtension = from;
+ }
+
+ /** store toExtension **/
+ public void setToExtension(String to) {
+ toExtension = to;
+ }
+
+ /**
+ * store replace attribute - this determines whether the target file
+ * should be overwritten if present
+ */
+ public void setReplace(String replaceString) {
+ replace = Project.toBoolean(replaceString);
+ }
+
+ /**
+ * Set the source dir to find the files to be renamed.
+ */
+ public void setSrcDir(String srcDirName) {
+ srcDir = project.resolveFile(srcDirName);
+ }
+
+ /**
+ * Executes the task, i.e. does the actual compiler call
+ */
+ public void execute() throws BuildException {
+
+ // first off, make sure that we've got a from and to extension
+ if (fromExtension == null || toExtension == null || srcDir == null) {
+ throw new BuildException("srcDir, destDir, fromExtension and toExtension attributes must be set!");
+ }
+
+ // scan source and dest dirs to build up rename list
+ DirectoryScanner ds = getDirectoryScanner(srcDir);
+
+ String[] files = ds.getIncludedFiles();
+
+ Hashtable renameList = scanDir(srcDir, files);
+
+ Enumeration e = renameList.keys();
+ File fromFile = null;
+ File toFile = null;
+ while (e.hasMoreElements()) {
+ fromFile = (File)e.nextElement();
+ toFile = (File)renameList.get(fromFile);
+ if (toFile.exists() && replace) toFile.delete();
+ if (!fromFile.renameTo(toFile)) throw new BuildException("Rename from: '" + fromFile + "' to '" + toFile + "' failed.");
+ }
+
+ }
+ private Hashtable scanDir(File srcDir, String[] files) {
+ Hashtable list = new Hashtable();
+ for (int i = 0; i < files.length; i++) {
+ File srcFile = new File(srcDir, files[i]);
+ String filename = files[i];
+ // if it's a file that ends in the fromExtension, copy to the rename list
+ if (filename.toLowerCase().endsWith(fromExtension)) {
+ File destFile = new File(srcDir, filename.substring(0, filename.lastIndexOf(fromExtension)) + toExtension);
+ if (replace || !destFile.exists()) {
+ list.put(srcFile, destFile);
+ } else {
+ project.log("Rejecting file: '" + srcFile + "' for rename as replace is false and file exists", Project.MSG_VERBOSE);
+ }
+ } else {
+ project.log("File '"+ filename + "' doesn't match fromExtension: '" + fromExtension + "'", Project.MSG_VERBOSE);
+ }
+ }
+ return list;
+ }
+
+}