KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > TraXLiaison


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs.optional;
20
21 import java.io.BufferedInputStream JavaDoc;
22 import java.io.BufferedOutputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Vector JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.net.URL JavaDoc;
33 import javax.xml.parsers.ParserConfigurationException JavaDoc;
34 import javax.xml.parsers.SAXParserFactory JavaDoc;
35 import javax.xml.transform.ErrorListener JavaDoc;
36 import javax.xml.transform.Source JavaDoc;
37 import javax.xml.transform.SourceLocator JavaDoc;
38 import javax.xml.transform.Templates JavaDoc;
39 import javax.xml.transform.Transformer JavaDoc;
40 import javax.xml.transform.TransformerException JavaDoc;
41 import javax.xml.transform.TransformerFactory JavaDoc;
42 import javax.xml.transform.URIResolver JavaDoc;
43 import javax.xml.transform.sax.SAXSource JavaDoc;
44 import javax.xml.transform.stream.StreamResult JavaDoc;
45 import javax.xml.transform.stream.StreamSource JavaDoc;
46 import javax.xml.transform.TransformerConfigurationException JavaDoc;
47 import org.apache.tools.ant.BuildException;
48 import org.apache.tools.ant.Project;
49 import org.apache.tools.ant.taskdefs.XSLTLiaison3;
50 import org.apache.tools.ant.taskdefs.XSLTLogger;
51 import org.apache.tools.ant.taskdefs.XSLTLoggerAware;
52 import org.apache.tools.ant.taskdefs.XSLTProcess;
53 import org.apache.tools.ant.types.XMLCatalog;
54 import org.apache.tools.ant.types.Resource;
55 import org.apache.tools.ant.types.resources.FileResource;
56 import org.apache.tools.ant.types.resources.URLResource;
57 import org.apache.tools.ant.util.FileUtils;
58 import org.apache.tools.ant.util.JAXPUtils;
59 import org.xml.sax.EntityResolver JavaDoc;
60 import org.xml.sax.InputSource JavaDoc;
61 import org.xml.sax.SAXException JavaDoc;
62 import org.xml.sax.XMLReader JavaDoc;
63
64 /**
65  * Concrete liaison for XSLT processor implementing TraX. (ie JAXP 1.1)
66  *
67  * @since Ant 1.3
68  */

69 public class TraXLiaison implements XSLTLiaison3, ErrorListener JavaDoc, XSLTLoggerAware {
70
71     /**
72      * Helper for transforming filenames to URIs.
73      *
74      * @since Ant 1.7
75      */

76     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
77
78     /**
79      * The current <code>Project</code>
80      */

81     private Project project;
82
83     /**
84      * the name of the factory implementation class to use
85      * or null for default JAXP lookup.
86      */

87     private String JavaDoc factoryName = null;
88
89     /** The trax TransformerFactory */
90     private TransformerFactory JavaDoc tfactory = null;
91
92     /** stylesheet to use for transformation */
93     private Resource stylesheet;
94
95     private XSLTLogger logger;
96
97     /** possible resolver for publicIds */
98     private EntityResolver JavaDoc entityResolver;
99
100     /** transformer to use for processing files */
101     private Transformer JavaDoc transformer;
102
103     /** The In memory version of the stylesheet */
104     private Templates JavaDoc templates;
105
106     /**
107      * The modification time of the stylesheet from which the templates
108      * are read
109      */

110     private long templatesModTime;
111
112     /** possible resolver for URIs */
113     private URIResolver JavaDoc uriResolver;
114
115     /** transformer output properties */
116     private Vector JavaDoc outputProperties = new Vector JavaDoc();
117
118     /** stylesheet parameters */
119     private Hashtable JavaDoc params = new Hashtable JavaDoc();
120
121     /** factory attributes */
122     private Vector JavaDoc attributes = new Vector JavaDoc();
123
124     /**
125      * Constructor for TraXLiaison.
126      * @throws Exception never
127      */

128     public TraXLiaison() throws Exception JavaDoc {
129     }
130
131     /**
132      * Set the stylesheet file.
133      * @param stylesheet a <code>File</code> value
134      * @throws Exception on error
135      */

136     public void setStylesheet(File JavaDoc stylesheet) throws Exception JavaDoc {
137         FileResource fr = new FileResource();
138         fr.setProject(project);
139         fr.setFile(stylesheet);
140         setStylesheet(fr);
141     }
142
143     /**
144      * Set the stylesheet file.
145      * @param stylesheet a {@link org.apache.tools.ant.types.Resource} value
146      * @throws Exception on error
147      */

148     public void setStylesheet(Resource stylesheet) throws Exception JavaDoc {
149         if (this.stylesheet != null) {
150             // resetting the stylesheet - reset transformer
151
transformer = null;
152
153             // do we need to reset templates as well
154
if (!this.stylesheet.equals(stylesheet)
155                 || (stylesheet.getLastModified() != templatesModTime)) {
156                 templates = null;
157             }
158         }
159         this.stylesheet = stylesheet;
160     }
161
162     /**
163      * Transform an input file.
164      * @param infile the file to transform
165      * @param outfile the result file
166      * @throws Exception on error
167      */

168     public void transform(File JavaDoc infile, File JavaDoc outfile) throws Exception JavaDoc {
169         if (transformer == null) {
170             createTransformer();
171         }
172
173         InputStream JavaDoc fis = null;
174         OutputStream JavaDoc fos = null;
175         try {
176             fis = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(infile));
177             fos = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(outfile));
178             StreamResult JavaDoc res = new StreamResult JavaDoc(fos);
179             // not sure what could be the need of this...
180
res.setSystemId(JAXPUtils.getSystemId(outfile));
181             Source JavaDoc src = getSource(fis, infile);
182
183             // set parameters on each transformation, maybe something has changed
184
//(e.g. value of file name parameter)
185
setTransformationParameters();
186
187             transformer.transform(src, res);
188         } finally {
189             // make sure to close all handles, otherwise the garbage
190
// collector will close them...whenever possible and
191
// Windows may complain about not being able to delete files.
192
try {
193                 if (fis != null) {
194                     fis.close();
195                 }
196             } catch (IOException JavaDoc ignored) {
197                 // ignore
198
}
199             try {
200                 if (fos != null) {
201                     fos.close();
202                 }
203             } catch (IOException JavaDoc ignored) {
204                 // ignore
205
}
206         }
207     }
208
209     /**
210      * Get the source instance from the stream and id of the file.
211      * @param is the stream containing the stylesheet data.
212      * @param infile the file that will be used for the systemid.
213      * @return the configured source instance matching the stylesheet.
214      * @throws ParserConfigurationException if a parser cannot be created which
215      * satisfies the requested configuration.
216      * @throws SAXException in case of problem detected by the SAX parser.
217      */

