View Javadoc

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  package org.apache.portals.applications.transform.impl;
18  
19  import java.io.IOException;
20  import java.io.InputStreamReader;
21  import java.io.OutputStream;
22  import java.io.Writer;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.Map;
26  
27  import javax.xml.parsers.DocumentBuilder;
28  import javax.xml.parsers.DocumentBuilderFactory;
29  import javax.xml.parsers.ParserConfigurationException;
30  import javax.xml.parsers.SAXParserFactory;
31  import javax.xml.transform.Templates;
32  import javax.xml.transform.Transformer;
33  import javax.xml.transform.TransformerFactory;
34  import javax.xml.transform.dom.DOMSource;
35  import javax.xml.transform.sax.SAXTransformerFactory;
36  import javax.xml.transform.sax.TemplatesHandler;
37  import javax.xml.transform.sax.TransformerHandler;
38  import javax.xml.transform.stream.StreamResult;
39  
40  import org.apache.portals.applications.transform.Transform;
41  import org.apache.portals.applications.transform.TransformException;
42  import org.apache.portals.applications.transform.TransformObjectPublisher;
43  import org.apache.portals.applications.util.Streams;
44  import org.w3c.dom.Document;
45  import org.xml.sax.InputSource;
46  import org.xml.sax.XMLReader;
47  import org.xml.sax.helpers.XMLReaderFactory;
48  
49  /***
50   * TransformComponent
51   * 
52   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
53   * @version $Id: JetspeedTransform.java 516448 2007-03-09 16:25:47Z ate $
54   */
55  public class JetspeedTransform implements Transform
56  {
57      public JetspeedTransform()
58      {
59          // TODO: make all JAX factories configurable
60          synchronized (mutex)
61          {
62              if (transformerFactory == null)
63              {
64                  System.setProperty(JAX_TRANSFORM_PROPERTY, jaxTransformFactoryProp);
65                  System.setProperty(JAX_SAX_PARSER_PROPERTY, jaxSaxFactoryProp);
66                  System.setProperty(JAX_DOM_PARSER_PROPERTY, jaxDomFactoryProp);
67                  System.setProperty(SAX_XML_READER_PROPERTY, saxXmlReaderProp);
68  
69                  TransformerFactory tFactory = TransformerFactory.newInstance();
70                  domFactory = DocumentBuilderFactory.newInstance();
71                  domFactory.setValidating(false);
72                  saxFactory = SAXParserFactory.newInstance();
73                  saxFactory.setValidating(false);
74                  //if (!tFactory.getFeature(SAXTransformerFactory.FEATURE)) { throw new TransformException(
75                  //        "Invalid SAX Tranformer. Doesn't support SAX"); }
76                  transformerFactory = ((SAXTransformerFactory) tFactory);
77              }
78          }
79          
80          publisher = new TransformObjectPublisher();        
81      }
82      
83      private static DocumentBuilderFactory domFactory = null;
84  
85      private static SAXParserFactory saxFactory = null;
86  
87      private static SAXTransformerFactory transformerFactory = null;
88  
89      //
90      // JAXP Service Configuration
91      //
92      private final static String CONFIG_JAX_FACTORY_SAX = "jax.factory.sax";
93  
94      private final static String jaxSaxFactoryProp = "org.apache.xerces.jaxp.SAXParserFactoryImpl";
95  
96      private final static String CONFIG_JAX_FACTORY_DOM = "jax.factory.dom";
97  
98      private final static String jaxDomFactoryProp = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
99  
100     private final static String CONFIG_JAX_FACTORY_TRANSFORM = "jax.factory.transform";
101 
102     private final static String jaxTransformFactoryProp = "org.apache.xalan.processor.TransformerFactoryImpl";
103 
104     private final static Object mutex = new Object();
105 
106     //
107     // JAXP System Wide Properties
108     //
109     private static final String JAX_TRANSFORM_PROPERTY = "javax.xml.transform.TransformerFactory";
110 
111     private static final String JAX_SAX_PARSER_PROPERTY = "javax.xml.parsers.SAXParserFactory";
112 
113     private static final String JAX_DOM_PARSER_PROPERTY = "javax.xml.parsers.DocumentBuilderFactory";
114 
115     //
116     // Standard Parser Vendor Property
117     //
118     private static final String SAX_XML_READER_PROPERTY = "org.xml.sax.driver";
119 
120     //
121     // Standard Parser Vendor Configuration
122     //
123     private final static String saxXmlReaderProp = "org.apache.xerces.parsers.SAXParser";
124 
125     // DTD Map
126     static private Map dtds = new HashMap();
127 
128     private TransformObjectPublisher publisher = null;
129 
130     public void transform(String xslt, InputSource inputSource, OutputStream os, Map parameters)
131             throws TransformException
132     {
133         if (xslt == null)
134         {
135             try
136             { // if no stylesheet specified simply drain the stream
137                 Streams.drain(inputSource.getByteStream(), os);
138             }
139             catch (IOException e)
140             {
141                 throw new TransformException(e);
142             }
143         }
144         else
145         {
146             transformStream(xslt, inputSource, new StreamResult(os), parameters);
147         }
148     }
149 
150     public  void transform(String xslt, InputSource inputSource, Writer writer, Map parameters)
151             throws TransformException
152     {
153         if (xslt == null)
154         {
155             try
156             { // if no stylesheet specified simply drain the stream
157                 Streams.drain(inputSource.getCharacterStream(), writer);
158             }
159             catch (IOException e)
160             {
161                 throw new TransformException(e);
162             }
163         }
164         else
165         {
166             transformStream(xslt, inputSource, new StreamResult(writer), parameters);
167         }
168     }
169 
170     private static void transformStream(String xslt, InputSource inputSource, StreamResult streamResult, Map parameters)
171             throws TransformException
172     {
173         if (xslt == null) { throw new TransformException("Invalid Transform, no stylesheet set!"); }
174 
175         //
176         // create a new document builder to load the XML file for transformation
177         //
178         DocumentBuilder docBuilder = null;
179         try
180         {
181             docBuilder = domFactory.newDocumentBuilder();
182             docBuilder.setEntityResolver(new TransformDTDEntityResolver(dtds));
183 
184         }
185         catch (ParserConfigurationException e)
186         {
187             throw new TransformException("Failed to load JAX Document Builder: " + e.toString());
188         }
189 
190         try
191         {
192             // Create a ContentHandler to handle parsing of the stylesheet.
193             TemplatesHandler templatesHandler = transformerFactory.newTemplatesHandler();
194 
195             // Create an XMLReader and set its ContentHandler.
196             XMLReader reader = XMLReaderFactory.createXMLReader();
197             reader.setContentHandler(templatesHandler);
198 
199             // Set it to solve Entities via cache
200             reader.setEntityResolver(new TransformDTDEntityResolver(dtds));
201 
202             //
203             // Get the stylesheet's content from the deployment
204             //                         
205             java.io.FileInputStream is = new java.io.FileInputStream(xslt);
206             InputStreamReader ssreader = new InputStreamReader(is);
207 
208             // Parse the stylesheet.
209             final InputSource xstyle = new InputSource(ssreader);
210             xstyle.setSystemId(xslt);
211             reader.parse(xstyle);
212 
213             //Get the Templates object from the ContentHandler.
214             Templates templates = templatesHandler.getTemplates();
215 
216             // Create a ContentHandler to handle parsing of the XML source.
217             TransformerHandler handler = transformerFactory.newTransformerHandler(templates);
218 
219             // Reset the XMLReader's ContentHandler.
220             reader.setContentHandler(handler);
221 
222             //
223             // Parse the Document into a DOM tree
224             // 
225             //
226             org.w3c.dom.Document doc = docBuilder.parse(inputSource);
227 
228             // reader.setProperty("http://xml.org/sax/properties/lexical-handler",
229             // handler);
230 
231             final Transformer processor = handler.getTransformer();
232 
233             //
234             // Get the transform variables (parameters)
235             //
236             Iterator keys = parameters.keySet().iterator();
237             while (keys.hasNext())
238             {
239                 String name = (String) keys.next();
240                 String value = (String) parameters.get(name);
241                 processor.setParameter(name, value); 
242             }
243 
244             //
245             // do the transformation now
246             //
247             processor.transform(new DOMSource(doc), streamResult);
248 
249         }
250         catch (Exception e)
251         {
252             throw new TransformException("Error in Transformation: " + e.toString());
253         }
254     }
255 
256     private static void transformStream(String xslt, Document document, StreamResult streamResult, Map parameters)
257             throws TransformException
258     {
259         if (xslt == null) { throw new TransformException("Invalid Transform, no stylesheet set!"); }
260 
261         synchronized (mutex)
262         {
263             if (transformerFactory == null)
264             {
265                 System.setProperty(JAX_TRANSFORM_PROPERTY, jaxTransformFactoryProp);
266                 System.setProperty(JAX_SAX_PARSER_PROPERTY, jaxSaxFactoryProp);
267                 System.setProperty(JAX_DOM_PARSER_PROPERTY, jaxDomFactoryProp);
268                 System.setProperty(SAX_XML_READER_PROPERTY, saxXmlReaderProp);
269 
270                 TransformerFactory tFactory = TransformerFactory.newInstance();
271                 domFactory = DocumentBuilderFactory.newInstance();
272                 domFactory.setValidating(false);
273                 saxFactory = SAXParserFactory.newInstance();
274                 saxFactory.setValidating(false);
275                 if (!tFactory.getFeature(SAXTransformerFactory.FEATURE)) { throw new TransformException(
276                         "Invalid SAX Tranformer. Doesn't support SAX"); }
277                 transformerFactory = ((SAXTransformerFactory) tFactory);
278             }
279         }
280 
281         //
282         // create a new document builder to load the XML file for transformation
283         //
284         DocumentBuilder docBuilder = null;
285         try
286         {
287             docBuilder = domFactory.newDocumentBuilder();
288             docBuilder.setEntityResolver(new TransformDTDEntityResolver(dtds));
289 
290         }
291         catch (ParserConfigurationException e)
292         {
293             throw new TransformException("Failed to load JAX Document Builder: " + e.toString());
294         }
295 
296         try
297         {
298             // Create a ContentHandler to handle parsing of the stylesheet.
299             TemplatesHandler templatesHandler = transformerFactory.newTemplatesHandler();
300 
301             // Create an XMLReader and set its ContentHandler.
302             XMLReader reader = XMLReaderFactory.createXMLReader();
303             reader.setContentHandler(templatesHandler);
304 
305             // Set it to solve Entities via cache
306             reader.setEntityResolver(new TransformDTDEntityResolver(dtds));
307 
308             //
309             // Get the stylesheet's content from the deployment
310             //                         
311             java.io.FileInputStream is = new java.io.FileInputStream(xslt);
312             InputStreamReader ssreader = new InputStreamReader(is);
313 
314             // Parse the stylesheet.
315             final InputSource xstyle = new InputSource(ssreader);
316             xstyle.setSystemId(xslt);
317             reader.parse(xstyle);
318 
319             //Get the Templates object from the ContentHandler.
320             Templates templates = templatesHandler.getTemplates();
321 
322             // Create a ContentHandler to handle parsing of the XML source.
323             TransformerHandler handler = transformerFactory.newTransformerHandler(templates);
324 
325             // Reset the XMLReader's ContentHandler.
326             reader.setContentHandler(handler);
327 
328             //
329             // Parse the Document into a DOM tree
330             // 
331             //
332             // org.w3c.dom.Document doc = docBuilder.parse(inputSource);
333 
334             // reader.setProperty("http://xml.org/sax/properties/lexical-handler",
335             // handler);
336 
337             final Transformer processor = handler.getTransformer();
338 
339             //
340             // Get the transform variables (parameters)
341             //
342             Iterator keys = parameters.keySet().iterator();
343             while (keys.hasNext())
344             {
345                 String name = (String) keys.next();
346                 String value = (String) parameters.get(name);
347                 processor.setParameter(name, value); 
348             }
349 
350             //
351             // do the transformation now
352             //
353             processor.transform(new DOMSource(document), streamResult);
354 
355         }
356         catch (Exception e)
357         {
358             throw new TransformException("Error in Transformation: " + e.toString());
359         }
360 
361     }
362 
363     public void transform(String xslt, Document document, OutputStream os, Map parameters)
364             throws TransformException
365     {
366         if (xslt == null)
367         {
368             throw new TransformException("xslt is null");
369         }
370         else
371         {
372             transformStream(xslt, document, new StreamResult(os), parameters);
373         }
374     }
375     
376     /* (non-Javadoc)
377      * @see org.apache.jetspeed.syndication.services.transform.TransformService#getPublisher()
378      */
379     public TransformObjectPublisher getPublisher()
380     {
381         return publisher;
382     }
383     
384 
385 }