| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.bsf.engines.xslt; |
| |
| import java.io.File; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.net.URL; |
| import java.util.Vector; |
| |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.dom.DOMResult; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.apache.bsf.BSFDeclaredBean; |
| import org.apache.bsf.BSFException; |
| import org.apache.bsf.BSFManager; |
| import org.apache.bsf.BSF_Log; |
| import org.apache.bsf.BSF_LogFactory; |
| import org.apache.bsf.util.BSFEngineImpl; |
| import org.apache.bsf.util.BSFFunctions; |
| import org.apache.xpath.objects.XObject; |
| import org.w3c.dom.Node; |
| |
| /** |
| * Xerces XSLT interface to BSF. Requires Xalan and Xerces from Apache. |
| * |
| * This integration uses the BSF registry to pass in any src document |
| * and stylesheet base URI that the user may wish to set. |
| * |
| * @author Sanjiva Weerawarana |
| * @author Sam Ruby |
| * |
| * Re-implemented for the Xalan 2 codebase |
| * |
| * @author Victor J. Orlikowski |
| * @author Rony G. Flatscher (added BSF_Log[Factory] to allow BSF to run without org.apache.commons.logging present) |
| */ |
| public class XSLTEngine extends BSFEngineImpl { |
| TransformerFactory tFactory; |
| Transformer transformer; |
| |
| // Log logger = LogFactory.getLog(this.getClass().getName()); |
| BSF_Log logger = null; |
| |
| public XSLTEngine () |
| { |
| // handle logger |
| logger = BSF_LogFactory.getLog(this.getClass().getName()); |
| } |
| |
| |
| /** |
| * call the named method of the given object. |
| */ |
| public Object call (Object object, String method, Object[] args) |
| throws BSFException { |
| throw new BSFException (BSFException.REASON_UNSUPPORTED_FEATURE, |
| "BSF:XSLTEngine can't call methods"); |
| } |
| |
| /** |
| * Declare a bean by setting it as a parameter |
| */ |
| public void declareBean (BSFDeclaredBean bean) throws BSFException { |
| transformer.setParameter (bean.name, new XObject (bean.bean)); |
| } |
| |
| /** |
| * Evaluate an expression. In this case, an expression is assumed |
| * to be a stylesheet of the template style (see the XSLT spec). |
| */ |
| public Object eval (String source, int lineNo, int columnNo, |
| Object oscript) throws BSFException { |
| // get the style base URI (the place from where Xerces XSLT will |
| // look for imported/included files and referenced docs): if a |
| // bean named "xslt:styleBaseURI" is registered, then cvt it |
| // to a string and use that. Otherwise use ".", which means the |
| // base is the directory where the process is running from |
| Object sbObj = mgr.lookupBean ("xslt:styleBaseURI"); |
| String styleBaseURI = (sbObj == null) ? "." : sbObj.toString (); |
| |
| // Locate the stylesheet. |
| StreamSource styleSource; |
| |
| styleSource = |
| new StreamSource(new StringReader(oscript.toString ())); |
| styleSource.setSystemId(styleBaseURI); |
| |
| try { |
| transformer = tFactory.newTransformer(styleSource); |
| } catch (Exception e) { |
| logger.error("Exception from Xerces XSLT:", e); |
| throw new BSFException (BSFException.REASON_EXECUTION_ERROR, |
| "Exception from Xerces XSLT: " + e, e); |
| } |
| |
| // get the src to work on: if a bean named "xslt:src" is registered |
| // and its a Node, then use it as the source. If its not a Node, then |
| // if its a URL parse it, if not treat it as a file and make a URL and |
| // parse it and go. If no xslt:src is found, use an empty document |
| // (stylesheet is treated as a literal result element stylesheet) |
| Object srcObj = mgr.lookupBean ("xslt:src"); |
| Object xis = null; |
| if (srcObj != null) { |
| if (srcObj instanceof Node) { |
| xis = new DOMSource((Node)srcObj); |
| } else { |
| try { |
| String mesg = "as anything"; |
| if (srcObj instanceof Reader) { |
| xis = new StreamSource ((Reader) srcObj); |
| mesg = "as a Reader"; |
| } else if (srcObj instanceof File) { |
| xis = new StreamSource ((File) srcObj); |
| mesg = "as a file"; |
| } else { |
| String srcObjstr=srcObj.toString(); |
| xis = new StreamSource (new StringReader(srcObjstr)); |
| if (srcObj instanceof URL) { |
| mesg = "as a URL"; |
| } else { |
| ((StreamSource) xis).setPublicId (srcObjstr); |
| mesg = "as an XML string"; |
| } |
| } |
| |
| if (xis == null) { |
| throw new Exception ("Unable to get input from '" + |
| srcObj + "' " + mesg); |
| } |
| } catch (Exception e) { |
| throw new BSFException (BSFException.REASON_EXECUTION_ERROR, |
| "BSF:XSLTEngine: unable to get " + |
| "input from '" + srcObj + "' as XML", e); |
| } |
| } |
| } else { |
| // create an empty document - real src must come into the |
| // stylesheet using "doc(...)" [see XSLT spec] or the stylesheet |
| // must be of literal result element type |
| xis = new StreamSource(); |
| } |
| |
| // set all declared beans as parameters. |
| for (int i = 0; i < declaredBeans.size (); i++) { |
| BSFDeclaredBean b = (BSFDeclaredBean) declaredBeans.elementAt (i); |
| transformer.setParameter (b.name, new XObject (b.bean)); |
| } |
| |
| // declare a "bsf" parameter which is the BSF handle so that |
| // the script can do BSF stuff if it wants to |
| transformer.setParameter ("bsf", |
| new XObject (new BSFFunctions (mgr, this))); |
| |
| // do it |
| try { |
| DOMResult result = new DOMResult(); |
| transformer.transform ((StreamSource) xis, result); |
| return new XSLTResultNode (result.getNode()); |
| } catch (Exception e) { |
| throw new BSFException (BSFException.REASON_EXECUTION_ERROR, |
| "exception while eval'ing XSLT script" + e, e); |
| } |
| } |
| |
| /** |
| * Initialize the engine. |
| */ |
| public void initialize (BSFManager mgr, String lang, |
| Vector declaredBeans) throws BSFException { |
| super.initialize (mgr, lang, declaredBeans); |
| |
| tFactory = TransformerFactory.newInstance(); |
| } |
| |
| /** |
| * Undeclare a bean by setting he parameter represeting it to null |
| */ |
| public void undeclareBean (BSFDeclaredBean bean) throws BSFException { |
| // Cannot clear only one parameter in Xalan 2, so we set it to null |
| if ((transformer.getParameter (bean.name)) != null) { |
| transformer.setParameter (bean.name, null); |
| } |
| } |
| } |