Browse Source

New attribute - ignoreSstemClasses - added to <available>.

PR: 6031
Submitted by: peterj@liberate.com (Peter Janes)


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271903 13f79535-47bb-0310-9956-ffa450edef68
master
Magesh Umasankar 23 years ago
parent
commit
37cd9404c7
6 changed files with 220 additions and 115 deletions
  1. +2
    -0
      WHATSNEW
  2. +14
    -8
      docs/manual/CoreTasks/available.html
  3. +31
    -0
      src/etc/testcases/taskdefs/available.xml
  4. +113
    -103
      src/main/org/apache/tools/ant/AntClassLoader.java
  5. +23
    -3
      src/main/org/apache/tools/ant/taskdefs/Available.java
  6. +37
    -1
      src/testcases/org/apache/tools/ant/taskdefs/AvailableTest.java

+ 2
- 0
WHATSNEW View File

@@ -85,6 +85,8 @@ Fixed bugs:


Other changes: Other changes:
-------------- --------------
* <available> has a new attribute named ignoreSystemClasses.

* New filter readers: ClassConstants, ExpandProperties, HeadFilter, * New filter readers: ClassConstants, ExpandProperties, HeadFilter,
LineContains, LineContainsRegExp, PrefixLines, ReplaceTokens, LineContains, LineContainsRegExp, PrefixLines, ReplaceTokens,
StripJavaComments, StripLineBreaks, StripLineComments, TabsToSpaces, StripJavaComments, StripLineBreaks, StripLineComments, TabsToSpaces,


+ 14
- 8
docs/manual/CoreTasks/available.html View File

@@ -49,26 +49,32 @@ execution depending on system parameters.</p>
<tr> <tr>
<td valign="top">classpath</td> <td valign="top">classpath</td>
<td valign="top">The classpath to use when looking up <code>classname</code> or <code>resource</code>.</td> <td valign="top">The classpath to use when looking up <code>classname</code> or <code>resource</code>.</td>
<td align="center" valign="top">No</td>
<td align="center" valign="top">No</td>
</tr> </tr>
<tr> <tr>
<td valign="top">filepath</td> <td valign="top">filepath</td>
<td valign="top">The path to use when looking up <code>file</code>.</td> <td valign="top">The path to use when looking up <code>file</code>.</td>
<td align="center" valign="top">No</td>
<td align="center" valign="top">No</td>
</tr> </tr>
<tr> <tr>
<td valign="top">classpathref</td> <td valign="top">classpathref</td>
<td valign="top">The classpath to use, given as a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td> <td valign="top">The classpath to use, given as a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
<td align="center" valign="top">No</td>
<td align="center" valign="top">No</td>
</tr> </tr>
<tr> <tr>
<td valign="top">type</td> <td valign="top">type</td>
<td valign="top">The type of <code>file</code> to look for, either a directory (<code>type=&quot;dir&quot;</code>) or a file
(<code>type=&quot;file&quot;</code>). If not set, the property will be set if the name specified in the <code>file</code>
<td valign="top">The type of <code>file</code> to look for, either a directory (<code>type=&quot;dir&quot;</code>) or a file
(<code>type=&quot;file&quot;</code>). If not set, the property will be set if the name specified in the <code>file</code>
attribute exists as either a file or a directory.</td> attribute exists as either a file or a directory.</td>
<td align="center" valign="top">No</td>
<td align="center" valign="top">No</td>
</tr> </tr>
<tr>
<td valign="top">ignoresystemclasses</td>
<td valign="top">Ignore Ant's runtime classes, using only the specified
classpath. Only affects the "classname" attribute. Defaults to &quot;false&quot;</td>
<td align="center" valign="top">No</td>
</tr>