218     private Source JavaDoc getSource(InputStream JavaDoc is, File JavaDoc infile)
219         throws ParserConfigurationException JavaDoc, SAXException JavaDoc {
220         // todo: is this comment still relevant ??
221
// FIXME: need to use a SAXSource as the source for the transform
222
// so we can plug in our own entity resolver
223
Source JavaDoc src = null;
224         if (entityResolver != null) {
225             if (getFactory().getFeature(SAXSource.FEATURE)) {
226                 SAXParserFactory JavaDoc spFactory = SAXParserFactory.newInstance();
227                 spFactory.setNamespaceAware(true);
228                 XMLReader JavaDoc reader = spFactory.newSAXParser().getXMLReader();
229                 reader.setEntityResolver(entityResolver);
230                 src = new SAXSource JavaDoc(reader, new InputSource JavaDoc(is));
231             } else {
232                 throw new IllegalStateException JavaDoc("xcatalog specified, but "
233                     + "parser doesn't support SAX");
234             }
235         } else {
236             // WARN: Don't use the StreamSource(File) ctor. It won't work with
237
// xalan prior to 2.2 because of systemid bugs.
238
src = new StreamSource JavaDoc(is);
239         }
240         src.setSystemId(JAXPUtils.getSystemId(infile));
241         return src;
242     }
243
244     private Source JavaDoc getSource(InputStream JavaDoc is, Resource resource)
245         throws ParserConfigurationException JavaDoc, SAXException JavaDoc {
246         // todo: is this comment still relevant ??
247
// FIXME: need to use a SAXSource as the source for the transform
248
// so we can plug in our own entity resolver
249
Source JavaDoc src = null;
250         if (entityResolver != null) {
251             if (getFactory().getFeature(SAXSource.FEATURE)) {
252                 SAXParserFactory JavaDoc spFactory = SAXParserFactory.newInstance();
253                 spFactory.setNamespaceAware(true);
254                 XMLReader JavaDoc reader = spFactory.newSAXParser().getXMLReader();
255                 reader.setEntityResolver(entityResolver);
256                 src = new SAXSource JavaDoc(reader, new InputSource JavaDoc(is));
257             } else {
258                 throw new IllegalStateException JavaDoc("xcatalog specified, but "
259                     + "parser doesn't support SAX");
260             }
261         } else {
262             // WARN: Don't use the StreamSource(File) ctor. It won't work with
263
// xalan prior to 2.2 because of systemid bugs.
264
src = new StreamSource JavaDoc(is);
265         }
266         // The line below is a hack: the system id must an URI, but it is not
267
// cleat to get the URI of an resource, so just set the name of the
268
// resource as a system id
269
src.setSystemId(resourceToURI(resource));
270         return src;
271     }
272
273     private String JavaDoc resourceToURI(Resource resource) {
274         if (resource instanceof FileResource) {
275             File JavaDoc f = ((FileResource) resource).getFile();
276             return FILE_UTILS.toURI(f.getAbsolutePath());
277         }
278         if (resource instanceof URLResource) {
279             URL JavaDoc u = ((URLResource) resource).getURL();
280             return String.valueOf(u);
281         } else {
282             return resource.getName();
283         }
284     }
285
286     /**
287      * Read in templates from the stylesheet
288      */

