001: /* *****************************************************************************
002: * TransformUtils.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.utils;
011:
012: import java.io.*;
013: import java.util.*;
014: import javax.xml.transform.*;
015:
016: public abstract class TransformUtils {
017: /** {Pathname -> Templates} */
018: static private Map sTemplatesMap = new HashMap();
019: /** {Pathname -> lastModified} */
020: static private Map sTemplatesLastModified = new HashMap();
021:
022: static public Templates getTemplates(String styleSheetPathname)
023: throws IOException {
024: synchronized (sTemplatesMap) {
025: Templates templates = (Templates) sTemplatesMap
026: .get(styleSheetPathname);
027: Long lastModified = new Long(new File(styleSheetPathname)
028: .lastModified());
029: if (templates != null
030: && !sTemplatesLastModified.get(styleSheetPathname)
031: .equals(lastModified))
032: templates = null;
033: if (templates == null) {
034: CollectingErrorListener errorListener = new CollectingErrorListener();
035: // name the class instead of using
036: // TransformerFactory.newInstance(), to insure that we
037: // get saxon and thereby work around bug 3924
038: TransformerFactory factory = new com.icl.saxon.TransformerFactoryImpl();
039: factory.setErrorListener(errorListener);
040: java.io.InputStream xslInput = new java.net.URL("file",
041: "", styleSheetPathname).openStream();
042: try {
043: Source xslSource = new javax.xml.transform.stream.StreamSource(
044: xslInput);
045: templates = factory.newTemplates(xslSource);
046: } catch (TransformerConfigurationException e) {
047: if (errorListener.isEmpty())
048: throw new ChainedException(e);
049: else
050: throw new ChainedException(errorListener
051: .getMessage(), e);
052: } finally {
053: xslInput.close();
054: }
055: sTemplatesMap.put(styleSheetPathname, templates);
056: sTemplatesLastModified.put(styleSheetPathname,
057: lastModified);
058: }
059: return templates;
060: }
061: }
062:
063: public static void applyTransform(String styleSheetPathname,
064: String xmlString, OutputStream out) throws IOException {
065: applyTransform(styleSheetPathname, new Properties(), xmlString,
066: out);
067: }
068:
069: // http://xml.apache.org/xalan-j/usagepatterns.html#multithreading
070: // describes this usage pattern.
071: static public void applyTransform(String styleSheetPathname,
072: Properties properties, String xmlString, OutputStream out)
073: throws IOException {
074: PrintWriter writer = new PrintWriter(out);
075: CollectingErrorListener errorListener = new CollectingErrorListener();
076: try {
077: Templates template = getTemplates(styleSheetPathname);
078: Transformer transformer = template.newTransformer();
079: transformer.setErrorListener(errorListener);
080: Source xmlSource = new javax.xml.transform.stream.StreamSource(
081: new StringReader(xmlString));
082: for (Iterator iter = properties.keySet().iterator(); iter
083: .hasNext();) {
084: String key = (String) iter.next();
085: String value = properties.getProperty(key);
086: transformer.setParameter(key, value);
087: }
088: // Perform the transformation, sending the output to the response.
089: transformer
090: .transform(
091: xmlSource,
092: new javax.xml.transform.stream.StreamResult(
093: writer));
094: writer.close();
095: } catch (TransformerConfigurationException e) {
096: if (errorListener.isEmpty())
097: throw new ChainedException(e);
098: else
099: throw new ChainedException(errorListener.getMessage(),
100: e);
101: } catch (TransformerException e) {
102: if (errorListener.isEmpty())
103: throw new ChainedException(e);
104: else
105: throw new ChainedException(errorListener.getMessage(),
106: e);
107: }
108: }
109: }
110:
111: class CollectingErrorListener implements
112: javax.xml.transform.ErrorListener {
113: protected StringBuffer messageBuffer = new StringBuffer();
114: protected String separator = "";
115: protected int messageCount = 0;
116:
117: private void appendErrorString(TransformerException exception) {
118: messageBuffer.append(separator);
119: separator = "\n";
120: messageBuffer.append(exception.getMessageAndLocation());
121: messageCount++;
122: }
123:
124: public void error(TransformerException exception) {
125: appendErrorString(exception);
126: }
127:
128: public void warning(TransformerException exception) {
129: appendErrorString(exception);
130: }
131:
132: public void fatalError(TransformerException exception) {
133: appendErrorString(exception);
134: }
135:
136: boolean isEmpty() {
137: return messageCount == 0;
138: }
139:
140: String getMessage() {
141: return messageBuffer.toString();
142: }
143: }
|