diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java
index 893decbb8..403abcbc4 100644
--- a/src/main/org/apache/tools/ant/AntClassLoader.java
+++ b/src/main/org/apache/tools/ant/AntClassLoader.java
@@ -70,6 +70,7 @@ import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.net.MalformedURLException;
import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.LoaderUtils;
/**
* Used to load classes within ant with a different claspath from
@@ -181,8 +182,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* The components of the classpath that the classloader searches
* for classes.
*/
- // XXX: Any reason this shouldn't be private?
- Vector pathComponents = new Vector();
+ private Vector pathComponents = new Vector();
/**
* The project to which this class loader belongs.
@@ -228,7 +228,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
private Hashtable zipFiles = new Hashtable();
/**
- * The context loader saved when setting the thread's current context loader.
+ * The context loader saved when setting the thread's current
+ * context loader.
*/
private ClassLoader savedContextLoader = null;
/**
@@ -248,29 +249,18 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
*/
private static Method defineClassProtectionDomain = null;
- /**
- * Reflection method reference for getContextClassLoader;
- * used to avoid 1.1-compatibility problems.
- */
- private static Method getContextClassLoader = null;
-
- /**
- * Reflection method reference for setContextClassLoader;
- * used to avoid 1.1-compatibility problems.
- */
- private static Method setContextClassLoader = null;
// Set up the reflection-based Java2 methods if possible
static {
try {
- getProtectionDomain = Class.class.getMethod("getProtectionDomain", new Class[0]);
- Class protectionDomain = Class.forName("java.security.ProtectionDomain");
- Class[] args = new Class[] {String.class, byte[].class, Integer.TYPE, Integer.TYPE, protectionDomain};
- defineClassProtectionDomain = ClassLoader.class.getDeclaredMethod("defineClass", args);
-
- getContextClassLoader = Thread.class.getMethod("getContextClassLoader", new Class[0]);
- args = new Class[] {ClassLoader.class};
- setContextClassLoader = Thread.class.getMethod("setContextClassLoader", args);
+ getProtectionDomain
+ = Class.class.getMethod("getProtectionDomain", new Class[0]);
+ Class protectionDomain
+ = Class.forName("java.security.ProtectionDomain");
+ Class[] args = new Class[] {String.class, byte[].class,
+ Integer.TYPE, Integer.TYPE, protectionDomain};
+ defineClassProtectionDomain
+ = ClassLoader.class.getDeclaredMethod("defineClass", args);
}
catch (Exception e) {}
}
@@ -299,7 +289,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
addPathElement(pathElements[i]);
}
catch (BuildException e) {
- // ignore path elements which are invalid relative to the project
+ // ignore path elements which are invalid
+ // relative to the project
}
}
}
@@ -345,7 +336,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* classloader should be consulted before trying to
* load the a class through this loader.
*/
- public AntClassLoader(Project project, Path classpath, boolean parentFirst) {
+ public AntClassLoader(Project project, Path classpath,
+ boolean parentFirst) {
this(null, project, classpath, parentFirst);
}
@@ -398,26 +390,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (isContextLoaderSaved) {
throw new BuildException("Context loader has not been reset");
}
- if (getContextClassLoader != null && setContextClassLoader != null) {
- try {
- savedContextLoader
- = (ClassLoader)getContextClassLoader.invoke(Thread.currentThread(), new Object[0]);
- Object[] args = null;
- if ("only".equals(project.getProperty("build.sysclasspath"))) {
- args = new Object[] {this.getClass().getClassLoader()};
- } else {
- args = new Object[] {this};
- }
- setContextClassLoader.invoke(Thread.currentThread(), args);
- isContextLoaderSaved = true;
- }
- catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- throw new BuildException(t.toString());
- }
- catch (Exception e) {
- throw new BuildException(e.toString());
- }
+ if (LoaderUtils.isContextLoaderAvailable()) {
+ savedContextLoader = LoaderUtils.getContextClassLoader();
+ LoaderUtils.setContextClassLoader(this);
+ isContextLoaderSaved = true;
}
}
@@ -425,21 +401,11 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* Resets the current thread's context loader to its original value.
*/
public void resetThreadContextLoader() {
- if (isContextLoaderSaved &&
- getContextClassLoader != null && setContextClassLoader != null) {
- try {
- Object[] args = new Object[] {savedContextLoader};
- setContextClassLoader.invoke(Thread.currentThread(), args);
- savedContextLoader = null;
- isContextLoaderSaved = false;
- }
- catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- throw new BuildException(t.toString());
- }
- catch (Exception e) {
- throw new BuildException(e.toString());
- }
+ if (LoaderUtils.isContextLoaderAvailable()
+ && isContextLoaderSaved) {
+ LoaderUtils.setContextClassLoader(savedContextLoader);
+ savedContextLoader = null;
+ isContextLoaderSaved = false;
}
}
@@ -575,7 +541,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath.
*/
- public Class forceLoadClass(String classname) throws ClassNotFoundException {
+ public Class forceLoadClass(String classname)
+ throws ClassNotFoundException {
log("force loading " + classname, Project.MSG_DEBUG);
Class theClass = findLoadedClass(classname);
@@ -603,7 +570,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath.
*/
- public Class forceLoadSystemClass(String classname) throws ClassNotFoundException {
+ public Class forceLoadSystemClass(String classname)
+ throws ClassNotFoundException {
log("force system loading " + classname, Project.MSG_DEBUG);
Class theClass = findLoadedClass(classname);
@@ -674,8 +642,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* the resource cannot be found on the loader's classpath.
*/
private InputStream loadResource(String name) {
- // we need to search the components of the path to see if we can find the
- // class we want.
+ // 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 = pathComponents.elements(); e.hasMoreElements() && stream == null; ) {
@@ -743,8 +711,9 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
}
}
catch (Exception e) {
- log("Ignoring Exception " + e.getClass().getName() + ": " + e.getMessage() +
- " reading resource " + resourceName + " from " + file, Project.MSG_VERBOSE);
+ log("Ignoring Exception " + e.getClass().getName()
+ + ": " + e.getMessage() + " reading resource " + resourceName
+ + " from " + file, Project.MSG_VERBOSE);
}
return null;
@@ -765,7 +734,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
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 parent one)
+ // designated to use a specific loader first
+ // (this one or the parent one)
// XXX - shouldn't this always return false in isolated mode?
@@ -803,11 +773,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* adequate privileges to get the resource.
*/
public URL getResource(String name) {
- // we need to search the components of the path to see if we can find the
- // class we want.
+ // we need to search the components of the path to see if
+ // we can find the class we want.
URL url = null;
if (isParentFirst(name)) {
- url = (parent == null) ? super.getResource(name) : parent.getResource(name);
+ url = (parent == null) ? super.getResource(name)
+ : parent.getResource(name);
}
if (url != null) {
@@ -881,7 +852,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (resource.exists()) {
try {
- return new URL("file:"+resource.toString());
+ return new URL("file:" + resource.toString());
} catch (MalformedURLException ex) {
return null;
}
@@ -897,7 +868,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
ZipEntry entry = zipFile.getEntry(resourceName);
if (entry != null) {
try {
- return new URL("jar:file:"+file.toString()+"!/"+entry);
+ return new URL("jar:file:" + file.toString()
+ + "!/" + entry);
} catch (MalformedURLException ex) {
return null;
}
@@ -931,7 +903,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* on the system classpath (when not in isolated mode) or this loader's
* classpath.
*/
- protected Class loadClass(String classname, boolean resolve) throws ClassNotFoundException {
+ protected Class loadClass(String classname, boolean resolve)
+ throws ClassNotFoundException {
Class theClass = findLoadedClass(classname);
if (theClass != null) {
@@ -941,24 +914,28 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (isParentFirst(classname)) {
try {
theClass = findBaseClass(classname);
- log("Class " + classname + " loaded from parent loader", Project.MSG_DEBUG);
+ log("Class " + classname + " loaded from parent loader",
+ Project.MSG_DEBUG);
}
catch (ClassNotFoundException cnfe) {
theClass = findClass(classname);
- 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);
- 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);
- log("Class " + classname + " loaded from parent loader", Project.MSG_DEBUG);
+ log("Class " + classname + " loaded from parent loader",
+ Project.MSG_DEBUG);
}
}
@@ -1008,12 +985,16 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
byte[] classData = baos.toByteArray();
// Simply put:
- // defineClass(classname, classData, 0, classData.length, Project.class.getProtectionDomain());
+ // defineClass(classname, classData, 0, classData.length,
+ // Project.class.getProtectionDomain());
// Made more elaborate to be 1.1-safe.
if (defineClassProtectionDomain != null) {
try {
- Object domain = getProtectionDomain.invoke(Project.class, new Object[0]);
- Object[] args = new Object[] {classname, classData, new Integer(0), new Integer(classData.length), domain};
+ Object domain
+ = getProtectionDomain.invoke(Project.class, new Object[0]);
+ Object[] args
+ = new Object[] {classname, classData, new Integer(0),
+ new Integer(classData.length), domain};
return (Class)defineClassProtectionDomain.invoke(this, args);
}
catch (InvocationTargetException ite) {
@@ -1066,9 +1047,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath.
*/
- 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.
+ 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 {
@@ -1082,7 +1064,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
}
catch (IOException ioe) {
// ioe.printStackTrace();
- log("Exception reading component " + pathComponent , Project.MSG_VERBOSE);
+ log("Exception reading component " + pathComponent ,
+ Project.MSG_VERBOSE);
}
}
@@ -1143,6 +1126,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the buildStarted event
*/
public void buildStarted(BuildEvent event) {
}
@@ -1150,6 +1135,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/**
* Cleans up any resources held by this classloader at the end
* of a build.
+ *
+ * @param event the buildFinished event
*/
public void buildFinished(BuildEvent event) {
cleanup();
@@ -1157,30 +1144,40 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the targetStarted event
*/
public void targetStarted(BuildEvent event) {
}
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the targetFinished event
*/
public void targetFinished(BuildEvent event) {
}
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the taskStarted event
*/
public void taskStarted(BuildEvent event) {
}
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the taskFinished event
*/
public void taskFinished(BuildEvent event) {
}
/**
* Empty implementation to satisfy the BuildListener interface.
+ *
+ * @param event the messageLogged event
*/
public void messageLogged(BuildEvent event) {
}
diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java
index d3d5ec0f4..5b9657464 100644
--- a/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -70,6 +70,7 @@ import java.lang.reflect.Method;
import org.xml.sax.AttributeList;
import org.apache.tools.ant.helper.ProjectHelperImpl;
+import org.apache.tools.ant.util.LoaderUtils;
/**
* Configures a Project (complete with Targets and Tasks) based on
@@ -236,30 +237,11 @@ public class ProjectHelper {
public static ClassLoader getContextClassLoader()
throws BuildException
{
- // Are we running on a JDK 1.2 or later system?
- Method method = null;
- try {
- method = Thread.class.getMethod("getContextClassLoader", null);
- } catch (NoSuchMethodException e) {
- // we are running on JDK 1.1
- return null;
- }
-
- // Get the thread context class loader (if there is one)
- ClassLoader classLoader = null;
- try {
- classLoader = (ClassLoader)
- method.invoke(Thread.currentThread(), null);
- } catch (IllegalAccessException e) {
- throw new BuildException
- ("Unexpected IllegalAccessException", e);
- } catch (InvocationTargetException e) {
- throw new BuildException
- ("Unexpected InvocationTargetException", e);
+ if (!LoaderUtils.isContextLoaderAvailable()) {
+ return null;
}
-
- // Return the selected class loader
- return (classLoader);
+
+ return LoaderUtils.getContextClassLoader();
}
// -------------------- Static utils, used by most helpers --------------------
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
index e15a8ee46..1ab56536d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
@@ -65,7 +65,7 @@ import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.types.XCatalog;
+import org.apache.tools.ant.types.XMLCatalog;
import org.xml.sax.EntityResolver;
/**
@@ -142,7 +142,7 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger {
private String outputtype = null;
/** for resolving entities such as dtds */
- private XCatalog xcatalog;
+ private XMLCatalog xmlCatalog;
/** Name of the TRAX Liason class */
private static final String TRAX_LIAISON_CLASS =
@@ -344,12 +344,12 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger {
}
/**
- * store the xcatalog for resolving entities
+ * store the xml catalog for resolving entities
*
- * @param xcatalog the xcatalog instance to use to look up DTDs
+ * @param xmlCatalog the XMLCatalog instance to use to look up DTDs
*/
- public void addXcatalog(XCatalog xcatalog) {
- this.xcatalog = xcatalog;
+ public void addXMLcatalog(XMLCatalog xmlCatalog) {
+ this.xmlCatalog = xmlCatalog;
}
/**
@@ -660,16 +660,16 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger {
Param p = (Param)e.nextElement();
liaison.addParam( p.getName(), p.getExpression() );
}
- // if liaison is a TraxLiason, use XCatalog as the entity
+ // if liaison is a TraxLiason, use XMLCatalog as the entity
// resolver
if (liaison.getClass().getName().equals(TRAX_LIAISON_CLASS) &&
- xcatalog != null) {
+ xmlCatalog != null) {
log("Configuring TraxLiaison and calling entity resolver",
Project.MSG_DEBUG);
Method resolver = liaison.getClass()
.getDeclaredMethod("setEntityResolver",
new Class[] {EntityResolver.class});
- resolver.invoke(liaison, new Object[] {xcatalog});
+ resolver.invoke(liaison, new Object[] {xmlCatalog});
}
} catch (Exception ex) {
log("Failed to read stylesheet " + stylesheet, Project.MSG_INFO);
diff --git a/src/main/org/apache/tools/ant/types/XCatalog.java b/src/main/org/apache/tools/ant/types/XMLCatalog.java
similarity index 89%
rename from src/main/org/apache/tools/ant/types/XCatalog.java
rename to src/main/org/apache/tools/ant/types/XMLCatalog.java
index 5f1ae3871..f95a5160a 100644
--- a/src/main/org/apache/tools/ant/types/XCatalog.java
+++ b/src/main/org/apache/tools/ant/types/XMLCatalog.java
@@ -59,13 +59,15 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
-import java.util.Enumeration;
+import java.util.Iterator;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.apache.tools.ant.util.LoaderUtils;
+import org.apache.tools.ant.util.FileUtils;
/**
* This data type provides a catalog of DTD locations
@@ -90,7 +92,9 @@ import org.xml.sax.SAXException;
* @author dIon Gillard
* @version $Id$
*/
-public class XCatalog extends DataType implements Cloneable, EntityResolver {
+public class XMLCatalog extends DataType implements Cloneable, EntityResolver {
+
+ private FileUtils fileUtils = FileUtils.newFileUtils();
//-- Fields ----------------------------------------------------------------
@@ -121,7 +125,7 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
* @param aDTD the DTDLocation instance to be aded to the catalog
*/
private void addElement(DTDLocation aDTD) {
- getElements().addElement(aDTD);
+ getElements().add(aDTD);
}
/**
@@ -135,7 +139,7 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
if (isReference()) {
throw noChildrenAllowed();
}
- getElements().addElement(dtd);
+ getElements().add(dtd);
}
/**
@@ -165,9 +169,9 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
// change this to get the objects from the other reference
Object o = r.getReferencedObject(getProject());
// we only support references to other XCatalogs
- if (o instanceof XCatalog) {
+ if (o instanceof XMLCatalog) {
// set all elements from referenced catalog to this one
- XCatalog catalog = (XCatalog) o;
+ XMLCatalog catalog = (XMLCatalog) o;
setElements(catalog.getElements());
} else {
String msg = r.getRefId() + " doesn\'t refer to an XCatalog";
@@ -191,16 +195,20 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
Project.MSG_DEBUG);
File dtdFile = new File(matchingDTD.getLocation());
if (dtdFile.exists() && dtdFile.canRead()) {
- source = new InputSource( new FileInputStream(dtdFile) );
- source.setSystemId(dtdFile.toURL().toExternalForm());
+ source = new InputSource(new FileInputStream(dtdFile));
+ URL dtdFileURL = fileUtils.getFileURL(dtdFile);
+ source.setSystemId(dtdFileURL.toExternalForm());
log("matched a readable file", Project.MSG_DEBUG);
} else {
// check if publicId is a resource
// FIXME: ClassLoader: should this be context?
- ClassLoader loader
- = Thread.currentThread().getContextClassLoader();
- InputStream is = loader.getResourceAsStream(
- matchingDTD.getLocation() );
+ ClassLoader loader = LoaderUtils.getContextClassLoader();
+ if (loader == null) {
+ loader = getClass().getClassLoader();
+ }
+
+ InputStream is
+ = loader.getResourceAsStream(matchingDTD.getLocation());
if (is != null) {
source = new InputSource(is);
source.setSystemId(loader.getResource(
@@ -242,10 +250,10 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
* of the DTD or null if no such information is available
*/
private DTDLocation findMatchingDTD(String publicId) {
- Enumeration elements = getElements().elements();
+ Iterator elements = getElements().iterator();
DTDLocation element = null;
- while (elements.hasMoreElements()) {
- element = (DTDLocation)elements.nextElement();
+ while (elements.hasNext()) {
+ element = (DTDLocation)elements.next();
if (element.getPublicId().equals(publicId)) {
return element;
}
diff --git a/src/main/org/apache/tools/ant/types/defaults.properties b/src/main/org/apache/tools/ant/types/defaults.properties
index 3deff353d..3fb5f1c31 100644
--- a/src/main/org/apache/tools/ant/types/defaults.properties
+++ b/src/main/org/apache/tools/ant/types/defaults.properties
@@ -8,5 +8,5 @@ description=org.apache.tools.ant.types.Description
classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet
substitution=org.apache.tools.ant.types.Substitution
regexp=org.apache.tools.ant.types.RegularExpression
-xcatalog=org.apache.tools.ant.types.XCatalog
+xmlcatalog=org.apache.tools.ant.types.XMLCatalog
diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java
index 84a4d7a05..804fed50e 100644
--- a/src/main/org/apache/tools/ant/util/FileUtils.java
+++ b/src/main/org/apache/tools/ant/util/FileUtils.java
@@ -74,6 +74,8 @@ import java.util.Random;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;
+import java.net.URL;
+import java.net.MalformedURLException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -115,6 +117,25 @@ public class FileUtils {
*/
protected FileUtils() {}
+ /**
+ * Get the URL for a file taking into account # characters
+ *
+ * @param file the file whose URL representation is required.
+ * @return The FileURL value
+ * @throws MalformedURLException if the URL representation cannot be
+ * formed.
+ */
+ public URL getFileURL(File file) throws MalformedURLException {
+ String uri = "file:" + file.getAbsolutePath().replace('\\', '/');
+ for (int i = uri.indexOf('#'); i != -1; i = uri.indexOf('#')) {
+ uri = uri.substring(0, i) + "%23" + uri.substring(i + 1);
+ }
+ if (file.isDirectory()) {
+ uri += "/";
+ }
+ return new URL(uri);
+ }
+
/**
* Convienence method to copy a file from a source to a destination.
* No filtering is performed.
diff --git a/src/main/org/apache/tools/ant/util/LoaderUtils.java b/src/main/org/apache/tools/ant/util/LoaderUtils.java
new file mode 100644
index 000000000..d72ef44c5
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/LoaderUtils.java
@@ -0,0 +1,150 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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.util;
+
+import java.lang.reflect.InvocationTargetException;
+
+import java.lang.reflect.Method;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * ClassLoader utility methods
+ *
+ * @author Conor MacNeill
+ * @created 11 March 2002
+ */
+public class LoaderUtils {
+ /** The getContextClassLoader method */
+ private static Method getContextClassLoader;
+ /** The setContextClassLoader method */
+ private static Method setContextClassLoader;
+
+ // Set up the reflection-based Java2 methods if possible
+ static {
+ try {
+ getContextClassLoader
+ = Thread.class.getMethod("getContextClassLoader",
+ new Class[0]);
+ Class[] setContextArgs = new Class[]{ClassLoader.class};
+ setContextClassLoader
+ = Thread.class.getMethod("setContextClassLoader",
+ setContextArgs);
+ } catch (Exception e) {
+ // ignore any problems accessing the methods - probably JDK 1.1
+ }
+ }
+
+ /**
+ * JDK1.1 compatible access to get the context class loader. Has no
+ * effect on JDK 1.1
+ *
+ * @param loader the ClassLoader to be used as the context class loader
+ * on the current thread.
+ */
+ public static void setContextClassLoader(ClassLoader loader) {
+ if (setContextClassLoader == null) {
+ return;
+ }
+
+ try {
+ Thread currentThread = Thread.currentThread();
+ setContextClassLoader.invoke(currentThread,
+ new Object[]{loader});
+ } catch (IllegalAccessException e) {
+ throw new BuildException
+ ("Unexpected IllegalAccessException", e);
+ } catch (InvocationTargetException e) {
+ throw new BuildException
+ ("Unexpected InvocationTargetException", e);
+ }
+
+ }
+
+
+ /**
+ * JDK1.1 compatible access to set the context class loader.
+ *
+ * @return the ClassLoader instance being used as the context
+ * classloader on the current thread. Returns null on JDK 1.1
+ */
+ public static ClassLoader getContextClassLoader() {
+ if (getContextClassLoader == null) {
+ return null;
+ }
+
+ try {
+ Thread currentThread = Thread.currentThread();
+ return (ClassLoader)getContextClassLoader.invoke(currentThread,
+ new Object[0]);
+ } catch (IllegalAccessException e) {
+ throw new BuildException
+ ("Unexpected IllegalAccessException", e);
+ } catch (InvocationTargetException e) {
+ throw new BuildException
+ ("Unexpected InvocationTargetException", e);
+ }
+ }
+
+ /**
+ * Indicates if the context class loader methods are available
+ *
+ * @return true if the get and set methods dealing with the context
+ * classloader are available.
+ */
+ public static boolean isContextLoaderAvailable() {
+ return getContextClassLoader != null &&
+ setContextClassLoader != null;
+ }
+}
+