Ant manual for XSLT task says classpath the classpath to use when looking up the XSLT processor. The XSLT task uses the defined classpath to look up the XSLTLiason class. Historically, this made sense. Now, Trax is standard and the XSL:P and Xalan liasons are deprecated. It would seem to make sense to allow the TraXLiason to use the defined classpath to look up the transformer to use. The factory element allows you to specify the precise transformer class to use, but if that class isn't on the default classpath you're sunk. If TraXLiason could use the XSLTProcess' classpath, you can ship your processor of choice in your build configuration and the problem is solved.
Proposed patches to implement - diff -u -r1.85 XSLTProcess.java --- XSLTProcess.java 16 Apr 2004 09:59:02 -0000 1.85 +++ XSLTProcess.java 16 Jun 2004 10:53:00 -0000 @@ -414,7 +414,7 @@ * @return the requested class. * @exception Exception if the class could not be loaded. */ - private Class loadClass(String classname) throws Exception { + public Class loadClass(String classname) throws Exception { if (classpath == null) { return Class.forName(classname); } else { diff -u -r1.35 TraXLiaison.java --- TraXLiaison.java 9 Mar 2004 16:48:15 -0000 1.35 +++ TraXLiaison.java 16 Jun 2004 10:53:49 -0000 @@ -66,6 +66,9 @@ */ private String factoryName = null; + /** the owning XSLT task */ + private XSLTProcess xsltTask = null; + /** The trax TransformerFactory */ private TransformerFactory tfactory = null; @@ -259,7 +262,7 @@ tfactory = TransformerFactory.newInstance(); } else { try { - Class clazz = Class.forName(factoryName); + Class clazz = xsltTask.loadClass(factoryName); tfactory = (TransformerFactory) clazz.newInstance(); } catch (Exception e) { throw new BuildException(e); @@ -401,6 +404,8 @@ * is to be configured. */ public void configure(XSLTProcess xsltTask) { + this.xsltTask = xsltTask; + XSLTProcess.Factory factory = xsltTask.getFactory(); if (factory != null) { setFactory(factory.getName()); @@ -413,6 +418,8 @@ setAttribute(attr.getName(), attr.getValue()); } } + + XMLCatalog xmlCatalog = xsltTask.getXMLCatalog(); // use XMLCatalog as the entity resolver and URI resolver
Ant 1.6.2 will set the context classloader for the current thread since the TransformerFactory will use that. This is probably going to help with your issue. Any chance you could try a hand-crafted build of Ant's CVS HEAD? If not, please revisit this bug once Ant 1.6.2 has been released as beta (shouldn't be too long from now).
*** Bug 39248 has been marked as a duplicate of this bug. ***
Not solved in 1.6.5 see duplicate BUG 39248 !!! Greetings Surfer
neither the classpath element/attribute nor the classpathref attribute works
Fixed it for me i just use the contextClassLoader in Class.forName because there is nothing to change in calling class: TraXLiaison.java try { final Class clazz = Class.forName(factoryName, true, Thread.currentThread().getContextClassLoader()); tfactory = (TransformerFactory) clazz.newInstance(); } catch (Exception e) { throw new BuildException(e); } Surfer
well, we have two options here. the original patch or the context class loader. I'm not overhappy with the second, even though it does work, because I dont like context class loaders -they are a bit of a hack. Can we be 100% sure that it will always be set and valid?
So the TraXLiaison is only called from XSLTProcess and if there is a defined classpath the contextclassloader is set and valid. But if there is no defined classpath i knew the contextclassloader must also be set but not if it is valid - in the current meaning. In my environment i only work with a defined classpath. So what about mixing the two options... first try to load in the original way and if not found try to load from contextloader. Then it should work as expected... Class clazz = null; try { clazz = Class.forName(factoryName); } catch(...) { try { clazz = Class.forName(factoryName, true, Thread.currentThread().getContextClassLoader()); } catch ...
*** This bug has been marked as a duplicate of bug 46172 ***