KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > xtags > xslt > StyleTag


1 /*
2  * Copyright 1999,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.taglibs.xtags.xslt;
18
19 import java.io.File JavaDoc;
20 import java.io.FileReader JavaDoc;
21 import java.io.FileWriter JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.io.StringReader JavaDoc;
27 import java.io.StringWriter JavaDoc;
28 import java.io.Writer JavaDoc;
29 import java.net.MalformedURLException JavaDoc;
30 import java.net.URL JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Map JavaDoc;
34
35 import javax.servlet.ServletContext JavaDoc;
36 import javax.servlet.jsp.JspException JavaDoc;
37 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
38
39 import javax.xml.transform.Result JavaDoc;
40 import javax.xml.transform.Source JavaDoc;
41 import javax.xml.transform.OutputKeys JavaDoc;
42 import javax.xml.transform.Transformer JavaDoc;
43 import javax.xml.transform.TransformerException JavaDoc;
44 import javax.xml.transform.TransformerFactory JavaDoc;
45 import javax.xml.transform.URIResolver JavaDoc;
46 import javax.xml.transform.dom.DOMResult JavaDoc;
47 import javax.xml.transform.dom.DOMSource JavaDoc;
48 import javax.xml.transform.sax.SAXResult JavaDoc;
49 import javax.xml.transform.sax.SAXSource JavaDoc;
50 import javax.xml.transform.stream.StreamResult JavaDoc;
51 import javax.xml.transform.stream.StreamSource JavaDoc;
52
53 import org.dom4j.Node;
54 import org.dom4j.Document;
55 import org.dom4j.io.DocumentSource;
56
57 import org.apache.taglibs.xtags.util.JspNestedException;
58 import org.apache.taglibs.xtags.util.URLHelper;
59
60 import org.xml.sax.ContentHandler JavaDoc;
61 import org.xml.sax.InputSource JavaDoc;
62 import org.xml.sax.SAXException JavaDoc;
63
64 /** A tag which performs an XSLT transformation on a given XML document
65   *
66   * @author James Strachan
67   */

