Hi guys,
Sorry if I make unnecessary noise here due to my incompetence. But I was trying
to refactor
org.apache.cocoon.sax.component.XSLTTransformer by enabling users to choose a
transfomerfactory of their choice. I added a new constructor and did some basic
refactoring.
public XSLTTransformer(final URL source, final Map<String, Object>
attributes, final String factoryClassName) {
super();
this.loadXSLT(source, attributes, factoryClassName);
}
private void loadXSLT(final URL source, final Map<String, Object> attributes,
final String factoryClassName) {
....
SAXTransformerFactory transformerFactory;
if (factoryClassName != null) {
//we need to use factoryclassname
transformerFactory =
createNewSAXTransformerFactory(factoryClassName, null);
} else {
//we need to check for attributes
if (attributes == null || attributes.isEmpty()) {
//we can use static factory
transformerFactory = TRAX_FACTORY;
} else {
//we need to instantiate new default factory
transformerFactory = createNewSAXTransformerFactory();
}
}
....
}
private static SAXTransformerFactory createNewSAXTransformerFactory() {
return (SAXTransformerFactory) TransformerFactory.newInstance();
}
private static SAXTransformerFactory createNewSAXTransformerFactory(final
String factoryClassName, final ClassLoader classLoader) {
return (SAXTransformerFactory)
TransformerFactory.newInstance(factoryClassName, classLoader);
}
But then I hit a brick wall while running the unit test below:
public void testPipelineWithMultipleXSLTProcessors() throws Exception {
newCachingPipeline()
.setStarter(new
XMLGenerator(getClass().getResource("/movies.xml")))
.addComponent(new
XSLTTransformer(this.getClass().getResource("/moviesByDirector.xslt"), null,
"net.sf.saxon.TransformerFactoryImpl"))
.addComponent(new
XSLTTransformer(this.getClass().getResource("/indent.xslt"), null,
"org.apache.xalan.processor.TransformerFactoryImpl"))
.setFinisher(new XMLSerializer())
.withEmptyConfiguration()
.setup(System.out)
.execute();
}
Don’t look at linenumbers as I have different code now of course (and I added
saxon as dependency to test this):
org.apache.cocoon.pipeline.SetupException: Could not initialize transformer
handler.
at
org.apache.cocoon.sax.component.XSLTTransformer.setSAXConsumer(XSLTTransformer.java:247)
at
org.apache.cocoon.sax.AbstractSAXProducer.setConsumer(AbstractSAXProducer.java:39)
at
org.apache.cocoon.pipeline.AbstractPipeline.linkComponents(AbstractPipeline.java:214)
at
org.apache.cocoon.pipeline.AbstractPipeline.setupComponents(AbstractPipeline.java:187)
at
org.apache.cocoon.pipeline.AbstractPipeline.setup(AbstractPipeline.java:132)
at
org.apache.cocoon.pipeline.CachingPipeline.setup(CachingPipeline.java:183)
at
org.apache.cocoon.pipeline.AbstractPipeline.setup(AbstractPipeline.java:118)
at
org.apache.cocoon.pipeline.builder.PipelineBuilder$1$1$1$1.setup(PipelineBuilder.java:122)
at
org.apache.cocoon.sax.PipelineTest.testPipelineWithMultipleXSLTProcessors(PipelineTest.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at
org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at
com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.ClassCastException: net.sf.saxon.Controller cannot be cast
to org.apache.xalan.xsltc.trax.TransformerImpl
at
org.apache.xalan.xsltc.trax.TransformerFactoryImpl.newTransformerHandler(TransformerFactoryImpl.java:928)
at
org.apache.cocoon.sax.component.XSLTTransformer.setSAXConsumer(XSLTTransformer.java:245)
... 30 more
This is probably due to
@Override
protected void setSAXConsumer(final SAXConsumer consumer) {
TransformerHandler transformerHandler;
try {
transformerHandler =
TRAX_FACTORY.newTransformerHandler(this.templates);
} catch (Exception e) {
throw new SetupException("Could not initialize transformer
handler.", e);
}
...
}
I think we shouldn’t just ALWAYS create a new transformerhandler using the
default TRAX_FACTORY but it should the same SAXTransformerFactory we created in
loadXSLT.
But setSAXConsumer is called from within AbstractPipeline.setConsumer which
again translates to AbstractSAXProducer.setConsumer which sets the SaxConsumer.
mmmm.... Anyone who is expert in this matter?
Robby