1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: FuncExtFunction.java,v 1.24 2004/02/17 04:34:01 minchau Exp $
  18. */
  19. package com.sun.org.apache.xpath.internal.functions;
  20. import java.util.Vector;
  21. import com.sun.org.apache.xalan.internal.res.XSLMessages;
  22. import com.sun.org.apache.xpath.internal.Expression;
  23. import com.sun.org.apache.xpath.internal.ExpressionNode;
  24. import com.sun.org.apache.xpath.internal.ExpressionOwner;
  25. import com.sun.org.apache.xpath.internal.ExtensionsProvider;
  26. import com.sun.org.apache.xpath.internal.XPathContext;
  27. import com.sun.org.apache.xpath.internal.XPathVisitor;
  28. import com.sun.org.apache.xpath.internal.objects.XNull;
  29. import com.sun.org.apache.xpath.internal.objects.XObject;
  30. import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  31. /**
  32. * An object of this class represents an extension call expression. When
  33. * the expression executes, it calls ExtensionsTable#extFunction, and then
  34. * converts the result to the appropriate XObject.
  35. * @xsl.usage advanced
  36. */
  37. public class FuncExtFunction extends Function
  38. {
  39. /**
  40. * The namespace for the extension function, which should not normally
  41. * be null or empty.
  42. * @serial
  43. */
  44. String m_namespace;
  45. /**
  46. * The local name of the extension.
  47. * @serial
  48. */
  49. String m_extensionName;
  50. /**
  51. * Unique method key, which is passed to ExtensionsTable#extFunction in
  52. * order to allow caching of the method.
  53. * @serial
  54. */
  55. Object m_methodKey;
  56. /**
  57. * Array of static expressions which represent the parameters to the
  58. * function.
  59. * @serial
  60. */
  61. Vector m_argVec = new Vector();
  62. /**
  63. * This function is used to fixup variables from QNames to stack frame
  64. * indexes at stylesheet build time.
  65. * @param vars List of QNames that correspond to variables. This list
  66. * should be searched backwards for the first qualified name that
  67. * corresponds to the variable reference qname. The position of the
  68. * QName in the vector from the start of the vector will be its position
  69. * in the stack frame (but variables above the globalsTop value will need
  70. * to be offset to the current stack frame).
  71. * NEEDSDOC @param globalsSize
  72. */
  73. public void fixupVariables(java.util.Vector vars, int globalsSize)
  74. {
  75. if (null != m_argVec)
  76. {
  77. int nArgs = m_argVec.size();
  78. for (int i = 0; i < nArgs; i++)
  79. {
  80. Expression arg = (Expression) m_argVec.elementAt(i);
  81. arg.fixupVariables(vars, globalsSize);
  82. }
  83. }
  84. }
  85. /**
  86. * Return the namespace of the extension function.
  87. *
  88. * @return The namespace of the extension function.
  89. */
  90. public String getNamespace()
  91. {
  92. return m_namespace;
  93. }
  94. /**
  95. * Return the name of the extension function.
  96. *
  97. * @return The name of the extension function.
  98. */
  99. public String getFunctionName()
  100. {
  101. return m_extensionName;
  102. }
  103. /**
  104. * Return the method key of the extension function.
  105. *
  106. * @return The method key of the extension function.
  107. */
  108. public Object getMethodKey()
  109. {
  110. return m_methodKey;
  111. }
  112. /**
  113. * Return the nth argument passed to the extension function.
  114. *
  115. * @param n The argument number index.
  116. * @return The Expression object at the given index.
  117. */
  118. public Expression getArg(int n) {
  119. if (n >= 0 && n < m_argVec.size())
  120. return (Expression) m_argVec.elementAt(n);
  121. else
  122. return null;
  123. }
  124. /**
  125. * Return the number of arguments that were passed
  126. * into this extension function.
  127. *
  128. * @return The number of arguments.
  129. */
  130. public int getArgCount() {
  131. return m_argVec.size();
  132. }
  133. /**
  134. * Create a new FuncExtFunction based on the qualified name of the extension,
  135. * and a unique method key.
  136. *
  137. * @param namespace The namespace for the extension function, which should
  138. * not normally be null or empty.
  139. * @param extensionName The local name of the extension.
  140. * @param methodKey Unique method key, which is passed to
  141. * ExtensionsTable#extFunction in order to allow caching
  142. * of the method.
  143. */
  144. public FuncExtFunction(java.lang.String namespace,
  145. java.lang.String extensionName, Object methodKey)
  146. {
  147. //try{throw new Exception("FuncExtFunction() " + namespace + " " + extensionName);} catch (Exception e){e.printStackTrace();}
  148. m_namespace = namespace;
  149. m_extensionName = extensionName;
  150. m_methodKey = methodKey;
  151. }
  152. /**
  153. * Execute the function. The function must return
  154. * a valid object.
  155. * @param xctxt The current execution context.
  156. * @return A valid XObject.
  157. *
  158. * @throws javax.xml.transform.TransformerException
  159. */
  160. public XObject execute(XPathContext xctxt)
  161. throws javax.xml.transform.TransformerException
  162. {
  163. XObject result;
  164. Vector argVec = new Vector();
  165. int nArgs = m_argVec.size();
  166. for (int i = 0; i < nArgs; i++)
  167. {
  168. Expression arg = (Expression) m_argVec.elementAt(i);
  169. XObject xobj = arg.execute(xctxt);
  170. /*
  171. * Should cache the arguments for func:function
  172. */
  173. xobj.allowDetachToRelease(false);
  174. argVec.addElement(xobj);
  175. }
  176. //dml
  177. ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject();
  178. Object val = extProvider.extFunction(this, argVec);
  179. if (null != val)
  180. {
  181. result = XObject.create(val, xctxt);
  182. }
  183. else
  184. {
  185. result = new XNull();
  186. }
  187. return result;
  188. }
  189. /**
  190. * Set an argument expression for a function. This method is called by the
  191. * XPath compiler.
  192. *
  193. * @param arg non-null expression that represents the argument.
  194. * @param argNum The argument number index.
  195. *
  196. * @throws WrongNumberArgsException If the argNum parameter is beyond what
  197. * is specified for this function.
  198. */
  199. public void setArg(Expression arg, int argNum)
  200. throws WrongNumberArgsException
  201. {
  202. m_argVec.addElement(arg);
  203. }
  204. /**
  205. * Check that the number of arguments passed to this function is correct.
  206. *
  207. *
  208. * @param argNum The number of arguments that is being passed to the function.
  209. *
  210. * @throws WrongNumberArgsException
  211. */
  212. public void checkNumberArgs(int argNum) throws WrongNumberArgsException{}
  213. class ArgExtOwner implements ExpressionOwner
  214. {
  215. Expression m_exp;
  216. ArgExtOwner(Expression exp)
  217. {
  218. m_exp = exp;
  219. }
  220. /**
  221. * @see ExpressionOwner#getExpression()
  222. */
  223. public Expression getExpression()
  224. {
  225. return m_exp;
  226. }
  227. /**
  228. * @see ExpressionOwner#setExpression(Expression)
  229. */
  230. public void setExpression(Expression exp)
  231. {
  232. exp.exprSetParent(FuncExtFunction.this);
  233. m_exp = exp;
  234. }
  235. }
  236. /**
  237. * Call the visitors for the function arguments.
  238. */
  239. public void callArgVisitors(XPathVisitor visitor)
  240. {
  241. for (int i = 0; i < m_argVec.size(); i++)
  242. {
  243. Expression exp = (Expression)m_argVec.elementAt(i);
  244. exp.callVisitors(new ArgExtOwner(exp), visitor);
  245. }
  246. }
  247. /**
  248. * Set the parent node.
  249. * For an extension function, we also need to set the parent
  250. * node for all argument expressions.
  251. *
  252. * @param n The parent node
  253. */
  254. public void exprSetParent(ExpressionNode n)
  255. {
  256. super.exprSetParent(n);
  257. int nArgs = m_argVec.size();
  258. for (int i = 0; i < nArgs; i++)
  259. {
  260. Expression arg = (Expression) m_argVec.elementAt(i);
  261. arg.exprSetParent(n);
  262. }
  263. }
  264. /**
  265. * Constructs and throws a WrongNumberArgException with the appropriate
  266. * message for this function object. This class supports an arbitrary
  267. * number of arguments, so this method must never be called.
  268. *
  269. * @throws WrongNumberArgsException
  270. */
  271. protected void reportWrongNumberArgs() throws WrongNumberArgsException {
  272. String fMsg = XSLMessages.createXPATHMessage(
  273. XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
  274. new Object[]{ "Programmer's assertion: the method FunctionMultiArgs.reportWrongNumberArgs() should never be called." });
  275. throw new RuntimeException(fMsg);
  276. }
  277. }