diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java
index ab958cf84..e9cedf16b 100644
--- a/src/main/org/apache/tools/ant/AntClassLoader.java
+++ b/src/main/org/apache/tools/ant/AntClassLoader.java
@@ -57,6 +57,7 @@ package org.apache.tools.ant;
import java.util.*;
import java.util.zip.*;
import java.io.*;
+import org.apache.tools.ant.types.Path;
/**
* Used to load classes within ant with a different claspath from that used to start ant.
@@ -75,7 +76,7 @@ public class AntClassLoader extends ClassLoader {
/**
* The classpath that is to be used when loading classes using this class loader.
*/
- private org.apache.tools.ant.types.Path classpath;
+ private Path classpath;
/**
* The project to which this class loader belongs.
@@ -83,9 +84,22 @@ public class AntClassLoader extends ClassLoader {
private Project project;
/**
- * The File components of the path. Typically these will be directories or jar files.
+ * Indicates whether the system class loader should be
+ * consulted before trying to load with this class loader.
*/
- private Vector components = null;
+ private boolean systemFirst = true;
+
+ /**
+ * These are the package roots that are to be loaded by the system class loader
+ * regardless of whether the system class loader is being searched first or not.
+ */
+ private Vector systemPackages = new Vector();
+
+ /**
+ * These are the package roots that are to be loaded by this class loader
+ * regardless of whether the system class loader is being searched first or not.
+ */
+ private Vector loaderPackages = new Vector();
/**
* Create a classloader for the given project using the classpath given.
@@ -93,28 +107,47 @@ public class AntClassLoader extends ClassLoader {
* @param project the project to ehich this classloader is to belong.
* @param classpath the classpath to use to load the classes.
*/
- public AntClassLoader(Project project,
- org.apache.tools.ant.types.Path classpath) {
+ public AntClassLoader(Project project, Path classpath) {
this.project = project;
this.classpath = classpath;
}
/**
- * Set up this classloader for the first time.
+ * Create a classloader for the given project using the classpath given.
*
- * This method will set up the components field with the components from the
- * given classpath.
+ * @param project the project to ehich this classloader is to belong.
+ * @param classpath the classpath to use to load the classes.
*/
- private void setup() {
- // We iterate through the class path, resolving each element.
- components = new Vector();
-
- String[] pathElements = classpath.list();
- for (int i = 0; i < pathElements.length; ++i) {
- File element = project.resolveFile(pathElements[i]);
- components.addElement(element);
- }
+ public AntClassLoader(Project project, Path classpath, boolean systemFirst) {
+ this(project, classpath);
+ this.systemFirst = systemFirst;
}
+
+ /**
+ * Add a package root to the list of packages which must be loaded on the
+ * system loader.
+ *
+ * All subpackages are also included.
+ *
+ * @param packageRoot the root of akll packages to be included.
+ */
+ public void addSystemPackageRoot(String packageRoot) {
+ systemPackages.addElement(packageRoot + ".");
+ }
+
+ /**
+ * Add a package root to the list of packages which must be loaded using
+ * this loader.
+ *
+ * All subpackages are also included.
+ *
+ * @param packageRoot the root of akll packages to be included.
+ */
+ public void addLoaderPackageRoot(String packageRoot) {
+ loaderPackages.addElement(packageRoot + ".");
+ }
+
+
/**
* Load a class through this class loader even if that class is available on the
@@ -131,6 +164,7 @@ public class AntClassLoader extends ClassLoader {
* this loader's classpath.
*/
public Class forceLoadClass(String classname) throws ClassNotFoundException {
+ project.log("force loading " + classname, Project.MSG_VERBOSE);
Class theClass = findLoadedClass(classname);
if (theClass == null) {
@@ -140,6 +174,30 @@ public class AntClassLoader extends ClassLoader {
return theClass;
}
+ /**
+ * Load a class through this class loader but defer to the system class loader
+ *
+ * This ensures that instances of the returned class will be compatible with instances which
+ * which have already been loaded on the system loader.
+ *
+ * @param classname the classname to be loaded.
+ *
+ * @return the required Class object
+ *
+ * @throws ClassNotFoundException if the requested class does not exist on
+ * this loader's classpath.
+ */
+ public Class forceLoadSystemClass(String classname) throws ClassNotFoundException {
+ project.log("force system loading " + classname, Project.MSG_VERBOSE);
+ Class theClass = findLoadedClass(classname);
+
+ if (theClass == null) {
+ theClass = findSystemClass(classname);
+ }
+
+ return theClass;
+ }
+
/**
* Get a stream to read the requested resource name.
*
@@ -149,17 +207,13 @@ public class AntClassLoader extends ClassLoader {
* found on the loader's classpath.
*/
public InputStream getResourceAsStream(String name) {
- if (components == null) {
- // we haven't set up the list of directories and jars yet.
- setup();
- }
-
// we need to search the components of the path to see if we can find the
// class we want.
InputStream stream = null;
-
- for (Enumeration e = components.elements(); e.hasMoreElements() && stream == null; ) {
- File pathComponent = (File)e.nextElement();
+
+ String[] pathElements = classpath.list();
+ for (int i = 0; i < pathElements.length && stream == null; ++i) {
+ File pathComponent = project.resolveFile((String)pathElements[i]);
stream = getResourceStream(pathComponent, name);
}
@@ -168,7 +222,7 @@ public class AntClassLoader extends ClassLoader {
/**
* Get an inputstream to a given resource in the given file which may
- * either be a directory or a jar type file.
+ * either be a directory or a zip file.
*
* @param file the file (directory or jar) in which to search for the resource.
* @param resourceName the name of the resource for which a stream is required.
@@ -184,6 +238,7 @@ public class AntClassLoader extends ClassLoader {
if (file.isDirectory()) {
File resource = new File(file, resourceName);
+
if (resource.exists()) {
return new FileInputStream(resource);
}
@@ -238,14 +293,49 @@ public class AntClassLoader extends ClassLoader {
* the system classpath or this loader's classpath.
*/
protected Class loadClass(String classname, boolean resolve) throws ClassNotFoundException {
-
+
+ // default to the global setting and then see
+ // if this class belongs to a package which has been
+ // designated to use a specific loader first (this one or the system one)
+ boolean useSystemFirst = systemFirst;
+
+ for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) {
+ String packageName = (String)e.nextElement();
+ if (classname.startsWith(packageName)) {
+ useSystemFirst = true;
+ break;
+ }
+ }
+
+ for (Enumeration e = loaderPackages.elements(); e.hasMoreElements();) {
+ String packageName = (String)e.nextElement();
+ if (classname.startsWith(packageName)) {
+ useSystemFirst = false;
+ break;
+ }
+ }
+
Class theClass = findLoadedClass(classname);
if (theClass == null) {
- try {
- theClass = findSystemClass(classname);
+ if (useSystemFirst) {
+ try {
+ theClass = findSystemClass(classname);
+ project.log("Class " + classname + " loaded from system loader", Project.MSG_VERBOSE);
+ }
+ catch (ClassNotFoundException cnfe) {
+ theClass = findClass(classname);
+ project.log("Class " + classname + " loaded from ant loader", Project.MSG_VERBOSE);
+ }
}
- catch (ClassNotFoundException cnfe) {
- theClass = findClass(classname);
+ else {
+ try {
+ theClass = findClass(classname);
+ project.log("Class " + classname + " loaded from ant loader", Project.MSG_VERBOSE);
+ }
+ catch (ClassNotFoundException cnfe) {
+ theClass = findSystemClass(classname);
+ project.log("Class " + classname + " loaded from system loader", Project.MSG_VERBOSE);
+ }
}
}
@@ -294,6 +384,7 @@ public class AntClassLoader extends ClassLoader {
return defineClass(classname, classData, 0, classData.length);
}
+
/**
* Search for and load a class on the classpath of this class loader.
*
@@ -305,18 +396,29 @@ public class AntClassLoader extends ClassLoader {
* this loader's classpath.
*/
public Class findClass(String name) throws ClassNotFoundException {
- if (components == null) {
- // we haven't set up the list of directories and jars yet.
- setup();
+ project.log("Finding class " + name, Project.MSG_VERBOSE);
+
+ try {
+ return findClass(name, classpath);
+ }
+ catch (ClassNotFoundException e) {
+ throw e;
}
+ }
+
+ /**
+ * Find a class on the given classpath.
+ */
+ private Class findClass(String name, Path path) throws ClassNotFoundException {
// we need to search the components of the path to see if we can find the
// class we want.
InputStream stream = null;
String classFilename = getClassFilename(name);
try {
- for (Enumeration e = components.elements(); e.hasMoreElements() && stream == null; ) {
- File pathComponent = (File)e.nextElement();
+ String[] pathElements = path.list();
+ for (int i = 0; i < pathElements.length && stream == null; ++i) {
+ File pathComponent = project.resolveFile((String)pathElements[i]);
stream = getResourceStream(pathComponent, classFilename);
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/Ejbc.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/Ejbc.java
index 2f6844d2c..dfc34be11 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/Ejbc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/Ejbc.java
@@ -54,9 +54,7 @@
package org.apache.tools.ant.taskdefs.optional.ejb;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.Project;
+import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.Path;
@@ -70,6 +68,19 @@ import java.io.File;
* @author Conor MacNeill, Cortex ebusiness Pty Limited
*/
public class Ejbc extends MatchingTask {
+ static public interface Helper {
+ public void initialize(Ejbc ejbcTask);
+ public void setDescriptorDir(File dir);
+ public void setDest(File dir);
+ public void setManifest(File manifestFile);
+ public void setClasspath(Path classpath);
+ public void setSrc(File dir);
+ public void setDescriptors(String[] descriptors);
+ public void execute();
+ }
+
+
+
/**
* The root directory of the tree containing the serialised deployment desciptors. The actual
* deployment descriptor files are selected using include and exclude constructs
@@ -91,7 +102,7 @@ public class Ejbc extends MatchingTask {
* The classpath to be used in the weblogic ejbc calls. It must contain the weblogic
* classes and the implementation classes of the home and remote interfaces.
*/
- private String classpath;
+ private Path classpath;
/**
* The source directory for the home and remote interfaces. This is used to determine if
@@ -129,49 +140,53 @@ public class Ejbc extends MatchingTask {
}
String systemClassPath = System.getProperty("java.class.path");
- String execClassPath = project.translatePath(systemClassPath + ":" + classpath +
- ":" + generatedFilesDirectory);
+ Path execClassPath = new Path(project, classpath + ":" + generatedFilesDirectory + ":" + systemClassPath);
+
// get all the files in the descriptor directory
DirectoryScanner ds = super.getDirectoryScanner(descriptorDirectory);
- String[] files = ds.getIncludedFiles();
+ String[] descriptorNames = ds.getIncludedFiles();
+
- Java helperTask = (Java)project.createTask("java");
- helperTask.setFork(true);
- helperTask.setClassname("org.apache.tools.ant.taskdefs.optional.ejb.EjbcHelper");
- String args = "";
- args += " " + descriptorDirectory;
- args += " " + generatedFilesDirectory;
- args += " " + sourceDirectory;
- args += " " + generatedManifestFile;
- for (int i = 0; i < files.length; ++i) {
- args += " " + files[i];
+ // create an class loader
+ AntClassLoader loader = new AntClassLoader(project, execClassPath, false);
+ loader.addSystemPackageRoot("org.apache.tools.ant");
+ loader.addSystemPackageRoot("javax");
+ try {
+ Helper helper = (Helper)(loader.forceLoadClass("org.apache.tools.ant.taskdefs.optional.ejb.EjbcHelper").newInstance());
+ helper.initialize(this);
+ helper.setDescriptorDir(descriptorDirectory);
+ helper.setDest(generatedFilesDirectory);
+ helper.setManifest(generatedManifestFile);
+ helper.setSrc(sourceDirectory);
+ helper.setDescriptors(descriptorNames);
+ helper.setClasspath(execClassPath);
+ helper.execute();
+ helper = null;
}
-
- helperTask.setArgs(args);
- helperTask.setClasspath(new Path(project, execClassPath));
- if (helperTask.executeJava() != 0) {
- throw new BuildException("Execution of ejbc helper failed");
+ catch (Exception e) {
+ throw new BuildException(e);
}
+ loader = null;
}
/**
* Set the directory from where the serialised deployment descriptors are
* to be read.
*
- * @param dirName the name of the directory containing the serialised deployment descriptors.
+ * @param dir the directory containing the serialised deployment descriptors.
*/
- public void setDescriptors(String dirName) {
- descriptorDirectory = new File(dirName);
+ public void setDescriptors(File dir) {
+ descriptorDirectory = dir;
}
/**
* Set the directory into which the support classes, RMI stubs, etc are to be written
*
- * @param dirName the name of the directory into which code is generated
+ * @param dir the directory into which code is generated
*/
- public void setDest(String dirName) {
- generatedFilesDirectory = new File(dirName);
+ public void setDest(File dir) {
+ generatedFilesDirectory = dir;
}
/**
@@ -180,27 +195,27 @@ public class Ejbc extends MatchingTask {
* For each EJB that is processed an entry is created in this file. This can then be used
* to create a jar file for dploying the beans.
*
- * @param manfestFilename the name of the manifest file to be generated.
+ * @param manfestFilename the manifest file to be generated.
*/
- public void setManifest(String manifestFilename) {
- generatedManifestFile = new File(manifestFilename);
+ public void setManifest(File manifestFile) {
+ generatedManifestFile = manifestFile;
}
/**
* Set the classpath to be used for this compilation.
*/
- public void setClasspath(String s) {
- this.classpath = project.translatePath(s);
+ public void setClasspath(Path classpath) {
+ this.classpath = classpath;
}
/**
* Set the directory containing the source code for the home interface, remote interface
* and public key class definitions.
*
- * @param dirName the directory containg the source tree for the EJB's interface classes.
+ * @param dir the directory containg the source tree for the EJB's interface classes.
*/
- public void setSrc(String dirName) {
- sourceDirectory = new File(dirName);
+ public void setSrc(File dir) {
+ sourceDirectory = dir;
}
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbcHelper.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbcHelper.java
index 262ff887a..f68345f83 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbcHelper.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbcHelper.java
@@ -53,16 +53,13 @@
*/
package org.apache.tools.ant.taskdefs.optional.ejb;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.FileWriter;
+import java.io.*;
import javax.ejb.deployment.EntityDescriptor;
import javax.ejb.deployment.DeploymentDescriptor;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.Path;
/**
* A helper class which performs the actual work of the ejbc task.
@@ -72,7 +69,7 @@ import javax.ejb.deployment.DeploymentDescriptor;
*
* @author Conor MacNeill, Cortex ebusiness Pty Limited
*/
-public class EjbcHelper {
+public class EjbcHelper implements Ejbc.Helper {
/**
* The root directory of the tree containing the serialised deployment desciptors.
*/
@@ -92,43 +89,127 @@ public class EjbcHelper {
* The classpath to be used in the weblogic ejbc calls. It must contain the weblogic
* classes and the implementation classes of the home and remote interfaces.
*/
- private String classpath;
+ private Path classpath;
/**
* The source directory for the home and remote interfaces. This is used to determine if
* the generated deployment classes are out of date.
*/
private File sourceDirectory;
+
+ /**
+ * The array of descriptor filenames to be processed
+ */
+ private String[] files;
+
+ /**
+ * The Ejbc task that this helper is helping
+ */
+ private Ejbc ejbcTask;
/**
* The names of the serialised deployment descriptors
*/
String[] descriptors;
+ public EjbcHelper() {
+ }
+
+ public void initialize(Ejbc ejbcTask) {
+ this.ejbcTask = ejbcTask;
+ }
+
/**
- * Command line interface for the ejbc helper task.
- */
- public static void main(String[] args) throws Exception {
- EjbcHelper helper = new EjbcHelper(args);
- helper.process();
+ * Set the directory from where the serialised deployment descriptors are
+ * to be read.
+ *
+ * @param dir the directory containing the serialised deployment descriptors.
+ */
+ public void setDescriptorDir(File dir) {
+ descriptorDirectory = dir;
+ }
+
+ /**
+ * Set the directory into which the support classes, RMI stubs, etc are to be written
+ *
+ * @param dir the directory into which code is generated
+ */
+ public void setDest(File dir) {
+ generatedFilesDirectory = dir;
}
/**
- * Initialise the EjbcHelper by reading the command arguments.
- */
- private EjbcHelper(String[] args) {
- int index = 0;
- descriptorDirectory = new File(args[index++]);
- generatedFilesDirectory = new File(args[index++]);
- sourceDirectory = new File(args[index++]);
- manifestFile = new File(args[index++]);
-
- descriptors = new String[args.length - index];
- for (int i = 0; index < args.length; ++i) {
- descriptors[i] = args[index++];
+ * Set the generated manifest file.
+ *
+ * For each EJB that is processed an entry is created in this file. This can then be used
+ * to create a jar file for dploying the beans.
+ *
+ * @param manfestFilename the manifest file to be generated.
+ */
+ public void setManifest(File manifestFile) {
+ this.manifestFile = manifestFile;
+ }
+
+ /**
+ * Set the classpath to be used for this compilation.
+ */
+ public void setClasspath(Path classpath) {
+ this.classpath = classpath;
+ }
+
+ /**
+ * Set the list of desciptors which ar eto be processed.
+ *
+ * @param descriptors an array of serialised deployment descriptor filenames to be processed.
+ */
+ public void setDescriptors(String[] descriptors) {
+ this.descriptors = descriptors;
+ }
+
+
+
+ /**
+ * Set the directory containing the source code for the home interface, remote interface
+ * and public key class definitions.
+ *
+ * @param dir the directory containg the source tree for the EJB's interface classes.
+ */
+ public void setSrc(File dir) {
+ sourceDirectory = dir;
+ }
+
+ /**
+ * Perform the weblogic compiles.
+ */
+ public void execute() throws BuildException {
+ try {
+ String manifest = "Manifest-Version: 1.0\n\n";
+ for (int i = 0; i < descriptors.length; ++i) {
+ String descriptorName = descriptors[i];
+ File descriptorFile = new File(descriptorDirectory, descriptorName);
+
+ if (isRegenRequired(descriptorFile)) {
+ ejbcTask.log("Running ejbc for " + descriptorFile.getName(), Project.MSG_INFO);
+ regenerateSupportClasses(descriptorFile);
+ }
+ else {
+ ejbcTask.log(descriptorFile.getName() + " is up to date", Project.MSG_VERBOSE);
+ }
+ manifest += "Name: " + descriptorFile.getName() + "\nEnterprise-Bean: True\n\n";
+ }
+
+ FileWriter fw = new FileWriter(manifestFile);
+ PrintWriter pw = new PrintWriter(fw);
+ pw.print(manifest);
+ fw.flush();
+ fw.close();
+ }
+ catch (IOException e) {
+ throw new BuildException(e);
}
}
+
/**
* Determine if the weblogic EJB support classes need to be regenerated
* for a given deployment descriptor.
@@ -210,7 +291,8 @@ public class EjbcHelper {
}
}
catch (Throwable descriptorLoadException) {
- System.out.println("Exception occurred reading " + descriptorFile.getName() + " - continuing");
+ ejbcTask.log("Exception occurred reading " + descriptorFile.getName() + " - continuing",
+ Project.MSG_WARN);
// any problems - just regenerate
return true;
}
@@ -223,56 +305,57 @@ public class EjbcHelper {
return false;
}
- /**
- * Process the descriptors in turn generating support classes for each and a manifest
- * file for all of the beans.
- */
- private void process() throws Exception {
- String manifest = "Manifest-Version: 1.0\n\n";
- for (int i = 0; i < descriptors.length; ++i) {
- String descriptorName = descriptors[i];
- File descriptorFile = new File(descriptorDirectory, descriptorName);
-
- if (isRegenRequired(descriptorFile)) {
- System.out.println("Running ejbc for " + descriptorFile.getName());
- regenerateSupportClasses(descriptorFile);
- }
- else {
- System.out.println(descriptorFile.getName() + " is up to date");
- }
- manifest += "Name: " + descriptorFile.getName() + "\nEnterprise-Bean: True\n\n";
- }
-
- FileWriter fw = new FileWriter(manifestFile);
- PrintWriter pw = new PrintWriter(fw);
- pw.print(manifest);
- fw.flush();
- fw.close();
- }
-
/**
* Perform the weblogic.ejbc call to regenerate the support classes.
*
* Note that this method relies on an undocumented -noexit option to the
* ejbc tool to stop the ejbc tool exiting the VM altogether.
*/
- private void regenerateSupportClasses(File descriptorFile) throws Exception {
- // create a Java task to do the rebuild
+ private void regenerateSupportClasses(File descriptorFile) {
+ Project project = ejbcTask.getProject();
+ String javaHome = System.getProperty("java.home");
- String[] args = {"-noexit",
- "-keepgenerated",
- "-d", generatedFilesDirectory.getPath(),
- descriptorFile.getPath()};
+ String compiler = project.getProperty("build.compiler");
+ String[] args = null;
+ if (compiler.equalsIgnoreCase("jikes")) {
+ Path execClassPath = new Path(project);
+ if (Project.getJavaVersion() == Project.JAVA_1_1) {
+ execClassPath.addExisting(new Path(project, System.getProperty("java.home")
+ + "/lib/classes.zip"));
+ } else {
+ execClassPath.addExisting(new Path(project,
+ System.getProperty("java.home")
+ + "/lib/rt.jar"));
+ // Just keep the old version as well and let addExisting
+ // sort it out.
+ execClassPath.addExisting(new Path(project,
+ System.getProperty("java.home")
+ + "/jre/lib/rt.jar"));
+ }
+ execClassPath.append(classpath);
+
+ args = new String[] {"-noexit",
+ "-keepgenerated",
+ "-compiler", "Jikes",
+ "-d", generatedFilesDirectory.getPath(),
+ "-classpath", execClassPath.toString(),
+ descriptorFile.getPath()};
+ }
+ else {
+ args = new String[]{"-noexit",
+ "-keepgenerated",
+ "-d", generatedFilesDirectory.getPath(),
+ "-classpath", classpath.toString(),
+ descriptorFile.getPath()};
+ }
+
try {
weblogic.ejbc.main(args);
}
catch (Exception e) {
- // run with no exit for better reporting
- String[] newArgs = {"-keepgenerated",
- "-d", generatedFilesDirectory.getPath(),
- descriptorFile.getPath()};
- weblogic.ejbc.main(newArgs);
+ e.printStackTrace();
+ throw new BuildException(e);
}
}
}