Bug 47002

Summary: junitreport: expose classpath of internal XSLTProcess task
Product: Ant Reporter: Martin von Gagern <Martin.vGagern>
Component: Optional TasksAssignee: Ant Notifications List <notifications>
Status: RESOLVED FIXED    
Severity: enhancement Keywords: PatchAvailable
Priority: P2    
Version: 1.7.1   
Target Milestone: 1.9.5   
Hardware: PC   
OS: Linux   
Attachments: Expose classpath and factory
Expose classpath and factory

Description Martin von Gagern 2009-04-08 14:25:06 UTC
junitreport does create an internal xslt task to format its report. It doesn't expose most of the configuration options of that task, though. In particular, it does not allow the classpath to be specified.

I've been writing a build.xml relying only on ant core, and fetching optional tasks along with their dependency libs through ivy. I <taskdef>ed junitreport to its implementing class with a suitable classpath, but still got a ClassNotFoundException because XSLTProcess couldn't find its TraXLiaison.

As XSLTProcess itself is core, it was loaded using the main ant classloader, not the one used to load the junit classes like XMLResultAggregator. That class loader didn't know about my additional libs, so adding ant-trax to the classpath used when redefining the jnitreport task didn't help at all.

While some cleaner solution to load tasks on the fly would be desirable, and I'll write a separate bug report about this, the quick solition would be to provide some nested classpath element, maybe as a child of the report element.
Comment 1 Martin von Gagern 2009-04-09 02:27:52 UTC
Created attachment 23470 [details]
Expose classpath and factory

This patch creates the nested XSLTProcess at creation of the AggregateTransformer, not upon execution of the transformation. This way it is much easier to simply wrap parts of the interface I'd like to expose, like the new <classpath> and <factory> nested elements, but also the existing <param> elements.

I haven't called XSLTProcess.init(), as the previous code didn't do that either. I don't fully understand the difference between init() and a constructor, but it might be a good thing to init the task somewhere.

The approach I chose is something like a whitelist delegation: the XSLTProcess is a private member, and only selected methods of its interface are wrapped and thus exposed to be configured. As an alternative, one could do something like a blacklist delegation by deriving a class from XSLTProcess and forbidding access to certain settings by ovverriding the corresponding methods and throwing exceptions therein. In that case, one might even turn the class derived from XSLTProcess into a nested <xslt> element, which would be probably much clearer, as it would be configured in the same way that a top-level <xslt> task is. I didn't choose this approach in my patch for now, but if you prefer it, I can implement that as well.
Comment 2 Martin von Gagern 2010-06-01 14:44:56 UTC
Created attachment 25506 [details]
Expose classpath and factory

Updated patch to apply to trunk after r948574. Also tweaked "since" lines to refer to 1.9, as this patch most obviously won't make it for 1.8. :-(
Comment 3 Stefan Bodewig 2014-11-26 19:58:06 UTC
Thank you for your patience.  I don't really know why this slipped through the cracks more than four years ago.