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;
     }
   }