| package org.apache.turbine.services.xslt; |
| |
| /* ==================================================================== |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Apache" and "Apache Software Foundation" and |
| * "Apache Turbine" must not be used to endorse or promote products |
| * derived from this software without prior written permission. For |
| * written permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * "Apache Turbine", nor may "Apache" appear in their name, without |
| * prior written permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| import java.io.File; |
| import java.io.Reader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.xml.transform.Result; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.Templates; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.apache.commons.configuration.Configuration; |
| |
| import org.apache.commons.lang.StringUtils; |
| |
| import org.apache.turbine.Turbine; |
| import org.apache.turbine.services.InitializationException; |
| import org.apache.turbine.services.TurbineBaseService; |
| |
| import org.w3c.dom.Node; |
| |
| /** |
| * Implementation of the Turbine XSLT Service. It transforms xml with a given |
| * xsl file. XSL stylesheets are compiled and cached (if the property in |
| * TurbineResources.properties is set) to improve speeds. |
| * |
| * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a> |
| * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a> |
| */ |
| public class TurbineXSLTService |
| extends TurbineBaseService |
| implements XSLTService |
| |
| { |
| /** |
| * Property to control the caching of StyleSheetRoots. |
| */ |
| protected boolean caching = false; |
| |
| /** |
| * Path to style sheets used for tranforming well-formed |
| * XML documents. The path is relative to the webapp context. |
| */ |
| protected String path; |
| |
| /** |
| * Cache of compiled StyleSheetRoots. |
| */ |
| protected Map cache = new HashMap(); |
| |
| /** |
| * Factory for producing templates and null transformers |
| */ |
| private static TransformerFactory tfactory; |
| |
| /** |
| * Initialize the TurbineXSLT Service. Load the path to search for |
| * xsl files and initiates the cache. |
| */ |
| public void init() |
| throws InitializationException |
| { |
| Configuration conf = getConfiguration(); |
| |
| path = Turbine.getRealPath(conf.getString(STYLESHEET_PATH, null)); |
| |
| if (StringUtils.isNotEmpty(path)) |
| { |
| if (!path.endsWith("/") && !path.endsWith ("\\")) |
| { |
| path = path + File.separator; |
| } |
| } |
| |
| caching = conf.getBoolean(STYLESHEET_CACHING); |
| |
| tfactory = TransformerFactory.newInstance(); |
| |
| setInit(true); |
| } |
| |
| /** |
| * Get a valid and existing filename from a template name. |
| * The extension is removed and replaced with .xsl. If this |
| * file does not exist the method attempts to find default.xsl. |
| * If it fails to find default.xsl it returns null. |
| */ |
| protected String getFileName(String templateName) |
| { |
| // First we chop of the existing extension |
| int colon = templateName.lastIndexOf("."); |
| if (colon > 0) |
| { |
| templateName = templateName.substring(0, colon); |
| } |
| |
| // Now we try to find the file ... |
| File f = new File(path + templateName + ".xsl"); |
| if (f.exists()) |
| { |
| return path + templateName + ".xsl"; |
| } |
| else |
| { |
| // ... or the default file |
| f = new File(path + "default.xsl"); |
| if (f.exists()) |
| { |
| return path + "default.xsl"; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| } |
| |
| /** |
| * Compile Templates from an input file. |
| */ |
| protected Templates compileTemplates(String source) throws Exception |
| { |
| StreamSource xslin = new StreamSource(new File(source)); |
| Templates root = tfactory.newTemplates(xslin); |
| return root; |
| } |
| |
| /** |
| * Retrieves Templates. If caching is switched on the |
| * first attempt is to load the Templates from the cache. |
| * If caching is switched of or if the Stylesheet is not found |
| * in the cache a new StyleSheetRoot is compiled from an input |
| * file. |
| * <p> |
| * This method is synchronized on the xsl cache so that a thread |
| * does not attempt to load a StyleSheetRoot from the cache while |
| * it is still being compiled. |
| */ |
| protected Templates getTemplates(String xslName) throws Exception |
| { |
| synchronized (cache) |
| { |
| if (caching && cache.containsKey(xslName)) |
| { |
| return (Templates) cache.get(xslName); |
| } |
| |
| String fn = getFileName(xslName); |
| |
| if (fn == null) return null; |
| |
| Templates sr = compileTemplates(fn); |
| |
| if (caching) |
| { |
| cache.put(xslName, sr); |
| } |
| |
| return sr; |
| } |
| |
| } |
| |
| protected void transform(String xslName, Source xmlin, Result xmlout) |
| throws Exception |
| { |
| Templates sr = getTemplates(xslName); |
| Transformer transformer; |
| |
| |
| // If there is no stylesheet we just echo the xml |
| if (sr == null) |
| { |
| transformer = tfactory.newTransformer(); |
| } |
| else |
| { |
| transformer = sr.newTransformer(); |
| } |
| |
| transformer.transform(xmlin, xmlout); |
| } |
| |
| /** |
| * Execute an xslt |
| */ |
| public void transform(String xslName, Reader in, Writer out) |
| throws Exception |
| { |
| Source xmlin = new StreamSource(in); |
| Result xmlout = new StreamResult(out); |
| |
| transform(xslName, xmlin, xmlout); |
| } |
| |
| /** |
| * Execute an xslt |
| */ |
| public String transform(String xslName, Reader in) throws Exception |
| { |
| StringWriter sw = new StringWriter(); |
| transform(xslName, in, sw); |
| return sw.toString(); |
| } |
| |
| /** |
| * Execute an xslt |
| */ |
| public void transform (String xslName, Node in, Writer out) |
| throws Exception |
| { |
| Source xmlin = new DOMSource(in); |
| Result xmlout = new StreamResult(out); |
| |
| transform(xslName, xmlin, xmlout); |
| } |
| |
| /** |
| * Execute an xslt |
| */ |
| public String transform (String xslName, Node in) |
| throws Exception |
| { |
| StringWriter sw = new StringWriter(); |
| transform(xslName, in, sw); |
| return sw.toString(); |
| } |
| |
| } |