diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java index 4b0b0f8f4..697da33af 100644 --- a/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java +++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java @@ -59,7 +59,7 @@ import java.net.*; import java.io.*; /** - * The AntClassLoader is a type of URL classloader which reverse the standard + * The AntClassLoader is a type of URL classloader which reverses the standard * lookup order to load things from the URLs first and then to use the parent class * loader only if the class does not exist in the URLs. * diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java index f9dc88dd6..42d138d27 100644 --- a/src/main/org/apache/tools/ant/AntClassLoader.java +++ b/src/main/org/apache/tools/ant/AntClassLoader.java @@ -70,7 +70,7 @@ import org.apache.tools.ant.types.Path; * @author Conor MacNeill * @author Jesse Glick */ -public class AntClassLoader extends ClassLoader implements BuildListener { +public class AntClassLoader extends ClassLoader implements BuildListener { /** * An enumeration of all resources of a given name found within the @@ -90,11 +90,6 @@ public class AntClassLoader extends ClassLoader implements BuildListener { */ private String resourceName; - /** - * The array of classpath elements. - */ - private String[] pathElements; - /** * The index of the next classpath element to search. */ @@ -115,7 +110,6 @@ public class AntClassLoader extends ClassLoader implements BuildListener { */ ResourceEnumeration(String name) { this.resourceName = name; - this.pathElements = AntClassLoader.this.classpath.list(); this.pathElementsIndex = 0; findNextResource(); } @@ -150,13 +144,13 @@ public class AntClassLoader extends ClassLoader implements BuildListener { */ private void findNextResource() { URL url = null; - while ((this.pathElementsIndex < this.pathElements.length) && + while ((pathElementsIndex < pathComponents.size()) && (url == null)) { try { - File pathComponent = AntClassLoader.this.project.resolveFile( - (String)this.pathElements[this.pathElementsIndex]); + File pathComponent + = (File)pathComponents.elementAt(pathElementsIndex); url = getResourceURL(pathComponent, this.resourceName); - this.pathElementsIndex++; + pathElementsIndex++; } catch (BuildException e) { // ignore path elements which are not valid relative to the project @@ -172,9 +166,9 @@ public class AntClassLoader extends ClassLoader implements BuildListener { static private final int BUFFER_SIZE = 1024; /** - * The classpath that is to be used when loading classes using this class loader. - */ - private Path classpath; + * The components of the classpath that the classloader searches for classes + */ + Vector pathComponents = new Vector(); /** * The project to which this class loader belongs. @@ -182,28 +176,33 @@ public class AntClassLoader extends ClassLoader implements BuildListener { private Project project; /** - * Indicates whether the system class loader should be + * Indicates whether the parent class loader should be * consulted before trying to load with this class loader. */ - private boolean systemFirst = true; + private boolean parentFirst = 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. + * These are the package roots that are to be loaded by the parent class loader + * regardless of whether the parent 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. + * regardless of whether the parent class loader is being searched first or not. */ private Vector loaderPackages = new Vector(); /** * This flag indicates that the classloader will ignore the base - * classloader if it can;t find a class. + * classloader if it can't find a class. */ private boolean ignoreBase = false; + + /** + * The parent class loader, if one is given or can be determined + */ + private ClassLoader parent = null; private static Method getProtectionDomain = null; private static Method defineClassProtectionDomain = null; @@ -227,24 +226,75 @@ public class AntClassLoader extends ClassLoader implements BuildListener { * determined by the value of ${build.sysclasspath} */ public AntClassLoader(Project project, Path classpath) { + parent = AntClassLoader.class.getClassLoader(); this.project = project; - this.project.addBuildListener(this); - this.classpath = classpath.concatSystemClasspath("ignore"); + project.addBuildListener(this); + if (classpath != null) { + Path actualClasspath = classpath.concatSystemClasspath("ignore"); + String[] pathElements = actualClasspath.list(); + for (int i = 0; i < pathElements.length; ++i) { + try { + addPathElement((String)pathElements[i]); + } + catch (BuildException e) { + // ignore path elements which are invalid relative to the project + } + } + } } - + /** * Create a classloader for the given project using the classpath given. * * @param project the project to which this classloader is to belong. * @param classpath the classpath to use to load the classes. */ - public AntClassLoader(Project project, Path classpath, boolean systemFirst) { + public AntClassLoader(ClassLoader parent, Project project, Path classpath, + boolean parentFirst) { this(project, classpath); - this.systemFirst = systemFirst; + if (parent != null) { + this.parent = parent; + } + this.parentFirst = parentFirst; addSystemPackageRoot("java"); addSystemPackageRoot("javax"); } + /** + * Create an empty class loader + * + */ + public AntClassLoader(ClassLoader parent, boolean parentFirst) { + if (parent != null) { + this.parent = parent; + } + else { + parent = AntClassLoader.class.getClassLoader(); + } + project = null; + this.parentFirst = parentFirst; + } + + protected void log(String message, int priority) { + if (project != null) { + project.log(message, priority); + } +// else { +// System.out.println(message); +// } + } + + /** + * Add an element to the classpath to be searched + * + */ + public void addPathElement(String pathElement) throws BuildException { + File pathComponent + = project != null ? project.resolveFile(pathElement) + : new File(pathElement); + pathComponents.addElement(pathComponent); + } + /** * Set this classloader to run in isolated mode. In isolated mode, classes not * found on the given classpath will not be referred to the base class loader @@ -272,7 +322,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener { /** * Add a package root to the list of packages which must be loaded on the - * system loader. + * parent loader. * * All subpackages are also included. * @@ -298,7 +348,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener { /** * Load a class through this class loader even if that class is available on the - * system classpath. + * parent classpath. * * This ensures that any classes which are loaded by the returned class will use this * classloader. @@ -311,7 +361,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener { * this loader's classpath. */ public Class forceLoadClass(String classname) throws ClassNotFoundException { - project.log("force loading " + classname, Project.MSG_DEBUG); + log("force loading " + classname, Project.MSG_DEBUG); + Class theClass = findLoadedClass(classname); if (theClass == null) { @@ -322,10 +373,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener { } /** - * Load a class through this class loader but defer to the system class loader + * Load a class through this class loader but defer to the parent 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. + * which have already been loaded on the parent loader. * * @param classname the classname to be loaded. * @@ -335,7 +386,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener { * this loader's classpath. */ public Class forceLoadSystemClass(String classname) throws ClassNotFoundException { - project.log("force system loading " + classname, Project.MSG_DEBUG); + log("force system loading " + classname, Project.MSG_DEBUG); + Class theClass = findLoadedClass(classname); if (theClass == null) { @@ -356,38 +408,38 @@ public class AntClassLoader extends ClassLoader implements BuildListener { public InputStream getResourceAsStream(String name) { InputStream resourceStream = null; - if (isSystemFirst(name)) { + if (isParentFirst(name)) { resourceStream = loadBaseResource(name); if (resourceStream != null) { - project.log("ResourceStream for " + name - + " loaded from system loader", Project.MSG_DEBUG); + log("ResourceStream for " + name + + " loaded from parent loader", Project.MSG_DEBUG); } else { resourceStream = loadResource(name); if (resourceStream != null) { - project.log("ResourceStream for " + name - + " loaded from ant loader", Project.MSG_DEBUG); + log("ResourceStream for " + name + + " loaded from ant loader", Project.MSG_DEBUG); } } } else { resourceStream = loadResource(name); if (resourceStream != null) { - project.log("ResourceStream for " + name - + " loaded from ant loader", Project.MSG_DEBUG); + log("ResourceStream for " + name + + " loaded from ant loader", Project.MSG_DEBUG); } else { resourceStream = loadBaseResource(name); if (resourceStream != null) { - project.log("ResourceStream for " + name - + " loaded from system loader", Project.MSG_DEBUG); + log("ResourceStream for " + name + + " loaded from parent loader", Project.MSG_DEBUG); } } } if (resourceStream == null) { - project.log("Couldn't load ResourceStream for " + name, - Project.MSG_WARN); + log("Couldn't load ResourceStream for " + name, + Project.MSG_WARN); } return resourceStream; @@ -408,30 +460,22 @@ public class AntClassLoader extends ClassLoader implements BuildListener { // class we want. InputStream stream = null; - String[] pathElements = classpath.list(); - for (int i = 0; i < pathElements.length && stream == null; ++i) { - try { - File pathComponent = project.resolveFile((String)pathElements[i]); - stream = getResourceStream(pathComponent, name); - } - catch (BuildException e) { - // ignore path elements which are invalid relative to the project - } + for (Enumeration e = pathComponents.elements(); e.hasMoreElements() && stream == null; ) { + File pathComponent = (File)e.nextElement(); + stream = getResourceStream(pathComponent, name); } - return stream; } /** - * Find a system resource (which should be loaded from the same classloader as the Ant core). + * Find a system resource (which should be loaded from the parent classloader). */ private InputStream loadBaseResource(String name) { - ClassLoader base = AntClassLoader.class.getClassLoader(); - if (base == null) { + if (parent == null) { return getSystemResourceAsStream(name); } else { - return base.getResourceAsStream(name); + return parent.getResourceAsStream(name); } } @@ -485,22 +529,23 @@ public class AntClassLoader extends ClassLoader implements BuildListener { } } catch (Exception e) { - e.printStackTrace(); + log("Ignoring Exception " + e.getClass().getName() + ": " + e.getMessage() + + " reading resource " + resourceName + " from " + file, Project.MSG_VERBOSE); } return null; } - private boolean isSystemFirst(String resourceName) { + private boolean isParentFirst(String resourceName) { // 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; + // designated to use a specific loader first (this one or the parent one) + boolean useParentFirst = parentFirst; for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) { String packageName = (String)e.nextElement(); if (resourceName.startsWith(packageName)) { - useSystemFirst = true; + useParentFirst = true; break; } } @@ -508,12 +553,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener { for (Enumeration e = loaderPackages.elements(); e.hasMoreElements();) { String packageName = (String)e.nextElement(); if (resourceName.startsWith(packageName)) { - useSystemFirst = false; + useParentFirst = false; break; } } - return useSystemFirst; + return useParentFirst; } @@ -536,45 +581,40 @@ public class AntClassLoader extends ClassLoader implements BuildListener { // we need to search the components of the path to see if we can find the // class we want. URL url = null; - if (isSystemFirst(name)) { - url = super.getResource(name); + if (isParentFirst(name)) { + url = (parent == null) ? super.getResource(name) : parent.getResource(name); } if (url != null) { - project.log("Resource " + name + " loaded from system loader", - Project.MSG_DEBUG); + log("Resource " + name + " loaded from parent loader", + Project.MSG_DEBUG); } else { // try and load from this loader if the parent either didn't find // it or wasn't consulted. - String[] pathElements = classpath.list(); - for (int i = 0; i < pathElements.length && url == null; ++i) { - try { - File pathComponent = project.resolveFile((String)pathElements[i]); - url = getResourceURL(pathComponent, name); - if (url != null) { - project.log("Resource " + name - + " loaded from ant loader", - Project.MSG_DEBUG); - } - } - catch (BuildException e) { - // ignore path elements which are invalid relative to the project + for (Enumeration e = pathComponents.elements(); e.hasMoreElements() && url == null; ) { + File pathComponent = (File)e.nextElement(); + url = getResourceURL(pathComponent, name); + if (url != null) { + log("Resource " + name + + " loaded from ant loader", + Project.MSG_DEBUG); } } } - if (url == null && !isSystemFirst(name)) { + if (url == null && !isParentFirst(name)) { // this loader was first but it didn't find it - try the parent - url = super.getResource(name); + + url = (parent == null) ? super.getResource(name) : parent.getResource(name); if (url != null) { - project.log("Resource " + name + " loaded from system loader", - Project.MSG_DEBUG); + log("Resource " + name + " loaded from parent loader", + Project.MSG_DEBUG); } } if (url == null) { - project.log("Couldn't load Resource " + name, Project.MSG_WARN); + log("Couldn't load Resource " + name, Project.MSG_WARN); } return url; @@ -673,27 +713,27 @@ public class AntClassLoader extends ClassLoader implements BuildListener { return theClass; } - if (isSystemFirst(classname)) { + if (isParentFirst(classname)) { try { theClass = findBaseClass(classname); - project.log("Class " + classname + " loaded from system loader", Project.MSG_DEBUG); + log("Class " + classname + " loaded from parent loader", Project.MSG_DEBUG); } catch (ClassNotFoundException cnfe) { theClass = findClass(classname); - project.log("Class " + classname + " loaded from ant loader", Project.MSG_DEBUG); + log("Class " + classname + " loaded from ant loader", Project.MSG_DEBUG); } } else { try { theClass = findClass(classname); - project.log("Class " + classname + " loaded from ant loader", Project.MSG_DEBUG); + log("Class " + classname + " loaded from ant loader", Project.MSG_DEBUG); } catch (ClassNotFoundException cnfe) { if (ignoreBase) { throw cnfe; } theClass = findBaseClass(classname); - project.log("Class " + classname + " loaded from system loader", Project.MSG_DEBUG); + log("Class " + classname + " loaded from parent loader", Project.MSG_DEBUG); } } @@ -705,12 +745,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener { } /** - * Convert the class dot notation to a file system equivalent for + * Convert the class dot notation to a filesystem equivalent for * searching purposes. * * @param classname the class name in dot format (ie java.lang.Integer) * - * @return the classname in file system format (ie java/lang/Integer.class) + * @return the classname in filesystem format (ie java/lang/Integer.class) */ private String getClassFilename(String classname) { return classname.replace('.', '/') + ".class"; @@ -777,45 +817,34 @@ public class AntClassLoader extends ClassLoader implements BuildListener { * this loader's classpath. */ public Class findClass(String name) throws ClassNotFoundException { - project.log("Finding class " + name, Project.MSG_DEBUG); + log("Finding class " + name, Project.MSG_DEBUG); - try { - return findClass(name, classpath); - } - catch (ClassNotFoundException e) { - throw e; - } + return findClassInComponents(name); } /** * Find a class on the given classpath. */ - private Class findClass(String name, Path path) throws ClassNotFoundException { + private Class findClassInComponents(String name) 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 { - String[] pathElements = path.list(); - for (int i = 0; i < pathElements.length && stream == null; ++i) { + for (Enumeration e = pathComponents.elements(); e.hasMoreElements(); ) { + File pathComponent = (File)e.nextElement(); try { - File pathComponent = project.resolveFile((String)pathElements[i]); stream = getResourceStream(pathComponent, classFilename); + if (stream != null) { + return getClassFromStream(stream, name); + } } - catch (BuildException e) { - // ignore invalid paths + catch (IOException ioe) { + log("Exception reading component " + pathComponent , Project.MSG_VERBOSE); } } - - if (stream == null) { - throw new ClassNotFoundException(); - } - - return getClassFromStream(stream, name); - } - catch (IOException ioe) { - ioe.printStackTrace(); + throw new ClassNotFoundException(); } finally { @@ -832,19 +861,18 @@ public class AntClassLoader extends ClassLoader implements BuildListener { * Find a system class (which should be loaded from the same classloader as the Ant core). */ private Class findBaseClass(String name) throws ClassNotFoundException { - ClassLoader base = AntClassLoader.class.getClassLoader(); - if (base == null) { + if (parent == null) { return findSystemClass(name); } else { - return base.loadClass(name); + return parent.loadClass(name); } } public void buildStarted(BuildEvent event) {} public void buildFinished(BuildEvent event) { - classpath = null; + pathComponents = null; project = null; } diff --git a/src/main/org/apache/tools/ant/Launcher.java b/src/main/org/apache/tools/ant/Launcher.java new file mode 100644 index 000000000..6b14b98a5 --- /dev/null +++ b/src/main/org/apache/tools/ant/Launcher.java @@ -0,0 +1,201 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.lang.reflect.*; + +/** + * This is the Ant command line front end to end. This front end + * works out where ant is installed and loads the ant libraries before + * starting Ant proper. + * + * @author Conor MacNeill + */ +public class Launcher { + static private File determineAntHome11() { + String classpath = System.getProperty("java.class.path"); + StringTokenizer tokenizer = new StringTokenizer(classpath, System.getProperty("path.separator")); + while (tokenizer.hasMoreTokens()) { + String path = tokenizer.nextToken(); + if (path.endsWith("ant.jar")) { + File antJarFile = new File(path); + File libDirectory = new File(antJarFile.getParent()); + File antHome = new File(libDirectory.getParent()); + return antHome; + } + } + return null; + } + + static private File determineAntHome(ClassLoader systemClassLoader) { + try { + String className = Launcher.class.getName().replace('.', '/') + ".class"; + URL classResource = systemClassLoader.getResource(className); + String fileComponent = classResource.getFile(); + if (classResource.getProtocol().equals("file")) { + // Class comes from a directory of class files rather than + // from a jar. + int classFileIndex = fileComponent.lastIndexOf(className); + if (classFileIndex != -1) { + fileComponent = fileComponent.substring(0, classFileIndex); + } + File classFilesDir = new File(fileComponent); + File buildDir = new File(classFilesDir.getParent()); + File devAntHome = new File(buildDir.getParent()); + return devAntHome; + } + else if (classResource.getProtocol().equals("jar")) { + // Class is coming from a jar. The file component of the URL + // is actually the URL of the jar file + int classSeparatorIndex = fileComponent.lastIndexOf("!"); + if (classSeparatorIndex != -1) { + fileComponent = fileComponent.substring(0, classSeparatorIndex); + } + URL antJarURL = new URL(fileComponent); + File antJarFile = new File(antJarURL.getFile()); + File libDirectory = new File(antJarFile.getParent()); + File antHome = new File(libDirectory.getParent()); + return antHome; + } + } + catch (MalformedURLException e) { + e.printStackTrace(); + } + return null; + } + + static private void addDirJars(AntClassLoader classLoader, File jarDir) { + String[] fileList = jarDir.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + + if (fileList != null) { + for (int i = 0; i < fileList.length; ++i) { + File jarFile = new File(jarDir, fileList[i]); + classLoader.addPathElement(jarFile.getAbsolutePath()); + } + } + } + + static private void addToolsJar(AntClassLoader antLoader) { + String javaHome = System.getProperty("java.home"); + if (javaHome.endsWith("jre")) { + javaHome = javaHome.substring(0, javaHome.length() - 4); + } + System.out.println("Java home is " + javaHome); + File toolsJar = new File(javaHome, "lib/tools.jar"); + if (!toolsJar.exists()) { + System.out.println("Unable to find tools.jar at " + toolsJar.getPath()); + } + else { + antLoader.addPathElement(toolsJar.getAbsolutePath()); + } + } + + + static public void main(String[] args) { + File antHome = null; + ClassLoader systemClassLoader = Launcher.class.getClassLoader(); + if (systemClassLoader == null) { + antHome = determineAntHome11(); + } + else { + antHome = determineAntHome(systemClassLoader); + } + if (antHome == null) { + System.err.println("Unable to determine ANT_HOME"); + System.exit(1); + } + + System.out.println("ANT_HOME is " + antHome); + + // We now create the class loader with which we are going to launch ant + AntClassLoader antLoader = new AntClassLoader(systemClassLoader, false); + + // need to find tools.jar + addToolsJar(antLoader); + + // add everything in the lib directory to this classloader + File libDir = new File(antHome, "lib"); + addDirJars(antLoader, libDir); + + File optionalDir = new File(antHome, "lib/optional"); + addDirJars(antLoader, optionalDir); + + Properties launchProperties = new Properties(); + launchProperties.put("ant.home", antHome.getAbsolutePath()); + + try { + Class mainClass = antLoader.loadClass("org.apache.tools.ant.Main"); + antLoader.initializeClass(mainClass); + + final Class[] param = {Class.forName("[Ljava.lang.String;"), + Properties.class, ClassLoader.class}; + final Method startMethod = mainClass.getMethod("start", param); + final Object[] argument = {args, launchProperties, systemClassLoader}; + startMethod.invoke(null, argument); + } + catch (Exception e) { + System.out.println("Exception running Ant: " + e.getClass().getName() + ": " + e.getMessage()); + e.printStackTrace(); + } + } +} + diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java index 00a1a7cdb..e8512a240 100644 --- a/src/main/org/apache/tools/ant/Main.java +++ b/src/main/org/apache/tools/ant/Main.java @@ -129,13 +129,10 @@ public class Main { } /** - * Command line entry point. This method kicks off the building - * of a project object and executes a build using either a given - * target or the default target. - * - * @param args Command line args. + * Entry point allowing for more options from other front ends */ - public static void main(String[] args) { + public static void start(String[] args, Properties additionalUserProperties, + ClassLoader systemLoader) { Main m = null; try { @@ -145,8 +142,16 @@ public class Main { System.exit(1); } + if (additionalUserProperties != null) { + for (Enumeration e = additionalUserProperties.keys(); e.hasMoreElements(); ) { + String key = (String) e.nextElement(); + String property = additionalUserProperties.getProperty(key); + m.definedProps.put(key, property); + } + } + try { - m.runBuild(); + m.runBuild(systemLoader); System.exit(0); } catch (BuildException be) { if (m.err != System.err) { @@ -158,6 +163,19 @@ public class Main { System.exit(1); } } + + + + /** + * Command line entry point. This method kicks off the building + * of a project object and executes a build using either a given + * target or the default target. + * + * @param args Command line args. + */ + public static void main(String[] args) { + start(args, null, null); + } protected Main(String[] args) throws BuildException { @@ -364,7 +382,7 @@ public class Main { /** * Executes the build. */ - private void runBuild() throws BuildException { + private void runBuild(ClassLoader systemLoader) throws BuildException { if (!readyToRun) { return; @@ -377,7 +395,8 @@ public class Main { } Project project = new Project(); - + project.setSystemLoader(systemLoader); + Throwable error = null; try { diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index edc73c53c..fc2aff151 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -111,6 +111,9 @@ public class Project { private static java.lang.reflect.Method setLastModified = null; private static Object lockReflection = new Object(); + /** The system classloader - may be null */ + private ClassLoader systemLoader = null; + static { // Determine the Java version by looking at available classes @@ -212,6 +215,14 @@ public class Project { } } + public void setSystemLoader(ClassLoader systemLoader) { + this.systemLoader = systemLoader; + } + + public ClassLoader getSystemLoader() { + return systemLoader; + } + public void addBuildListener(BuildListener listener) { listeners.addElement(listener); } diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java index 7fca86257..f85f5fec9 100644 --- a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java @@ -119,7 +119,8 @@ public class ExecuteJava { if (classpath == null) { target = Class.forName(classname); } else { - AntClassLoader loader = new AntClassLoader(project, classpath, false); + AntClassLoader loader + = new AntClassLoader(project.getSystemLoader(), project, classpath, false); loader.setIsolated(true); target = loader.forceLoadClass(classname); AntClassLoader.initializeClass(target); diff --git a/src/main/org/apache/tools/ant/taskdefs/Java.java b/src/main/org/apache/tools/ant/taskdefs/Java.java index 2576a3bfe..5bab1d8a2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Java.java +++ b/src/main/org/apache/tools/ant/taskdefs/Java.java @@ -54,7 +54,6 @@ package org.apache.tools.ant.taskdefs; -import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java index f3422792d..483ab368d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java @@ -529,7 +529,7 @@ public class JUnitTask extends Task { if (classpath != null) { log("Using CLASSPATH " + classpath, Project.MSG_VERBOSE); - cl = new AntClassLoader(project, classpath, false); + cl = new AntClassLoader(null, project, classpath, false); // make sure the test will be accepted as a TestCase cl.addSystemPackageRoot("junit"); // will cause trouble in JDK 1.1 if omitted