Extension Enhancements, including EXSLT Function and Result.
diff --git a/src/org/apache/xalan/extensions/ExpressionContext.java b/src/org/apache/xalan/extensions/ExpressionContext.java index 6522f67..9901062 100644 --- a/src/org/apache/xalan/extensions/ExpressionContext.java +++ b/src/org/apache/xalan/extensions/ExpressionContext.java
@@ -103,8 +103,19 @@ * * @throws javax.xml.transform.TransformerException */ - public XObject getVariableOrParam(org.apache.xml.utils.QName qname) throws javax.xml.transform.TransformerException; + + /** + * Get the XPathContext that owns this ExpressionContext. + * + * Note: exslt:function requires the XPathContext to access + * the variable stack and TransformerImpl. + * + * @return The current XPathContext. + * @throws javax.xml.transform.TransformerException + */ + public org.apache.xpath.XPathContext getXPathContext() + throws javax.xml.transform.TransformerException; }
diff --git a/src/org/apache/xalan/extensions/ExpressionVisitor.java b/src/org/apache/xalan/extensions/ExpressionVisitor.java new file mode 100644 index 0000000..717c93d --- /dev/null +++ b/src/org/apache/xalan/extensions/ExpressionVisitor.java
@@ -0,0 +1,106 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.extensions; + +import org.apache.xpath.XPathVisitor; +import org.apache.xpath.ExpressionOwner; +import org.apache.xpath.functions.Function; +import org.apache.xpath.functions.FuncExtFunction; +import org.apache.xalan.templates.StylesheetRoot; + +/** + * When {@link org.apache.xalan.templates.StylesheetHandler} creates + * an {@link org.apache.xpath.XPath}, the ExpressionVisitor + * visits the XPath expression. For any extension functions it + * encounters, it instructs StylesheetRoot to register the + * extension namespace. + * + * This mechanism is required to locate extension functions + * that may be embedded within an expression. + */ +public class ExpressionVisitor extends XPathVisitor +{ + private StylesheetRoot m_sroot; + + /** + * The constructor sets the StylesheetRoot variable which + * is used to register extension namespaces. + * @param sroot the StylesheetRoot that is being constructed. + */ + public ExpressionVisitor (StylesheetRoot sroot) + { + m_sroot = sroot; + } + + /** + * If the function is an extension function, register the namespace. + * + * @param owner The current XPath object that owns the expression. + * @param function The function currently being visited. + * + * @return true to continue the visit in the subtree, if any. + */ + public boolean visitFunction(ExpressionOwner owner, Function func) + { + if (func instanceof FuncExtFunction) + { + String namespace = ((FuncExtFunction)func).getNamespace(); + m_sroot.getExtensionNamespacesManager().registerExtension(namespace); + } + return true; + } +} \ No newline at end of file
diff --git a/src/org/apache/xalan/extensions/ExtensionHandlerExsltFunction.java b/src/org/apache/xalan/extensions/ExtensionHandlerExsltFunction.java new file mode 100644 index 0000000..70a57b4 --- /dev/null +++ b/src/org/apache/xalan/extensions/ExtensionHandlerExsltFunction.java
@@ -0,0 +1,237 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.extensions; + +import java.util.Vector; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.io.IOException; + +import org.w3c.dom.NodeList; +import org.w3c.dom.Node; + +import org.apache.xalan.transformer.TransformerImpl; + +import org.apache.xalan.templates.ElemTemplateElement; +import org.apache.xalan.templates.Stylesheet; +import org.apache.xalan.templates.StylesheetRoot; +import org.apache.xalan.templates.ElemTemplate; +import org.apache.xalan.templates.ElemExsltFunction; +import org.apache.xalan.templates.ElemExsltFuncResult; +import org.apache.xalan.templates.Constants; + +import org.apache.xml.utils.QName; + +import org.apache.xpath.XPathContext; +import org.apache.xpath.VariableStack; +import org.apache.xpath.objects.XObject; +import org.apache.xpath.objects.XString; +import javax.xml.transform.TransformerException; + +/** + * Execute EXSLT functions, determine the availability of EXSLT functions, and the + * availability of an EXSLT result element. + */ +public class ExtensionHandlerExsltFunction extends ExtensionHandler +{ + private String m_namespace; + private StylesheetRoot m_stylesheet; + private static final QName RESULTQNAME = + new QName(Constants.S_EXSLT_FUNCTIONS_URL, + Constants.EXSLT_ELEMNAME_FUNCRESULT_STRING); + /** + * Constructor called from ElemExsltFunction runtimeInit(). + */ + public ExtensionHandlerExsltFunction(String ns, StylesheetRoot stylesheet) + { + super(ns, "xml"); // required by ExtensionHandler interface. + m_namespace = ns; + m_stylesheet = stylesheet; + } + + /** + * Required by ExtensionHandler (an abstract method). No-op. + */ + public void processElement( + String localPart, ElemTemplateElement element, TransformerImpl transformer, + Stylesheet stylesheetTree, Object methodKey) throws TransformerException, IOException + {} + + /** + * Get the ElemExsltFunction element associated with the + * function. + * + * @param funcName Local name of the function. + * @return the ElemExsltFunction element associated with + * the function, null if none exists. + */ + public ElemExsltFunction getFunction(String funcName) + { + QName qname = new QName(m_namespace, funcName); + ElemTemplate templ = m_stylesheet.getTemplateComposed(qname); + if (templ != null && templ instanceof ElemExsltFunction) + return (ElemExsltFunction) templ; + else + return null; + } + + + /** + * Does the EXSLT function exist? + * + * @param funcName Local name of the function. + * @return true if the function exists. + */ + public boolean isFunctionAvailable(String funcName) + { + return getFunction(funcName)!= null; + } + + /** If an element-available() call applies to an EXSLT result element within + * an EXSLT function element, return true. + * + * Note: The EXSLT function element is a template-level element, and + * element-available() returns false for it. + * + * @param Local name of the function. + * @return true if the function is available. + */ + public boolean isElementAvailable(String elemName) + { + if (!(new QName(m_namespace, elemName).equals(RESULTQNAME))) + { + return false; + } + else + { + ElemTemplateElement elem = m_stylesheet.getFirstChildElem(); + while (elem != null && elem != m_stylesheet) + { + if (elem instanceof ElemExsltFuncResult && ancestorIsFunction(elem)) + return true; + ElemTemplateElement nextElem = elem.getFirstChildElem(); + if (nextElem == null) + nextElem = elem.getNextSiblingElem(); + if (nextElem == null) + nextElem = elem.getParentElem(); + elem = nextElem; + } + } + return false; + } + + /** + * Determine whether the func:result element is within a func:function element. + * If not, it is illegal. + */ + private boolean ancestorIsFunction(ElemTemplateElement child) + { + while (child.getParentElem() != null + && !(child.getParentElem() instanceof StylesheetRoot)) + { + if (child.getParentElem() instanceof ElemExsltFunction) + return true; + child = child.getParentElem(); + } + return false; + } + + /** + * Execute the EXSLT function and return the result value. + * + * @param funcName Name of the EXSLT function. + * @param args The arguments of the function call. + * @param methodKey Not used. + * @param exprContext Used to get the XPathContext. + * @return the return value of the function evaluation. + * @throws TransformerException + */ + public Object callFunction( + String funcName, Vector args, Object methodKey, + ExpressionContext exprContext) throws TransformerException + { + XObject[] methodArgs; + methodArgs = new XObject[args.size()]; + try + { + for (int i = 0; i < methodArgs.length; i++) + { + methodArgs[i] = XObject.create(args.elementAt(i)); + } + ElemExsltFunction elemFunc = getFunction(funcName); + XPathContext context = exprContext.getXPathContext(); + TransformerImpl transformer = (TransformerImpl)context.getOwnerObject(); + elemFunc.execute(transformer, methodArgs); + + VariableStack varStack = context.getVarStack(); + XObject val = new XString(""); // value returned if no result element. + + int resultIndex = elemFunc.getResultIndex(); + if (varStack.isLocalSet(resultIndex)) + val = varStack.getLocalVariable(context, resultIndex); + return val; + } + catch (Exception e) + { + // e.printStackTrace(); + throw new TransformerException(e); + } + } + +}
diff --git a/src/org/apache/xalan/extensions/ExtensionNamespaceSupport.java b/src/org/apache/xalan/extensions/ExtensionNamespaceSupport.java new file mode 100644 index 0000000..14b90be --- /dev/null +++ b/src/org/apache/xalan/extensions/ExtensionNamespaceSupport.java
@@ -0,0 +1,85 @@ +package org.apache.xalan.extensions; + +import java.lang.reflect.Constructor; +import javax.xml.transform.TransformerException; + +/** + * During styleseet composition, an ExtensionNamespaceSupport object is created for each extension + * namespace the stylesheet uses. At the beginning of a transformation, TransformerImpl generates + * an ExtensionHandler for each of these objects and adds an entry to the ExtensionsTable hashtable. + */ +public class ExtensionNamespaceSupport +{ + // Namespace, ExtensionHandler class name, constructor signature + // and arguments. + String m_namespace = null; + String m_handlerClass = null; + Class [] m_sig = null; + Object [] m_args = null; + + public ExtensionNamespaceSupport(String namespace, + String handlerClass, + Object[] constructorArgs) + { + m_namespace = namespace; + m_handlerClass = handlerClass; + m_args = constructorArgs; + // Create the constructor signature. + m_sig = new Class[m_args.length]; + for (int i = 0; i < m_args.length; i++) + { + if (m_args[i] != null) + m_sig[i] = m_args[i].getClass();//System.out.println("arg class " + i + " " +m_sig[i]); + else // If an arguments is null, pick the constructor later. + { + m_sig = null; + break; + } + } + } + + public String getNamespace() + { + return m_namespace; + } + + /** + * Launch the ExtensionHandler that this ExtensionNamespaceSupport object defines. + */ + public ExtensionHandler launch() + throws TransformerException + { + ExtensionHandler handler = null; + try + { + Class cl = ExtensionHandler.getClassForName(m_handlerClass); + Constructor con = null; + System.out.println("class " + cl + " " + m_args + " " + m_args.length + " " + m_sig); + if (m_sig != null) + con = cl.getConstructor(m_sig); + else // Pick the constructor based on number of args. + { + Constructor[] cons = cl.getConstructors(); + for (int i = 0; i < cons.length; i ++) + { + if (cons[i].getParameterTypes().length == m_args.length) + { + con = cons[i]; + break; + } + } + } + // System.out.println("constructor " + con); + if (con != null) + handler = (ExtensionHandler)con.newInstance(m_args); + else + throw new TransformerException("ExtensionHandler constructor not found"); + } + catch (Exception e) + { + throw new TransformerException(e); + } + return handler; + } + +} \ No newline at end of file
diff --git a/src/org/apache/xalan/extensions/ExtensionNamespacesManager.java b/src/org/apache/xalan/extensions/ExtensionNamespacesManager.java new file mode 100644 index 0000000..cce83ac --- /dev/null +++ b/src/org/apache/xalan/extensions/ExtensionNamespacesManager.java
@@ -0,0 +1,286 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.extensions; + +import org.apache.xalan.templates.Constants; +import java.util.Vector; + +/** + * Used during assembly of a stylesheet to collect the information for each + * extension namespace that is required during the transformation process + * to generate an {@link ExtensionHandler}. + * + */ +public class ExtensionNamespacesManager +{ + /** + * Vector of ExtensionNamespaceSupport objects to be used to generate ExtensionHandlers. + */ + private Vector m_extensions = new Vector(); + /** + * Vector of ExtensionNamespaceSupport objects for predefined ExtensionNamespaces. Elements + * from this vector are added to the m_extensions vector when encountered in the stylesheet. + */ + private Vector m_predefExtensions = new Vector(7); + /** + * Vector of extension namespaces for which sufficient information is not yet available to + * complete the registration process. + */ + private Vector m_unregisteredExtensions = new Vector(); + + /** + * An ExtensionNamespacesManager is instantiated the first time an extension function or + * element is found in the stylesheet. During initialization, a vector of ExtensionNamespaceSupport + * objects is created, one for each predefined extension namespace. + */ + public ExtensionNamespacesManager() + { + setPredefinedNamespaces(); + } + + /** + * If necessary, register the extension namespace found compiling a function or + * creating an extension element. + * + * If it is a predefined namespace, create a + * support object to simplify the instantiate of an appropriate ExtensionHandler + * during transformation runtime. Otherwise, add the namespace, if necessary, + * to a vector of undefined extension namespaces, to be defined later. + * + */ + public void registerExtension(String namespace) + { + if (namespaceIndex(namespace, m_extensions) == -1) + { + int predef = namespaceIndex(namespace, m_predefExtensions); + if (predef !=-1) + m_extensions.addElement(m_predefExtensions.get(predef)); + else if (!(m_unregisteredExtensions.contains(namespace))) + m_unregisteredExtensions.addElement(namespace); + } + } + + /** + * Register the extension namespace for an ElemExtensionDecl or ElemFunction, + * and prepare a support object to launch the appropriate ExtensionHandler at + * transformation runtime. + */ + public void registerExtension(ExtensionNamespaceSupport extNsSpt) + { + String namespace = extNsSpt.getNamespace(); + if (namespaceIndex(namespace, m_extensions) == -1) + { + m_extensions.addElement(extNsSpt); + if (m_unregisteredExtensions.contains(namespace)) + m_unregisteredExtensions.removeElement(namespace); + } + + } + + /** + * Get the index for a namespace entry in the extension namespace Vector, -1 if + * no such entry yet exists. + */ + public int namespaceIndex(String namespace, Vector extensions) + { + for (int i = 0; i < extensions.size(); i++) + { + if (((ExtensionNamespaceSupport)extensions.elementAt(i)).getNamespace().equals(namespace)) + return i; + } + return -1; + } + + + /** + * Get the vector of extension namespaces. Used to provide + * the extensions table access to a list of extension + * namespaces encountered during composition of a stylesheet. + */ + public Vector getExtensions() + { + return m_extensions; + } + + /** + * Attempt to register any unregistered extension namespaces. + */ + public void registerUnregisteredNamespaces() + { + for (int i = 0; i < m_unregisteredExtensions.size(); i++) + { + String ns = (String)m_unregisteredExtensions.elementAt(i); + ExtensionNamespaceSupport extNsSpt = defineJavaNamespace(ns); + if (extNsSpt != null) + m_extensions.addElement(extNsSpt); + } + } + + /** + * For any extension namespace that is not either predefined or defined + * by a "component" declaration or exslt function declaration, attempt + * to create an ExtensionNamespaceSuport object for the appropriate + * Java class or Java package Extension Handler. + * + * Called by StylesheetRoot.recompose(), after all ElemTemplate compose() + * operations have taken place, in order to set up handlers for + * the remaining extension namespaces. + * + * @param ns The extension namespace URI. + * @return An ExtensionNamespaceSupport object for this namespace + * (which defines the ExtensionHandler to be used), or null if such + * an object cannot be created. + * + * @throws javax.xml.transform.TransformerException + */ + public ExtensionNamespaceSupport defineJavaNamespace(String ns) + { + return defineJavaNamespace(ns, ns); + } + public ExtensionNamespaceSupport defineJavaNamespace(String ns, String classOrPackage) + { + if(null == ns || ns.trim().length() == 0) // defensive. I don't think it's needed. -sb + return null; + + // Prepare the name of the actual class or package, stripping + // out any leading "class:". Next, see if there is a /. If so, + // only look at the text to the right of the rightmost /. + String className = classOrPackage; + if (className.startsWith("class:")) + className = className.substring(6); + + int lastSlash = className.lastIndexOf("/"); + if (-1 != lastSlash) + className = className.substring(lastSlash + 1); + + // The className can be null here, and can cause an error in getClassForName + // in JDK 1.8. + if(null == className || className.trim().length() == 0) + return null; + + try + { + ExtensionHandler.getClassForName(className); + return new ExtensionNamespaceSupport( + ns, + "org.apache.xalan.extensions.ExtensionHandlerJavaClass", + new Object[]{ns, "javaclass", className}); + } + catch (ClassNotFoundException e) + { + return new ExtensionNamespaceSupport( + ns, + "org.apache.xalan.extensions.ExtensionHandlerJavaPackage", + new Object[]{ns, "javapackage", className + "."}); + } + } + +/* + public ExtensionNamespaceSupport getSupport(int index, Vector extensions) + { + return (ExtensionNamespaceSupport)extensions.elementAt(index); + } +*/ + + + /** + * Set up a Vector for predefined extension namespaces. + */ + private void setPredefinedNamespaces() + { + String uri = Constants.S_EXTENSIONS_JAVA_URL; + String handlerClassName = "org.apache.xalan.extensions.ExtensionHandlerJavaPackage"; + String lang = "javapackage"; + String lib = ""; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + uri = Constants.S_EXTENSIONS_LOTUSXSL_JAVA_URL; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + uri = Constants.S_EXTENSIONS_XALANLIB_URL; + handlerClassName = "org.apache.xalan.extensions.ExtensionHandlerJavaClass"; + lang = "javaclass"; // for remaining predefined extension namespaces. + lib = "org.apache.xalan.lib.Extensions"; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + //EXSLT namespaces (not including EXSLT function namespaces which are + // registered by the associated ElemFunction. + uri = Constants.S_EXSLT_COMMON_URL; + lib = "org.apache.xalan.lib.ExsltCommon"; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + uri = Constants.S_EXSLT_MATH_URL; + lib = "org.apache.xalan.lib.ExsltMath"; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + uri = Constants.S_EXSLT_SETS_URL; + lib = "org.apache.xalan.lib.ExsltSets"; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + + uri = Constants.S_EXSLT_DATETIME_URL; + lib = "org.apache.xalan.lib.ExsltDatetime"; + m_predefExtensions.addElement(new ExtensionNamespaceSupport(uri, handlerClassName, + new Object[]{uri, lang, lib})); + } + +} \ No newline at end of file
diff --git a/src/org/apache/xalan/extensions/ExtensionsTable.java b/src/org/apache/xalan/extensions/ExtensionsTable.java index 047db95..531cf56 100644 --- a/src/org/apache/xalan/extensions/ExtensionsTable.java +++ b/src/org/apache/xalan/extensions/ExtensionsTable.java
@@ -58,6 +58,7 @@ import java.util.Hashtable; import java.util.Vector; +import org.apache.xml.utils.StringVector; import org.apache.xpath.objects.XNull; import org.apache.xpath.XPathProcessorException; @@ -65,13 +66,27 @@ import org.apache.xalan.res.XSLMessages; import org.apache.xalan.res.XSLTErrorResources; +import org.apache.xalan.transformer.TransformerImpl; + +import org.apache.xalan.templates.Constants; +import org.apache.xalan.templates.ElemTemplateElement; +import org.apache.xalan.templates.ElemTemplate; +import org.apache.xalan.templates.StylesheetRoot; +import org.apache.xalan.templates.TemplateList; + +import org.apache.xpath.XPathContext; + +import org.apache.xml.utils.QName; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + /** * <meta name="usage" content="internal"/> * Class holding a table registered extension namespace handlers */ public class ExtensionsTable -{ - +{ /** * <meta name="usage" content="internal"/> * Table of extensions that may be called from the expression language @@ -79,50 +94,33 @@ * name. */ public Hashtable m_extensionFunctionNamespaces = new Hashtable(); - + /** - * <meta name="usage" content="internal"/> - * Primes the new ExtensionsTable object with built-in namespaces. + * The StylesheetRoot associated with this extensions table. */ - public ExtensionsTable() + private StylesheetRoot m_sroot; + + /** + * <meta name="usage" content="advanced"/> + * The constructor (called from TransformerImpl) registers the + * StylesheetRoot for the transformation and instantiates an + * ExtensionHandler for each extension namespace. + */ + public ExtensionsTable(StylesheetRoot sroot) + throws javax.xml.transform.TransformerException { - - // register the java namespace as being implemented by the - // xslt-javaclass engine. Note that there's no real code - // per se for this extension as the functions carry the - // object on which to call etc. and all the logic of breaking - // that up is in the xslt-javaclass engine. - String uri = "http://xml.apache.org/xslt/java"; - ExtensionHandler fh = new ExtensionHandlerJavaPackage(uri, - "xslt-javaclass", ""); - - addExtensionNamespace(uri, fh); - - uri = "http://xsl.lotus.com/java"; - - addExtensionNamespace(uri, fh); - - uri = "http://xml.apache.org/xalan"; - fh = new ExtensionHandlerJavaClass(uri, "javaclass", - "org.apache.xalan.lib.Extensions"); - - addExtensionNamespace(uri, fh); - - //Add EXSLT namespaces and map to org.apache.xalan.lib.ExsltXxx. - uri = "http://exslt.org/common"; - fh = new ExtensionHandlerJavaClass(uri, "javaclass", - "org.apache.xalan.lib.ExsltCommon"); - addExtensionNamespace(uri, fh); - uri = "http://exslt.org/math"; - fh = new ExtensionHandlerJavaClass(uri, "javaclass", - "org.apache.xalan.lib.ExsltMath"); - addExtensionNamespace(uri, fh); - uri = "http://exslt.org/sets"; - fh = new ExtensionHandlerJavaClass(uri, "javaclass", - "org.apache.xalan.lib.ExsltSets"); - addExtensionNamespace(uri, fh); - } - + m_sroot = sroot; + Vector extensions = m_sroot.getExtensions(); + for (int i = 0; i < extensions.size(); i++) + { + ExtensionNamespaceSupport extNamespaceSpt = + (ExtensionNamespaceSupport)extensions.elementAt(i); + ExtensionHandler extHandler = extNamespaceSpt.launch(); + if (extHandler != null) + addExtensionNamespace(extNamespaceSpt.getNamespace(), extHandler); + } + } + /** * Get an ExtensionHandler object that represents the * given namespace. @@ -162,71 +160,41 @@ public boolean functionAvailable(String ns, String funcName) throws javax.xml.transform.TransformerException { - boolean isAvailable = false; - + if (null != ns) { - ExtensionHandler extNS = - (ExtensionHandler) m_extensionFunctionNamespaces.get(ns); - - if (extNS == null) - { - extNS = makeJavaNamespace(ns); - - addExtensionNamespace(ns, extNS); - } - + ExtensionHandler extNS = + (ExtensionHandler) m_extensionFunctionNamespaces.get(ns); if (extNS != null) - { isAvailable = extNS.isFunctionAvailable(funcName); - } } - - // System.err.println (">>> functionAvailable (ns=" + ns + - // ", func=" + funcName + ") = " + isAvailable); return isAvailable; } - + /** * Execute the element-available() function. * @param ns the URI of namespace in which the function is needed - * @param funcName the function name being tested * @param elemName name of element being tested * - * @return whether the given function is available or not. + * @return whether the given element is available or not. * * @throws javax.xml.transform.TransformerException */ public boolean elementAvailable(String ns, String elemName) throws javax.xml.transform.TransformerException { - boolean isAvailable = false; - if (null != ns) { - ExtensionHandler extNS = - (ExtensionHandler) m_extensionFunctionNamespaces.get(ns); - - if (extNS == null) - { - extNS = makeJavaNamespace(ns); - - addExtensionNamespace(ns, extNS); - } - - if (extNS != null) - { + ExtensionHandler extNS = + (ExtensionHandler) m_extensionFunctionNamespaces.get(ns); + if (extNS != null) // defensive isAvailable = extNS.isElementAvailable(elemName); - } - } - - // System.err.println (">>> elementAvailable (ns=" + ns + - // ", elem=" + elemName + ") = " + isAvailable); - return isAvailable; - } - + } + return isAvailable; + } + /** * Handle an extension function. * @param ns the URI of namespace in which the function is needed @@ -242,28 +210,16 @@ * * @throws javax.xml.transform.TransformerException */ - public Object extFunction( - String ns, String funcName, Vector argVec, Object methodKey, - ExpressionContext exprContext) + public Object extFunction(String ns, String funcName, + Vector argVec, Object methodKey, + ExpressionContext exprContext) throws javax.xml.transform.TransformerException { - Object result = null; - if (null != ns) { ExtensionHandler extNS = (ExtensionHandler) m_extensionFunctionNamespaces.get(ns); - - // If the handler for this extension URI is not found try to auto declare - // this extension namespace: - if (null == extNS) - { - extNS = makeJavaNamespace(ns); - - addExtensionNamespace(ns, extNS); - } - if (null != extNS) { try @@ -282,61 +238,10 @@ } else { - throw new XPathProcessorException(XSLMessages.createMessage(XSLTErrorResources.ER_EXTENSION_FUNC_UNKNOWN, new Object[]{ns, funcName })); //"Extension function '" + ns + ":" - // + funcName + "' is unknown"); + throw new XPathProcessorException(XSLMessages.createMessage(XSLTErrorResources.ER_EXTENSION_FUNC_UNKNOWN, new Object[]{ns, funcName })); + //"Extension function '" + ns + ":" + funcName + "' is unknown"); } } - - return result; - } - - /** - * Declare the appropriate java extension handler. - * @param ns the URI of namespace in which the function is needed - * @return an ExtensionHandler for this namespace, or null if - * not found. - * - * @throws javax.xml.transform.TransformerException - */ - public ExtensionHandler makeJavaNamespace(String ns) - throws javax.xml.transform.TransformerException - { - if(null == ns || ns.trim().length() == 0) // defensive. I don't think it's needed. -sb - return null; - - // First, prepare the name of the actual class or package. We strip - // out any leading "class:". Next, we see if there is a /. If so, - // only look at anything to the right of the rightmost /. - // In the documentation, we state that any classes or packages - // declared using this technique must start with xalan://. However, - // in this version, we don't enforce that. - String className = ns; - - if (className.startsWith("class:")) - { - className = className.substring(6); - } - - int lastSlash = className.lastIndexOf("/"); - - if (-1 != lastSlash) - className = className.substring(lastSlash + 1); - - // The className can be null here, and can cause an error in getClassForName - // in JDK 1.8. - if(null == className || className.trim().length() == 0) - return null; - - try - { - ExtensionHandler.getClassForName(className); - - return new ExtensionHandlerJavaClass(ns, "javaclass", className); - } - catch (ClassNotFoundException e) - { - return new ExtensionHandlerJavaPackage(ns, "javapackage", - className + "."); - } + return result; } }
diff --git a/src/org/apache/xalan/processor/ProcessorExsltFuncResult.java b/src/org/apache/xalan/processor/ProcessorExsltFuncResult.java new file mode 100644 index 0000000..81a6e25 --- /dev/null +++ b/src/org/apache/xalan/processor/ProcessorExsltFuncResult.java
@@ -0,0 +1,116 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.processor; + +import org.apache.xalan.templates.ElemTemplateElement; +import org.apache.xalan.templates.ElemExsltFunction; +import org.apache.xalan.templates.ElemExsltFuncResult; +import org.apache.xalan.templates.ElemVariable; +import org.apache.xalan.templates.ElemParam; +import org.apache.xalan.templates.ElemFallback; +import org.apache.xalan.res.XSLTErrorResources; + +import javax.xml.transform.TransformerException; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.lang.NoSuchMethodException; +import java.lang.InstantiationException; +import java.lang.IllegalAccessException; + +import java.util.Vector; + +/** + * <meta name="usage" content="internal"/> + * This class processes parse events for an exslt func:result element. + */ +public class ProcessorExsltFuncResult extends ProcessorTemplateElem +{ + + /** + * Verify that the func:result element does not appear within a variable, + * parameter, or another func:result, and that it belongs to a func:function + * element. + */ + public void startElement( + StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) + throws SAXException + { + String msg = ""; + + super.startElement(handler, uri, localName, rawName, attributes); + ElemTemplateElement ancestor = handler.getElemTemplateElement().getParentElem(); + while (ancestor != null && !(ancestor instanceof ElemExsltFunction)) + { + if (ancestor instanceof ElemVariable + || ancestor instanceof ElemParam + || ancestor instanceof ElemExsltFuncResult) + { + msg = "func:result cannot appear within a variable, parameter, or another func:result."; + handler.error(msg, new SAXException(msg)); + } + ancestor = ancestor.getParentElem(); + } + if (ancestor == null) + { + msg = "func:result must appear in a func:function element"; + handler.error(msg, new SAXException(msg)); + } + } +} \ No newline at end of file
diff --git a/src/org/apache/xalan/processor/ProcessorExsltFunction.java b/src/org/apache/xalan/processor/ProcessorExsltFunction.java new file mode 100644 index 0000000..80512eb --- /dev/null +++ b/src/org/apache/xalan/processor/ProcessorExsltFunction.java
@@ -0,0 +1,212 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.processor; + +import org.apache.xalan.templates.ElemLiteralResult; +import org.apache.xalan.templates.ElemElement; +import org.apache.xalan.templates.ElemTemplateElement; +import org.apache.xalan.templates.Stylesheet; +import org.apache.xalan.templates.ElemExtensionCall; +import org.apache.xalan.templates.ElemTemplate; +import org.apache.xalan.templates.ElemExsltFunction; +import org.apache.xalan.templates.ElemExsltFuncResult; +import org.apache.xalan.templates.ElemFallback; +import org.apache.xalan.templates.ElemVariable; +import org.apache.xalan.templates.ElemParam; +import org.apache.xalan.templates.ElemValueOf; +import org.apache.xalan.templates.Constants; +import org.apache.xpath.XPath; +import org.apache.xalan.templates.StylesheetRoot; + +import javax.xml.transform.SourceLocator; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerConfigurationException; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.apache.xalan.res.XSLTErrorResources; + + +/** + * <meta name="usage" content="internal"/> + * This class processes parse events for an exslt func:function element. + */ +public class ProcessorExsltFunction extends ProcessorTemplateElem +{ + /** + * Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a + * namespace. + */ + public void startElement( + StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) + throws SAXException + { + //System.out.println("ProcessorFunction.startElement()"); + String msg = ""; + if (!(handler.getElemTemplateElement() instanceof StylesheetRoot)) + { + msg = "func:function element must be top level."; + handler.error(msg, new SAXException(msg)); + } + super.startElement(handler, uri, localName, rawName, attributes); + + String val = attributes.getValue("name"); + int indexOfColon = val.indexOf(":"); + if (indexOfColon > 0) + { + String prefix = val.substring(0, indexOfColon); + String localVal = val.substring(indexOfColon + 1); + String ns = handler.getNamespaceSupport().getURI(prefix); + //if (ns.length() > 0) + // System.out.println("fullfuncname " + ns + localVal); + } + else + { + msg = "func:function name must have namespace"; + handler.error(msg, new SAXException(msg)); + } + } + + /** + * Must include; super doesn't suffice! + */ + protected void appendAndPush( + StylesheetHandler handler, ElemTemplateElement elem) + throws SAXException + { + //System.out.println("ProcessorFunction appendAndPush()" + elem); + super.appendAndPush(handler, elem); + //System.out.println("originating node " + handler.getOriginatingNode()); + elem.setDOMBackPointer(handler.getOriginatingNode()); + handler.getStylesheet().setTemplate((ElemTemplate) elem); + } + + /** + * End an ElemExsltFunction, and verify its validity. + */ + public void endElement( + StylesheetHandler handler, String uri, String localName, String rawName) + throws SAXException + { + ElemTemplateElement function = handler.getElemTemplateElement(); + SourceLocator locator = handler.getLocator(); + validate(function, handler); // may throw exception + super.endElement(handler, uri, localName, rawName); + } + + /** + * Non-recursive traversal of FunctionElement tree based on TreeWalker to verify that + * there are no literal result elements except within a func:result element and that + * the func:result element does not contain any following siblings except xsl:fallback. + */ + public void validate(ElemTemplateElement elem, StylesheetHandler handler) + throws SAXException + { + String msg = ""; + while (elem != null) + { + //System.out.println("elem " + elem); + if (elem instanceof ElemExsltFuncResult + && elem.getNextSiblingElem() != null + && !(elem.getNextSiblingElem() instanceof ElemFallback)) + { + msg = "func:result has an illegal following sibling (only xsl:fallback allowed)"; + handler.error(msg, new SAXException(msg)); + } + if (elem instanceof ElemValueOf || + (elem instanceof ElemLiteralResult || elem instanceof ElemElement) + && !(ancestorIsOk(elem))) + { + msg ="misplaced literal result in a func:function container."; + handler.error(msg, new SAXException(msg)); + } + ElemTemplateElement nextElem = elem.getFirstChildElem(); + while (nextElem == null) + { + nextElem = elem.getNextSiblingElem(); + if (nextElem == null) + elem = elem.getParentElem(); + if (elem == null || elem instanceof ElemExsltFunction) + return; // ok + } + elem = nextElem; + } + } + + /** + * Verify that a literal result belongs to a result element, a variable, + * or a parameter. + */ + + boolean ancestorIsOk(ElemTemplateElement child) + { + while (child.getParentElem() != null && !(child.getParentElem() instanceof ElemExsltFunction)) + { + ElemTemplateElement parent = child.getParentElem(); + if (parent instanceof ElemExsltFuncResult + || parent instanceof ElemVariable + || parent instanceof ElemParam) + return true; + child = parent; + } + return false; + } + +} \ No newline at end of file
diff --git a/src/org/apache/xalan/processor/StylesheetHandler.java b/src/org/apache/xalan/processor/StylesheetHandler.java index d360b78..bc1f308 100644 --- a/src/org/apache/xalan/processor/StylesheetHandler.java +++ b/src/org/apache/xalan/processor/StylesheetHandler.java
@@ -85,6 +85,8 @@ import org.apache.xpath.XPathFactory; import org.apache.xpath.XPath; +import org.apache.xpath.functions.FuncExtFunction; +import org.apache.xalan.extensions.ExpressionVisitor; import org.w3c.dom.Node; import org.xml.sax.Attributes; @@ -194,7 +196,10 @@ throws javax.xml.transform.TransformerException { ErrorListener handler = m_stylesheetProcessor.getErrorListener(); - return new XPath(str, owningTemplate, this, XPath.SELECT, handler); + XPath xpath = new XPath(str, owningTemplate, this, XPath.SELECT, handler); + // Visit the expression, registering namespaces for any extension functions it includes. + xpath.callVisitors(xpath, new ExpressionVisitor(getStylesheetRoot())); + return xpath; } /**
diff --git a/src/org/apache/xalan/processor/XSLTSchema.java b/src/org/apache/xalan/processor/XSLTSchema.java index 182a206..3bb8f8f 100644 --- a/src/org/apache/xalan/processor/XSLTSchema.java +++ b/src/org/apache/xalan/processor/XSLTSchema.java
@@ -267,9 +267,12 @@ XSLTAttributeDef xslResultAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "*", XSLTAttributeDef.T_CDATA, false); - XSLTElementDef[] templateElements = new XSLTElementDef[21]; - XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[22]; - XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[22]; + XSLTElementDef[] templateElements = new XSLTElementDef[22]; + XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[23]; + XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[23]; + //exslt + XSLTElementDef[] exsltFunctionElements = new XSLTElementDef[23]; + XSLTElementDef[] charTemplateElements = new XSLTElementDef[15]; XSLTElementDef resultElement = new XSLTElementDef(this, null, "*", null /*alias */, @@ -293,8 +296,8 @@ xslVersionAttr, xslResultAttr, resultAttr }, - new ProcessorUnknown(), - ElemUnknown.class /* class object */, 20, true); + new ProcessorUnknown(), + ElemUnknown.class /* class object */, 20, true); XSLTElementDef xslValueOf = new XSLTElementDef(this, Constants.S_XSLNAMESPACEURL, "value-of", null /*alias */, null /* elements */, @@ -485,8 +488,27 @@ new XSLTAttributeDef[]{ spaceAttr }, new ProcessorTemplateElem(), ElemFallback.class /* class object */, 20, true); + //exslt + XSLTElementDef exsltFunction = + new XSLTElementDef(this, + Constants.S_EXSLT_FUNCTIONS_URL, + "function", + null /*alias */, + exsltFunctionElements /* elements */, + new XSLTAttributeDef[]{ nameAttrRequired }, + new ProcessorExsltFunction(), + ElemExsltFunction.class /* class object */); + XSLTElementDef exsltResult = + new XSLTElementDef(this, + Constants.S_EXSLT_FUNCTIONS_URL, + "result", + null /*alias */, + templateElements /* elements */, + new XSLTAttributeDef[]{ selectAttrOpt }, + new ProcessorExsltFuncResult(), + ElemExsltFuncResult.class /* class object */); + int i = 0; - templateElements[i++] = charData; // #PCDATA // char-instructions @@ -512,22 +534,20 @@ templateElements[i++] = xslAttribute; templateElements[i++] = resultElement; templateElements[i++] = unknownElement; + templateElements[i++] = exsltResult; int k; for (k = 0; k < i; k++) { templateElementsAndParams[k] = templateElements[k]; - } - - templateElementsAndParams[k] = xslParam; - - for (k = 0; k < i; k++) - { templateElementsAndSort[k] = templateElements[k]; + exsltFunctionElements[k] = templateElements[k]; } - + templateElementsAndParams[k] = xslParam; templateElementsAndSort[k] = xslSort; + exsltFunctionElements[k] = xslParam; + i = 0; charTemplateElements[i++] = charData; // #PCDATA @@ -561,156 +581,172 @@ new ProcessorInclude(), null /* class object */, 20, true); - XSLTElementDef[] topLevelElements = new XSLTElementDef[]{ includeDef, - importDef, - // resultElement, - whiteSpaceOnly, - unknownElement, - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "strip-space", - null /*alias */, - null /* elements */, - new XSLTAttributeDef[]{ - elementsAttr }, - new ProcessorStripSpace(), - null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "preserve-space", - null /*alias */, - null /* elements */, - new XSLTAttributeDef[]{ - elementsAttr }, - new ProcessorPreserveSpace(), - null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "output", - null /*alias */, - null /* elements */, - new XSLTAttributeDef[]{ - methodAttr, - versionAttr, - encodingAttr, - omitXmlDeclarationAttr, - standaloneAttr, - doctypePublicAttr, - doctypeSystemAttr, - cdataSectionElementsAttr, - indentAttr, - mediaTypeAttr, - XSLTAttributeDef.m_foreignAttr }, - new ProcessorOutputElem(), null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "key", - null /*alias */, - null /* elements */, // EMPTY - new XSLTAttributeDef[]{ nameAttrRequired, - matchAttrRequired, - useAttr }, - new ProcessorKey(), null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "decimal-format", - null /*alias */, - null /* elements */, // EMPTY - new XSLTAttributeDef[]{ - nameAttrOpt, - decimalSeparatorAttr, - groupingSeparatorAttr, - infinityAttr, - minusSignAttr, - NaNAttr, - percentAttr, - perMilleAttr, - zeroDigitAttr, - digitAttr, - patternSeparatorAttr }, - new ProcessorDecimalFormat(), - null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "attribute-set", - null /*alias */, - new XSLTElementDef[]{ - xslAttribute } /* elements */, - new XSLTAttributeDef[]{ - nameAttrRequired, - useAttributeSetsAttr }, new ProcessorAttributeSet(), - null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "variable", - null /*alias */, - templateElements /* elements */, - new XSLTAttributeDef[]{ - nameAttrRequired, - selectAttrOpt }, new ProcessorGlobalVariableDecl(), - ElemVariable.class /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "param", - null /*alias */, - templateElements /* elements */, - new XSLTAttributeDef[]{ - nameAttrRequired, - selectAttrOpt }, new ProcessorGlobalParamDecl(), - ElemParam.class /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "template", - null /*alias */, - templateElementsAndParams /* elements */, - new XSLTAttributeDef[]{ - matchAttrOpt, - nameAttrOpt, - priorityAttr, - modeAttr, - spaceAttr }, new ProcessorTemplate(), ElemTemplate.class /* class object */, true, 20, true), - new XSLTElementDef( - this, - Constants.S_XSLNAMESPACEURL, - "namespace-alias", - null /*alias */, - null /* elements */, // EMPTY - new XSLTAttributeDef[]{ stylesheetPrefixAttr, - resultPrefixAttr }, - new ProcessorNamespaceAlias(), null /* class object */, 20, true), - new XSLTElementDef( - this, - Constants.S_BUILTIN_EXTENSIONS_URL, - "component", - null /*alias */, - new XSLTElementDef[]{ - new XSLTElementDef( - this, - Constants.S_BUILTIN_EXTENSIONS_URL, - "script", - null /*alias */, - new XSLTElementDef[]{ charData } /* elements */, - new XSLTAttributeDef[]{ - new XSLTAttributeDef( - null, - "lang", - XSLTAttributeDef.T_NMTOKEN, - true), - new XSLTAttributeDef(null, "src", XSLTAttributeDef.T_URL, false) }, - new ProcessorLRE(), - ElemExtensionScript.class /* class object */, 20, true) }, // EMPTY - new XSLTAttributeDef[]{ new XSLTAttributeDef(null, "prefix", XSLTAttributeDef.T_NMTOKEN, true), - new XSLTAttributeDef(null, "elements", XSLTAttributeDef.T_STRINGLIST, false), - new XSLTAttributeDef(null, "functions", XSLTAttributeDef.T_STRINGLIST, false) }, new ProcessorLRE(), ElemExtensionDecl.class /* class object */) }; + + XSLTElementDef[] topLevelElements = new XSLTElementDef[] + {includeDef, + importDef, + // resultElement, + whiteSpaceOnly, + unknownElement, + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "strip-space", + null /*alias */, + null /* elements */, + new XSLTAttributeDef[]{ + elementsAttr }, + new ProcessorStripSpace(), + null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "preserve-space", + null /*alias */, + null /* elements */, + new XSLTAttributeDef[]{ + elementsAttr }, + new ProcessorPreserveSpace(), + null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "output", + null /*alias */, + null /* elements */, + new XSLTAttributeDef[]{ + methodAttr, + versionAttr, + encodingAttr, + omitXmlDeclarationAttr, + standaloneAttr, + doctypePublicAttr, + doctypeSystemAttr, + cdataSectionElementsAttr, + indentAttr, + mediaTypeAttr, + XSLTAttributeDef.m_foreignAttr }, + new ProcessorOutputElem(), null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "key", + null /*alias */, + null /* elements */, // EMPTY + new XSLTAttributeDef[]{ nameAttrRequired, + matchAttrRequired, + useAttr }, + new ProcessorKey(), null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "decimal-format", + null /*alias */, + null /* elements */, // EMPTY + new XSLTAttributeDef[]{ + nameAttrOpt, + decimalSeparatorAttr, + groupingSeparatorAttr, + infinityAttr, + minusSignAttr, + NaNAttr, + percentAttr, + perMilleAttr, + zeroDigitAttr, + digitAttr, + patternSeparatorAttr }, + new ProcessorDecimalFormat(), + null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "attribute-set", + null /*alias */, + new XSLTElementDef[]{ + xslAttribute } /* elements */, + new XSLTAttributeDef[]{ + nameAttrRequired, + useAttributeSetsAttr }, + new ProcessorAttributeSet(), + null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "variable", + null /*alias */, + templateElements /* elements */, + new XSLTAttributeDef[]{ + nameAttrRequired, + selectAttrOpt }, + new ProcessorGlobalVariableDecl(), + ElemVariable.class /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "param", + null /*alias */, + templateElements /* elements */, + new XSLTAttributeDef[]{ + nameAttrRequired, + selectAttrOpt }, + new ProcessorGlobalParamDecl(), + ElemParam.class /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "template", + null /*alias */, + templateElementsAndParams /* elements */, + new XSLTAttributeDef[]{ + matchAttrOpt, + nameAttrOpt, + priorityAttr, + modeAttr, + spaceAttr }, + new ProcessorTemplate(), ElemTemplate.class /* class object */, true, 20, true), + new XSLTElementDef( + this, + Constants.S_XSLNAMESPACEURL, + "namespace-alias", + null /*alias */, + null /* elements */, // EMPTY + new XSLTAttributeDef[]{ + stylesheetPrefixAttr, + resultPrefixAttr }, + new ProcessorNamespaceAlias(), null /* class object */, 20, true), + new XSLTElementDef( + this, + Constants.S_BUILTIN_EXTENSIONS_URL, + "component", + null /*alias */, + new XSLTElementDef[]{ + new XSLTElementDef( + this, + Constants.S_BUILTIN_EXTENSIONS_URL, + "script", + null /*alias */, + new XSLTElementDef[]{ + charData } /* elements */, + new XSLTAttributeDef[]{ + new XSLTAttributeDef( + null, + "lang", + XSLTAttributeDef.T_NMTOKEN, + true), + new XSLTAttributeDef( + null, "src", XSLTAttributeDef.T_URL, false) }, + new ProcessorLRE(), + ElemExtensionScript.class /* class object */, 20, true) }, // EMPTY + new XSLTAttributeDef[]{ + new XSLTAttributeDef( + null, "prefix", XSLTAttributeDef.T_NMTOKEN, true), + new XSLTAttributeDef( + null, "elements", XSLTAttributeDef.T_STRINGLIST, false), + new XSLTAttributeDef( + null, "functions", XSLTAttributeDef.T_STRINGLIST, false) }, + new ProcessorLRE(), ElemExtensionDecl.class /* class object */), + exsltFunction}/* exslt */; //end of topevelElements + XSLTAttributeDef excludeResultPrefixesAttr = new XSLTAttributeDef(null, "exclude-result-prefixes", XSLTAttributeDef.T_STRINGLIST, false);
diff --git a/src/org/apache/xalan/templates/Constants.java b/src/org/apache/xalan/templates/Constants.java index d144fa7..fc567e7 100644 --- a/src/org/apache/xalan/templates/Constants.java +++ b/src/org/apache/xalan/templates/Constants.java
@@ -110,6 +110,25 @@ S_BUILTIN_EXTENSIONS_URL = "http://xml.apache.org/xslt"; /** + * Xalan extension namespaces. + */ + public static final String + S_EXTENSIONS_JAVA_URL = "http://xml.apache.org/xslt/java", + S_EXTENSIONS_LOTUSXSL_JAVA_URL = "http://xsl.lotus.com/java", + S_EXTENSIONS_XALANLIB_URL = "http://xml.apache.org/xalan"; + + /** + * EXSLT extension namespaces. + */ + public static final String + S_EXSLT_COMMON_URL = "http://exslt.org/common", + S_EXSLT_MATH_URL = "http://exslt.org/math", + S_EXSLT_SETS_URL = "http://exslt.org/sets", + S_EXSLT_DATETIME_URL = "http://exslt.org/dates-and-times", + S_EXSLT_FUNCTIONS_URL = "http://exslt.org/functions"; + + + /** * The minimum version of XSLT supported by this processor. */ public static final double XSLTVERSUPPORTED = 1.0; @@ -177,7 +196,7 @@ ELEMNAME_EXTENSIONSCRIPT = 86, ELEMNAME_OUTPUT = 80, ELEMNAME_COMPONENT = 81, ELEMNAME_SCRIPT = 82; - // Next free number: 87 + // Next free number: 90 (88 and 89 used for EXSLT elements); /** * Literals for XSL element names. Note that there are more @@ -253,6 +272,17 @@ ELEMNAME_WITHPARAM_STRING = "with-param"; /** + * Literals for EXSLT function elements. + */ + public static final String + EXSLT_ELEMNAME_FUNCTION_STRING = "function", + EXSLT_ELEMNAME_FUNCRESULT_STRING = "result"; + public static final int + EXSLT_ELEMNAME_FUNCTION = 88, + EXSLT_ELEMNAME_FUNCRESULT = 89; + + + /** * Literals for XSL attribute names. Note that there may be more * names than IDs, because some names may map to the same ID. */
diff --git a/src/org/apache/xalan/templates/ElemExsltFuncResult.java b/src/org/apache/xalan/templates/ElemExsltFuncResult.java new file mode 100644 index 0000000..b94c2f5 --- /dev/null +++ b/src/org/apache/xalan/templates/ElemExsltFuncResult.java
@@ -0,0 +1,93 @@ +package org.apache.xalan.templates; + +//import org.w3c.dom.*; +import org.apache.xml.dtm.DTM; + +import org.xml.sax.*; + +import org.apache.xpath.*; +import org.apache.xpath.Expression; +import org.apache.xpath.objects.XObjectFactory; +import org.apache.xpath.objects.XObject; +import org.apache.xpath.objects.XString; +import org.apache.xpath.objects.XRTreeFrag; +import org.apache.xpath.objects.XRTreeFragSelectWrapper; +import org.apache.xml.utils.QName; +import org.apache.xalan.trace.SelectionEvent; +import org.apache.xalan.res.XSLTErrorResources; +import org.apache.xalan.transformer.TransformerImpl; + +import javax.xml.transform.TransformerException; + +/** + * Handles the EXSLT result element within an EXSLT function element. + */ +public class ElemExsltFuncResult extends ElemVariable +{ + + /** + * Generate the EXSLT function return value, and assign it to the variable + * index slot assigned for it in ElemExsltFunction compose(). + * + */ + public void execute(TransformerImpl transformer) throws TransformerException + { + XPathContext context = transformer.getXPathContext(); + VariableStack varStack = context.getVarStack(); + // ElemExsltFunc result should always be within an ElemExsltFunction. + ElemExsltFunction owner = getOwnerFunction(); + if (owner != null) + { + int resultIndex = owner.getResultIndex(); + // Verify that result has not already been set by another result + // element. Recursion is allowed: intermediate results are cleared + // in the owner ElemExsltFunction execute(). + if (varStack.isLocalSet(resultIndex)) + throw new TransformerException + ("An EXSLT function cannot set more than one result!"); + int sourceNode = context.getCurrentNode(); + // Set the return value; + XObject var = getValue(transformer, sourceNode); + varStack.setLocalVariable(resultIndex, var); + } + } + + /** + * Get an integer representation of the element type. + * + * @return An integer representation of the element, defined in the + * Constants class. + * @see org.apache.xalan.templates.Constants + */ + public int getXSLToken() + { + return Constants.EXSLT_ELEMNAME_FUNCRESULT; + } + + /** + * Return the node name, defined in the + * Constants class. + * @see org.apache.xalan.templates.Constants. + * @return The node name + * + */ + public String getNodeName() + { + return Constants.EXSLT_ELEMNAME_FUNCRESULT_STRING; + } + + /** + * Get the ElemExsltFunction that contains the ElemResult so we can set an ElemExsltFunction variable + * to the local variable stack index to the return value. + */ + public ElemExsltFunction getOwnerFunction() + { + ElemTemplateElement elem = this; + while((elem != null) && !(elem instanceof ElemExsltFunction)) + { + elem = elem.getParentElem(); + } + return (ElemExsltFunction)elem; + } + +}
diff --git a/src/org/apache/xalan/templates/ElemExsltFunction.java b/src/org/apache/xalan/templates/ElemExsltFunction.java new file mode 100644 index 0000000..df1c33b --- /dev/null +++ b/src/org/apache/xalan/templates/ElemExsltFunction.java
@@ -0,0 +1,242 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xalan.templates; + +//import org.w3c.dom.*; +import org.apache.xml.dtm.DTM; + +import org.xml.sax.*; + +import org.apache.xpath.*; +import org.apache.xpath.Expression; +import org.apache.xpath.objects.XObject; +import org.apache.xpath.objects.XString; +import org.apache.xpath.objects.XNumber; +import org.apache.xpath.objects.XRTreeFrag; +import org.apache.xpath.objects.XRTreeFragSelectWrapper; +import org.apache.xml.utils.QName; +import org.apache.xalan.trace.SelectionEvent; +import org.apache.xalan.res.XSLTErrorResources; +import org.apache.xalan.transformer.TransformerImpl; + +import org.apache.xalan.extensions.ExtensionsTable; + +import javax.xml.transform.TransformerException; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.apache.xalan.extensions.ExtensionNamespaceSupport; +import org.apache.xalan.extensions.ExtensionHandlerExsltFunction; + + +/** + * <meta name="usage" content="advanced"/> + * Implement func:function. + */ +public class ElemExsltFunction extends ElemTemplate +{ + + /** + * Get an integer representation of the element type. + * + * @return An integer representation of the element, defined in the + * Constants class. + * @see org.apache.xalan.templates.Constants + */ + public int getXSLToken() + { + return Constants.EXSLT_ELEMNAME_FUNCTION; + } + + /** + * Return the node name, defined in the + * Constants class. + * @see org.apache.xalan.templates.Constants. + * @return The node name + * + */ + public String getNodeName() + { + return Constants.EXSLT_ELEMNAME_FUNCTION_STRING; + } + + public void execute(TransformerImpl transformer, XObject[] args) + throws TransformerException + { + XPathContext xctxt = transformer.getXPathContext(); + VariableStack vars = xctxt.getVarStack(); + + // Set parameters. + NodeList children = this.getChildNodes(); + int numparams =0; + for (int i = 0; i < args.length; i ++) + { + Node child = children.item(i); + if (children.item(i) instanceof ElemParam) + { + numparams++; + ElemParam param = (ElemParam)children.item(i); + vars.setLocalVariable (param.m_index, args[i]); + } + } + if (numparams < args.length) + throw new TransformerException ("function called with too many args"); + + // Removed ElemTemplate 'push' and 'pop' of RTFContext, in order to avoid losing the RTF context + // before a value can be returned. ElemExsltFunction operates in the scope of the template that called + // the function. + // xctxt.pushRTFContext(); + + if (TransformerImpl.S_DEBUG) + transformer.getTraceManager().fireTraceEvent(this); + + // Be sure the return value is not set (so can verify that only one result + // is generated per ElemExsltFunction execute). + vars.setLocalVariable(_resultIndex, null); + transformer.executeChildTemplates(this, true); + + if (TransformerImpl.S_DEBUG) + transformer.getTraceManager().fireTraceEndEvent(this); + + // Following ElemTemplate 'pop' removed -- see above. + // xctxt.popRTFContext(); + + } + //int m_inArgsSize; + //public int m_frameSize; + + /** + * Called after everything else has been + * recomposed, and allows the function to set remaining + * values that may be based on some other property that + * depends on recomposition. Also adds a slot to the variable + * stack for the return value. The result element will place + * its value in this slot. + */ + public void compose(StylesheetRoot sroot) throws TransformerException + { + super.compose(sroot); + StylesheetRoot.ComposeState cstate = sroot.getComposeState(); + // Add a position on the variable stack for the return value. + setResultIndex(cstate.addVariableName + (new QName(Constants.S_EXSLT_COMMON_URL, "result"))); + + // Register the function namespace (if not already registered). + String namespace = getName().getNamespace(); + String handlerClass = "org.apache.xalan.extensions.ExtensionHandlerExsltFunction"; + Object[] args ={namespace, sroot}; + ExtensionNamespaceSupport extNsSpt = + new ExtensionNamespaceSupport(namespace, handlerClass, args); + sroot.getExtensionNamespacesManager().registerExtension(extNsSpt); + // Make sure there is a handler for the EXSLT functions namespace + // -- for isElementAvailable(). + if (!(namespace.equals(Constants.S_EXSLT_FUNCTIONS_URL))) + { + namespace = Constants.S_EXSLT_FUNCTIONS_URL; + args = new Object[]{namespace, sroot}; + extNsSpt = new ExtensionNamespaceSupport(namespace, handlerClass, args); + sroot.getExtensionNamespacesManager().registerExtension(extNsSpt); + } + } + + /** + * Add the namespace to the StylesheetRoot vector of extension namespaces. Be sure the + * exslt:function namespace is also added. + */ +/* public void runtimeInit(TransformerImpl transformer) throws TransformerException + { + //System.out.println("ElemExsltFunction.runtimeInit()"); + String namespace = getName().getNamespace(); + ExtensionsTable etable = transformer.getExtensionsTable(); + StylesheetRoot sroot = transformer.getStylesheet(); + ExtensionHandlerExsltFunction exsltHandler = + new ExtensionHandlerExsltFunction(namespace, sroot); + //etable.addExtensionNamespace(namespace, exsltHandler); + // Make sure there is a handler for the EXSLT functions namespace + // -- for isElementAvailable(). + if (!(namespace.equals(Constants.S_EXSLT_FUNCTIONS_URL))) + { + exsltHandler = new ExtensionHandlerExsltFunction( + Constants.S_EXSLT_FUNCTIONS_URL, + sroot); + // etable.addExtensionNamespace(Constants.S_EXSLT_FUNCTIONS_URL, + // exsltHandler); + } + } +*/ + + private int _resultIndex; + + /** + * Sets aside a position on the local variable stack index + * to refer to the result element return value. + */ + void setResultIndex(int stackIndex) + { + _resultIndex = stackIndex; + } + + /** + * Provides the EXSLT extension handler access to the return value. + */ + public int getResultIndex() + { + return _resultIndex; + } + +} \ No newline at end of file
diff --git a/src/org/apache/xalan/templates/ElemExtensionCall.java b/src/org/apache/xalan/templates/ElemExtensionCall.java index 7a107a1..be38e82 100644 --- a/src/org/apache/xalan/templates/ElemExtensionCall.java +++ b/src/org/apache/xalan/templates/ElemExtensionCall.java
@@ -91,8 +91,6 @@ public class ElemExtensionCall extends ElemLiteralResult { - // ExtensionNSHandler nsh; - /** The Namespace URI for this extension call element. * @serial */ String m_extns; @@ -144,51 +142,15 @@ */ public void compose(StylesheetRoot sroot) throws TransformerException { - super.compose(sroot); - m_extns = this.getNamespace(); - - StylesheetRoot stylesheet = this.getStylesheetRoot(); - - m_decl = getElemExtensionDecl(stylesheet, m_extns); - - if (null != m_decl) - { - for (ElemTemplateElement child = m_decl.getFirstChildElem(); - child != null; child = child.getNextSiblingElem()) - { - if (Constants.ELEMNAME_EXTENSIONSCRIPT == child.getXSLToken()) - { - ElemExtensionScript sdecl = (ElemExtensionScript) child; - - m_lang = sdecl.getLang(); - m_srcURL = sdecl.getSrc(); - - ElemTemplateElement childOfSDecl = sdecl.getFirstChildElem(); - - if (null != childOfSDecl) - { - if (Constants.ELEMNAME_TEXTLITERALRESULT - == childOfSDecl.getXSLToken()) - { - ElemTextLiteral tl = (ElemTextLiteral) childOfSDecl; - char[] chars = tl.getChars(); - - m_scriptSrc = new String(chars); - } - } - - break; - } - } - } - else - { - - // stylesheet.error(xxx); - } + m_extns = this.getNamespace(); + m_decl = getElemExtensionDecl(sroot, m_extns); + // Register the extension namespace if the extension does not have + // an ElemExtensionDecl ("component"). + if (m_decl == null) + sroot.getExtensionNamespacesManager().registerExtension(m_extns); } - + /** * Return the ElemExtensionDecl for this extension element * @@ -281,25 +243,13 @@ { transformer.getResultTreeHandler().flushPending(); - XPathContext liaison = ((XPathContext) transformer.getXPathContext()); - ExtensionsTable etable = liaison.getExtensionsTable(); + ExtensionsTable etable = transformer.getExtensionsTable(); ExtensionHandler nsh = etable.get(m_extns); - // We're seeing this extension namespace used for the first time. Try to - // autodeclare it as a java namespace. - if (null == nsh) { - nsh = etable.makeJavaNamespace(m_extns); - - if(null != nsh) - etable.addExtensionNamespace(m_extns, nsh); - else - { - executeFallbacks(transformer); - return; - } - + executeFallbacks(transformer); + return; } try
diff --git a/src/org/apache/xalan/templates/ElemExtensionDecl.java b/src/org/apache/xalan/templates/ElemExtensionDecl.java index c59963e..7dd2615 100644 --- a/src/org/apache/xalan/templates/ElemExtensionDecl.java +++ b/src/org/apache/xalan/templates/ElemExtensionDecl.java
@@ -73,6 +73,10 @@ import org.apache.xalan.res.XSLTErrorResources; import org.apache.xalan.res.XSLMessages; +// dml +import org.apache.xalan.extensions.ExtensionNamespacesManager; +import org.apache.xalan.extensions.ExtensionNamespaceSupport; + /** * <meta name="usage" content="internal"/> * Implement the declaration of an extension element @@ -106,7 +110,7 @@ } /** - * Set the prefix for this extension element + * Get the prefix for this extension element * * * @return Prefix for this extension element @@ -238,7 +242,78 @@ { return Constants.ELEMNAME_EXTENSIONDECL; } + + public void compose(StylesheetRoot sroot) throws TransformerException + { + super.compose(sroot); + String prefix = getPrefix(); + String declNamespace = getNamespaceForPrefix(prefix); + String lang = null; + String srcURL = null; + String scriptSrc = null; + if (null == declNamespace) + throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[]{prefix})); + //"Prefix " + prefix does not have a corresponding namespace declaration"); + for (ElemTemplateElement child = getFirstChildElem(); child != null; + child = child.getNextSiblingElem()) + { + if (Constants.ELEMNAME_EXTENSIONSCRIPT == child.getXSLToken()) + { + ElemExtensionScript sdecl = (ElemExtensionScript) child; + lang = sdecl.getLang(); + srcURL = sdecl.getSrc(); + ElemTemplateElement childOfSDecl = sdecl.getFirstChildElem(); + if (null != childOfSDecl) + { + if (Constants.ELEMNAME_TEXTLITERALRESULT + == childOfSDecl.getXSLToken()) + { + ElemTextLiteral tl = (ElemTextLiteral) childOfSDecl; + char[] chars = tl.getChars(); + scriptSrc = new String(chars); + if (scriptSrc.trim().length() == 0) + scriptSrc = null; + } + } + } + } + if (null == lang) + lang = "javaclass"; + if (lang.equals("javaclass") && (scriptSrc != null)) + throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[]{scriptSrc})); + //"Element content not allowed for lang=javaclass " + scriptSrc); + // Register the extension namespace if it has not already been registered. + ExtensionNamespaceSupport extNsSpt = null; + ExtensionNamespacesManager extNsMgr = sroot.getExtensionNamespacesManager(); + if (extNsMgr.namespaceIndex(declNamespace, + extNsMgr.getExtensions()) == -1) + { + if (lang.equals("javaclass")) + { + if (null == srcURL) + { + extNsSpt = extNsMgr.defineJavaNamespace(declNamespace); + } + else if (extNsMgr.namespaceIndex(srcURL, + extNsMgr.getExtensions()) == -1) + { + extNsSpt = extNsMgr.defineJavaNamespace(declNamespace, srcURL); + } + } + else // not java + { + String handler = "org.apache.xalan.extensions.ExtensionHandlerGeneral"; + Object [] args = {declNamespace, this.m_elements, this.m_functions, + lang, srcURL, scriptSrc, getSystemId()}; + extNsSpt = new ExtensionNamespaceSupport(declNamespace, handler, args); + } + } + if (extNsSpt != null) + extNsMgr.registerExtension(extNsSpt); + } + + /** * This function will be called on top-level elements * only, just before the transform begins. @@ -246,10 +321,10 @@ * @param transformer The XSLT TransformerFactory. * * @throws TransformerException - */ + */ public void runtimeInit(TransformerImpl transformer) throws TransformerException { - +/* //System.out.println("ElemExtensionDecl.runtimeInit()"); String lang = null; String srcURL = null; String scriptSrc = null; @@ -257,9 +332,8 @@ String declNamespace = getNamespaceForPrefix(prefix); if (null == declNamespace) - throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[]{prefix})); //"Prefix " + prefix - //+ " does not have a corresponding " - //+ "namespace declaration"); + throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[]{prefix})); + //"Prefix " + prefix does not have a corresponding namespace declaration"); for (ElemTemplateElement child = getFirstChildElem(); child != null; child = child.getNextSiblingElem()) @@ -294,11 +368,11 @@ lang = "javaclass"; if (lang.equals("javaclass") && (scriptSrc != null)) - throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[]{scriptSrc})); //"Element content not allowed for lang=javaclass " - //+ scriptSrc); - - XPathContext liaison = ((XPathContext) transformer.getXPathContext()); - ExtensionsTable etable = liaison.getExtensionsTable(); + throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[]{scriptSrc})); + //"Element content not allowed for lang=javaclass " + scriptSrc); + + // Instantiate a handler for this extension namespace. + ExtensionsTable etable = transformer.getExtensionsTable(); ExtensionHandler nsh = etable.get(declNamespace); // If we have no prior ExtensionHandler for this namespace, we need to @@ -337,6 +411,6 @@ } etable.addExtensionNamespace(declNamespace, nsh); - } + }*/ } }
diff --git a/src/org/apache/xalan/templates/StylesheetRoot.java b/src/org/apache/xalan/templates/StylesheetRoot.java index db43f1b..612ccba 100644 --- a/src/org/apache/xalan/templates/StylesheetRoot.java +++ b/src/org/apache/xalan/templates/StylesheetRoot.java
@@ -89,6 +89,11 @@ import javax.xml.transform.ErrorListener; import org.apache.xml.dtm.ref.ExpandedNameTable; +//dml +import org.apache.xml.utils.StringVector; +import org.apache.xalan.extensions.ExtensionNamespaceSupport; +import org.apache.xalan.extensions.ExtensionHandler; +import org.apache.xalan.extensions.ExtensionNamespacesManager; /** * <meta name="usage" content="general"/> @@ -126,7 +131,7 @@ * @serial */ private Hashtable m_availElems; - + /** * Creates a StylesheetRoot and retains a pointer to the schema used to create this * StylesheetRoot. The schema may be needed later for an element-available() function call. @@ -139,7 +144,6 @@ this(listener); m_availElems = schema.getElemsAvailable(); - } /** @@ -162,6 +166,39 @@ { return m_availElems; } + + private ExtensionNamespacesManager m_extNsMgr = null; + + /** + * Only instantiate an ExtensionNamespacesManager if one is called for + * (i.e., if the stylesheet contains extension functions and/or elements). + */ + public ExtensionNamespacesManager getExtensionNamespacesManager() + { + if (m_extNsMgr == null) + m_extNsMgr = new ExtensionNamespacesManager(); + return m_extNsMgr; + } + + /** + * Get the vector of extension namespaces. Used to provide + * the extensions table access to a list of extension + * namespaces encountered during composition of a stylesheet. + */ + public Vector getExtensions() + { + return m_extNsMgr != null ? m_extNsMgr.getExtensions() : null; + } + +/* + public void runtimeInit(TransformerImpl transformer) throws TransformerException + { + System.out.println("StylesheetRoot.runtimeInit()"); + + // try{throw new Exception("StylesheetRoot.runtimeInit()");} catch(Exception e){e.printStackTrace();} + + } +*/ //============== Templates Interface ================ @@ -243,12 +280,8 @@ // Calculate the number of this import. m_globalImportList[j--].recomposeImports(); } - } - - - + } // Next, we walk the import tree and add all of the recomposable elements to the vector. - int n = getGlobalImportCount(); for (int i = 0; i < n; i++) @@ -303,7 +336,10 @@ composeTemplates(included); } } - + // Attempt to register any remaining unregistered extension namespaces. + if (m_extNsMgr != null) + m_extNsMgr.registerUnregisteredNamespaces(); + clearComposeState(); }
diff --git a/src/org/apache/xalan/transformer/TransformerImpl.java b/src/org/apache/xalan/transformer/TransformerImpl.java index 71f8ac1..2564007 100644 --- a/src/org/apache/xalan/transformer/TransformerImpl.java +++ b/src/org/apache/xalan/transformer/TransformerImpl.java
@@ -130,6 +130,10 @@ import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; +//dml +import org.apache.xpath.ExtensionsProvider; +import org.apache.xalan.extensions.ExtensionsTable; + /** * <meta name="usage" content="advanced"/> * This class implements the @@ -137,7 +141,7 @@ * representation of the transformation execution.</p> */ public class TransformerImpl extends Transformer - implements Runnable, DTMWSFilter + implements Runnable, DTMWSFilter, ExtensionsProvider { // Synch object to gaurd against setting values from the TrAX interface @@ -382,7 +386,7 @@ private Stack m_modes = new Stack(); //========================================================== - // SECTION: Constructors + // SECTION: Constructor //========================================================== /** @@ -391,12 +395,73 @@ * @param stylesheet The root of the stylesheet tree. */ public TransformerImpl(StylesheetRoot stylesheet) + // throws javax.xml.transform.TransformerException { - setStylesheet(stylesheet); setXPathContext(new XPathContext(this)); getXPathContext().setNamespaceContext(stylesheet); } + + // ================ ExtensionsTable =================== + + /** + * The table of ExtensionHandlers. + */ + private ExtensionsTable m_extensionsTable = null; + + /** + * Get the extensions table object. + * + * @return The extensions table. + */ + public ExtensionsTable getExtensionsTable() + { + return m_extensionsTable; + } + + /** + * If the stylesheet contains extensions, set the extensions table object. + * + * + * @param sroot The stylesheet. + * @throws javax.xml.transform.TransformerException + */ + void setExtensionsTable(StylesheetRoot sroot) + throws javax.xml.transform.TransformerException + { + try + { + if (sroot.getExtensions() != null) + m_extensionsTable = new ExtensionsTable(sroot); + } + catch (javax.xml.transform.TransformerException te) + {te.printStackTrace();} + } + + //== Implementation of the XPath ExtensionsProvider interface. + + public boolean functionAvailable(String ns, String funcName) + throws javax.xml.transform.TransformerException + { + return getExtensionsTable().functionAvailable(ns, funcName); + } + + public boolean elementAvailable(String ns, String elemName) + throws javax.xml.transform.TransformerException + { + return getExtensionsTable().elementAvailable(ns, elemName); + } + + public Object extFunction(String ns, String funcName, + Vector argVec, Object methodKey) + throws javax.xml.transform.TransformerException + {//System.out.println("TransImpl.extFunction() " + ns + " " + funcName +" " + getExtensionsTable()); + return getExtensionsTable().extFunction(ns, funcName, + argVec, methodKey, + getXPathContext().getExpressionContext()); + } + + //========================= /** * Reset the state. This needs to be called after a process() call @@ -1068,6 +1133,7 @@ public void transformNode(int node, Result outputTarget) throws TransformerException { + ContentHandler handler = createResultContentHandler(outputTarget); @@ -1089,7 +1155,8 @@ */ public void transformNode(int node) throws TransformerException { - + //dml + setExtensionsTable(getStylesheet()); // Make sure we're not writing to the same output content handler. synchronized (m_outputContentHandler) { @@ -1126,8 +1193,7 @@ } } } - - // =========== + // =========== // System.out.println("Calling applyTemplateToNode - "+Thread.currentThread().getName()); DTMIterator dtmIter = new org.apache.xpath.axes.SelfIteratorNoPredicate(); dtmIter.setRoot(node, xctxt); @@ -1589,7 +1655,7 @@ * <p>If we encounter a variable * that is already defined in the variable stack, we ignore it. This * is because the second variable definition will be at a lower import - * precedence. Presumably, global variables at the same import precedence + * precedence. Presumably, global"variables at the same import precedence * with the same name will have been caught during the recompose process. * <p>However, if we encounter a parameter that is already defined in the * variable stack, we need to see if this is a parameter whose value was
diff --git a/src/org/apache/xpath/ExtensionsProvider.java b/src/org/apache/xpath/ExtensionsProvider.java new file mode 100644 index 0000000..87a0fd7 --- /dev/null +++ b/src/org/apache/xpath/ExtensionsProvider.java
@@ -0,0 +1,87 @@ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999 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 "Xalan" and "Apache Software Foundation" 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", + * 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 and was + * originally based on software copyright (c) 1999, Lotus + * Development Corporation., http://www.lotus.com. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.apache.xpath; + +import java.util.Vector; + +/** + * Interface that XPath objects can call to obtain access to an + * ExtensionsTable. + * + */ +public interface ExtensionsProvider +{ + /** + * Is the extension function available? + */ + + public boolean functionAvailable(String ns, String funcName) + throws javax.xml.transform.TransformerException; + + /** + * Is the extension element available? + */ + public boolean elementAvailable(String ns, String elemName) + throws javax.xml.transform.TransformerException; + + /** + * Execute the extension function. + */ + public Object extFunction(String ns, String funcName, + Vector argVec, Object methodKey) + throws javax.xml.transform.TransformerException; +}
diff --git a/src/org/apache/xpath/XPathContext.java b/src/org/apache/xpath/XPathContext.java index d6070e3..62958e6 100644 --- a/src/org/apache/xpath/XPathContext.java +++ b/src/org/apache/xpath/XPathContext.java
@@ -92,9 +92,6 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.dom.DOMSource; -// Temporary!!! -import org.apache.xalan.extensions.ExtensionsTable; - import javax.xml.transform.SourceLocator; import javax.xml.transform.Source; import javax.xml.transform.ErrorListener; @@ -464,34 +461,6 @@ return m_owner; } - // ================ extensionsTable =================== - - /** - * The table of Extension Handlers. - */ - private ExtensionsTable m_extensionsTable = new ExtensionsTable(); - - /** - * Get the extensions table object. - * - * @return The extensions table. - */ - public ExtensionsTable getExtensionsTable() - { - return m_extensionsTable; - } - - /** - * Set the extensions table object. - * - * - * @param table The extensions table object. - */ - void setExtensionsTable(ExtensionsTable table) - { - m_extensionsTable = table; - } - // ================ VarStack =================== /**
diff --git a/src/org/apache/xpath/functions/FuncExtElementAvailable.java b/src/org/apache/xpath/functions/FuncExtElementAvailable.java index a46dd63..ecc09f1 100644 --- a/src/org/apache/xpath/functions/FuncExtElementAvailable.java +++ b/src/org/apache/xpath/functions/FuncExtElementAvailable.java
@@ -68,6 +68,7 @@ import org.apache.xpath.XPathContext; import org.apache.xpath.XPath; +import org.apache.xpath.ExtensionsProvider; import org.apache.xpath.objects.XObject; import org.apache.xpath.objects.XBoolean; @@ -128,9 +129,9 @@ } else { - ExtensionsTable etable = xctxt.getExtensionsTable(); - - return etable.elementAvailable(namespace, methName) + //dml + ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject(); + return extProvider.elementAvailable(namespace, methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE; } }
diff --git a/src/org/apache/xpath/functions/FuncExtFunction.java b/src/org/apache/xpath/functions/FuncExtFunction.java index 28826b4..5fe1676 100644 --- a/src/org/apache/xpath/functions/FuncExtFunction.java +++ b/src/org/apache/xpath/functions/FuncExtFunction.java
@@ -60,7 +60,9 @@ import org.apache.xpath.Expression; import org.apache.xpath.XPathContext; +import org.apache.xpath.ExtensionsProvider; import org.apache.xpath.objects.*; +import org.apache.xalan.transformer.TransformerImpl; import org.apache.xalan.extensions.ExtensionsTable; import org.apache.xml.dtm.DTMIterator; @@ -133,6 +135,15 @@ } } } + //called by StylesheetHandler.createXPath() -- dml + public String getNamespace() + { + return m_namespace; + } + public String getFunctionName() + { + return m_extensionName; + } /** * Create a new FuncExtFunction based on the qualified name of the extension, @@ -148,7 +159,7 @@ public FuncExtFunction(java.lang.String namespace, java.lang.String extensionName, Object methodKey) { - + //try{throw new Exception("FuncExtFunction() " + namespace + " " + extensionName);} catch (Exception e){e.printStackTrace();} m_namespace = namespace; m_extensionName = extensionName; m_methodKey = methodKey; @@ -178,11 +189,10 @@ argVec.addElement(xobj); } - - ExtensionsTable etable = xctxt.getExtensionsTable(); - Object val = etable.extFunction(m_namespace, m_extensionName, argVec, - m_methodKey, - xctxt.getExpressionContext()); + //dml + ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject(); + Object val = extProvider.extFunction(m_namespace, m_extensionName, + argVec, m_methodKey); if (null != val) {
diff --git a/src/org/apache/xpath/functions/FuncExtFunctionAvailable.java b/src/org/apache/xpath/functions/FuncExtFunctionAvailable.java index f819961..c71a2e0 100644 --- a/src/org/apache/xpath/functions/FuncExtFunctionAvailable.java +++ b/src/org/apache/xpath/functions/FuncExtFunctionAvailable.java
@@ -58,7 +58,8 @@ import org.apache.xml.utils.PrefixResolver; import org.apache.xalan.templates.Constants; -import org.apache.xalan.extensions.ExtensionsTable; +//import org.apache.xalan.transformer.TransformerImpl; +//import org.apache.xalan.extensions.ExtensionsTable; //import org.w3c.dom.Node; @@ -66,6 +67,7 @@ import org.apache.xpath.XPathContext; import org.apache.xpath.XPath; +import org.apache.xpath.ExtensionsProvider; import org.apache.xpath.compiler.Keywords; import org.apache.xpath.objects.XObject; import org.apache.xpath.objects.XBoolean; @@ -123,9 +125,9 @@ } else { - ExtensionsTable etable = xctxt.getExtensionsTable(); - - return etable.functionAvailable(namespace, methName) + //dml + ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject(); + return extProvider.functionAvailable(namespace, methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE; } }