diff --git a/docs/faq.html b/docs/faq.html index 87a7b0fa0..24b3f0e99 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -288,6 +288,10 @@
+ + + <style> or <junit> ignores my + <classpath> + + + |
+ ++ |
CLASSPATH
environment variable.
Do neither of the above, and instead, specify their locations using
a <classpath>
element in the build file.
-See the
-bugs database for details.
+See the
+FAQ for details.
diff --git a/xdocs/faq.xml b/xdocs/faq.xml
index 6d3d177e7..c891770a8 100644
--- a/xdocs/faq.xml
+++ b/xdocs/faq.xml
@@ -951,6 +951,122 @@ mv /tmp/foo $ANT_HOME/bin/antRun
the front of the PATH fixes the problem.
+
+ These tasks don't ignore your classpath setting, you + are facing a common problem with delegating classloaders.
+ +First of all let's state that Ant adds all
+ .jar
files from ANT_HOME/lib
to
+ CLASSPATH
, therefore "in
+ CLASSPATH
" shall mean "either in your
+ CLASSPATH
environment variable or
+ ANT_HOME/lib
" for the rest of this
+ answer.
This question collects a common type of problem: A task
+ needs an external library and it has a nested classpath
+ element so that you can point it to this external library, but
+ that doesn't work unless you put the external library into the
+ CLASSPATH
.
The root of the problem is that the class that needs the
+ external library is on the CLASSPATH
.
When you specify a nested <classpath>
in
+ Ant, Ant creates a new class loader that uses the path you
+ have specified. It then tries to load additional classes from
+ this classloader.
In most cases - for example the two cases above - Ant + doesn't load the external library directly, it is the loaded + class that does so.
+ +In the case of <junit>
it is the task
+ implementation itself and in the case of
+ <style>
it is the implementation of the
+ org.apache.tools.ant.taskdefs.XSLTLiaison
+ class.
Ant's class loader implementation uses Java's + delegation model, see http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html + the paragraph
+ +The+ +ClassLoader
class uses a + delegation model to search for classes and resources. Each + instance ofClassLoader
has an associated parent + class loader. When called upon to find a class or resource, a +ClassLoader
instance will delegate the search for + the class or resource to its parent class loader before + attempting to find the class or resource itself. The virtual + machine's built-in class loader, called the bootstrap + class loader, does not itself have a parent but may serve as + the parent of aClassLoader
+ instance.
This means, Ant's class loader will consult the
+ bootstrap class loader first, which tries to load classes from
+ CLASSPATH
. The bootstrap class loader
+ doesn't know anything about Ant's class loader or
+ even the path you have specified.
If the bootstrap class loader can load the class Ant has
+ asked it to load, this class will try to load the external
+ library from CLASSPATH
as well - it doesn't
+ know anything else - and will not find it unless the library
+ is in CLASSPATH
as well.
To solve this, you have two major options:
+ +CLASSPATH
as well this is not what you want,
+ otherwise you wouldn't have found this FAQ entry.CLASSPATH
.The easiest way to do this is to remove
+ optional.jar
from ANT_HOME/lib
. If
+ you do so, you will have to <taskdef>
all
+ optional tasks and use nested <classpath>
+ elements in the <taskdef>
tasks that point
+ to the new location of optional.jar
. Also,
+ don't forget to add the new location of
+ optional.jar
to the
+ <classpath>
of your
+ <style>
or <junit>
+ task.
If you want to avoid to <taskdef>
all
+ optional tasks you need, the only other option is to remove
+ the classes that should not be loaded via the bootstrap class
+ loader from optional.jar
and put them into a
+ separate archive. Add this separate archive to the
+ <classpath>
of your
+ <style>
or <junit>
task
+ - and make sure the separate archive is not in
+ CLASSPATH
.
In the case of <junit>
you'd have
+ to remove all classes that are in the
+ org/apache/tools/ant/taskdefs/optional/junit
+ directory, in the <style>
case it is one of
+ the *Liaison
classes in
+ org/apache/tools/ant/taskdefs/optional
.
If you use the option to break up optional.jar
+ for <junit>
, you still have to use a
+ <taskdef>
with a nested
+ <classpath>
to define the junit task.