KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > infohazard > maverick > transform > XSLTransform


1 /*
2  * $Id: XSLTransform.java,v 1.20 2004/06/07 20:38:11 eelco12 Exp $
3  * $Source: /cvsroot/mav/maverick/src/java/org/infohazard/maverick/transform/XSLTransform.java,v $
4  */

5 package org.infohazard.maverick.transform;
6
7 import java.io.File JavaDoc;
8 import java.io.IOException JavaDoc;
9 import java.net.MalformedURLException JavaDoc;
10 import java.util.Iterator JavaDoc;
11 import java.util.Map JavaDoc;
12
13 import javax.servlet.ServletContext JavaDoc;
14 import javax.servlet.ServletException JavaDoc;
15 import javax.xml.transform.Result JavaDoc;
16 import javax.xml.transform.Source JavaDoc;
17 import javax.xml.transform.Templates JavaDoc;
18 import javax.xml.transform.Transformer JavaDoc;
19 import javax.xml.transform.TransformerConfigurationException JavaDoc;
20 import javax.xml.transform.TransformerException JavaDoc;
21 import javax.xml.transform.TransformerFactory JavaDoc;
22 import javax.xml.transform.URIResolver JavaDoc;
23 import javax.xml.transform.sax.SAXResult JavaDoc;
24 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
25 import javax.xml.transform.sax.TransformerHandler JavaDoc;
26 import javax.xml.transform.stream.StreamResult JavaDoc;
27 import javax.xml.transform.stream.StreamSource JavaDoc;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.infohazard.maverick.flow.ConfigException;
32 import org.infohazard.maverick.flow.Transform;
33 import org.infohazard.maverick.flow.TransformContext;
34 import org.infohazard.maverick.flow.TransformStep;
35 import org.xml.sax.ContentHandler JavaDoc;
36
37 /**
38  * This Transform runs the input through a series of XSLT transformations.
39  *
40  * @author Jeff Schnitzer
41  * @author Scott Hernandez
42  * @version $Revision: 1.20 $ $Date: 2004/06/07 20:38:11 $
43  */