289     private void readTemplates()
290         throws IOException JavaDoc, TransformerConfigurationException JavaDoc,
291                ParserConfigurationException JavaDoc, SAXException JavaDoc {
292
293         // Use a stream so that you can close it yourself quickly
294
// and avoid keeping the handle until the object is garbaged.
295
// (always keep control), otherwise you won't be able to delete
296
// the file quickly on windows.
297
InputStream JavaDoc xslStream = null;
298         try {
299             xslStream
300                 = new BufferedInputStream JavaDoc(stylesheet.getInputStream());
301             templatesModTime = stylesheet.getLastModified();
302             Source JavaDoc src = getSource(xslStream, stylesheet);
303             templates = getFactory().newTemplates(src);
304         } finally {
305             if (xslStream != null) {
306                 xslStream.close();
307             }
308         }
309     }
310
311     /**
312      * Create a new transformer based on the liaison settings
313      * @throws Exception thrown if there is an error during creation.
314      * @see #setStylesheet(java.io.File)
315      * @see #addParam(java.lang.String, java.lang.String)
316      * @see #setOutputProperty(java.lang.String, java.lang.String)
317      */

318     private void createTransformer() throws Exception JavaDoc {
319         if (templates == null) {
320             readTemplates();
321         }
322
323         transformer = templates.newTransformer();
324
325         // configure the transformer...
326
transformer.setErrorListener(this);
327         if (uriResolver != null) {
328             transformer.setURIResolver(uriResolver);
329         }
330         for (int i = 0; i < outputProperties.size(); i++) {
331             final String JavaDoc[] pair = (String JavaDoc[]) outputProperties.elementAt(i);
332             transformer.setOutputProperty(pair[0], pair[1]);
333         }
334     }
335
336     /**
337      * Sets the paramters for the transformer.
338      */

339     private void setTransformationParameters() {
340         for (final Enumeration JavaDoc enumeration = params.keys();
341              enumeration.hasMoreElements();) {
342             final String JavaDoc name = (String JavaDoc) enumeration.nextElement();
343             final String JavaDoc value = (String JavaDoc) params.get(name);
344             transformer.setParameter(name, value);
345         }
346     }
347
348     /**
349      * return the Transformer factory associated to this liaison.
350      * @return the Transformer factory associated to this liaison.
351      * @throws BuildException thrown if there is a problem creating
352      * the factory.
353      * @see #setFactory(String)
354      * @since Ant 1.5.2
355      */

356     private TransformerFactory JavaDoc getFactory() throws BuildException {
357         if (tfactory != null) {
358             return tfactory;
359         }
360         // not initialized yet, so create the factory
361
if (factoryName == null) {
362             tfactory = TransformerFactory.newInstance();
363         } else {
364             try {
365                 Class JavaDoc clazz = Class.forName(factoryName);
366                 tfactory = (TransformerFactory JavaDoc) clazz.newInstance();
367             } catch (Exception JavaDoc e) {
368                 throw new BuildException(e);
369             }
370         }
371         tfactory.setErrorListener(this);
372
373         // specific attributes for the transformer
374
for (int i = 0; i < attributes.size(); i++) {
375             final Object JavaDoc[] pair = (Object JavaDoc[]) attributes.elementAt(i);
376             tfactory.setAttribute((String JavaDoc) pair[0], pair[1]);
377         }
378
379         if (uriResolver != null) {
380             tfactory.setURIResolver(uriResolver);
381         }
382         return tfactory;
383     }
384
385
386     /**
387      * Set the factory name to use instead of JAXP default lookup.
388      * @param name the fully qualified class name of the factory to use
389      * or null for the default JAXP look up mechanism.
390      * @since Ant 1.6
391      */

392     public void setFactory(String JavaDoc name) {
393         factoryName = name;
394     }
395
396     /**
397      * Set a custom attribute for the JAXP factory implementation.
398      * @param name the attribute name.
399      * @param value the value of the attribute, usually a boolean
400      * string or object.
401      * @since Ant 1.6
402      */

403     public void setAttribute(String JavaDoc name, Object JavaDoc value) {
404         final Object JavaDoc[] pair = new Object JavaDoc[]{name, value};
405         attributes.addElement(pair);
406     }
407
408     /**
409      * Set the output property for the current transformer.
410      * Note that the stylesheet must be set prior to calling
411      * this method.
412      * @param name the output property name.
413      * @param value the output property value.
414      * @since Ant 1.5
415      * @since Ant 1.5
416      */

