1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.util;
18
19
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import java.io.OutputStreamWriter;
23 import java.io.PipedInputStream;
24 import java.io.PipedOutputStream;
25 import java.io.Reader;
26 import java.io.StringWriter;
27 import java.io.Writer;
28 import java.util.Iterator;
29 import java.util.Map;
30
31
32 import javax.xml.transform.TransformerFactory;
33 import javax.xml.transform.Transformer;
34 import javax.xml.transform.Templates;
35
36 import javax.xml.transform.stream.StreamResult;
37 import javax.xml.transform.dom.DOMSource;
38 import javax.xml.transform.sax.SAXSource;
39 import javax.xml.transform.sax.SAXTransformerFactory;
40 import javax.xml.transform.sax.TemplatesHandler;
41 import javax.xml.transform.sax.TransformerHandler;
42
43
44 import org.apache.xpath.objects.XString;
45
46
47 import org.xml.sax.XMLReader;
48 import org.xml.sax.SAXException;
49 import org.xml.sax.helpers.XMLReaderFactory;
50 import org.xml.sax.InputSource;
51
52
53 import org.w3c.dom.Document;
54
55
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
83
84
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 t)
96 {
97
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 transform( Document doc,
107 String stylesheet_url)
108 throws SAXException
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 transform( Document doc,
120 String stylesheet_url,
121 Map params)
122 throws SAXException
123 {
124
125
126 TransformerFactory tFactory = TransformerFactory.newInstance();
127
128
129 if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
130 {
131 logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
132 throw new SAXException( "Invalid SAX Tranformer" );
133 }
134 try
135 {
136
137 SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
138
139 TemplatesHandler templatesHandler = saxTFactory.newTemplatesHandler();
140
141
142 XMLReader reader = XMLReaderFactory.createXMLReader();
143 reader.setContentHandler(templatesHandler);
144
145 reader.setEntityResolver( new JetspeedXMLEntityResolver() );
146
147
148 final InputSource xstyle = new InputSource( JetspeedDiskCache.getInstance()
149 .getEntry( stylesheet_url ).getReader() );
150 xstyle.setSystemId( stylesheet_url );
151 reader.parse( xstyle );
152
153
154 Templates templates = templatesHandler.getTemplates();
155
156 TransformerHandler handler
157 = saxTFactory.newTransformerHandler(templates);
158
159
160 reader.setContentHandler(handler);
161
162
163
164 try
165 {
166 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
167 }
168 catch( org.xml.sax.SAXNotRecognizedException e ) {}
169
170 final Transformer processor = handler.getTransformer();
171
172 if( params != null ) {
173 Iterator keys = params.keySet().iterator();
174 while( keys.hasNext() )
175 {
176 String name = (String) keys.next();
177 String value = (String) params.get(name);
178 processor.setParameter(name,
179 value );
180
181 }
182 }
183
184 StringWriter pw = new StringWriter();
185
186
187
188 processor.transform( new DOMSource( doc ),
189 new StreamResult( pw ) );
190
191 try
192 {
193
194 pw.flush();
195 pw.close();
196
197 }
198 catch (IOException e)
199 {
200
201 logger.error("Exception", e);
202 }
203 return pw.toString();
204 }
205 catch (Exception e)
206 {
207 logger.error( "Invalid SAX Transformer: " , e );
208 throw new SAXException( "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 transform( String url,
217 String stylesheet_url )
218 throws SAXException
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 transform( String url,
230 String stylesheet_url,
231 Map params )
232 throws SAXException
233 {
234
235
236
237 InputSource in;
238 InputSource style;
239 try
240 {
241 in = new InputSource( JetspeedDiskCache.getInstance().getEntry( url ).getReader() );
242 style = new InputSource( JetspeedDiskCache.getInstance().getEntry( stylesheet_url ).getReader() );
243 }
244 catch (IOException e)
245 {
246 logger.error("Exception", e);
247
248 in = new InputSource( url );
249 style = new InputSource( 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 transform( InputSource content,
273 InputSource stylesheet,
274 Map params)
275 throws SAXException
276 {
277
278
279 TransformerFactory tFactory = TransformerFactory.newInstance();
280
281
282 if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
283 {
284 logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
285 throw new SAXException( "Invalid SAX Tranformer" );
286 }
287 try
288 {
289
290 SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
291
292 TemplatesHandler templatesHandler = saxTFactory.newTemplatesHandler();
293
294
295 XMLReader reader = XMLReaderFactory.createXMLReader();
296 reader.setContentHandler(templatesHandler);
297
298
299 reader.parse( stylesheet );
300
301
302 Templates templates = templatesHandler.getTemplates();
303
304 TransformerHandler handler
305 = saxTFactory.newTransformerHandler(templates);
306
307
308 reader.setContentHandler(handler);
309
310
311
312 try
313 {
314 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
315 }
316 catch( org.xml.sax.SAXNotRecognizedException e ) {}
317
318 final Transformer processor = handler.getTransformer();
319
320
321 if( params != null )
322 {
323 Iterator keys = params.keySet().iterator();
324 while( keys.hasNext() )
325 {
326 String name = (String) keys.next();
327 String value = (String) params.get(name);
328 processor.setParameter(name,
329 new XString( value )
330
331 }
332 }
333
334 StringWriter pw = new StringWriter();
335
336
337
338 processor.transform( new SAXSource( content ),
339 new StreamResult( pw ) );
340
341 try
342 {
343 pw.flush();
344 pw.close();
345 }
346 catch (IOException e)
347 {
348
349 logger.error("Exception", e);
350 }
351 return pw.toString();
352 }
353 catch (Exception e)
354 {
355 logger.error( "Invalid SAX Transformer: " , e);
356 throw new SAXException( "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 SAXTransform( String content_url,
372 String stylesheet_url,
373 Map params) throws IOException
374 {
375
376
377 TransformerFactory tFactory = TransformerFactory.newInstance();
378
379
380 if (!tFactory.getFeature(SAXTransformerFactory.FEATURE) )
381 {
382 logger.error( "SimpleTransform: nobody told you that we need a SAX Transformer?" );
383 throw new IOException( "Invalid SAX Tranformer" );
384 }
385 try
386 {
387
388 SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
389
390 TemplatesHandler templatesHandler = saxTFactory.newTemplatesHandler();
391
392
393 XMLReader reader = XMLReaderFactory.createXMLReader();
394 reader.setContentHandler(templatesHandler);
395
396 reader.setEntityResolver( new JetspeedXMLEntityResolver() );
397
398
399 InputSource style = new InputSource( JetspeedDiskCache.getInstance()
400 .getEntry( stylesheet_url ).getReader() );
401 style.setSystemId( stylesheet_url );
402 final InputSource xstyle = style;
403
404 reader.parse( xstyle );
405
406
407 Templates templates = templatesHandler.getTemplates();
408
409 TransformerHandler handler
410 = saxTFactory.newTransformerHandler(templates);
411
412
413 reader.setContentHandler(handler);
414
415
416
417 try
418 {
419 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
420 }
421 catch( org.xml.sax.SAXNotRecognizedException e ) {}
422
423 final Transformer processor = handler.getTransformer();
424
425
426 if( params != null )
427 {
428 Iterator keys = params.keySet().iterator();
429 while( keys.hasNext() )
430 {
431 String name = (String) keys.next();
432 String value = (String) params.get(name);
433
434
435 processor.setParameter(name,
436 new XString( value ) );
437 }
438 }
439
440 PipedInputStream pis = new PipedInputStream();
441 PipedOutputStream pos = new PipedOutputStream( pis );
442 try
443 {
444
445 final Writer pw = new OutputStreamWriter( pos, "utf-8" );
446 InputSource is = new InputSource( JetspeedDiskCache.getInstance()
447 .getEntry( content_url ).getReader() );
448 is.setSystemId( content_url );
449
450 final SAXSource xinput = new SAXSource( is );
451
452
453 Thread t = new Thread( new Runnable()
454 {
455 public void run()
456 {
457
458
459
460
461 logger.debug("Starting SAX thread...");
462 try
463 {
464 processor.transform( xinput,
465 new StreamResult( pw ) );
466 pw.close();
467 logger.debug("...ending SAX thread.");
468 }
469 catch( Exception se)
470 {
471 logger.debug("Error in SAXTransform" + se.toString(), se );
472 }
473 }
474 } );
475 t.start();
476 }
477 catch (java.io.UnsupportedEncodingException uee)
478 {
479 logger.error("Need utf-8 encoding to SAXTransform", uee);
480 }
481 return new InputStreamReader ( pis, "utf-8" );
482 }
483 catch (Exception e)
484 {
485 logger.error( "Invalid SAX Transformer:" , e);
486 throw new IOException( "problem in SAX transform: " + e.toString() );
487 }
488 }
489
490 }