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.URL;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import org.apache.tools.ant.types.Path; 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 * 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 * The components of the classpath that the classloader searches
* for classes. * 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. * The project to which this class loader belongs.
@@ -228,7 +228,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
private Hashtable zipFiles = new Hashtable(); 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; private ClassLoader savedContextLoader = null;
/** /**
@@ -248,29 +249,18 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
*/ */
private static Method defineClassProtectionDomain = null; 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 // Set up the reflection-based Java2 methods if possible
static { static {
try { 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) {} catch (Exception e) {}
} }
@@ -299,7 +289,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
addPathElement(pathElements[i]); addPathElement(pathElements[i]);
} }
catch (BuildException e) { 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 * classloader should be consulted before trying to
* load the a class through this loader. * 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); this(null, project, classpath, parentFirst);
} }


@@ -398,26 +390,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (isContextLoaderSaved) { if (isContextLoaderSaved) {
throw new BuildException("Context loader has not been reset"); 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. * Resets the current thread's context loader to its original value.
*/ */
public void resetThreadContextLoader() { 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 * @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath. * 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); log("force loading " + classname, Project.MSG_DEBUG);


Class theClass = findLoadedClass(classname); Class theClass = findLoadedClass(classname);
@@ -603,7 +570,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @exception ClassNotFoundException if the requested class does not exist * @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath. * 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); log("force system loading " + classname, Project.MSG_DEBUG);


Class theClass = findLoadedClass(classname); 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. * the resource cannot be found on the loader's classpath.
*/ */
private InputStream loadResource(String name) { 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; InputStream stream = null;


for (Enumeration e = pathComponents.elements(); e.hasMoreElements() && 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) { 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; return null;
@@ -765,7 +734,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
private boolean isParentFirst(String resourceName) { private boolean isParentFirst(String resourceName) {
// default to the global setting and then see // default to the global setting and then see
// if this class belongs to a package which has been // 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? // 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. * adequate privileges to get the resource.
*/ */
public URL getResource(String name) { 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; URL url = null;
if (isParentFirst(name)) { if (isParentFirst(name)) {
url = (parent == null) ? super.getResource(name) : parent.getResource(name);
url = (parent == null) ? super.getResource(name)
: parent.getResource(name);
} }


if (url != null) { if (url != null) {
@@ -881,7 +852,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {


if (resource.exists()) { if (resource.exists()) {
try { try {
return new URL("file:"+resource.toString());
return new URL("file:" + resource.toString());
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
return null; return null;
} }
@@ -897,7 +868,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
ZipEntry entry = zipFile.getEntry(resourceName); ZipEntry entry = zipFile.getEntry(resourceName);
if (entry != null) { if (entry != null) {
try { try {
return new URL("jar:file:"+file.toString()+"!/"+entry);
return new URL("jar:file:" + file.toString()
+ "!/" + entry);
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
return null; 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 * on the system classpath (when not in isolated mode) or this loader's
* classpath. * classpath.
*/ */
protected Class loadClass(String classname, boolean resolve) throws ClassNotFoundException {
protected Class loadClass(String classname, boolean resolve)
throws ClassNotFoundException {


Class theClass = findLoadedClass(classname); Class theClass = findLoadedClass(classname);
if (theClass != null) { if (theClass != null) {
@@ -941,24 +914,28 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (isParentFirst(classname)) { if (isParentFirst(classname)) {
try { try {
theClass = findBaseClass(classname); 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) { catch (ClassNotFoundException cnfe) {
theClass = findClass(classname); theClass = findClass(classname);
log("Class " + classname + " loaded from ant loader", Project.MSG_DEBUG);
log("Class " + classname + " loaded from ant loader",
Project.MSG_DEBUG);
} }
} }
else { else {
try { try {
theClass = findClass(classname); 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) { catch (ClassNotFoundException cnfe) {
if (ignoreBase) { if (ignoreBase) {
throw cnfe; throw cnfe;
} }
theClass = findBaseClass(classname); 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(); byte[] classData = baos.toByteArray();


// Simply put: // 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. // Made more elaborate to be 1.1-safe.
if (defineClassProtectionDomain != null) { if (defineClassProtectionDomain != null) {
try { 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); return (Class)defineClassProtectionDomain.invoke(this, args);
} }
catch (InvocationTargetException ite) { catch (InvocationTargetException ite) {
@@ -1066,9 +1047,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @exception ClassNotFoundException if the requested class does not exist * @exception ClassNotFoundException if the requested class does not exist
* on this loader's classpath. * 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; InputStream stream = null;
String classFilename = getClassFilename(name); String classFilename = getClassFilename(name);
try { try {
@@ -1082,7 +1064,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
} }
catch (IOException ioe) { catch (IOException ioe) {
// ioe.printStackTrace(); // 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. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the buildStarted event
*/ */
public void buildStarted(BuildEvent 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 * Cleans up any resources held by this classloader at the end
* of a build. * of a build.
*
* @param event the buildFinished event
*/ */
public void buildFinished(BuildEvent event) { public void buildFinished(BuildEvent event) {
cleanup(); cleanup();
@@ -1157,30 +1144,40 @@ public class AntClassLoader extends ClassLoader implements BuildListener {


/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the targetStarted event
*/ */
public void targetStarted(BuildEvent event) { public void targetStarted(BuildEvent event) {
} }


/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the targetFinished event
*/ */
public void targetFinished(BuildEvent event) { public void targetFinished(BuildEvent event) {
} }


/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the taskStarted event
*/ */
public void taskStarted(BuildEvent event) { public void taskStarted(BuildEvent event) {
} }


/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the taskFinished event
*/ */
public void taskFinished(BuildEvent event) { public void taskFinished(BuildEvent event) {
} }


/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
*
* @param event the messageLogged event
*/ */
public void messageLogged(BuildEvent 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.xml.sax.AttributeList;
import org.apache.tools.ant.helper.ProjectHelperImpl; import org.apache.tools.ant.helper.ProjectHelperImpl;
import org.apache.tools.ant.util.LoaderUtils;


/** /**
* Configures a Project (complete with Targets and Tasks) based on * Configures a Project (complete with Targets and Tasks) based on
@@ -236,30 +237,11 @@ public class ProjectHelper {
public static ClassLoader getContextClassLoader() public static ClassLoader getContextClassLoader()
throws BuildException 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 -------------------- // -------------------- 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.Path;
import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils; 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; import org.xml.sax.EntityResolver;


/** /**
@@ -142,7 +142,7 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger {
private String outputtype = null; private String outputtype = null;
/** for resolving entities such as dtds */ /** for resolving entities such as dtds */
private XCatalog xcatalog;
private XMLCatalog xmlCatalog;
/** Name of the TRAX Liason class */ /** Name of the TRAX Liason class */
private static final String TRAX_LIAISON_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(); Param p = (Param)e.nextElement();
liaison.addParam( p.getName(), p.getExpression() ); 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 // resolver
if (liaison.getClass().getName().equals(TRAX_LIAISON_CLASS) && if (liaison.getClass().getName().equals(TRAX_LIAISON_CLASS) &&
xcatalog != null) {
xmlCatalog != null) {
log("Configuring TraxLiaison and calling entity resolver", log("Configuring TraxLiaison and calling entity resolver",
Project.MSG_DEBUG); Project.MSG_DEBUG);
Method resolver = liaison.getClass() Method resolver = liaison.getClass()
.getDeclaredMethod("setEntityResolver", .getDeclaredMethod("setEntityResolver",
new Class[] {EntityResolver.class}); new Class[] {EntityResolver.class});
resolver.invoke(liaison, new Object[] {xcatalog});
resolver.invoke(liaison, new Object[] {xmlCatalog});
} }
} catch (Exception ex) { } catch (Exception ex) {
log("Failed to read stylesheet " + stylesheet, Project.MSG_INFO); 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.InputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector; import java.util.Vector;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.xml.sax.EntityResolver; import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; 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 * This data type provides a catalog of DTD locations
@@ -90,7 +92,9 @@ import org.xml.sax.SAXException;
* @author dIon Gillard * @author dIon Gillard
* @version $Id$ * @version $Id$
*/ */
public class XCatalog extends DataType implements Cloneable, EntityResolver {
public class XMLCatalog extends DataType implements Cloneable, EntityResolver {
private FileUtils fileUtils = FileUtils.newFileUtils();
//-- Fields ---------------------------------------------------------------- //-- Fields ----------------------------------------------------------------
@@ -121,7 +125,7 @@ public class XCatalog extends DataType implements Cloneable, EntityResolver {
* @param aDTD the DTDLocation instance to be aded to the catalog * @param aDTD the DTDLocation instance to be aded to the catalog
*/ */
private void addElement(DTDLocation aDTD) { 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()) { if (isReference()) {
throw noChildrenAllowed(); 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 // change this to get the objects from the other reference
Object o = r.getReferencedObject(getProject()); Object o = r.getReferencedObject(getProject());
// we only support references to other XCatalogs // we only support references to other XCatalogs
if (o instanceof XCatalog) {
if (o instanceof XMLCatalog) {
// set all elements from referenced catalog to this one // set all elements from referenced catalog to this one
XCatalog catalog = (XCatalog) o;
XMLCatalog catalog = (XMLCatalog) o;
setElements(catalog.getElements()); setElements(catalog.getElements());
} else { } else {
String msg = r.getRefId() + " doesn\'t refer to an XCatalog"; 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); Project.MSG_DEBUG);
File dtdFile = new File(matchingDTD.getLocation()); File dtdFile = new File(matchingDTD.getLocation());
if (dtdFile.exists() && dtdFile.canRead()) { 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); log("matched a readable file", Project.MSG_DEBUG);
} else { } else {
// check if publicId is a resource // check if publicId is a resource
// FIXME: ClassLoader: should this be context? // 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) { if (is != null) {
source = new InputSource(is); source = new InputSource(is);
source.setSystemId(loader.getResource( 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 * of the DTD or null if no such information is available
*/ */
private DTDLocation findMatchingDTD(String publicId) { private DTDLocation findMatchingDTD(String publicId) {
Enumeration elements = getElements().elements();
Iterator elements = getElements().iterator();
DTDLocation element = null; DTDLocation element = null;
while (elements.hasMoreElements()) {
element = (DTDLocation)elements.nextElement();
while (elements.hasNext()) {
element = (DTDLocation)elements.next();
if (element.getPublicId().equals(publicId)) { if (element.getPublicId().equals(publicId)) {
return element; 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 classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet
substitution=org.apache.tools.ant.types.Substitution substitution=org.apache.tools.ant.types.Substitution
regexp=org.apache.tools.ant.types.RegularExpression 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.Stack;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.Vector; import java.util.Vector;
import java.net.URL;
import java.net.MalformedURLException;


import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
@@ -115,6 +117,25 @@ public class FileUtils {
*/ */
protected 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. * Convienence method to copy a file from a source to a destination.
* No filtering is performed. * 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