View Javadoc

1   /*
2    * 
3    *   Copyright 2005-2010, Mike Odling-Smee.  All rights reserved.
4    * 	
5    * 	Licensed under the Artistic License: 
6    * 	http://www.opensource.org/licenses/artistic-license.php
7    * 	
8    * Preamble
9    * 
10   *         The intent of this document is to state the conditions under which a 
11   *         Package may be copied, such that the Copyright Holder maintains some 
12   *         semblance of artistic control over the development of the package, while 
13   *         giving the users of the package the right to use and distribute the Package
14   * 	       in a more-or-less customary fashion, plus the right to make reasonable 
15   *         modifications.
16   * 
17   * Definitions:
18   * 
19   *         * "Package" refers to the collection of files distributed by the 
20   *         Copyright Holder, and derivatives of that collection of files created 
21   *         through textual modification. 
22   * 
23   *         * "Standard Version" refers to such a Package if it has not been modified, 
24   *         or has been modified in accordance with the wishes of the Copyright Holder.
25   * 
26   *         * "Copyright Holder" is whoever is named in the copyright or copyrights for
27   *         the package. 
28   * 
29   *         * "You" is you, if you're thinking about copying or distributing this Package.
30   * 
31   *         * "Reasonable copying fee" is whatever you can justify on the basis of 
32   *         media cost, duplication charges, time of people involved, and so on. 
33   *         (You will not be required to justify it to the Copyright Holder, but 
34   *         only to the computing community at large as a market that must bear the 
35   *         fee.) 
36   * 
37   *         * "Freely Available" means that no fee is charged for the item 
38   *         itself, though there may be fees involved in handling the item. It also 
39   *         means that recipients of the item may redistribute it under the same 
40   *         conditions they received it.
41   * 
42   * 	1. You may make and give away verbatim copies of the source form of the Standard 
43   * 	Version of this Package without restriction, provided that you duplicate all of 
44   * 	the original copyright notices and associated disclaimers.
45   * 	
46   * 	2. You may apply bug fixes, portability fixes and other modifications derived 
47   * 	from the Public Domain or from the Copyright Holder. A Package modified in such 
48   * 	a way shall still be considered the Standard Version.
49   * 	
50   * 	3. You may otherwise modify your copy of this Package in any way, provided that 
51   * 	you insert a prominent notice in each changed file stating how and when you 
52   * 	changed that file, and provided that you do at least ONE of the following:
53   * 	
54   * 		a) place your modifications in the Public Domain or otherwise make them 
55   * 		Freely Available, such as by posting said modifications to Usenet or an 
56   * 		equivalent medium, or placing the modifications on a major archive site such 
57   * 		as ftp.uu.net, or by allowing the Copyright Holder to include your modifications 
58   * 		in the Standard Version of the Package.
59   * 	
60   * 		b) use the modified Package only within your corporation or organization.
61   * 	
62   * 		c) rename any non-standard executables so the names do not conflict with 
63   * 		standard executables, which must also be provided, and provide a separate 
64   * 		manual page for each non-standard executable that clearly documents how it 
65   * 		differs from the Standard Version.
66   * 	
67   * 		d) make other distribution arrangements with the Copyright Holder.
68   * 	
69   * 	4. You may distribute the programs of this Package in object code or executable 
70   * 	form, provided that you do at least ONE of the following:
71   * 	
72   * 		a) distribute a Standard Version of the executables and library files, 
73   * 		together with instructions (in the manual page or equivalent) on where to 
74   * 		get the Standard Version.
75   * 	
76   * 		b) accompany the distribution with the machine-readable source of the 
77   * 		Package with your modifications.
78   * 	
79   * 		c) accompany any non-standard executables with their corresponding Standard 
80   * 		Version executables, giving the non-standard executables non-standard names, 
81   * 		and clearly documenting the differences in manual pages (or equivalent), 
82   * 		together with instructions on where to get the Standard Version.
83   * 	
84   * 		d) make other distribution arrangements with the Copyright Holder.
85   * 	
86   * 	5. You may charge a reasonable copying fee for any distribution of this Package. 
87   * 	You may charge any fee you choose for support of this Package. You may not 
88   * 	charge a fee for this Package itself. However, you may distribute this Package 
89   * 	in aggregate with other (possibly commercial) programs as part of a larger 
90   * 	(possibly commercial) software distribution provided that you do not advertise 
91   * 	this Package as a product of your own.
92   * 	
93   * 	6. The scripts and library files supplied as input to or produced as output from 
94   * 	the programs of this Package do not automatically fall under the copyright of 
95   * 	this Package, but belong to whomever generated them, and may be sold 
96   * 	commercially, and may be aggregated with this Package.
97   * 	
98   * 	7. C or perl subroutines supplied by you and linked into this Package shall not 
99   * 	be considered part of this Package.
100  * 	
101  * 	8. The name of the Copyright Holder may not be used to endorse or promote 
102  * 	products derived from this software without specific prior written permission.
103  * 	
104  * 	9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 
105  * 	WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 
106  * 	MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
107  * 
108  * The End
109  */
110 package net.sourceforge.xuse.build;
111 
112 import java.io.File;
113 import java.io.FileInputStream;
114 import java.io.FileNotFoundException;
115 import java.io.FileWriter;
116 import java.io.IOException;
117 import java.io.InputStream;
118 import java.io.Reader;
119 import java.io.StringReader;
120 import java.util.Arrays;
121 import java.util.HashMap;
122 import java.util.Iterator;
123 import java.util.List;
124 import java.util.Map;
125 import java.util.Map.Entry;
126 
127 import javax.xml.parsers.SAXParserFactory;
128 import javax.xml.transform.Transformer;
129 import javax.xml.transform.TransformerException;
130 import javax.xml.transform.TransformerFactory;
131 import javax.xml.transform.URIResolver;
132 import javax.xml.transform.stream.StreamResult;
133 import javax.xml.transform.stream.StreamSource;
134 
135 import net.sf.saxon.Controller;
136 import net.sf.saxon.FeatureKeys;
137 import net.sourceforge.xuse.log.Logger;
138 import net.sourceforge.xuse.utils.CommandLineWrapper;
139 import net.sourceforge.xuse.utils.Utils;
140 import net.sourceforge.xuse.utils.XuseUtils;
141 
142 import com.xmlsolutions.annotation.Requirement;
143 
144 
145 public class StylesheetInvoker {
146     
147     	private static final TransformerFactory transformerFactory = new net.sf.saxon.TransformerFactoryImpl();
148     	private static final SAXParserFactory saxFactory = SAXParserFactory.newInstance();
149     	private static final URIResolver uriResolver = transformerFactory.getURIResolver();
150     	private static final boolean DO_GRAPHS = CommandLineWrapper.graphVizAvailable(); 
151     	private static final String PERF_XML_OUT_BASE = "target/performance/";
152     	
153     	private static final StylesheetInvoker INSTANCE = new StylesheetInvoker();
154     	
155     	protected StylesheetInvoker() {
156     		Logger.debug(StylesheetInvoker.class, "Using TransformerFactory: " + transformerFactory.getClass().getCanonicalName());
157     		Logger.debug(StylesheetInvoker.class, "Using SAXParserFactory: " + saxFactory.getClass().getCanonicalName());
158     		Logger.debug(StylesheetInvoker.class, "Using URI Resolver: " + uriResolver.getClass().getCanonicalName());
159     		try {
160 				saxFactory.setFeature("http://xml.org/sax/features/validation", false);
161     			transformerFactory.setAttribute(FeatureKeys.DTD_VALIDATION, false);
162     			//Line numbers are useful in the processed peformance analysis graphs
163     			if (XusePropertiesReader.doPerformanceAnalysis()) {
164     				transformerFactory.setAttribute(FeatureKeys.LINE_NUMBERING,Boolean.TRUE);
165     			}
166     			//Some parsers cannot handle XInclude directives
167     			try {
168     				transformerFactory.setAttribute(FeatureKeys.XINCLUDE, true);
169     				//Create a dummy transformer to test XInclude support
170     				transformerFactory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream("xslts/utils/core-utils.xsl")));
171     			} catch (Throwable t) {
172     				Logger.warn(StylesheetInvoker.class, "It seems that your parser (" + saxFactory.getClass().getCanonicalName() + ") does not support XInclude directives so these will not be processed");
173     				//Reset the XInclude support
174     				transformerFactory.setAttribute(FeatureKeys.XINCLUDE, false);
175     			}
176     			File perfDir = new File(PERF_XML_OUT_BASE);
177     			if (!perfDir.exists()) {
178     				perfDir.mkdirs();
179     			}
180 			} catch (Throwable t) {
181 				Logger.error(this, "Could not initialise XML parser", t);
182 			}
183     	}
184     	
185     	public static final StylesheetInvoker getInstance() {
186 			return INSTANCE;
187 		}
188 	
189     public void invokeXslForString(String xmlString, String output, String xslFile, String templateName, Map args) throws BuildException {
190     	try {
191 			Reader source = new StringReader(xmlString);
192 	        StreamSource xmlSource = new StreamSource(source);
193 	        this.invokeXslForStreamSource(xmlSource, output, xslFile, templateName, args);
194 		} catch (Throwable t) {
195 			throw new BuildException("Error transforming xml with " + xslFile + "\nto output : " + output + "\nerror was: "+  t.getLocalizedMessage(), t);
196 		}
197     }
198     
199     private void invokeXslForStreamSource(StreamSource xmlSource, String output, String xslFile, String templateName, Map args) throws TransformerException {
200     		// Create a transformer for the stylesheet.
201 	        StreamSource xsl = getXsl(xslFile);
202 			Transformer transformer = this.initTransformer(xsl, args);	        
203 			if(templateName != null && templateName.trim().length() > 0) {
204 				//We have a dependency on Saxon here
205 		        ((Controller)transformer).setInitialTemplate(templateName);
206 			}	        
207 	        File outFile = new File(output);
208 	        StreamResult tempResult = new StreamResult(outFile.toURI().toString());
209 	        tempResult.setSystemId(outFile.toURI().toString());
210 	        transformer.transform(xmlSource, tempResult);
211         
212     }
213 	
214     public void invokeXsl(String input, String output, String xslFile, String templateName, Map args) throws BuildException {
215 		Logger.debug(this, "Applying transform: " + xslFile + " to " + input + " writing " + output + " usings args (" + args + ")");
216 		try {
217 			StreamSource xmlSource = null;
218 			if (input != null) {
219 				//Have we got an absolute or relative path?
220 				File srcXML = new File(input);
221 				if (!srcXML.exists()) {
222 					//Does not exist assume relative path
223 					srcXML = new File(new File("."), input);
224 			        if (!srcXML.exists()) {
225 			        	Logger.warn(this, "Cannot find: " + srcXML.getAbsolutePath());
226 			        }
227 				}
228 		        InputStream source = new FileInputStream(srcXML);
229 		        xmlSource = new StreamSource(source);
230 		        xmlSource.setSystemId(srcXML.getAbsolutePath());
231 			}
232 	        this.invokeXslForStreamSource(xmlSource, output, xslFile, templateName, args);
233 		} catch (Throwable t) {
234 			throw new BuildException("Error transforming " + input + "\nwith " + xslFile + "\nto output : " + output + "\nerror was: "+  t.getLocalizedMessage(), t);
235 		}
236 	}
237 	
238 	public void invokeXsl(StreamSource source, StreamResult result, String xslFile, String templateName, Map args) throws BuildException {
239 		try {
240 		    // Create a transformer for the stylesheet.
241 		    StreamSource xsl = getXsl(xslFile);
242 		    Transformer transformer = this.initTransformer(xsl, args);
243 		    if(templateName != null && templateName.trim().length() > 0) {
244 				//We have a dependency on Saxon here
245 				((Controller)transformer).setInitialTemplate(templateName);
246 		    }
247 		    transformer.transform(source, result);
248 		} catch (Throwable t) {
249 		    throw new BuildException("Error transforming " + source.getSystemId() + "\nwith " + xslFile + "\nto output : " + result.getSystemId() + "\nerror was: "+  t.getLocalizedMessage(), t);
250 		}
251 	}
252 	
253 	public void invokeXsl(String input, String output, String xslFile) throws BuildException {
254 		this.invokeXsl(input, output, xslFile, null, null);
255 	}
256 	
257 	@Requirement(traceTo={"RQ58"})
258 	public void invokePDFUseCases() throws BuildException {
259 		if (XusePropertiesReader.doPerformanceAnalysis()) {
260 			//Note this is not thread safe but Xuse is only single threaded so we are OK
261 			transformerFactory.setAttribute(FeatureKeys.TRACE_LISTENER,TraceListenerFactory.getInstance().getTraceListener(PERF_XML_OUT_BASE + "pdf-use-cases.xml"));
262 		}		
263 		String xslID = XusePropertiesReader.getSitePdfXslController();
264 		String sourceID = XusePropertiesReader.getRequirementsRepositoryFile();
265 		this.invokeXsl(sourceID, "deleteme.xml", xslID, "do-use-cases", null);
266 	}
267 	
268 	@Requirement(traceTo={"RQ58"})
269 	public void invokePDFSingleUseCase(String useCaseId) throws BuildException {
270 		if (XusePropertiesReader.doPerformanceAnalysis()) {
271 			//Note this is not thread safe but Xuse is only single threaded so we are OK
272 			transformerFactory.setAttribute(FeatureKeys.TRACE_LISTENER,TraceListenerFactory.getInstance().getTraceListener(PERF_XML_OUT_BASE + "pdf-use-case.xml"));
273 		}
274 		String xslID = XusePropertiesReader.getSitePdfXslController();
275 		String sourceID = XusePropertiesReader.getRequirementsRepositoryFile();
276 		Map<String, String> args = new HashMap<String, String>();
277 		args.put("uc-id", useCaseId);
278 		this.invokeXsl(sourceID, "deleteme.xml", xslID, "single-use-case", args);
279 	}
280 	
281 	public void invokeImportTraceReport() throws BuildException {
282 		String xslID = "xslts/data-imports/import-trace-report.xsl";
283 		String sourceID = XusePropertiesReader.getTraceReportInput();
284 		String upgradedRepositoryFileName = XusePropertiesReader.getTraceReportOutput();
285 		Logger.info(INSTANCE, "Importing traces from " + sourceID + ", wrting result " + upgradedRepositoryFileName);
286 		this.invokeXsl(sourceID, upgradedRepositoryFileName, xslID, null, null);
287 	}
288 
289 	public void invokeBuildHTMLSite() throws BuildException {
290 		if (XusePropertiesReader.doPerformanceAnalysis()) {
291 			//Note this is not thread safe but Xuse is only single threaded so we are OK
292 			transformerFactory.setAttribute(FeatureKeys.TRACE_LISTENER,TraceListenerFactory.getInstance().getTraceListener(PERF_XML_OUT_BASE + "html.xml"));
293 		}
294 		String xslID = XusePropertiesReader.getSiteXslController();
295 		String sourceID = XusePropertiesReader.getRequirementsRepositoryFile();
296 		this.invokeXsl(sourceID, "deleteme.xml", xslID, "main", null);
297 	}
298 	
299 	public void processPerformanceResults() throws BuildException {
300 		if (XusePropertiesReader.doPerformanceAnalysis()) {
301 			Logger.info(this, "Plotting performance results...");
302 			try {
303 				/*
304 				 * Cannot use-the default factory as this would try
305 				 * do performance analysis on itself probably ending
306 				 * up in some recursive mess!!
307 				 */
308 				TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl();
309 				Transformer transformer = factory.newTransformer(getXsl("timing-profile.xsl"));
310 				List<File> performanceXMLFiles = Arrays.asList(new File(PERF_XML_OUT_BASE).listFiles());
311 				File outDir = new File(XusePropertiesReader.getOutputDirectory() + "/performance");
312 				if (!outDir.exists()) {
313 					outDir.mkdirs();
314 				}
315 				for (File performanceXMLFile : performanceXMLFiles) {
316 					Logger.debug(this, "Creating performance results for: " + performanceXMLFile.getAbsolutePath());
317 					InputStream source = new FileInputStream(performanceXMLFile);
318 			        StreamSource xmlSource = new StreamSource(source);
319 			        xmlSource.setSystemId(performanceXMLFile.getAbsolutePath());
320 					File outFile = new File(outDir, "performance-results-" + performanceXMLFile.getName().substring(0, performanceXMLFile.getName().lastIndexOf(".")) + ".html");
321 			        StreamResult result = new StreamResult(outFile.toURI().toString());
322 			        result.setSystemId(outFile.toURI().toString());
323 					transformer.transform(xmlSource, result);
324 				}
325 			} catch (Throwable t) {
326 				throw new BuildException("Error generating performance results", t);
327 			}
328 		}
329 	}
330 	
331 	@Requirement(traceTo={"RQ19", "RQ60"})
332 	public void invokeBuildHTMLDocuments() throws BuildException {
333 		
334 		List<String> allDocs = XuseUtils.getDocuments();
335 		if (allDocs != null) {
336 			for (String currentDoc : allDocs) {
337 				File currentFile = new File(currentDoc);
338 				if (currentFile.exists() && currentFile.isFile()) {
339 					if (XusePropertiesReader.doPerformanceAnalysis()) {
340 						//Note this is not thread safe but Xuse is only single threaded so we are OK
341 						String docSuffix =  currentFile.getName().substring(0, currentFile.getName().lastIndexOf("."));
342 						transformerFactory.setAttribute(FeatureKeys.TRACE_LISTENER, TraceListenerFactory.getInstance().getTraceListener(PERF_XML_OUT_BASE + "html-documents-" + docSuffix + ".xml"));
343 					}
344 					String xslID = XusePropertiesReader.getGenericDocumentXsl();
345 					this.invokeXsl(currentDoc, XusePropertiesReader.getOutputDirectory() + "/deleteme.html", xslID, null, null);
346 					File deleteMeHTML = new File(XusePropertiesReader.getOutputDirectory() + "/deleteme.html");
347 					if (!deleteMeHTML.delete()) {
348 						Logger.debug(this, "Could not delete temporary file " + deleteMeHTML.getAbsolutePath());
349 					}
350 				} else {
351 					Logger.warn(this, "Location " + currentFile + " does not appear to be a valid file");
352 				}
353 			}
354 		}		
355 	}
356 	
357 	public void invokeGraphRequirement(String requirementId) throws BuildException {
358 		String requirementsDoc = XusePropertiesReader.getRequirementsRepositoryFile();
359 		//TODO - get this from properties file
360 		String xsl = "xslts/graph/requirement-graph.xsl";
361 		Map<String, String> args = new HashMap<String, String>();
362 		args.put("req-id", requirementId);
363 		String dotDir = XusePropertiesReader.getOutputDirectory();
364 		String dotFile =  "req-" + requirementId + ".dot";
365 		String svgTempFile = XusePropertiesReader.getOutputDirectory() + "/req-" + requirementId + "-temp.svg";
366 		String svgFile = XusePropertiesReader.getOutputDirectory() + "/req-" + requirementId + ".svg";
367 		this.invokeXsl(requirementsDoc, dotFile, xsl, null, args);
368 		FileWriter svgResultFile = null;
369 		try {
370 			String resultSvgRaw = CommandLineWrapper.executeGraphVizForSvg(dotDir, dotFile);
371 			svgResultFile = new FileWriter(svgTempFile);
372 			svgResultFile.append(resultSvgRaw);
373 			this.invokeXslForString(resultSvgRaw, svgFile, "xslts/graph/prettying-graphviz.xsl", null, null);
374 		} catch (IOException ioe) {
375 			throw new BuildException("Could not create requirement graph", ioe);
376 		} finally {
377 			if (svgResultFile != null) {
378 				try {
379 					svgResultFile.close();
380 				} catch (IOException e) {
381 					throw new BuildException("Could not close SVG result file", e);
382 				}
383 			}
384 		}
385 	}
386 	
387 	@Requirement(traceTo={"RQ48"})
388 	public void invokeValidateProject() throws BuildException {
389 		if (XusePropertiesReader.doPerformanceAnalysis()) {
390 			//Note this is not thread safe but Xuse is only single threaded so we are OK
391 			transformerFactory.setAttribute(FeatureKeys.TRACE_LISTENER,TraceListenerFactory.getInstance().getTraceListener("validate.xml"));
392 		}
393 		String xslID = XusePropertiesReader.getSiteXslController();
394 		String sourceID = XusePropertiesReader.getRequirementsRepositoryFile();
395 		this.invokeXsl(sourceID, "deleteme.xml", xslID, "validate", null);
396 	}
397 
398 	public void invokeUpgrade() throws BuildException {
399 		String xslID = XusePropertiesReader.getUpgradeXslController();
400 		String sourceID = XusePropertiesReader.getRequirementsRepositoryFile();
401 		this.invokeXsl(sourceID, "deleteme.xml", xslID, "main", null);
402 	}
403 
404 	public Transformer initTransformer(StreamSource xsl, Map<String, String> addtionalArgs) throws BuildException {
405 		//System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
406 		try {
407 			//TransformerFactory tFactory = TransformerFactory.newInstance();
408 			
409 			Transformer transformer = transformerFactory.newTransformer(xsl);
410 			File baseDir = new File(".");
411 			transformer.setParameter("baseDir", baseDir.getAbsolutePath());
412 			transformer.setParameter("theme", XusePropertiesReader.getHTMLTheme());
413 			transformer.setParameter("useCaseFolder", XusePropertiesReader.getUseCaseDirectory());
414 			transformer.setParameter("html-output-location", XusePropertiesReader.getOutputDirectory());
415 			transformer.setParameter("dictionary", XusePropertiesReader.getDictionary());
416 			transformer.setParameter("userDictionary", XusePropertiesReader.getUserDictionary());
417 			transformer.setParameter("requirement-xml-file", XusePropertiesReader.getRequirementsRepositoryFile());
418 			transformer.setParameter("actors-xml-file", XusePropertiesReader.getActors());
419 			transformer.setParameter("stakeholders-xml-file", XusePropertiesReader.getStakeholders());
420 			transformer.setParameter("glossary-xml-file", XusePropertiesReader.getGlossary());
421 			transformer.setParameter("company", XusePropertiesReader.getCompanyName());
422 			transformer.setParameter("project", XusePropertiesReader.getProjectName());
423 			transformer.setParameter("customer", XusePropertiesReader.getCustomerName());
424 			transformer.setParameter("company-logo", XusePropertiesReader.getCompanyLogo());
425 			transformer.setParameter("project-logo", XusePropertiesReader.getProjectLogo());
426 			transformer.setParameter("customer-logo", XusePropertiesReader.getCustomerLogo());
427 			transformer.setParameter("req-nav-style", XusePropertiesReader.getRequirementNavigationViewStyle());
428 			transformer.setParameter("req-list-style", XusePropertiesReader.getRequirementListStyle());
429 			//All settings for doing graphics
430 			transformer.setParameter("graphviz-available", new Boolean(DO_GRAPHS));
431 			transformer.setParameter("usecase-pkg-diag-html", new Boolean(XusePropertiesReader.graphUseCasePackageHTML()));
432 			transformer.setParameter("usecase-pkg-diag-pdf", new Boolean(XusePropertiesReader.graphUseCasePackagePDF()));
433 			transformer.setParameter("usecase-pkg-diag-splines", XusePropertiesReader.graphUseCasePackageSplines());
434 			transformer.setParameter("usecase-pkg-diag-degrees", XusePropertiesReader.graphUseCasePackageDegrees());
435 			transformer.setParameter("use-case-activity-html", new Boolean(XusePropertiesReader.graphUseCaseActivityDiagramsHTML()));
436 			transformer.setParameter("use-case-activity-pdf", new Boolean(XusePropertiesReader.graphUseCaseActivityDiagramsPDF()));
437 			transformer.setParameter("use-case-activity-splines", XusePropertiesReader.graphUseCaseActivityDiagramsSplines());
438 			//Miscellaneous
439 			transformer.setParameter("min-log-level", XusePropertiesReader.getLogLevelAsStr());
440 			transformer.setParameter("skip-model-validation", new Boolean(XusePropertiesReader.skipModelValidation()));
441 			transformer.setParameter("store-model-memento", new Boolean(XusePropertiesReader.storeModelMemento()));
442 			transformer.setParameter("skip-glossary-linking", new Boolean(XusePropertiesReader.skipGlossaryLinking()));
443 			
444 			//transformer.setParameter("trace-report", XusePropertiesReader.getTraceReport());
445 			if (addtionalArgs != null && !addtionalArgs.isEmpty()) {
446 				Iterator<Entry<String, String>> iter =  addtionalArgs.entrySet().iterator();
447 				Map.Entry<String,String> entry = null;
448 				while (iter.hasNext()) {
449 					entry = iter.next();
450 					Logger.debug(this, "Adding parameter: " + entry.getKey() + "; " + entry.getValue());
451 					transformer.setParameter((String)entry.getKey(), entry.getValue());
452 				}
453 			}
454 			this.overrideTransforInitialisation(transformer);	
455 			return transformer;
456 		} catch (Throwable t) {
457 			t.printStackTrace();
458 			throw new BuildException("Error initialising XSLT: " + t.getLocalizedMessage(), t);
459 		}
460 	}
461 	
462 	protected void overrideTransforInitialisation(Transformer transformer) throws BuildException {
463 	    //Do nothing
464 	}
465 	
466 	private StreamSource getXsl(String name) throws BuildException {
467 		//File userDir = new File(System.getProperty("user.home"));
468 		//File xuseDir = new File(userDir, ".xuse");
469 		File xuseDir = new File(XusePropertiesReader.getXuseWorkingDir());
470 		File file = new File(xuseDir, name);
471 		StreamSource streamSource = null;
472 		try {
473 			if (!file.exists()) {
474 				InputStream is = ClassLoader.getSystemResourceAsStream(name);
475 				if (is != null) {
476 					streamSource = new StreamSource(is);
477 				} else {
478 					throw new BuildException("Could not locate " + name + " in " + xuseDir.getAbsolutePath() + ", or in the classpath");
479 				}
480 			} else {
481 				streamSource = new StreamSource(new FileInputStream(file));
482 				streamSource.setSystemId(file.toURI().toString());
483 			}
484 		} catch (FileNotFoundException fnfe) {
485 			throw new BuildException("Error finding the file - " + name + " - in the classpath.", fnfe);
486 		}
487 		return streamSource;
488 	}
489 	
490 	
491 
492 }