KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xsl > TransformerImpl


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.xsl;
31
32 import com.caucho.java.LineMap;
33 import com.caucho.util.L10N;
34 import com.caucho.vfs.Encoding;
35 import com.caucho.vfs.IOExceptionWrapper;
36 import com.caucho.vfs.Path;
37 import com.caucho.vfs.Vfs;
38 import com.caucho.vfs.WriteStream;
39 import com.caucho.xml.*;
40 import com.caucho.xpath.XPathFun;
41
42 import org.w3c.dom.Document JavaDoc;
43 import org.w3c.dom.Node JavaDoc;
44 import org.xml.sax.ContentHandler JavaDoc;
45 import org.xml.sax.InputSource JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import org.xml.sax.XMLReader JavaDoc;
48 import org.xml.sax.ext.LexicalHandler JavaDoc;
49
50 import javax.xml.transform.ErrorListener JavaDoc;
51 import javax.xml.transform.OutputKeys JavaDoc;
52 import javax.xml.transform.Result JavaDoc;
53 import javax.xml.transform.Source JavaDoc;
54 import javax.xml.transform.TransformerException JavaDoc;
55 import javax.xml.transform.URIResolver JavaDoc;
56 import javax.xml.transform.dom.DOMResult JavaDoc;
57 import javax.xml.transform.dom.DOMSource JavaDoc;
58 import javax.xml.transform.sax.SAXResult JavaDoc;
59 import javax.xml.transform.sax.SAXSource JavaDoc;
60 import javax.xml.transform.stream.StreamResult JavaDoc;
61 import javax.xml.transform.stream.StreamSource JavaDoc;
62 import java.io.IOException JavaDoc;
63 import java.io.InputStream JavaDoc;
64 import java.io.OutputStream JavaDoc;
65 import java.io.OutputStreamWriter JavaDoc;
66 import java.io.Writer JavaDoc;
67 import java.util.ArrayList JavaDoc;
68 import java.util.HashMap JavaDoc;
69 import java.util.Properties JavaDoc;
70
71 public class TransformerImpl extends javax.xml.transform.Transformer JavaDoc {
72   protected static L10N L = new L10N(TransformerImpl.class);
73   
74   public final static String JavaDoc LINE_MAP = "caucho.line-map";
75   public final static String JavaDoc CACHE_DEPENDS = "caucho.cache.depends";
76   public final static String JavaDoc GENERATE_LOCATION = "caucho.generate.location";
77
78   protected StylesheetImpl _stylesheet;
79   protected HashMap JavaDoc<String JavaDoc,Object JavaDoc> _properties = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>();
80   protected HashMap JavaDoc<String JavaDoc,Object JavaDoc> _parameters;
81   
82   private URIResolver JavaDoc _uriResolver;
83   private ErrorListener JavaDoc _errorListener;
84
85   private Properties JavaDoc _output;
86   
87   protected LineMap _lineMap;
88
89   protected ArrayList JavaDoc<Path> _cacheDepends = new ArrayList JavaDoc<Path>();
90
91   protected TransformerImpl(StylesheetImpl stylesheet)
92   {
93     _stylesheet = stylesheet;
94     _uriResolver = stylesheet.getURIResolver();
95   }
96
97   /**
98    * Returns the URI to filename resolver.
99    */

100   public URIResolver JavaDoc getURIResolver()
101   {
102     return _uriResolver;
103   }
104
105   /**
106    * Sets the URI to filename resolver.
107    */

108   public void setURIResolver(URIResolver JavaDoc uriResolver)
109   {
110     _uriResolver = uriResolver;
111   }
112
113   /**
114    * Returns the error listener.
115    */

116   public ErrorListener JavaDoc getErrorListener()
117   {
118     return _errorListener;
119   }
120
121   /**
122    * Sets the error listener.
123    */

124   public void setErrorListener(ErrorListener JavaDoc errorListener)
125   {
126     _errorListener = errorListener;
127   }
128   
129   public boolean getFeature(String JavaDoc name)
130   {
131     if (name.equals(DOMResult.FEATURE))
132       return true;
133     else if (name.equals(DOMSource.FEATURE))
134       return true;
135     else if (name.equals(StreamSource.FEATURE))
136       return true;
137     else if (name.equals(StreamResult.FEATURE))
138       return true;
139     else if (name.equals(SAXSource.FEATURE))
140       return true;
141     else if (name.equals(SAXResult.FEATURE))
142       return true;
143     else
144       return false;
145   }
146
147   public void setFeature(String JavaDoc name, boolean enable)
148   {
149     if (name.equals(GENERATE_LOCATION))
150       _stylesheet.setGenerateLocation(enable);
151   }
152
153   public StylesheetImpl getStylesheet()
154   {
155     return _stylesheet;
156   }
157
158   public Object JavaDoc getProperty(String JavaDoc name)
159   {
160     Object JavaDoc property = _properties.get(name);
161
162     if (property != null)
163       return property;
164     
165     if (name.equals(CACHE_DEPENDS))
166       return _cacheDepends;
167     else if (name.equals(LINE_MAP))
168       return _lineMap;
169     else
170       return _stylesheet.getProperty(name);
171   }
172
173   public void setProperty(String JavaDoc name, Object JavaDoc value)
174   {
175     _properties.put(name, value);
176   }
177
178   /**
179    * Sets a parameter that XPath expressions in the stylesheet can
180    * use as $name.
181    *
182    * @param name the name of the XPath variable.
183    * @param value the value for the variable.
184    */

185   public void setParameter(String JavaDoc name, Object JavaDoc value)
186   {
187     if (_parameters == null)
188       _parameters = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>();
189     
190     _parameters.put(name, value);
191   }
192
193   /**
194    * Returns a copy of the xsl:output properties.
195    *
196    * @return a copy of the properties.
197    */

198   public Properties JavaDoc getOutputProperties()
199   {
200     if (_output == null)
201       _output = (Properties JavaDoc) _stylesheet.getOutputProperties().clone();
202     
203     return (Properties JavaDoc) _output.clone();
204   }
205
206   /**
207    * Sets the output properties.
208    *
209    * @param properties the new output properties.
210    */

211   public void setOutputProperties(Properties JavaDoc properties)
212   {
213     _output = properties;
214   }
215
216   /**
217    * Sets a single xsl:output property.
218    *
219    * @param name the name of the property.
220    * @param value the value of the property.
221    */

222   public void setOutputProperty(String JavaDoc name, String JavaDoc value)
223   {
224     if (_output == null)
225       _output = (Properties JavaDoc) _stylesheet.getOutputProperties().clone();
226
227     _output.put(name, value);
228   }
229
230   /**
231    * Returns the value of a single named xsl:output property.
232    *
233    * @param name the name of the property.
234    */

235   public String JavaDoc getOutputProperty(String JavaDoc name)
236   {
237     if (_output == null)
238       _output = (Properties JavaDoc) _stylesheet.getOutputProperties().clone();
239
240     return (String JavaDoc) _output.get(name);
241   }
242
243   /**
244    * Returns the named stylesheet parameter.
245    *
246    * @param name the name of the parameter.
247    *
248    * @ return the value of the named parameter.
249    */

250   public Object JavaDoc getParameter(String JavaDoc name)
251   {
252     if (_parameters == null)
253       return null;
254     else
255       return _parameters.get(name);
256   }
257
258   /**
259    * Clears all the external stylesheet parameters.
260    */

261   public void clearParameters()
262   {
263     if (_parameters != null)
264       _parameters.clear();
265     
266     if (_cacheDepends != null)
267       _cacheDepends.clear();
268   }
269
270   /**
271    * Adds a new custom function.
272    *
273    * @param name the name of the function.
274    * @param fun the new function.
275    */

276   public void addFunction(String JavaDoc name, XPathFun fun)
277   {
278     _stylesheet.addFunction(name, fun);
279   }
280
281   /**
282    * Transforms the source into the result.
283    *
284    * @param source descriptor specifying the input source.
285    * @param result descriptor specifying the output result.
286    */

287   public void transform(Source JavaDoc source, Result JavaDoc result)
288     throws TransformerException JavaDoc
289   {
290     try {
291       Node JavaDoc node = parseDocument(source);
292       
293       if (result instanceof StreamResult JavaDoc) {
294         StreamResult JavaDoc stream = (StreamResult JavaDoc) result;
295
296         if (stream.getOutputStream() != null)
297           transform(node, stream.getOutputStream(), null, result.getSystemId());
298         else if (stream.getWriter() != null) {
299           Writer JavaDoc writer = stream.getWriter();
300           WriteStream os = Vfs.openWrite(writer);
301
302           if (writer instanceof OutputStreamWriter JavaDoc) {
303         String JavaDoc javaEncoding = ((OutputStreamWriter JavaDoc) writer).getEncoding();
304         String JavaDoc mimeEncoding = Encoding.getMimeName(javaEncoding);
305             transform(node, os, mimeEncoding, result.getSystemId());
306       }
307           else
308             transform(node, os, null, result.getSystemId());
309
310           os.flush();
311           os.free();
312         }
313         else {
314           WriteStream os = Vfs.lookup(result.getSystemId()).openWrite();
315             
316           try {
317             transform(node, os, null, result.getSystemId());
318           } finally {
319             os.close();
320           }
321         }
322       }
323       else if (result instanceof DOMResult JavaDoc) {
324     DOMResult JavaDoc domResult = (DOMResult JavaDoc) result;
325     
326         Node JavaDoc resultNode = domResult.getNode();
327
328         domResult.setNode(transform(node, resultNode));
329       }
330       else if (result instanceof SAXResult JavaDoc) {
331         SAXResult JavaDoc sax = (SAXResult JavaDoc) result;
332
333         transform(node, sax.getHandler(), sax.getLexicalHandler());
334       }
335       else
336         throw new TransformerException JavaDoc(String.valueOf(result));
337     } catch (TransformerException JavaDoc e) {
338       throw e;
339     } catch (Exception JavaDoc e) {
340       throw new TransformerExceptionWrapper(e);
341     }
342   }
343
344   public void transform(Node JavaDoc node, OutputStream JavaDoc os)
345     throws TransformerException JavaDoc
346   {
347     if (os instanceof WriteStream) {
348       String JavaDoc encoding = ((WriteStream) os).getEncoding();
349       if (encoding == null)
350     encoding = "ISO-8859-1";
351
352       transform(node, os, encoding, null);
353     }
354     else
355       transform(node, os, null, null);
356   }
357   /**
358    * Transforms from a DOM node to an output stream.
359    *
360    * @param node the source node
361    * @param os the destination stream
362    */

363   public void transform(Node JavaDoc node, OutputStream JavaDoc os,
364             String JavaDoc encoding, String JavaDoc systemId)
365     throws TransformerException JavaDoc
366   {
367     if (node == null)
368       throw new IllegalArgumentException JavaDoc("can't transform null node");
369
370     try {
371       _lineMap = null;
372       Properties JavaDoc output = getOutputProperties();
373
374       WriteStream ws;
375
376       if (os instanceof WriteStream)
377     ws = (WriteStream) os;
378       else {
379     ws = Vfs.openWrite(os);
380
381     if (systemId != null)
382       ws.setPath(Vfs.lookup(systemId));
383     else if (node instanceof QNode) {
384       String JavaDoc baseURI = ((QNode) node).getBaseURI();
385
386       if (baseURI != null)
387         ws.setPath(Vfs.lookup(baseURI));
388     }
389       }
390
391       XmlPrinter out = new XmlPrinter(ws);
392
393       String JavaDoc method = (String JavaDoc) output.get(OutputKeys.METHOD);
394       out.setMethod(method);
395       if (encoding == null)
396         encoding = (String JavaDoc) output.get(OutputKeys.ENCODING);
397       if (encoding == null && ! (os instanceof WriteStream) &&
398           ! "html".equals(method))
399         encoding = "UTF-8";
400       if (encoding != null)
401         out.setEncoding(encoding);
402       out.setMimeType((String JavaDoc) output.get(OutputKeys.MEDIA_TYPE));
403       String JavaDoc omit = (String JavaDoc) output.get(OutputKeys.OMIT_XML_DECLARATION);
404
405       if (omit == null || omit.equals("false") || omit.equals("no"))
406         out.setPrintDeclaration(true);
407       
408       out.setStandalone((String JavaDoc) output.get(OutputKeys.STANDALONE));
409       out.setSystemId((String JavaDoc) output.get(OutputKeys.DOCTYPE_SYSTEM));
410       out.setPublicId((String JavaDoc) output.get(OutputKeys.DOCTYPE_PUBLIC));
411     
412       String JavaDoc indent = (String JavaDoc) output.get(OutputKeys.INDENT);
413       if (indent != null)
414         out.setPretty(indent.equals("true") || indent.equals("yes"));
415       
416       String JavaDoc jsp = (String JavaDoc) output.get("caucho.jsp");
417       if (jsp != null)
418         out.setJSP(jsp.equals("true") || jsp.equals("yes"));
419       
420       out.setVersion((String JavaDoc) output.get(OutputKeys.VERSION));
421
422       String JavaDoc includeContentType = (String JavaDoc) output.get("include-content-type");
423       if (includeContentType != null)
424         out.setIncludeContentType(includeContentType.equals("true") ||
425                                   includeContentType.equals("yes"));
426       
427       if (! _stylesheet.getGenerateLocation()) {
428       }
429       else if (node instanceof CauchoNode) {
430         String JavaDoc filename = ((CauchoNode) node).getFilename();
431         if (filename != null)
432           out.setLineMap(filename);
433         else
434           out.setLineMap("anonymous.xsl");
435       }
436       else
437         out.setLineMap("anonymous.xsl");
438
439       //out.beginDocument();
440
_stylesheet.transform(node, out, this);
441       //out.endDocument();
442
_lineMap = out.getLineMap();
443       if (os != ws) {
444         ws.flush();
445         ws.free();
446       }
447     } catch (TransformerException JavaDoc e) {
448       throw e;
449     } catch (Exception JavaDoc e) {
450       throw new TransformerExceptionWrapper(e);
451     }
452   }
453
454   /**
455    * Transforms from the source node to the destination node, returning
456    * the destination node.
457    */

458   public Node JavaDoc transform(Node JavaDoc sourceNode, Node JavaDoc destNode)
459     throws SAXException JavaDoc, IOException JavaDoc
460   {
461     _lineMap = null;
462
463     if (destNode == null)
464       destNode = Xml.createDocument();
465
466     DOMBuilder out = new DOMBuilder();
467     out.init(destNode);
468
469     try {
470       out.startDocument();
471       _stylesheet.transform(sourceNode, out, this);
472       //out.endDocument();
473
} catch (Exception JavaDoc e) {
474       throw new IOExceptionWrapper(e);
475     }
476
477     return destNode;
478   }
479
480   /**
481    * Transforms from the source node to the sax handlers.
482    */

483   public void transform(Node JavaDoc sourceNode,
484                         ContentHandler JavaDoc contentHandler,
485                         LexicalHandler JavaDoc lexicalHandler)
486     throws SAXException JavaDoc, IOException JavaDoc, TransformerException JavaDoc
487   {
488     if (contentHandler == null)
489       throw new IllegalArgumentException JavaDoc(L.l("null content handler"));
490     
491     _lineMap = null;
492
493     SAXBuilder out = new SAXBuilder();
494     out.setContentHandler(contentHandler);
495
496     out.startDocument();
497     _stylesheet.transform(sourceNode, out, this);
498     //out.endDocument();
499
}
500
501   /**
502    * Parses the source XML document from the source.
503    *
504    * @param source the JAXP source.
505    *
506    * @return the parsed document.
507    */

508   protected Node JavaDoc parseDocument(Source JavaDoc source)
509     throws IOException JavaDoc, SAXException JavaDoc, TransformerException JavaDoc
510   {
511     if (source instanceof StreamSource JavaDoc) {
512       StreamSource JavaDoc stream = (StreamSource JavaDoc) source;
513
514       InputSource JavaDoc in = new InputSource JavaDoc();
515       in.setSystemId(stream.getSystemId());
516       in.setByteStream(stream.getInputStream());
517       in.setCharacterStream(stream.getReader());
518
519       XmlParser parser = Xml.create();
520
521       Node JavaDoc node = parser.parseDocument(in);
522
523       parser.free();
524
525       return node;
526
527       // return new QDocument();
528
}
529     else if (source instanceof DOMSource JavaDoc){
530       Node JavaDoc node = ((DOMSource JavaDoc) source).getNode();
531       
532       return node != null ? node : new QDocument();
533     }
534     else if (source instanceof StringSource) {
535       String JavaDoc string = ((StringSource) source).getString();
536
537       if (string != null)
538     return parseStringDocument(string, source.getSystemId());
539       else
540     return new QDocument();
541     }
542     else if (source instanceof SAXSource JavaDoc) {
543       SAXSource JavaDoc saxSource = (SAXSource JavaDoc) source;
544       
545       XMLReader JavaDoc reader = saxSource.getXMLReader();
546
547       if (reader == null)
548     return new QDocument();
549       
550       InputSource JavaDoc inputSource = saxSource.getInputSource();
551
552       Document JavaDoc doc = new QDocument();
553       DOMBuilder builder = new DOMBuilder();
554       builder.init(doc);
555       reader.setContentHandler(builder);
556
557       reader.parse(inputSource);
558       
559       return doc;
560     }
561
562     else
563       throw new TransformerException JavaDoc(L.l("unknown source {0}", source));
564   }
565   
566   /**
567    * Parses the source XML document from the input stream.
568    *
569    * @param is the source input stream.
570    * @param systemId the path of the source
571    *
572    * @return document DOM node for the parsed XML.
573    */

574   protected Node JavaDoc parseDocument(InputStream JavaDoc is, String JavaDoc systemId)
575     throws IOException JavaDoc, SAXException JavaDoc
576   {
577     XmlParser parser = Xml.create();
578
579     Node JavaDoc node = parser.parseDocument(is);
580
581     parser.free();
582
583     return node;
584   }
585
586   /**
587    * Parses the source document specified by a URL
588    *
589    * @param url path to the document to be parsed.
590    *
591    * @return the parsed document.
592    */

593   protected Node JavaDoc parseDocument(String JavaDoc url)
594     throws IOException JavaDoc, SAXException JavaDoc
595   {
596     XmlParser parser = Xml.create();
597
598     Node JavaDoc node = parser.parseDocument(url);
599
600     parser.free();
601
602     return node;
603   }
604   
605   /**
606    * Parses a string as an XML document.
607    *
608    * @param source the string to use as the XML source
609    * @param systemId the URL for the string document.
610    *
611    * @return the parsed document.
612    */

613   protected Node JavaDoc parseStringDocument(String JavaDoc source, String JavaDoc systemId)
614     throws IOException JavaDoc, SAXException JavaDoc
615   {
616     XmlParser parser = Xml.create();
617
618     Node JavaDoc node = parser.parseDocumentString(source);
619
620     parser.free();
621
622     return node;
623   }
624
625   public void addCacheDepend(Path path)
626   {
627     _cacheDepends.add(path);
628   }
629
630   protected void addCacheDepend(String JavaDoc path)
631   {
632     _cacheDepends.add(Vfs.lookup(path));
633   }
634
635   public ArrayList JavaDoc<Path> getCacheDepends()
636   {
637     return _cacheDepends;
638   }
639 }
640
Popular Tags