Browse Source

Restore 1.1 operation

Refactor context class loader methods into a utility class
Add URL method to FileUtils (still need to pick that up in Project)
Rename xcatalog to XMLCatalog


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271813 13f79535-47bb-0310-9956-ffa450edef68
master
Conor MacNeill 23 years ago
parent
commit
598017b1cd
7 changed files with 289 additions and 131 deletions
  1. +80
    -83
      src/main/org/apache/tools/ant/AntClassLoader.java
  2. +5
    -23
      src/main/org/apache/tools/ant/ProjectHelper.java
  3. +9
    -9
      src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
  4. +23
    -15
      src/main/org/apache/tools/ant/types/XMLCatalog.java
  5. +1
    -1
      src/main/org/apache/tools/ant/types/defaults.properties
  6. +21
    -0
      src/main/org/apache/tools/ant/util/FileUtils.java
  7. +150
    -0
      src/main/org/apache/tools/ant/util/LoaderUtils.java

+ 80
- 83
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -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) {
}


+ 5
- 23
src/main/org/apache/tools/ant/ProjectHelper.java View File

@@ -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 --------------------


+ 9
- 9
src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java View File

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


src/main/org/apache/tools/ant/types/XCatalog.java → src/main/org/apache/tools/ant/types/XMLCatalog.java View File

@@ -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;
}

+ 1
- 1
src/main/org/apache/tools/ant/types/defaults.properties View File

@@ -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


+ 21
- 0
src/main/org/apache/tools/ant/util/FileUtils.java View File

@@ -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.


+ 150
- 0
src/main/org/apache/tools/ant/util/LoaderUtils.java View File

@@ -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
* <http://www.apache.org/>.
*/
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 <a href="mailto:conor@apache.org">Conor MacNeill</a>
* @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;
}
}


Loading…
Cancel
Save