417     public void setOutputProperty(String JavaDoc name, String JavaDoc value) {
418         final String JavaDoc[] pair = new String JavaDoc[]{name, value};
419         outputProperties.addElement(pair);
420     }
421
422     /**
423      * Set the class to resolve entities during the transformation.
424      * @param aResolver the resolver class.
425      */

426     public void setEntityResolver(EntityResolver JavaDoc aResolver) {
427         entityResolver = aResolver;
428     }
429
430     /**
431      * Set the class to resolve URIs during the transformation
432      * @param aResolver a <code>EntityResolver</code> value
433      */

434     public void setURIResolver(URIResolver JavaDoc aResolver) {
435         uriResolver = aResolver;
436     }
437
438     /**
439      * Add a parameter.
440      * @param name the name of the parameter
441      * @param value the value of the parameter
442      */

443     public void addParam(String JavaDoc name, String JavaDoc value) {
444         params.put(name, value);
445     }
446
447     /**
448      * Set a logger.
449      * @param l a logger.
450      */

451     public void setLogger(XSLTLogger l) {
452         logger = l;
453     }
454
455     /**
456      * Log an error.
457      * @param e the exception to log.
458      */

459     public void error(TransformerException JavaDoc e) {
460         logError(e, "Error");
461     }
462
463     /**
464      * Log a fatal error.
465      * @param e the exception to log.
466      */

467     public void fatalError(TransformerException JavaDoc e) {
468         logError(e, "Fatal Error");
469         throw new BuildException("Fatal error during transformation", e);
470     }
471
472     /**
473      * Log a warning.
474      * @param e the exception to log.
475      */

476     public void warning(TransformerException JavaDoc e) {
477         logError(e, "Warning");
478     }
479
480     private void logError(TransformerException JavaDoc e, String JavaDoc type) {
481         if (logger == null) {
482             return;
483         }
484
485         StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
486         SourceLocator JavaDoc locator = e.getLocator();
487         if (locator != null) {
488             String JavaDoc systemid = locator.getSystemId();
489             if (systemid != null) {
490                 String JavaDoc url = systemid;
491                 if (url.startsWith("file:")) {
492                     url = FileUtils.getFileUtils().fromURI(url);
493                 }
494                 msg.append(url);
495             } else {
496                 msg.append("Unknown file");
497             }
498             int line = locator.getLineNumber();
499             if (line != -1) {
500                 msg.append(":");
501                 msg.append(line);
502                 int column = locator.getColumnNumber();
503                 if (column != -1) {
504                     msg.append(":");
505                     msg.append(column);
506                 }
507             }
508         }
509         msg.append(": ");
510         msg.append(type);
511         msg.append("! ");
512         msg.append(e.getMessage());
513         if (e.getCause() != null) {
514             msg.append(" Cause: ");
515             msg.append(e.getCause());
516         }
517
518         logger.log(msg.toString());
519     }
520
521     // kept for backwards compatibility
522
/**
523      * @param file the filename to use for the systemid
524      * @return the systemid
525      * @deprecated since 1.5.x.
526      * Use org.apache.tools.ant.util.JAXPUtils#getSystemId instead.
527      */

528     protected String JavaDoc getSystemId(File JavaDoc file) {
529         return JAXPUtils.getSystemId(file);
530     }
531
532
533     /**
534      * Specific configuration for the TRaX liaison.
535      * @param xsltTask the XSLTProcess task instance from which this liasion
536      * is to be configured.
537      */

538     public void configure(XSLTProcess xsltTask) {
539         project = xsltTask.getProject();
540         XSLTProcess.Factory factory = xsltTask.getFactory();
541         if (factory != null) {
542             setFactory(factory.getName());
543
544             // configure factory attributes
545
for (Enumeration JavaDoc attrs = factory.getAttributes();
546                     attrs.hasMoreElements();) {
547                 XSLTProcess.Factory.Attribute attr =
548                         (XSLTProcess.Factory.Attribute) attrs.nextElement();
549                 setAttribute(attr.getName(), attr.getValue());
550             }
551         }
552
553         XMLCatalog xmlCatalog = xsltTask.getXMLCatalog();
554         // use XMLCatalog as the entity resolver and URI resolver
555
if (xmlCatalog != null) {
556             setEntityResolver(xmlCatalog);
557             setURIResolver(xmlCatalog);
558         }
559
560
561         // configure output properties
562
for (Enumeration JavaDoc props = xsltTask.getOutputProperties();
563                 props.hasMoreElements();) {
564             XSLTProcess.OutputProperty prop
565                 = (XSLTProcess.OutputProperty) props.nextElement();
566             setOutputProperty(prop.getName(), prop.getValue());
567         }
568     }
569 }
570
Popular Tags