Extension Enhancements, including EXSLT Function and Result.
git-svn-id: https://svn.apache.org/repos/asf/xalan/java/branches/ExtensionEnhancements@336437 13f79535-47bb-0310-9956-ffa450edef68
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;
}
}