KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > util > SimpleTransform


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

16
17 package org.apache.jetspeed.util;
18
19 //java stuff
20
import java.io.IOException JavaDoc;
21 import java.io.InputStreamReader JavaDoc;
22 import java.io.OutputStreamWriter JavaDoc;
23 import java.io.PipedInputStream JavaDoc;
24 import java.io.PipedOutputStream JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.io.StringWriter JavaDoc;
27 import java.io.Writer JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Map JavaDoc;
30
31 //Trax support
32
import javax.xml.transform.TransformerFactory JavaDoc;
33 import javax.xml.transform.Transformer JavaDoc;
34 import javax.xml.transform.Templates JavaDoc;
35 //import javax.xml.transform.stream.StreamSource;
36
import javax.xml.transform.stream.StreamResult JavaDoc;
37 import javax.xml.transform.dom.DOMSource JavaDoc;
38 import javax.xml.transform.sax.SAXSource JavaDoc;
39 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
40 import javax.xml.transform.sax.TemplatesHandler JavaDoc;
41 import javax.xml.transform.sax.TransformerHandler JavaDoc;
42
43 //xpath objects
44
import org.apache.xpath.objects.XString;
45
46 //SAX Suport
47
import org.xml.sax.XMLReader JavaDoc;
48 import org.xml.sax.SAXException JavaDoc;
49 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
50 import org.xml.sax.InputSource JavaDoc;
51
52 //DOM Support
53
import org.w3c.dom.Document JavaDoc;
54
55 //Jetspeed stuff
56
import org.apache.jetspeed.cache.disk.JetspeedDiskCache;
57 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
58 import org.apache.jetspeed.services.logging.JetspeedLogger;
59 import org.apache.jetspeed.xml.JetspeedXMLEntityResolver;
60
61
62
63
64 /**
65  * Provides a very simple mechanism to transform a document using XSLT using
66  * one XML document and another XSL document. This implementation uses the TRAX API.
67  * It can be used with any TRAX transformer. This can be used for very
68  * simple XML -> XSL processing to reduce the complexity and possibility of a
69  * runtime failure.
70  *
71  * @author <a HREF="mailto:burton@apache.org">Kevin A. Burton</a>
72  * @author <a HREF="mailto:sgala@apache.org">Santiago Gala</a>
73  * @version $Id: SimpleTransform.java,v 1.23 2004/02/23 03:23:42 jford Exp $
74  */

