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