</table> </table>
<h3>Parameters specified as nested elements</h3> <h3>Parameters specified as nested elements</h3>
<h4>classpath</h4> <h4>classpath</h4>
@@ -114,7 +120,7 @@ if the class <code>javax.xml.transform.Transformer</code> is found in the classp
<p>sets the <code>have.extras</code> property to the value &quot;true&quot; <p>sets the <code>have.extras</code> property to the value &quot;true&quot;
if the resource-file <code>extratasks.properties</code> is found. if the resource-file <code>extratasks.properties</code> is found.
</p> </p>
<hr><p align="center">Copyright &copy; 2001 Apache Software Foundation. All rights
<hr><p align="center">Copyright &copy; 2001-2002 Apache Software Foundation. All rights
Reserved.</p> Reserved.</p>


</body> </body>


+ 31
- 0
src/etc/testcases/taskdefs/available.xml View File

@@ -103,4 +103,35 @@
file="available.xml" type="Foo"/> file="available.xml" type="Foo"/>
</target> </target>


<target name="test20">
<available property="test" ignoresystemclasses="true"
classname="java.awt.Graphics"/>
</target>

<target name="test21">
<available property="test" ignoresystemclasses="true"
classname="java.awt.Graphics" classpath="${java.home}/lib/rt.jar:${java.home}/lib/classes.zip"/>
</target>

<target name="test22">
<available property="test" ignoresystemclasses="false"
classname="java.awt.Graphics"/>
</target>

<target name="test23">
<available property="test"
classname="java.awt.Graphics"/>
</target>

<target name="test24">
<!-- create a dummy file and look for it -->
<mkdir dir="${user.dir}/test"/>
<echo message="package test;public class test {}" file="${user.dir}/test/test.java"/>
<javac srcdir="${user.dir}" includes="test/test.java"/>
<jar destfile="${user.dir}/test.jar" basedir="${user.dir}" includes="test/test.class"/>
<available property="test"
classname="test.test" classpath="${user.dir}/test.jar"/>
<delete dir="${user.dir}/test"/>
<delete file="${user.dir}/test.jar"/>
</target>
</project> </project>

+ 113
- 103
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -73,9 +73,9 @@ import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.LoaderUtils; import org.apache.tools.ant.util.LoaderUtils;


/** /**
* Used to load classes within ant with a different claspath from
* that used to start ant. Note that it is possible to force a class
* into this loader even when that class is on the system classpath by
* Used to load classes within ant with a different claspath from
* that used to start ant. Note that it is possible to force a class
* into this loader even when that class is on the system classpath by
* using the forceLoadClass method. Any subsequent classes loaded by that * using the forceLoadClass method. Any subsequent classes loaded by that
* class will then use this loader rather than the system class loader. * class will then use this loader rather than the system class loader.
* *
@@ -164,7 +164,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
url = getResourceURL(pathComponent, this.resourceName); url = getResourceURL(pathComponent, this.resourceName);
pathElementsIndex++; pathElementsIndex++;
} catch (BuildException e) { } catch (BuildException e) {
// ignore path elements which are not valid relative to the
// ignore path elements which are not valid relative to the
// project // project
} }
} }
@@ -195,15 +195,15 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
private boolean parentFirst = true; private boolean parentFirst = true;


/** /**
* 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
* 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. * first or not.
*/ */
private Vector systemPackages = new Vector(); private Vector systemPackages = new Vector();


/** /**
* These are the package roots that are to be loaded by this class loader * These are the package roots that are to be loaded by this class loader
* regardless of whether the parent class loader is being searched first
* regardless of whether the parent class loader is being searched first
* or not. * or not.
*/ */
private Vector loaderPackages = new Vector(); private Vector loaderPackages = new Vector();
@@ -227,7 +227,7 @@ 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
* The context loader saved when setting the thread's current
* context loader. * context loader.
*/ */
private ClassLoader savedContextLoader = null; private ClassLoader savedContextLoader = null;
@@ -248,17 +248,17 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
*/ */
private static Method defineClassProtectionDomain = null; private static Method defineClassProtectionDomain = null;


