001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: TemplateTransformerXslt.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.template;
009:
010: import com.uwyn.rife.resources.ResourceFinder;
011: import com.uwyn.rife.resources.ResourceFinderClasspath;
012: import com.uwyn.rife.template.exceptions.FilterNotFoundException;
013: import com.uwyn.rife.template.exceptions.TemplateException;
014: import com.uwyn.rife.template.exceptions.TransformerErrorException;
015: import com.uwyn.rife.xml.XmlInputSource;
016: import com.uwyn.rife.xml.XmlUriResolver;
017: import java.io.OutputStream;
018: import java.net.MalformedURLException;
019: import java.net.URL;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Enumeration;
023: import java.util.Iterator;
024: import java.util.Properties;
025: import javax.xml.parsers.FactoryConfigurationError;
026: import javax.xml.parsers.ParserConfigurationException;
027: import javax.xml.parsers.SAXParser;
028: import javax.xml.parsers.SAXParserFactory;
029: import javax.xml.transform.Source;
030: import javax.xml.transform.Transformer;
031: import javax.xml.transform.TransformerConfigurationException;
032: import javax.xml.transform.TransformerException;
033: import javax.xml.transform.TransformerFactory;
034: import javax.xml.transform.sax.SAXSource;
035: import javax.xml.transform.sax.SAXTransformerFactory;
036: import javax.xml.transform.stream.StreamResult;
037: import org.xml.sax.SAXException;
038: import org.xml.sax.XMLFilter;
039: import org.xml.sax.XMLReader;
040:
041: public class TemplateTransformerXslt implements TemplateTransformer {
042: private ResourceFinder mResourceFinder = ResourceFinderClasspath
043: .getInstance();
044: private ArrayList<SAXSource> mFilters = null;
045: private Properties mProperties = null;
046: private String mState = null;
047:
048: public final static String OUTPUT_METHOD = "method";
049: public final static String OUTPUT_INDENT = "indent";
050: public final static String OUTPUT_MEDIA_TYPE = "media-type";
051: public final static String OUTPUT_VERSION = "version";
052: public final static String OUTPUT_INDENT_AMOUNT = "{http\u003a//xml.apache.org/xalan}indent-amount";
053: public final static String OUTPUT_USE_URL_ESCAPING = "{http\u003a//xml.apache.org/xalan}use-url-escaping";
054: public final static String OUTPUT_OMIT_META_TAG = "{http\u003a//xml.apache.org/xalan}omit-meta-tag";
055:
056: public String getState() {
057: if (null == mState) {
058: StringBuilder state = new StringBuilder();
059:
060: if (mFilters != null) {
061: for (SAXSource filter : mFilters) {
062: state.append(filter.getInputSource().toString());
063: state.append(";");
064: }
065: }
066:
067: if (mProperties != null) {
068: state.append("\n");
069: Enumeration property_names = mProperties
070: .propertyNames();
071: String property_name = null;
072: while (property_names.hasMoreElements()) {
073: property_name = (String) property_names
074: .nextElement();
075: state.append(property_name);
076: state.append("=");
077: state
078: .append(mProperties
079: .getProperty(property_name));
080: state.append(";");
081: }
082: }
083:
084: mState = state.toString();
085: }
086:
087: return mState;
088: }
089:
090: public void addFilter(String xmlPath) throws TemplateException {
091: if (null == xmlPath)
092: throw new IllegalArgumentException("xmlPath can't be null");
093: if (0 == xmlPath.length())
094: throw new IllegalArgumentException("xmlPath can't be empty");
095:
096: if (null == mFilters) {
097: mFilters = new ArrayList<SAXSource>();
098: }
099:
100: URL resource = mResourceFinder.getResource(xmlPath);
101: if (null == resource) {
102: throw new FilterNotFoundException(xmlPath);
103: }
104:
105: mState = null;
106: mFilters.add(new SAXSource(new XmlInputSource(resource)));
107: }
108:
109: public void clearFilters() {
110: mState = null;
111: mFilters = null;
112: }
113:
114: public ResourceFinder getResourceFinder() {
115: return mResourceFinder;
116: }
117:
118: public void setResourceFinder(ResourceFinder resourceFinder) {
119: mResourceFinder = resourceFinder;
120: }
121:
122: public void setOutputProperty(String name, String value)
123: throws IllegalArgumentException {
124: if (null == mProperties) {
125: mProperties = new Properties();
126: }
127:
128: mState = null;
129: mProperties.setProperty(name, value);
130: }
131:
132: public void setOutputProperties(Properties properties)
133: throws IllegalArgumentException {
134: mState = null;
135: mProperties = properties;
136: }
137:
138: public Collection<URL> transform(String templateName, URL resource,
139: OutputStream result, String encoding)
140: throws TemplateException {
141: ArrayList<URL> stylesheets = new ArrayList<URL>();
142:
143: XmlInputSource input = new XmlInputSource(resource);
144:
145: if (encoding != null) {
146: input.setEncoding(encoding);
147: }
148:
149: try {
150: SAXParserFactory parser_factory = SAXParserFactory
151: .newInstance();
152: parser_factory.setNamespaceAware(true);
153:
154: SAXParser parser = parser_factory.newSAXParser();
155: XMLReader reader = parser.getXMLReader();
156: XMLReader parent = reader;
157: XMLFilter filter = null;
158:
159: SAXTransformerFactory transformer_factory = (SAXTransformerFactory) TransformerFactory
160: .newInstance();
161: transformer_factory.setURIResolver(new XmlUriResolver(
162: mResourceFinder));
163:
164: // try to obtain the associated stylesheet and use it as the first filter
165: Source stylesheet = transformer_factory
166: .getAssociatedStylesheet(new SAXSource(input),
167: null, null, null);
168: if (stylesheet != null) {
169: filter = transformer_factory.newXMLFilter(stylesheet);
170: filter.setParent(parent);
171: parent = filter;
172:
173: // store the stylesheet so that it can be included in the modification checks
174: stylesheets.add(new URL(stylesheet.getSystemId()));
175:
176: reader = filter;
177: }
178:
179: // set up the additional filters
180: if (mFilters != null && mFilters.size() > 0) {
181: Iterator<SAXSource> filters_it = mFilters.iterator();
182: while (filters_it.hasNext()) {
183: stylesheet = filters_it.next();
184: filter = transformer_factory
185: .newXMLFilter(stylesheet);
186: filter.setParent(parent);
187: parent = filter;
188:
189: // store the stylesheet so that it can be included in the modification checks
190: stylesheets.add(new URL(stylesheet.getSystemId()));
191: }
192: reader = filter;
193: }
194:
195: // setup the transformer by applying the custom properties
196: Transformer transformer = transformer_factory
197: .newTransformer();
198: if (mProperties != null) {
199: Properties merged_properties = transformer
200: .getOutputProperties();
201: merged_properties.putAll(mProperties);
202: transformer.setOutputProperties(merged_properties);
203: }
204:
205: // perform the transformation
206: StreamResult stream_result = new StreamResult(result);
207: SAXSource transform_source = new SAXSource(reader, input);
208: transformer.transform(transform_source, stream_result);
209: } catch (MalformedURLException e) {
210: throw new TransformerErrorException(resource, e);
211: } catch (TransformerConfigurationException e) {
212: throw new TransformerErrorException(resource, e);
213: } catch (TransformerException e) {
214: throw new TransformerErrorException(resource, e);
215: } catch (FactoryConfigurationError e) {
216: throw new TransformerErrorException(resource, e);
217: } catch (ParserConfigurationException e) {
218: throw new TransformerErrorException(resource, e);
219: } catch (SAXException e) {
220: throw new TransformerErrorException(resource, e);
221: }
222:
223: return stylesheets;
224: }
225:
226: public String getEncoding() {
227: if (mProperties != null && mProperties.containsKey("encoding")) {
228: return mProperties.getProperty("encoding");
229: }
230:
231: return null;
232: }
233: }
|