44 class XSLTransform implements Transform
45 {
46     /** Enumeration for the caching options */
47     public static final int CACHE_PRELOAD = 1;
48     /** Enumeration for the caching options */
49     public static final int CACHE_LAZY = 2;
50     /** Enumeration for the caching options */
51     public static final int CACHE_DISABLED = 3;
52
53     /** Logger. */
54     private static Log log = LogFactory.getLog(XSLTransform.class);
55
56     /** Mime type used if we stop before last transform. */
57     protected final static String JavaDoc UNFINISHED_CONTENTTYPE = "text/xml";
58
59     /** Path to the template */
60     protected String JavaDoc path;
61
62     /** If template file is monitored */
63     protected boolean isMonitoredFile = false;
64
65     /** Monitored template File */
66     protected File JavaDoc monitoredFile = null;
67
68     /** Monitored template File last modified time */
69     protected long monitoredFileLastModified;
70
71     /** Cached compiled templates */
72     protected Templates JavaDoc compiled;
73
74     /** The content-type to set if this is the last transform and it completes normally. */
75     protected String JavaDoc finalContentType;
76
77     /** If not null, set this as the uri resolver for xslt transformations */
78     protected URIResolver JavaDoc uriResolver;
79     
80     /** The caching style to use */
81     protected int cachingStyle;
82     
83     /**
84      * Expects that you will call addTemplate() to add the individual transformations.
85      *
86      * @param path The context-relative path to the template
87      * @param finishedContentType If this is the last transform and the chain
88      * completes successfully, this will be the content type set on the response.
89      * @param webAppContext Allows xsl files to be loaded as resources.
90      * @param uriRes Set a custom URI Resolver for transformation. Can be null.
91      * @param templateCachingStyle Must be one of the CACHE_ constants.
92      * @exception ConfigException Thrown if there is a problem with the configuration.
93      */

94     public XSLTransform(String JavaDoc path,
95                         boolean isMonitored,
96                         int templateCachingStyle,
97                         ServletContext JavaDoc webAppContext,
98                         String JavaDoc finishedContentType,
99                         URIResolver JavaDoc uriRes) throws ConfigException
100     {
101         log.debug("Creating xslt transform: " + path);
102
103         this.path = path;
104         this.isMonitoredFile = isMonitored;
105         this.finalContentType = finishedContentType;
106         this.uriResolver = uriRes;
107         this.cachingStyle = templateCachingStyle;
108         
109         if (cachingStyle == CACHE_PRELOAD)
110             this.compiled = loadTemplate(this.path, webAppContext);
111     }
112
113     /**
114      * @see org.infohazard.maverick.flow.Transform#createStep(org.infohazard.maverick.flow.TransformContext)
115      */

116     public TransformStep createStep(TransformContext tctx) throws ServletException JavaDoc
117     {
118         return new Step(tctx);
119     }
120
121     /**
122      * @param path Path, starting with /, relative to context root, of xsl
123      * @return The jaxp object for the specified path.
124      * @exception ConfigException
125      */

126     protected Templates JavaDoc loadTemplate(String JavaDoc path, ServletContext JavaDoc servletCtx) throws ConfigException
127     {
128
129         boolean pathIsFileUrl = false;
130         boolean pathIsOtherUrl = false;
131         java.net.URL JavaDoc resURL = null;
132
133         if (this.isMonitoredFile && this.monitoredFile != null)
134         {
135             // This happens if the file is monitored and it has changed on the filesystem
136
try
137             {
138                 resURL = this.monitoredFile.toURL();
139                 this.monitoredFileLastModified = this.monitoredFile.lastModified();
140             }
141             catch (MalformedURLException JavaDoc me)
142             {
143                 log.fatal("Eror parsing monitored template URL " + path + ": " + me.toString());
144                 throw new ConfigException(me);
145             }
146             catch (SecurityException JavaDoc se)
147             {
148                 log.fatal("Unable to access monitored template " + path + ": " + se.toString());
149                 throw new ConfigException(se);
150             }
151         }
152         else
153         {
154             // Check to see if the path is a URL and what type, otherwise make sure
155
// it's a proper servlet resource path
156
if (path.toLowerCase().startsWith("file:"))
157                 pathIsFileUrl = true;
158             else if (path.toLowerCase().startsWith("http:") ||
159                      path.toLowerCase().startsWith("https:") ||
160                      path.toLowerCase().startsWith("ftp:"))
161                 pathIsOtherUrl = true;
162             else if (!path.startsWith("/"))
163                 path = "/" + path;
164
165             try
166             {
167                 if (pathIsFileUrl && this.isMonitoredFile)
168                 {
169                     resURL = new java.net.URL JavaDoc(path);
170                     this.monitoredFile = new File JavaDoc(resURL.getFile());
171
172                     if (this.monitoredFile == null || !this.monitoredFile.canRead())
173                     {
174                         this.monitoredFile = null;
175                         log.fatal("Resource not found or unable to read file: " + path);
176                         throw new ConfigException("Resource not found or unable to read file: " + path);
177                     }
178
179                     this.monitoredFileLastModified = this.monitoredFile.lastModified();
180                 }
181                 else if (pathIsFileUrl || pathIsOtherUrl)
182                     resURL = new java.net.URL JavaDoc(path);
183                 else
184                     resURL = servletCtx.getResource(path);
185
186                 if (resURL == null)
187                 {
188                     log.fatal("Resource not found: " + path);
189                     throw new ConfigException("Resource not found: " + path);
190                 }
191             }
192             catch (MalformedURLException JavaDoc me)
193             {
194                 log.fatal("Eror parsing template URL " + path + ": " + me.toString());
195                 throw new ConfigException(me);
196             }
197         }
198
199         try
200         {
201             TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
202             if (this.uriResolver != null)
203                 tFactory.setURIResolver(this.uriResolver);
204
205             return tFactory.newTemplates(new StreamSource JavaDoc(resURL.openStream(), resURL.toString()));
206         }
207         catch (TransformerException JavaDoc ex)
208         {
209             log.fatal("Error loading template " + path + ": " + ex.toString());
210             throw new ConfigException(ex);
211         }
212         catch (IOException JavaDoc ex)
213         {
214             log.fatal("Eror loading template " + path + ": " + ex.toString());
215             throw new ConfigException(ex);
216         }
217
218     }
219
220     /**
221      * Set parameters on a transformer
222      *
223      * @param t
224      * @param params
225      */

226     protected void populateParams(Transformer JavaDoc t, Map JavaDoc params)
227     {
228         Iterator JavaDoc entriesIt = params.entrySet().iterator();
229         while (entriesIt.hasNext())
230         {
231             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)entriesIt.next();
232             t.setParameter((String JavaDoc)entry.getKey(), entry.getValue());
233         }
234     }
235
236     /**
237      * Step.
238      */

