You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mk...@apache.org on 2002/11/13 22:47:42 UTC
cvs commit: xml-xalan/java/src/org/apache/xalan/transformer TransformerImpl.java
mkwan 2002/11/13 13:47:41
Modified: java/src/org/apache/xalan/extensions ExtensionHandler.java
ExtensionHandlerExsltFunction.java
ExtensionHandlerGeneral.java
ExtensionHandlerJavaClass.java
ExtensionHandlerJavaPackage.java
ExtensionsTable.java
java/src/org/apache/xalan/templates ElemExsltFuncResult.java
ElemExsltFunction.java
java/src/org/apache/xalan/transformer TransformerImpl.java
Log:
For bugzilla 14236 and 14244. Cleanup in the extension handling code to make
EXSLT func:function and func:result work correctly.
New interfaces are added in ExtensionProvider, ExtensionsTable and
ExtensionHandler to pass the XPath extension function up to the extension
handler. In the case of an EXSLT function, we need to find out the frame
size of the caller template and use that to reset the frame bottom of
the variable stack. This prevents the local variables in the callee
from overwriting the variables in the caller. Also change the way to
handle the return result of the function to fix the problem in 14244.
Revision Changes Path
1.15 +16 -0 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandler.java
Index: ExtensionHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandler.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- ExtensionHandler.java 12 Jun 2001 19:14:32 -0000 1.14
+++ ExtensionHandler.java 13 Nov 2002 21:47:36 -0000 1.15
@@ -69,6 +69,7 @@
import org.apache.xalan.templates.Stylesheet;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xml.utils.QName;
+import org.apache.xpath.functions.FuncExtFunction;
// Temp??
import org.apache.xalan.transformer.TransformerImpl;
@@ -193,6 +194,21 @@
*/
public abstract Object callFunction(
String funcName, Vector args, Object methodKey,
+ ExpressionContext exprContext) throws TransformerException;
+
+ /**
+ * Process a call to a function.
+ *
+ * @param extFunction The XPath extension function.
+ * @param args The arguments of the function call.
+ * @param exprContext The context in which this expression is being executed.
+ *
+ * @return the return value of the function evaluation.
+ *
+ * @throws TransformerException if parsing trouble
+ */
+ public abstract Object callFunction(
+ FuncExtFunction extFunction, Vector args,
ExpressionContext exprContext) throws TransformerException;
/**
1.3 +49 -8 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerExsltFunction.java
Index: ExtensionHandlerExsltFunction.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerExsltFunction.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ExtensionHandlerExsltFunction.java 10 Jun 2002 19:24:41 -0000 1.2
+++ ExtensionHandlerExsltFunction.java 13 Nov 2002 21:47:37 -0000 1.3
@@ -80,8 +80,11 @@
import org.apache.xpath.XPathContext;
import org.apache.xpath.VariableStack;
+import org.apache.xpath.ExpressionNode;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XString;
+import org.apache.xpath.functions.FuncExtFunction;
+
import javax.xml.transform.TransformerException;
/**
@@ -206,6 +209,32 @@
String funcName, Vector args, Object methodKey,
ExpressionContext exprContext) throws TransformerException
{
+ throw new TransformerException("This method should not be called.");
+ }
+
+ /**
+ * Execute the EXSLT function and return the result value.
+ *
+ * @param extFunction The XPath extension function
+ * @param args The arguments of the function call.
+ * @param exprContext The context in which this expression is being executed.
+ * @return the return value of the function evaluation.
+ * @throws TransformerException
+ */
+ public Object callFunction(FuncExtFunction extFunction,
+ Vector args,
+ ExpressionContext exprContext)
+ throws TransformerException
+ {
+ // Find the template which invokes this EXSLT function.
+ ExpressionNode parent = extFunction.exprGetParent();
+ while (parent != null && !(parent instanceof ElemTemplate))
+ {
+ parent = parent.exprGetParent();
+ }
+
+ ElemTemplate callerTemplate = (parent != null) ? (ElemTemplate)parent: null;
+
XObject[] methodArgs;
methodArgs = new XObject[args.size()];
try
@@ -214,24 +243,36 @@
{
methodArgs[i] = XObject.create(args.elementAt(i));
}
- ElemExsltFunction elemFunc = getFunction(funcName);
+
+ ElemExsltFunction elemFunc = getFunction(extFunction.getFunctionName());
XPathContext context = exprContext.getXPathContext();
TransformerImpl transformer = (TransformerImpl)context.getOwnerObject();
+
+ // Reset the frame bottom before calling the EXSLT function.
+ if (callerTemplate != null)
+ elemFunc.setCallerFrameSize(callerTemplate.m_frameSize);
+ else
+ elemFunc.setCallerFrameSize(0);
+
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);
+ if (elemFunc.isResultSet())
+ {
+ val = elemFunc.getResult();
+ elemFunc.clearResult();
+ }
+
return val;
}
+ catch (TransformerException e)
+ {
+ throw e;
+ }
catch (Exception e)
{
- // e.printStackTrace();
throw new TransformerException(e);
- }
+ }
}
}
1.16 +19 -0 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerGeneral.java
Index: ExtensionHandlerGeneral.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerGeneral.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ExtensionHandlerGeneral.java 31 Jul 2001 21:33:14 -0000 1.15
+++ ExtensionHandlerGeneral.java 13 Nov 2002 21:47:39 -0000 1.16
@@ -81,6 +81,7 @@
// Temp??
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.functions.FuncExtFunction;
import org.apache.xpath.XPathProcessorException;
import org.apache.xml.utils.StringVector;
@@ -385,6 +386,24 @@
//+ " because of: " + e);
}
}
+ }
+
+ /**
+ * Process a call to an XPath extension function
+ *
+ * @param extFunction The XPath extension function
+ * @param args The arguments of the function call.
+ * @param exprContext The context in which this expression is being executed.
+ * @return the return value of the function evaluation.
+ * @throws TransformerException
+ */
+ public Object callFunction(FuncExtFunction extFunction,
+ Vector args,
+ ExpressionContext exprContext)
+ throws TransformerException
+ {
+ return callFunction(extFunction.getFunctionName(), args,
+ extFunction.getMethodKey(), exprContext);
}
/**
1.14 +19 -2 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaClass.java
Index: ExtensionHandlerJavaClass.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaClass.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ExtensionHandlerJavaClass.java 25 Oct 2002 19:24:27 -0000 1.13
+++ ExtensionHandlerJavaClass.java 13 Nov 2002 21:47:39 -0000 1.14
@@ -72,6 +72,7 @@
import org.apache.xml.utils.QName;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.functions.FuncExtFunction;
import javax.xml.transform.TransformerException;
/**
@@ -178,8 +179,7 @@
}
return false;
}
-
-
+
/**
* Process a call to a function in the java class represented by
* this <code>ExtensionHandlerJavaClass<code>.
@@ -377,6 +377,23 @@
}
}
+ /**
+ * Process a call to an XPath extension function
+ *
+ * @param extFunction The XPath extension function
+ * @param args The arguments of the function call.
+ * @param exprContext The context in which this expression is being executed.
+ * @return the return value of the function evaluation.
+ * @throws TransformerException
+ */
+ public Object callFunction(FuncExtFunction extFunction,
+ Vector args,
+ ExpressionContext exprContext)
+ throws TransformerException
+ {
+ return callFunction(extFunction.getFunctionName(), args,
+ extFunction.getMethodKey(), exprContext);
+ }
/**
* Process a call to this extension namespace via an element. As a side
1.14 +18 -0 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaPackage.java
Index: ExtensionHandlerJavaPackage.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaPackage.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ExtensionHandlerJavaPackage.java 25 Oct 2002 19:24:27 -0000 1.13
+++ ExtensionHandlerJavaPackage.java 13 Nov 2002 21:47:39 -0000 1.14
@@ -77,6 +77,7 @@
import org.apache.xml.utils.QName;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.functions.FuncExtFunction;
import javax.xml.transform.TransformerException;
/**
@@ -412,6 +413,23 @@
}
}
+ /**
+ * Process a call to an XPath extension function
+ *
+ * @param extFunction The XPath extension function
+ * @param args The arguments of the function call.
+ * @param exprContext The context in which this expression is being executed.
+ * @return the return value of the function evaluation.
+ * @throws TransformerException
+ */
+ public Object callFunction(FuncExtFunction extFunction,
+ Vector args,
+ ExpressionContext exprContext)
+ throws TransformerException
+ {
+ return callFunction(extFunction.getFunctionName(), args,
+ extFunction.getMethodKey(), exprContext);
+ }
/**
* Process a call to this extension namespace via an element. As a side
1.20 +47 -0 xml-xalan/java/src/org/apache/xalan/extensions/ExtensionsTable.java
Index: ExtensionsTable.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionsTable.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- ExtensionsTable.java 10 Jun 2002 19:24:41 -0000 1.19
+++ ExtensionsTable.java 13 Nov 2002 21:47:39 -0000 1.20
@@ -62,6 +62,7 @@
import org.apache.xpath.objects.XNull;
import org.apache.xpath.XPathProcessorException;
+import org.apache.xpath.functions.FuncExtFunction;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
@@ -243,5 +244,51 @@
}
}
return result;
+ }
+
+ /**
+ * Handle an extension function.
+ * @param extFunction the extension function
+ * @param argVec arguments to the function in a vector
+ * @param exprContext a context which may be passed to an extension function
+ * and provides callback functions to access various
+ * areas in the environment
+ *
+ * @return result of executing the function
+ *
+ * @throws javax.xml.transform.TransformerException
+ */
+ public Object extFunction(FuncExtFunction extFunction, Vector argVec,
+ ExpressionContext exprContext)
+ throws javax.xml.transform.TransformerException
+ {
+ Object result = null;
+ String ns = extFunction.getNamespace();
+ if (null != ns)
+ {
+ ExtensionHandler extNS =
+ (ExtensionHandler) m_extensionFunctionNamespaces.get(ns);
+ if (null != extNS)
+ {
+ try
+ {
+ result = extNS.callFunction(extFunction, argVec, exprContext);
+ }
+ catch (javax.xml.transform.TransformerException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new javax.xml.transform.TransformerException(e);
+ }
+ }
+ else
+ {
+ throw new XPathProcessorException(XSLMessages.createMessage(XSLTErrorResources.ER_EXTENSION_FUNC_UNKNOWN,
+ new Object[]{ns, extFunction.getFunctionName()}));
+ }
+ }
+ return result;
}
}
1.3 +5 -8 xml-xalan/java/src/org/apache/xalan/templates/ElemExsltFuncResult.java
Index: ElemExsltFuncResult.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemExsltFuncResult.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ElemExsltFuncResult.java 10 Jun 2002 19:24:42 -0000 1.2
+++ ElemExsltFuncResult.java 13 Nov 2002 21:47:40 -0000 1.3
@@ -33,22 +33,19 @@
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!");
+ if (owner.isResultSet())
+ 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);
+ XObject var = getValue(transformer, sourceNode);
+ owner.setResult(var);
}
}
1.3 +60 -45 xml-xalan/java/src/org/apache/xalan/templates/ElemExsltFunction.java
Index: ElemExsltFunction.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemExsltFunction.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ElemExsltFunction.java 10 Jun 2002 19:24:42 -0000 1.2
+++ ElemExsltFunction.java 13 Nov 2002 21:47:40 -0000 1.3
@@ -91,6 +91,15 @@
public class ElemExsltFunction extends ElemTemplate
{
+ // A flag indicating whether the return result is set
+ private boolean m_isResultSet = false;
+
+ // The return result
+ private XObject m_result;
+
+ // The frame size of the current caller
+ private int m_callerFrameSize = 0;
+
/**
* Get an integer representation of the element type.
*
@@ -118,9 +127,18 @@
public void execute(TransformerImpl transformer, XObject[] args)
throws TransformerException
{
+ // Reset the result before starting a function execution.
+ m_isResultSet = false;
+ m_result = null;
+
XPathContext xctxt = transformer.getXPathContext();
VariableStack vars = xctxt.getVarStack();
+ // Increment the frame bottom of the variable stack by the
+ // frame size of the caller template or EXSLT function.
+ int oldStackFrame = vars.getStackFrame();
+ vars.setStackFrame(m_callerFrameSize + oldStackFrame);
+
// Set parameters.
NodeList children = this.getChildNodes();
int numparams =0;
@@ -131,7 +149,7 @@
{
numparams++;
ElemParam param = (ElemParam)children.item(i);
- vars.setLocalVariable (param.m_index, args[i]);
+ vars.setLocalVariable (param.getIndex(), args[i]);
}
}
if (numparams < args.length)
@@ -145,10 +163,11 @@
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);
+ transformer.executeChildTemplates(this, true);
+
+ // Reset the stack frame after the function call
+ vars.setStackFrame(oldStackFrame);
+ m_callerFrameSize = 0;
if (TransformerImpl.S_DEBUG)
transformer.getTraceManager().fireTraceEndEvent(this);
@@ -157,24 +176,16 @@
// 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.
+ * depends on recomposition.
*/
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();
@@ -195,48 +206,52 @@
}
/**
- * Add the namespace to the StylesheetRoot vector of extension namespaces. Be sure the
- * exslt:function namespace is also added.
+ * Return the result of this EXSLT function
+ *
+ * @return The result of this EXSLT function
*/
-/* public void runtimeInit(TransformerImpl transformer) throws TransformerException
+ public XObject getResult()
{
- //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);
- }
+ return m_result;
}
-*/
-
- private int _resultIndex;
/**
- * Sets aside a position on the local variable stack index
- * to refer to the result element return value.
+ * Set the return result of this EXSLT function
+ *
+ * @param result The return result
*/
- void setResultIndex(int stackIndex)
- {
- _resultIndex = stackIndex;
+ public void setResult(XObject result)
+ {
+ m_isResultSet = true;
+ m_result = result;
}
/**
- * Provides the EXSLT extension handler access to the return value.
+ * Return true if the result has been set
+ *
+ * @return true if the result has been set
*/
- public int getResultIndex()
+ public boolean isResultSet()
{
- return _resultIndex;
+ return m_isResultSet;
}
+ /**
+ * Clear the return result of this EXSLT function
+ */
+ public void clearResult()
+ {
+ m_isResultSet = false;
+ m_result = null;
+ }
+
+ /**
+ * Set the frame size of the current caller for use in the variable stack.
+ *
+ * @param callerFrameSize The frame size of the caller
+ */
+ public void setCallerFrameSize(int callerFrameSize)
+ {
+ m_callerFrameSize = callerFrameSize;
+ }
}
1.140 +8 -0 xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java
Index: TransformerImpl.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java,v
retrieving revision 1.139
retrieving revision 1.140
diff -u -r1.139 -r1.140
--- TransformerImpl.java 30 Oct 2002 20:12:46 -0000 1.139
+++ TransformerImpl.java 13 Nov 2002 21:47:40 -0000 1.140
@@ -134,6 +134,7 @@
//dml
import org.apache.xpath.ExtensionsProvider;
import org.apache.xalan.extensions.ExtensionsTable;
+import org.apache.xpath.functions.FuncExtFunction;
/**
* <meta name="usage" content="advanced"/>
@@ -461,6 +462,13 @@
return getExtensionsTable().extFunction(ns, funcName,
argVec, methodKey,
getXPathContext().getExpressionContext());
+ }
+
+ public Object extFunction(FuncExtFunction extFunction, Vector argVec)
+ throws javax.xml.transform.TransformerException
+ {
+ return getExtensionsTable().extFunction(extFunction, argVec,
+ getXPathContext().getExpressionContext());
}
//=========================
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org