68 public class StyleTag extends BodyTagSupport JavaDoc implements ParameterAcceptingTag {
69     
70     /** The XML data resource. */
71     private Object JavaDoc xml;
72
73     /** The XSL stylesheet resource. */
74     private Object JavaDoc xsl;
75
76     /** The destination result of the XSLT transformation */
77     private Result JavaDoc result;
78
79     /** The XSLT output method, "xml", "html", "text" or whatever */
80     private String JavaDoc outputMethod;
81
82     /** XSLT parameters */
83     private Map JavaDoc parameters;
84     
85     /** Indirection buffer, used to avoid flush problems with BodyContent */
86     private StringWriter JavaDoc stringWriter;
87     
88     
89     // ParameterAcceptingTag interface
90
//-------------------------------------------------------------------------
91
public void setParameter(String JavaDoc name, Object JavaDoc value) {
92         if ( parameters == null ) {
93             parameters = new HashMap JavaDoc();
94         }
95         parameters.put( name, value );
96     }
97     
98
99     // BodyTag interface
100
//-------------------------------------------------------------------------
101

102     /** Evaluate the body content of this tag if
103       * we need to for either the XML or XSLT data; otherwise we skip it.
104      *
105      * @exception JspException if a JSP error occurs
106      */

107     public int doStartTag() throws JspException JavaDoc {
108         parameters = null;
109         return EVAL_BODY_TAG;
110     }
111
112
113     /** Extract the body if required for either the XML or XSLT
114       *
115       * @exception JspException if a JSP error has occurred
116       */

117     public int doAfterBody() throws JspException JavaDoc {
118         if ( bodyContent != null ) {
119             String JavaDoc text = bodyContent.getString().trim();
120             if ( text.length() > 0 ) {
121                 if ( xsl == null ) {
122                     xsl = new StringReader JavaDoc( text );
123                 }
124                 else if ( xml == null ) {
125                     xml = new StringReader JavaDoc( text );
126                 }
127             }
128         }
129     return SKIP_BODY;
130     }
131
132
133     /** Perform the transformation and render the output.
134       *
135       * @exception JspException if a JSP exception occurs
136       */

137     public int doEndTag() throws JspException JavaDoc {
138         if ( xml == null || xsl == null ) {
139             throw new JspException JavaDoc( "Must specify both XML and an XSLT to style" );
140         }
141         
142         // Prepare an input source for the data
143
Source JavaDoc data = getSource(xml);
144
145         // Prepare an input source for the stylesheet
146
Source JavaDoc style = getSource(xsl);
147
148         // Prepare an output source for the outputs
149
Result JavaDoc result = getResult();
150
151         // Use JAXP to perform the stylesheet
152
try {
153             TransformerFactory JavaDoc factory = TransformerFactory.newInstance();
154             factory.setURIResolver( createURIResolver() );
155             Transformer JavaDoc transformer = factory.newTransformer(style);
156             configure(transformer);
157             transformer.transform( data, result );
158             if ( stringWriter != null ) {
159                 pageContext.getOut().write( stringWriter.toString() );
160             }
161         }
162         catch (TransformerException JavaDoc e) {
163             handleException(e);
164         }
165         catch (IOException JavaDoc e) {
166             handleException(e);
167         }
168         finally {
169             stringWriter = null;
170         }
171     return EVAL_PAGE;
172     }
173
174     
175     /**
176      * Release any allocated resources.
177      */

178     public void release() {
179     xml = null;
180     xsl = null;
181     result = null;
182         parameters = null;
183     }
184
185
186
187     // Properties
188
//-------------------------------------------------------------------------
189

190     public void setOutputMethod(String JavaDoc outputMethod) {
191         this.outputMethod = outputMethod;
192     }
193     
194     /** Sets the dom4j document to be styled */
195     public void setDocument(Document document) {
196         this.xml = document;
197     }
198
199     /** Sets the XSLT transformer used to transform the document */
200     public void setTransformer(Transformer JavaDoc transformer) {
201         this.xsl = transformer;
202     }
203
204     /** Sets the JAXP Result instance to
205       */

206     public void setResult(Result JavaDoc result) {
207         this.result = result;
208     }
209
210     /** Sets where the output is written to
211       */

212     public void setWriter(Writer JavaDoc writer) {
213         setResult( new StreamResult JavaDoc( writer ) );
214     }
215
216     /** Sets the SAX ContentHandler that the output is written to */
217     public void setResultHandler(ContentHandler JavaDoc handler) {
218         setResult( new SAXResult JavaDoc( handler ) );
219     }
220
221     /** Sets the XML URL that the input document is read from */
222     public void setXml(String JavaDoc xml) {
223     this.xml = xml;
224     }
225
226     /** Sets the source of the XML document */
227     public void setXmlSource(Source JavaDoc source) {
228         this.xml = source;
229     }
230
231     public void setXmlReader(Reader JavaDoc reader) {
232         this.xml = reader;
233     }
234
235     /** Sets the XSL URL that the stylesheet is read from */
236     public void setXsl(String JavaDoc xsl) {
237     this.xsl = xsl;
238     }
239
240     public void setXslReader(Reader JavaDoc reader) {
241     this.xsl = reader;
242     }
243
244     /** Sets the source of the XML document */
245     public void setXslSource(Source JavaDoc source) {
246         this.xsl = source;
247     }
248
249
250
251
252     // Implementation methods
253
//-------------------------------------------------------------------------
254

255     /** Configures the Transformer before use
256       */

257     protected void configure(Transformer JavaDoc transformer) {
258         if ( outputMethod != null ) {
259             transformer.setOutputProperty( OutputKeys.METHOD, outputMethod );
260         }
261         if ( parameters != null ) {
262             for ( Iterator JavaDoc iter = parameters.entrySet().iterator(); iter.hasNext(); ) {
263                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
264                 String JavaDoc name = entry.getKey().toString();
265                 Object JavaDoc value = entry.getValue();
266                 transformer.setParameter( name, value );
267             }
268         }
269     }
270
271     /** Construct and return a JAXP Source to read the XML data to be styled.
272       *
273       * @param source is the object to be converted into a JAXP Source
274       * @exception JspException if a JSP error occurs
275       */

276     protected Source JavaDoc getSource(Object JavaDoc source) throws JspException JavaDoc {
277         if (source instanceof Source JavaDoc) {
278         return (Source JavaDoc) source;
279         }
280         else if (source instanceof Reader JavaDoc) {
281         return new StreamSource JavaDoc((Reader JavaDoc) source);
282         }
283         else if (source instanceof String JavaDoc) {
284             try {
285                 URL JavaDoc url = URLHelper.createURL( (String JavaDoc) source, pageContext );
286                 if ( url == null ) {
287                     throw new JspException JavaDoc("Bad URL: " + source + ".");
288                 }
289                 return new StreamSource JavaDoc(url.openStream(), url.toExternalForm());
290             }
291             catch (IOException JavaDoc e) {
292                 throw new JspException JavaDoc(
293                     "Bad URL: " + source + ". Exception: " + e.getMessage()
294                 );
295             }
296         }
297         else if (source instanceof Node) {
298         return new DocumentSource((Node) source);
299         }
300         else if (source instanceof org.w3c.dom.Node JavaDoc) {
301         return new DOMSource JavaDoc((org.w3c.dom.Node JavaDoc) source);
302         }
303         else if (source instanceof InputSource JavaDoc) {
304         return new SAXSource JavaDoc((InputSource JavaDoc) source);
305         }
306         else if ( source == null ) {
307         throw new JspException JavaDoc( "No XSLT source specified" );
308         }
309         else {
310         throw new JspException JavaDoc(
311                 "Invalid input source type '" + source.getClass().getName() + "'"
312             );
313         }
314     }
315  
316     /** Construct and return a JAXP Result
317       *
318       * @exception JspException if a JSP error occurs
319       */

320     protected Result JavaDoc getResult() throws JspException JavaDoc {
321         if ( result == null ) {
322             // use StringWriter to avoid flushing problems with BodyContent
323
stringWriter = new StringWriter JavaDoc();
324             return new StreamResult JavaDoc( stringWriter );
325         }
326         else {
327             stringWriter = null;
328         }
329         return result;
330     }
331     
332     /** Creates a URI resolver capable of resolving URIs when used in XSLT includes or imports */
333     protected URIResolver JavaDoc createURIResolver() {
334         return new URIResolver JavaDoc() {
335             public Source JavaDoc resolve(String JavaDoc href, String JavaDoc base)
336                throws TransformerException JavaDoc {
337                 try {
338                     return getSource(href);
339                 }
340                 catch(javax.servlet.jsp.JspException JavaDoc e) {
341                     return null;
342                 }
343             }
344
345         };
346     }
347
348     /** Handles non-JspExceptions thrown in this instance
349       */

350     protected void handleException( Exception JavaDoc e ) throws JspException JavaDoc {
351         if ( e instanceof JspException JavaDoc ) {
352             throw (JspException JavaDoc) e;
353         }
354         else {
355             pageContext.getServletContext().log( e.getMessage(), e );
356             e.printStackTrace();
357             throw new JspNestedException( e );
358         }
359     }
360 }
361
Popular Tags