239     protected class Step extends XMLTransformStep
240     {
241         /** */
242         protected boolean handlerUsed = false;
243         
244         /** */
245         public Step(TransformContext tctx) throws ServletException JavaDoc
246         {
247             super(tctx);
248         }
249     
250         /**
251          * Set the final content type for this sucka
252          */

253         protected void assignContentType(TransformContext tctx) throws ServletException JavaDoc
254         {
255             if (this.getNext().isLast() && !tctx.halting())
256                 this.getNext().setContentType(finalContentType);
257             else
258                 this.getNext().setContentType(UNFINISHED_CONTENTTYPE);
259         }
260         
261         /**
262          * Funnels stored output to go(Reader), or just passes on the
263          * done() message if TransformerHandler was used (yeay SAX!)
264          */

265         public void done() throws IOException JavaDoc, ServletException JavaDoc
266         {
267             log.debug("Done being written to");
268             
269             if (this.fakeResponse == null)
270             {
271                 if (this.handlerUsed)
272                     this.getNext().done();
273                 else
274                     throw new IllegalStateException JavaDoc("done() called illegally");
275             }
276             else
277             {
278                 this.go(this.fakeResponse.getOutputAsReader());
279                 this.fakeResponse = null;
280             }
281         }
282     
283         /** */
284         public ContentHandler JavaDoc getSAXHandler() throws IOException JavaDoc, ServletException JavaDoc
285         {
286             this.handlerUsed = true;
287             
288             // Set the content-type for the output
289
assignContentType(this.getTransformCtx());
290             
291             TransformerHandler JavaDoc tHandler;
292             try
293             {
294                 SAXTransformerFactory JavaDoc saxTFact = (SAXTransformerFactory JavaDoc)TransformerFactory.newInstance();
295                 tHandler = saxTFact.newTransformerHandler(this.getCompiled());
296             }
297             catch (TransformerConfigurationException JavaDoc ex)
298             {
299                 throw new ServletException JavaDoc(ex);
300             }
301             
302             // Populate any params which might have been set
303
if (this.getTransformCtx().getTransformParams() != null)
304                 populateParams(tHandler.getTransformer(), this.getTransformCtx().getTransformParams());
305             
306             if (this.getNext().isLast())
307                 tHandler.setResult(new StreamResult JavaDoc(this.getNext().getResponse().getOutputStream()));
308             else
309                 tHandler.setResult(new SAXResult JavaDoc(this.getNext().getSAXHandler()));
310                 
311             return tHandler;
312         }
313
314         /** */
315         public void go(Source JavaDoc input) throws IOException JavaDoc, ServletException JavaDoc
316         {
317             // Set the content-type for the output
318
assignContentType(this.getTransformCtx());
319             
320             Transformer JavaDoc trans;
321             try
322             {
323                 trans = this.getCompiled().newTransformer();
324             }
325             catch (TransformerConfigurationException JavaDoc ex)
326             {
327                 throw new ServletException JavaDoc(ex);
328             }
329             
330             // Populate any params which might have been set
331
if (this.getTransformCtx().getTransformParams() != null)
332                 populateParams(trans, this.getTransformCtx().getTransformParams());
333             
334             Result JavaDoc res;
335             if (this.getNext().isLast())
336                 res = new StreamResult JavaDoc(this.getNext().getResponse().getOutputStream());
337             else
338                 res = new SAXResult JavaDoc(this.getNext().getSAXHandler());
339
340             try
341             {
342                 trans.transform(input, res);
343             }
344             catch (TransformerException JavaDoc ex)
345             {
346                 throw new ServletException JavaDoc(ex);
347             }
348
349             this.getNext().done();
350         }
351
352         /**
353          * @return The compiled value
354          * @exception ConfigException
355          */

356         public Templates JavaDoc getCompiled() throws ConfigException
357         {
358
359             try
360             {
361                 if (isMonitoredFile && monitoredFile != null)
362                 {
363                     long lastModified = monitoredFile.lastModified();
364
365                     if (lastModified <= 0L)
366                     {
367                         log.error("Unable to access monitored template " + path);
368
369                         if (compiled != null)
370                             return compiled;
371                         else
372                             throw new IllegalStateException JavaDoc("Unable to access monitored template " + path);
373                     }
374                     else if (monitoredFileLastModified < lastModified)
375                     {
376                         compiled = loadTemplate(path, this.getTransformCtx().getServletContext());
377                         return compiled;
378                     }
379                 }
380
381                 switch (cachingStyle)
382                 {
383                     case CACHE_PRELOAD:
384                     {
385                         return compiled;
386                     }
387                     case CACHE_LAZY:
388                     {
389                         if (compiled == null)
390                             compiled = loadTemplate(path, this.getTransformCtx().getServletContext());
391
392                         return compiled;
393                     }
394                     case CACHE_DISABLED:
395                     {
396                         return loadTemplate(path, this.getTransformCtx().getServletContext());
397                     }
398                     default:
399                     {
400                         throw new IllegalStateException JavaDoc("Unknown caching style");
401                     }
402                 }
403
404             }
405             catch (SecurityException JavaDoc se)
406             {
407                 log.error("Unable to access monitored template " + path, se);
408
409                 if (compiled != null)
410                     return compiled;
411                 else
412                     throw new ConfigException(se);
413             }
414
415         }
416     }
417
418 }
419
420
Popular Tags