75 public class SimpleTransform
76 {
77     /**
78      * Static initialization of the logger for this class
79      */

80     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(SimpleTransform.class.getName());
81     
82     //FIXME: This code should go into the Turbine XSLTservice.
83
//Also, it is a temporary hack, as it should be configurable,
84
// and done later.
85
static
86     {
87         try
88         {
89             if( System.getProperty( "org.xml.sax.driver" ) == null )
90             {
91                 System.setProperty( "org.xml.sax.driver",
92                                     "org.apache.xerces.parsers.SAXParser" );
93             }
94         }
95         catch (Throwable JavaDoc t)
96         {
97             //be very cautious here. We are in class initialization.
98
t.printStackTrace();
99         }
100     }
101     
102     /**
103      * Given a a DOM and a URL to a stylesheet,
104      * transform the original document.
105      */

106     public static String JavaDoc transform( Document JavaDoc doc,
107                                     String JavaDoc stylesheet_url)
108         throws SAXException JavaDoc
109     {
110         return transform( doc, stylesheet_url, null );
111     }
112
113     
114     /**
115      * Given a a DOM and a URL to a stylesheet,
116      * transform the original document,
117      * passing parameters to the stylesheet
118      */

119     public static String JavaDoc transform( Document JavaDoc doc,
120                                     String JavaDoc stylesheet_url,
121                                     Map JavaDoc params)
122         throws SAXException JavaDoc
123     {
124
125         // Instantiate a TransformerFactory.
126
TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
127         // Determine whether the TransformerFactory supports the use of SAXSource
128
// and SAXResult
129
if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
130         {
131             logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
132             throw new SAXException JavaDoc( "Invalid SAX Tranformer" );
133         }
134         try
135         {
136             // Cast the TransformerFactory.
137
SAXTransformerFactory JavaDoc saxTFactory = ((SAXTransformerFactory JavaDoc) tFactory);
138             // Create a ContentHandler to handle parsing of the stylesheet.
139
TemplatesHandler JavaDoc templatesHandler = saxTFactory.newTemplatesHandler();
140
141             // Create an XMLReader and set its ContentHandler.
142
XMLReader JavaDoc reader = XMLReaderFactory.createXMLReader();
143             reader.setContentHandler(templatesHandler);
144             // Set it to solve Entities through Jetspeed URL Manager
145
reader.setEntityResolver( new JetspeedXMLEntityResolver() );
146     
147             // Parse the stylesheet.
148
final InputSource JavaDoc xstyle = new InputSource JavaDoc( JetspeedDiskCache.getInstance()
149                                                         .getEntry( stylesheet_url ).getReader() );
150             xstyle.setSystemId( stylesheet_url );
151             reader.parse( xstyle );
152
153             //Get the Templates object from the ContentHandler.
154
Templates JavaDoc templates = templatesHandler.getTemplates();
155             // Create a ContentHandler to handle parsing of the XML source.
156
TransformerHandler JavaDoc handler
157                 = saxTFactory.newTransformerHandler(templates);
158         
159             // Reset the XMLReader's ContentHandler.
160
reader.setContentHandler(handler);
161
162             // Set the ContentHandler to also function as a LexicalHandler, which
163
// includes "lexical" events (e.g., comments and CDATA).
164
try
165             {
166                 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
167             }
168             catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {}
169
170             final Transformer JavaDoc processor = handler.getTransformer();
171
172             if( params != null ) {
173                 Iterator JavaDoc keys = params.keySet().iterator();
174                 while( keys.hasNext() )
175                 {
176                     String JavaDoc name = (String JavaDoc) keys.next();
177                     String JavaDoc value = (String JavaDoc) params.get(name);
178                     processor.setParameter(name,
179                                            value ); //FIXME: maybe we need to quote again...
180
// was processor.createXString( value)
181
}
182             }
183         
184             StringWriter JavaDoc pw = new StringWriter JavaDoc();
185         
186             // Have the XSLTProcessor processor object transform "foo.xml" to
187
// System.out, using the XSLT instructions found in "foo.xsl".
188
processor.transform( new DOMSource JavaDoc( doc ),
189                                  new StreamResult JavaDoc( pw ) );
190                       
191             try
192             {
193
194                 pw.flush();
195                 pw.close();
196             
197             }
198             catch (IOException JavaDoc e)
199             {
200                 //should never really happen
201
logger.error("Exception", e);
202             }
203             return pw.toString();
204         }
205         catch (Exception JavaDoc e)
206         {
207             logger.error( "Invalid SAX Transformer: " , e );
208             throw new SAXException JavaDoc( "problem in SAX transform: " + e.toString() );
209         }
210     }
211     
212     /**
213      * Given a URL to an XML file and a URL to a stylesheet, transform the
214      * original document.
215      */

216     public static String JavaDoc transform( String JavaDoc url,
217                                     String JavaDoc stylesheet_url )
218         throws SAXException JavaDoc
219     {
220
221         return transform( url, stylesheet_url, null );
222     
223     }
224     
225     /**
226      * Given a URL to an XML file and a URL to a stylesheet, transform the
227      * original document.
228      */

229     public static String JavaDoc transform( String JavaDoc url,
230                                     String JavaDoc stylesheet_url,
231                                     Map JavaDoc params )
232         throws SAXException JavaDoc
233     {
234
235         //bring these URLs local if they happen to be remote
236

237         InputSource JavaDoc in;
238         InputSource JavaDoc style;
239         try
240         {
241             in = new InputSource JavaDoc( JetspeedDiskCache.getInstance().getEntry( url ).getReader() );
242             style = new InputSource JavaDoc( JetspeedDiskCache.getInstance().getEntry( stylesheet_url ).getReader() );
243         }
244         catch (IOException JavaDoc e)
245         {
246             logger.error("Exception", e);
247             //at this point we can just use the original url and stylesheet_url so this shouldn't be a problem
248
in = new InputSource JavaDoc( url );
249             style = new InputSource JavaDoc( stylesheet_url );
250         }
251         
252         if ( logger.isInfoEnabled() )
253         {
254             logger.info( "SimpleTransform: transforming url: " +
255                   url +
256                   " with stylesheet: " +
257                   stylesheet_url );
258         }
259
260         in.setSystemId( url );
261         style.setSystemId( stylesheet_url );
262
263         return transform( in,
264                           style,
265                           params );
266     
267     }
268     
269     /**
270      * Used internally to handle doing XSLT transformations directly.
271      */

272     public static String JavaDoc transform( InputSource JavaDoc content,
273                                     InputSource JavaDoc stylesheet,
274                                     Map JavaDoc params)
275         throws SAXException JavaDoc
276     {
277
278         // Instantiate a TransformerFactory.
279
TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
280         // Determine whether the TransformerFactory supports the use of SAXSource
281
// and SAXResult
282
if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
283         {
284             logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
285             throw new SAXException JavaDoc( "Invalid SAX Tranformer" );
286         }
287         try
288         {
289             // Cast the TransformerFactory.
290
SAXTransformerFactory JavaDoc saxTFactory = ((SAXTransformerFactory JavaDoc) tFactory);
291             // Create a ContentHandler to handle parsing of the stylesheet.
292
TemplatesHandler JavaDoc templatesHandler = saxTFactory.newTemplatesHandler();
293
294             // Create an XMLReader and set its ContentHandler.
295
XMLReader JavaDoc reader = XMLReaderFactory.createXMLReader();
296             reader.setContentHandler(templatesHandler);
297     
298             // Parse the stylesheet.
299
reader.parse( stylesheet );
300
301             //Get the Templates object from the ContentHandler.
302
Templates JavaDoc templates = templatesHandler.getTemplates();
303             // Create a ContentHandler to handle parsing of the XML source.
304
TransformerHandler JavaDoc handler
305                 = saxTFactory.newTransformerHandler(templates);
306         
307             // Reset the XMLReader's ContentHandler.
308
reader.setContentHandler(handler);
309
310             // Set the ContentHandler to also function as a LexicalHandler, which
311
// includes "lexical" events (e.g., comments and CDATA).
312
try
313             {
314                 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
315             }
316             catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {}
317             
318             final Transformer JavaDoc processor = handler.getTransformer();
319
320         
321             if( params != null )
322             {
323                 Iterator JavaDoc keys = params.keySet().iterator();
324                 while( keys.hasNext() )
325                 {
326                     String JavaDoc name = (String JavaDoc) keys.next();
327                     String JavaDoc value = (String JavaDoc) params.get(name);
328                     processor.setParameter(name,
329                                            new XString( value )
330                          /*FIXME: was processor.createXString( value) */ );
331                 }
332             }
333
334             StringWriter JavaDoc pw = new StringWriter JavaDoc();
335         
336             // Have the XSLTProcessor processor object transform "foo.xml" to
337
// System.out, using the XSLT instructions found in "foo.xsl".
338
processor.transform( new SAXSource JavaDoc( content ),
339                                  new StreamResult JavaDoc( pw ) );
340                       
341             try
342             {
343                 pw.flush();
344                 pw.close();
345             }
346             catch (IOException JavaDoc e)
347             {
348                 //should never really happen
349
logger.error("Exception", e);
350             }
351             return pw.toString();
352         }
353         catch (Exception JavaDoc e)
354         {
355             logger.error( "Invalid SAX Transformer: " , e);
356             throw new SAXException JavaDoc( "problem in SAX transform: " + e.toString() );
357         }
358     }
359
360     /**
361      * Perform a event based parsing of the given content_url,
362      * process it with the XSLT stylesheet stylesheet_url, using the params
363      * parameters, and return a Reader that will do the transformation dynamically.
364      *
365      * @param content_url The url of the xml document
366      * @param stylesheet_url The url of the stylesheet
367      * @param params A Map containing stylesheet parameters
368      * @return a Reader on the transformed document
369      *
370      */

371     public static Reader JavaDoc SAXTransform( String JavaDoc content_url,
372                                        String JavaDoc stylesheet_url,
373                                        Map JavaDoc params) throws IOException JavaDoc
374     {
375
376         // Instantiate a TransformerFactory.
377
TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
378         // Determine whether the TransformerFactory supports the use of SAXSource
379
// and SAXResult
380
if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
381         {
382             logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
383             throw new IOException JavaDoc( "Invalid SAX Tranformer" );
384         }
385         try
386         {
387             // Cast the TransformerFactory.
388
SAXTransformerFactory JavaDoc saxTFactory = ((SAXTransformerFactory JavaDoc) tFactory);
389             // Create a ContentHandler to handle parsing of the stylesheet.
390
TemplatesHandler JavaDoc templatesHandler = saxTFactory.newTemplatesHandler();
391
392             // Create an XMLReader and set its ContentHandler.
393
XMLReader JavaDoc reader = XMLReaderFactory.createXMLReader();
394             reader.setContentHandler(templatesHandler);
395             // Set it to solve Entities through Jetspeed URL Manager
396
reader.setEntityResolver( new JetspeedXMLEntityResolver() );
397
398             // Parse the stylesheet.
399
InputSource JavaDoc style = new InputSource JavaDoc( JetspeedDiskCache.getInstance()
400                                                  .getEntry( stylesheet_url ).getReader() );
401             style.setSystemId( stylesheet_url );
402             final InputSource JavaDoc xstyle = style;
403
404             reader.parse( xstyle );
405
406             //Get the Templates object from the ContentHandler.
407
Templates JavaDoc templates = templatesHandler.getTemplates();
408             // Create a ContentHandler to handle parsing of the XML source.
409
TransformerHandler JavaDoc handler
410                 = saxTFactory.newTransformerHandler(templates);
411         
412             // Reset the XMLReader's ContentHandler.
413
reader.setContentHandler(handler);
414
415             // Set the ContentHandler to also function as a LexicalHandler, which
416
// includes "lexical" events (e.g., comments and CDATA).
417
try
418             {
419                 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
420             }
421             catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {}
422
423             final Transformer JavaDoc processor = handler.getTransformer();
424
425             //Set the parameters (if any)
426
if( params != null )
427             {
428                 Iterator JavaDoc keys = params.keySet().iterator();
429                 while( keys.hasNext() )
430                 {
431                     String JavaDoc name = (String JavaDoc) keys.next();
432                     String JavaDoc value = (String JavaDoc) params.get(name);
433                     //FIXME: maybe we need to quote again...
434
// was processor.createXString( value)
435
processor.setParameter(name,
436                                            new XString( value ) );
437                 }
438             }
439
440             PipedInputStream JavaDoc pis = new PipedInputStream JavaDoc();
441             PipedOutputStream JavaDoc pos = new PipedOutputStream JavaDoc( pis );
442             try
443             {
444
445                 final Writer JavaDoc pw = new OutputStreamWriter JavaDoc( pos, "utf-8" );
446                 InputSource JavaDoc is = new InputSource JavaDoc( JetspeedDiskCache.getInstance()
447                                                   .getEntry( content_url ).getReader() );
448                 is.setSystemId( content_url );
449
450                 final SAXSource JavaDoc xinput = new SAXSource JavaDoc( is );
451                 //Perform the transformation on a new thread, using
452
// PipedStreams
453
Thread JavaDoc t = new Thread JavaDoc( new Runnable JavaDoc()
454                     {
455                         public void run()
456                         {
457                             // Have the processor object transform
458
// "foo.xml" to
459
// System.out, using the XSLT instructions
460
//found in "foo.xsl".
461
logger.debug("Starting SAX thread...");
462                             try
463                             {
464                                 processor.transform( xinput,
465                                                      new StreamResult JavaDoc( pw ) );
466                                 pw.close();
467                                 logger.debug("...ending SAX thread.");
468                             }
469                             catch( Exception JavaDoc se)
470                             {
471                                 logger.debug("Error in SAXTransform" + se.toString(), se );
472                             }
473                         }
474                     } );
475                 t.start();
476             }
477             catch (java.io.UnsupportedEncodingException JavaDoc uee)
478             {
479                 logger.error("Need utf-8 encoding to SAXTransform", uee);
480             }
481             return new InputStreamReader JavaDoc ( pis, "utf-8" );
482         }
483         catch (Exception JavaDoc e)
484         {
485             logger.error( "Invalid SAX Transformer:" , e);
486             throw new IOException JavaDoc( "problem in SAX transform: " + e.toString() );
487         }
488     }
489
490 }
491
Popular Tags