// Set up the reflection-based Java2 methods if possible // Set up the reflection-based Java2 methods if possible
static { static {
try { try {
getProtectionDomain
getProtectionDomain
= Class.class.getMethod("getProtectionDomain", new Class[0]); = Class.class.getMethod("getProtectionDomain", new Class[0]);
Class protectionDomain
Class protectionDomain
= Class.forName("java.security.ProtectionDomain"); = Class.forName("java.security.ProtectionDomain");
Class[] args = new Class[] {String.class, byte[].class,
Class[] args = new Class[] {String.class, byte[].class,
Integer.TYPE, Integer.TYPE, protectionDomain}; Integer.TYPE, Integer.TYPE, protectionDomain};
defineClassProtectionDomain
defineClassProtectionDomain
= ClassLoader.class.getDeclaredMethod("defineClass", args); = ClassLoader.class.getDeclaredMethod("defineClass", args);
} catch (Exception e) { } catch (Exception e) {
// ignore failure to get access to 1.2+ methods // ignore failure to get access to 1.2+ methods
@@ -288,7 +288,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
try { try {
addPathElement(pathElements[i]); addPathElement(pathElements[i]);
} catch (BuildException e) { } catch (BuildException e) {
// ignore path elements which are invalid
// ignore path elements which are invalid
// relative to the project // relative to the project
} }
} }
@@ -298,7 +298,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Creates a classloader for the given project using the classpath given. * Creates a classloader for the given project using the classpath given.
* *
* @param parent The parent classloader to which unsatisfied loading
* @param parent The parent classloader to which unsatisfied loading
* attempts are delegated. May be <code>null</code>, * attempts are delegated. May be <code>null</code>,
* in which case the classloader which loaded this * in which case the classloader which loaded this
* class is used as the parent. * class is used as the parent.
@@ -307,7 +307,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @param classpath the classpath to use to load the classes. * @param classpath the classpath to use to load the classes.
* May be <code>null</code>, in which case no path * May be <code>null</code>, in which case no path
* elements are set up to start with. * elements are set up to start with.
* @param parentFirst If <code>true</code>, indicates that the parent
* @param parentFirst If <code>true</code>, indicates that the parent
* 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.
*/ */
@@ -328,28 +328,28 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* *
* @param project The project to which this classloader is to belong. * @param project The project to which this classloader is to belong.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* @param classpath The classpath to use to load the classes. May be
* @param classpath The classpath to use to load the classes. May be
* <code>null</code>, in which case no path * <code>null</code>, in which case no path
* elements are set up to start with. * elements are set up to start with.
* @param parentFirst If <code>true</code>, indicates that the parent
* classloader should be consulted before trying to
* @param parentFirst If <code>true</code>, indicates that the parent
* 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,
public AntClassLoader(Project project, Path classpath,
boolean parentFirst) { boolean parentFirst) {
this(null, project, classpath, parentFirst); this(null, project, classpath, parentFirst);
} }


/** /**
* Creates an empty class loader. The classloader should be configured * Creates an empty class loader. The classloader should be configured
* with path elements to specify where the loader is to look for
* with path elements to specify where the loader is to look for
* classes. * classes.
* *
* @param parent The parent classloader to which unsatisfied loading
* @param parent The parent classloader to which unsatisfied loading
* attempts are delegated. May be <code>null</code>, * attempts are delegated. May be <code>null</code>,
* in which case the classloader which loaded this * in which case the classloader which loaded this
* class is used as the parent. * class is used as the parent.
* @param parentFirst If <code>true</code>, indicates that the parent
* @param parentFirst If <code>true</code>, indicates that the parent
* 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.
*/ */
@@ -366,9 +366,9 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Logs a message through the project object if one has been provided. * Logs a message through the project object if one has been provided.
* *
* @param message The message to log.
* @param message The message to log.
* Should not be <code>null</code>. * Should not be <code>null</code>.
*
*
* @param priority The logging priority of the message. * @param priority The logging priority of the message.
*/ */
protected void log(String message, int priority) { protected void log(String message, int priority) {
@@ -403,7 +403,7 @@ 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 (LoaderUtils.isContextLoaderAvailable()
if (LoaderUtils.isContextLoaderAvailable()
&& isContextLoaderSaved) { && isContextLoaderSaved) {
LoaderUtils.setContextClassLoader(savedContextLoader); LoaderUtils.setContextClassLoader(savedContextLoader);
savedContextLoader = null; savedContextLoader = null;
@@ -415,9 +415,9 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Adds an element to the classpath to be searched. * Adds an element to the classpath to be searched.
* *
* @param pathElement The path element to add. Must not be
* @param pathElement The path element to add. Must not be
* <code>null</code>. * <code>null</code>.
*
*
* @exception BuildException if the given path element cannot be resolved * @exception BuildException if the given path element cannot be resolved
* against the project. * against the project.
*/ */
@@ -430,8 +430,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {


/** /**
* Returns the classpath this classloader will consult. * Returns the classpath this classloader will consult.
*
* @return the classpath used for this classloader, with elements
*
* @return the classpath used for this classloader, with elements
* separated by the path separator for the system. * separated by the path separator for the system.
*/ */
public String getClasspath(){ public String getClasspath(){
@@ -450,12 +450,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
} }


/** /**
* Sets whether this classloader should run in isolated mode. In
* isolated mode, classes not found on the given classpath will
* not be referred to the parent class loader but will cause a
* Sets whether this classloader should run in isolated mode. In
* isolated mode, classes not found on the given classpath will
* not be referred to the parent class loader but will cause a
* ClassNotFoundException. * ClassNotFoundException.
*
* @param isolated Whether or not this classloader should run in
*
* @param isolated Whether or not this classloader should run in
* isolated mode. * isolated mode.
*/ */
public void setIsolated(boolean isolated) { public void setIsolated(boolean isolated) {
@@ -465,8 +465,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Forces initialization of a class in a JDK 1.1 compatible, albeit hacky * Forces initialization of a class in a JDK 1.1 compatible, albeit hacky
* way. * way.
*
* @param theClass The class to initialize.
*
* @param theClass The class to initialize.
* Must not be <code>null</code>. * Must not be <code>null</code>.
*/ */
public static void initializeClass(Class theClass) { public static void initializeClass(Class theClass) {
@@ -494,7 +494,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
// would have a constructor that takes in // would have a constructor that takes in
// 256 String arguments ;-) // 256 String arguments ;-)
// (In fact, they can't - according to JVM spec // (In fact, they can't - according to JVM spec
// section 4.10, the number of method parameters is limited
// section 4.10, the number of method parameters is limited
// to 255 by the definition of a method descriptor. // to 255 by the definition of a method descriptor.
// Constructors count as methods here.) // Constructors count as methods here.)
} }
@@ -505,7 +505,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Adds a package root to the list of packages which must be loaded on the * Adds a package root to the list of packages which must be loaded on the
* parent loader. * parent loader.
*
*
* All subpackages are also included. * All subpackages are also included.
* *
* @param packageRoot The root of all packages to be included. * @param packageRoot The root of all packages to be included.
@@ -518,10 +518,10 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Adds a package root to the list of packages which must be loaded using * Adds a package root to the list of packages which must be loaded using
* this loader. * this loader.
*
*
* All subpackages are also included. * All subpackages are also included.
* *
* @param packageRoot The root of all packages to be included.
* @param packageRoot The root of all packages to be included.
* Should not be <code>null</code>. * Should not be <code>null</code>.
*/ */
public void addLoaderPackageRoot(String packageRoot) { public void addLoaderPackageRoot(String packageRoot) {
@@ -531,11 +531,11 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Loads a class through this class loader even if that class is available * Loads a class through this class loader even if that class is available
* on the parent classpath. * on the parent classpath.
*
* This ensures that any classes which are loaded by the returned class
*
* This ensures that any classes which are loaded by the returned class
* will use this classloader. * will use this classloader.
* *
* @param classname The name of the class to be loaded.
* @param classname The name of the class to be loaded.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* *
* @return the required Class object * @return the required Class object
@@ -543,7 +543,7 @@ 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)
public Class forceLoadClass(String classname)
throws ClassNotFoundException { throws ClassNotFoundException {
log("force loading " + classname, Project.MSG_DEBUG); log("force loading " + classname, Project.MSG_DEBUG);


@@ -559,12 +559,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Loads a class through this class loader but defer to the parent class * Loads a class through this class loader but defer to the parent class
* loader. * loader.
*
* This ensures that instances of the returned class will be compatible
* with instances which which have already been loaded on the parent
*
* This ensures that instances of the returned class will be compatible
* with instances which which have already been loaded on the parent
* loader. * loader.
* *
* @param classname The name of the class to be loaded.
* @param classname The name of the class to be loaded.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* *
* @return the required Class object * @return the required Class object
@@ -572,7 +572,7 @@ 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)
public Class forceLoadSystemClass(String classname)
throws ClassNotFoundException { throws ClassNotFoundException {
log("force system loading " + classname, Project.MSG_DEBUG); log("force system loading " + classname, Project.MSG_DEBUG);


@@ -591,7 +591,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @param name The name of the resource for which a stream is required. * @param name The name of the resource for which a stream is required.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* *
* @return a stream to the required resource or <code>null</code> if the
* @return a stream to the required resource or <code>null</code> if the
* resource cannot be found on the loader's classpath. * resource cannot be found on the loader's classpath.
*/ */
public InputStream getResourceAsStream(String name) { public InputStream getResourceAsStream(String name) {
@@ -639,11 +639,11 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @param name The name of the resource for which a stream is required. * @param name The name of the resource for which a stream is required.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* *
* @return a stream to the required resource or <code>null</code> if
* @return a stream to the required resource or <code>null</code> if
* 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
// we need to search the components of the path to see if we can
// find the class we want. // find the class we want.
InputStream stream = null; InputStream stream = null;


@@ -656,12 +656,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
} }


/** /**
* Finds a system resource (which should be loaded from the parent
* Finds a system resource (which should be loaded from the parent
* classloader). * classloader).
*
* @param name The name of the system resource to load.
*
* @param name The name of the system resource to load.
* Must not be <code>null</code>. * Must not be <code>null</code>.
*
*
* @return a stream to the named resource, or <code>null</code> if * @return a stream to the named resource, or <code>null</code> if
* the resource cannot be found. * the resource cannot be found.
*/ */
@@ -677,12 +677,12 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* Returns an inputstream to a given resource in the given file which may * Returns an inputstream to a given resource in the given file which may
* either be a directory or a zip file. * either be a directory or a zip file.
* *
* @param file the file (directory or jar) in which to search for the
* @param file the file (directory or jar) in which to search for the
* resource. Must not be <code>null</code>. * resource. Must not be <code>null</code>.
* @param resourceName The name of the resource for which a stream is
* @param resourceName The name of the resource for which a stream is
* required. Must not be <code>null</code>. * required. Must not be <code>null</code>.
* *
* @return a stream to the required resource or <code>null</code> if
* @return a stream to the required resource or <code>null</code> if
* the resource cannot be found in the given file. * the resource cannot be found in the given file.
*/ */
private InputStream getResourceStream(File file, String resourceName) { private InputStream getResourceStream(File file, String resourceName) {
@@ -710,8 +710,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
} }
} }
} catch (Exception e) { } catch (Exception e) {
log("Ignoring Exception " + e.getClass().getName()
+ ": " + e.getMessage() + " reading resource " + resourceName
log("Ignoring Exception " + e.getClass().getName()
+ ": " + e.getMessage() + " reading resource " + resourceName
+ " from " + file, Project.MSG_VERBOSE); + " from " + file, Project.MSG_VERBOSE);
} }


@@ -723,21 +723,21 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* a resource before this one. If the resource matches both the * a resource before this one. If the resource matches both the
* "use parent classloader first" and the "use this classloader first" * "use parent classloader first" and the "use this classloader first"
* lists, the latter takes priority. * lists, the latter takes priority.
*
*
* @param resourceName The name of the resource to check. * @param resourceName The name of the resource to check.
* Must not be <code>null</code>. * Must not be <code>null</code>.
*
* @return whether or not the parent classloader should be checked for a
*
* @return whether or not the parent classloader should be checked for a
* resource before this one is. * resource before this one is.
*/ */
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
// designated to use a specific loader first
// (this one or the parent one) // (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?
boolean useParentFirst = parentFirst; boolean useParentFirst = parentFirst;


for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) { for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) {
@@ -767,16 +767,16 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* @param name The name of the resource for which a stream is required. * @param name The name of the resource for which a stream is required.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* *
* @return a URL for reading the resource, or <code>null</code> if the
* resource could not be found or the caller doesn't have
* @return a URL for reading the resource, or <code>null</code> if the
* resource could not be found or the caller doesn't have
* 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 need to search the components of the path to see if
// we can find the class we want. // 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)
url = (parent == null) ? super.getResource(name)
: parent.getResource(name); : parent.getResource(name);
} }


@@ -802,7 +802,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (url == null && !isParentFirst(name)) { if (url == null && !isParentFirst(name)) {
// this loader was first but it didn't find it - try the parent // this loader was first but it didn't find it - try the parent


url = (parent == null) ? super.getResource(name)
url = (parent == null) ? super.getResource(name)
: parent.getResource(name); : parent.getResource(name);
if (url != null) { if (url != null) {
log("Resource " + name + " loaded from parent loader", log("Resource " + name + " loaded from parent loader",
@@ -821,7 +821,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* Returns an enumeration of URLs representing all the resources with the * Returns an enumeration of URLs representing all the resources with the
* given name by searching the class loader's classpath. * given name by searching the class loader's classpath.
* *
* @param name The resource name to search for.
* @param name The resource name to search for.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* @return an enumeration of URLs for the resources * @return an enumeration of URLs for the resources
* @exception IOException if I/O errors occurs (can't happen) * @exception IOException if I/O errors occurs (can't happen)
@@ -868,7 +868,7 @@ 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()
return new URL("jar:file:" + file.toString()
+ "!/" + entry); + "!/" + entry);
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
return null; return null;
@@ -886,23 +886,23 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* Loads a class with this class loader. * Loads a class with this class loader.
* *
* This class attempts to load the class in an order determined by whether * This class attempts to load the class in an order determined by whether
* or not the class matches the system/loader package lists, with the
* loader package list taking priority. If the classloader is in isolated
* mode, failure to load the class in this loader will result in a
* or not the class matches the system/loader package lists, with the
* loader package list taking priority. If the classloader is in isolated
* mode, failure to load the class in this loader will result in a
* ClassNotFoundException. * ClassNotFoundException.
* *
* @param classname The name of the class to be loaded.
* @param classname The name of the class to be loaded.
* Must not be <code>null</code>. * Must not be <code>null</code>.
* @param resolve <code>true</code> if all classes upon which this class
* @param resolve <code>true</code> if all classes upon which this class
* depends are to be loaded. * depends are to be loaded.
* *
* @return the required Class object * @return the required Class object
* *
* @exception ClassNotFoundException if the requested class does not exist * @exception ClassNotFoundException if the requested class does not exist
* 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)
protected Class loadClass(String classname, boolean resolve)
throws ClassNotFoundException { throws ClassNotFoundException {


Class theClass = findLoadedClass(classname); Class theClass = findLoadedClass(classname);
@@ -913,24 +913,24 @@ 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",
log("Class " + classname + " loaded from parent loader",
Project.MSG_DEBUG); Project.MSG_DEBUG);
} catch (ClassNotFoundException cnfe) { } catch (ClassNotFoundException cnfe) {
theClass = findClass(classname); theClass = findClass(classname);
log("Class " + classname + " loaded from ant loader",
log("Class " + classname + " loaded from ant loader",
Project.MSG_DEBUG); Project.MSG_DEBUG);
} }
} else { } else {
try { try {
theClass = findClass(classname); theClass = findClass(classname);
log("Class " + classname + " loaded from ant loader",
log("Class " + classname + " loaded from ant loader",
Project.MSG_DEBUG); 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",
log("Class " + classname + " loaded from parent loader",
Project.MSG_DEBUG); Project.MSG_DEBUG);
} }
} }
@@ -967,6 +967,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* *
* @exception IOException if there is a problem reading the class from the * @exception IOException if there is a problem reading the class from the
* stream. * stream.
* @exception SecurityException if there is a security problem while
* reading the class from the stream.
*/ */
private Class getClassFromStream(InputStream stream, String classname) private Class getClassFromStream(InputStream stream, String classname)
throws IOException { throws IOException {
@@ -981,15 +983,15 @@ 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,
// defineClass(classname, classData, 0, classData.length,
// Project.class.getProtectionDomain()); // 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
Object domain
= getProtectionDomain.invoke(Project.class, new Object[0]); = getProtectionDomain.invoke(Project.class, new Object[0]);
Object[] args
= new Object[] {classname, classData, new Integer(0),
Object[] args
= new Object[] {classname, classData, new Integer(0),
new Integer(classData.length), domain}; new Integer(classData.length), domain};
return (Class)defineClassProtectionDomain.invoke(this, args); return (Class)defineClassProtectionDomain.invoke(this, args);
} catch (InvocationTargetException ite) { } catch (InvocationTargetException ite) {
@@ -998,7 +1000,11 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
throw (ClassFormatError)t; throw (ClassFormatError)t;
} else if (t instanceof NoClassDefFoundError) { } else if (t instanceof NoClassDefFoundError) {
throw (NoClassDefFoundError)t; throw (NoClassDefFoundError)t;
} else {
}
else if (t instanceof SecurityException) {
throw (SecurityException)t;
}
else {
throw new IOException(t.toString()); throw new IOException(t.toString());
} }
} catch (Exception e) { } catch (Exception e) {
@@ -1012,7 +1018,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Searches for and load a class on the classpath of this class loader. * Searches for and load a class on the classpath of this class loader.
* *
* @param name The name of the class to be loaded. Must not be
* @param name The name of the class to be loaded. Must not be
* <code>null</code>. * <code>null</code>.
* *
* @return the required Class object * @return the required Class object
@@ -1029,18 +1035,18 @@ public class AntClassLoader extends ClassLoader implements BuildListener {


/** /**
* Finds a class on the given classpath. * Finds a class on the given classpath.
*
* @param name The name of the class to be loaded. Must not be
*
* @param name The name of the class to be loaded. Must not be
* <code>null</code>. * <code>null</code>.
*
*
* @return the required Class object * @return the required Class object
* *
* @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)
private Class findClassInComponents(String name)
throws ClassNotFoundException { throws ClassNotFoundException {
// we need to search the components of the path to see if
// we need to search the components of the path to see if
// we can find the class we want. // we can find the class we want.
InputStream stream = null; InputStream stream = null;
String classFilename = getClassFilename(name); String classFilename = getClassFilename(name);
@@ -1053,9 +1059,13 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (stream != null) { if (stream != null) {
return getClassFromStream(stream, name); return getClassFromStream(stream, name);
} }
} catch (IOException ioe) {
}
catch (SecurityException se) {
throw se;
}
catch (IOException ioe) {
// ioe.printStackTrace(); // ioe.printStackTrace();
log("Exception reading component " + pathComponent ,
log("Exception reading component " + pathComponent ,
Project.MSG_VERBOSE); Project.MSG_VERBOSE);
} }
} }
@@ -1073,13 +1083,13 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
/** /**
* Finds a system class (which should be loaded from the same classloader * Finds a system class (which should be loaded from the same classloader
* as the Ant core). * as the Ant core).
*
*
* For JDK 1.1 compatability, this uses the findSystemClass method if * For JDK 1.1 compatability, this uses the findSystemClass method if
* no parent classloader has been specified. * no parent classloader has been specified.
*
* @param name The name of the class to be loaded.
*
* @param name The name of the class to be loaded.
* Must not be <code>null</code>. * Must not be <code>null</code>.
*
*
* @return the required Class object * @return the required Class object
* *
* @exception ClassNotFoundException if the requested class does not exist * @exception ClassNotFoundException if the requested class does not exist


+ 23
- 3
src/main/org/apache/tools/ant/taskdefs/Available.java View File

@@ -86,6 +86,7 @@ public class Available extends Task implements Condition {
private AntClassLoader loader; private AntClassLoader loader;
private String value = "true"; private String value = "true";
private boolean isTask = false; private boolean isTask = false;
private boolean ignoreSystemclasses = false;


public void setClasspath(Path classpath) { public void setClasspath(Path classpath) {
createClasspath().append(classpath); createClasspath().append(classpath);
@@ -152,6 +153,10 @@ public class Available extends Task implements Condition {
this.type = type; this.type = type;
} }


public void setIgnoresystemclasses(boolean ignore) {
this.ignoreSystemclasses = ignore;
}

public void execute() throws BuildException { public void execute() throws BuildException {
if (property == null) { if (property == null) {
throw new BuildException("property attribute is required", location); throw new BuildException("property attribute is required", location);
@@ -349,7 +354,22 @@ public class Available extends Task implements Condition {
private boolean checkClass(String classname) { private boolean checkClass(String classname) {
try { try {
Class requiredClass = null; Class requiredClass = null;
if( ignoreSystemclasses ) {
loader = new AntClassLoader(null,getProject(),classpath,false);
if (loader != null) { if (loader != null) {
try {
loader.findClass(classname);
}
catch( SecurityException se ) {
// class found but restricted name; this is actually
// the case we're looking for, so catch the exception
// and return
return true;
}
}
return false;
}
else if (loader != null) {
requiredClass = loader.loadClass(classname); requiredClass = loader.loadClass(classname);
} else { } else {
ClassLoader l = this.getClass().getClassLoader(); ClassLoader l = this.getClass().getClassLoader();
@@ -364,12 +384,12 @@ public class Available extends Task implements Condition {
AntClassLoader.initializeClass(requiredClass); AntClassLoader.initializeClass(requiredClass);
return true; return true;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
log("class \"" + classname + "\" was not found",
log("class \"" + classname + "\" was not found",
Project.MSG_DEBUG); Project.MSG_DEBUG);
return false; return false;
} catch (NoClassDefFoundError e) { } catch (NoClassDefFoundError e) {
log("Could not load dependent class \"" + e.getMessage()
+ "\" for class \"" + classname + "\"",
log("Could not load dependent class \"" + e.getMessage()
+ "\" for class \"" + classname + "\"",
Project.MSG_DEBUG); Project.MSG_DEBUG);
return false; return false;
} }


+ 37
- 1
src/testcases/org/apache/tools/ant/taskdefs/AvailableTest.java View File

@@ -1,7 +1,7 @@
/* /*
* The Apache Software License, Version 1.1 * The Apache Software License, Version 1.1
* *
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* Copyright (c) 2000-2002 The Apache Software Foundation. All rights
* reserved. * reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,8 @@
package org.apache.tools.ant.taskdefs; package org.apache.tools.ant.taskdefs;


import org.apache.tools.ant.BuildFileTest; import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.Project;

/** /**
* @author Nico Seessle <nico@seessle.de> * @author Nico Seessle <nico@seessle.de>
*/ */
@@ -189,4 +191,38 @@ public class AvailableTest extends BuildFileTest {
public void test19() { public void test19() {
expectBuildException("test19", "Invalid value for type attribute."); expectBuildException("test19", "Invalid value for type attribute.");
} }

// Core class that exists in system classpath is ignored
public void test20() {
executeTarget("test20");
assertNull(project.getProperty("test"));
}

// Core class that exists in system classpath is ignored, but found in specified classpath
public void test21() {
if (project.getJavaVersion() == Project.JAVA_1_1) {
// java.* classes are not found in JDK 1.1 even if specified in classpath attribute; test24 shows correct operation
return;
}
executeTarget("test21");
assertEquals("true",project.getProperty("test"));
}

// Core class that exists in system classpath is not ignored with ignoresystemclass="false"
public void test22() {
executeTarget("test22");
assertEquals("true",project.getProperty("test"));
}

// Core class that exists in system classpath is not ignored with default ignoresystemclasses value
public void test23() {
executeTarget("test23");
assertEquals("true",project.getProperty("test"));
}

// Class is found in specified classpath
public void test24() {
executeTarget("test24");
assertEquals("true",project.getProperty("test"));
}
} }

Loading…
Cancel
Save