Coverage Report - org.apache.commons.el.FunctionInvocation
 
Classes in this File Line Coverage Branch Coverage Complexity
FunctionInvocation
43%
29/67
33%
8/24
3.333
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.el;
 18  
 
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.lang.reflect.Method;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.ArrayList;
 24  
 
 25  
 import javax.servlet.jsp.el.ELException;
 26  
 import javax.servlet.jsp.el.FunctionMapper;
 27  
 import javax.servlet.jsp.el.VariableResolver;
 28  
 
 29  
 import org.apache.commons.logging.Log;
 30  
 import org.apache.commons.logging.LogFactory;
 31  
 
 32  
 /**
 33  
  *
 34  
  * <p>Represents a function call.</p>
 35  
  * 
 36  
  * @author Shawn Bayern (in the style of Nathan's other classes)
 37  
  **/
 38  
 
 39  
 public class FunctionInvocation
 40  
   extends Expression
 41  
 {
 42  
     //-------------------------------------
 43  
     // Constants
 44  
     //-------------------------------------
 45  2
     private static Log log = LogFactory.getLog(FunctionInvocation.class);
 46  
     
 47  
   //-------------------------------------
 48  
   // Properties
 49  
   //-------------------------------------
 50  
   // property index
 51  
 
 52  
   private String functionName;
 53  
   private List argumentList;
 54  0
   public String getFunctionName() { return functionName; }
 55  0
   public void setFunctionName(String f) { functionName = f; }
 56  0
   public List getArgumentList() { return argumentList; }
 57  0
   public void setArgumentList(List l) { argumentList = l; }
 58  
 
 59  
   //-------------------------------------
 60  
   /**
 61  
    * Constructor
 62  
    **/
 63  
   public FunctionInvocation (String functionName, List argumentList)
 64  6
   {
 65  6
     this.functionName = functionName;
 66  6
     this.argumentList = argumentList;
 67  6
   }
 68  
 
 69  
   //-------------------------------------
 70  
   // Expression methods
 71  
   //-------------------------------------
 72  
   /**
 73  
    * Returns the expression in the expression language syntax
 74  
    **/
 75  
   public String getExpressionString ()
 76  
   {
 77  0
     StringBuffer b = new StringBuffer();
 78  0
     b.append(functionName);
 79  0
     b.append("(");
 80  0
     Iterator i = argumentList.iterator();
 81  0
     while (i.hasNext()) {
 82  0
       b.append(((Expression) i.next()).getExpressionString());
 83  0
       if (i.hasNext())
 84  0
         b.append(", ");
 85  
     }
 86  0
     b.append(")");
 87  0
     return b.toString();
 88  
   }
 89  
 
 90  
 
 91  
   //-------------------------------------
 92  
   /**
 93  
    *
 94  
    * Evaluates by looking up the name in the VariableResolver
 95  
    **/
 96  
   public Object evaluate (VariableResolver pResolver,
 97  
                           FunctionMapper functions)
 98  
     throws ELException
 99  
   {
 100  
 
 101  9
     Method target = resolveFunction(functions);
 102  9
     if (target == null) {
 103  0
         if (log.isErrorEnabled()) {
 104  0
             String message = MessageUtil.getMessageWithArgs(
 105  
                 Constants.UNKNOWN_FUNCTION, functionName);
 106  0
             log.error(message);
 107  0
             throw new ELException(message);
 108  
         }
 109  
     }      
 110  
 
 111  
     // ensure that the number of arguments matches the number of parameters
 112  9
     Class[] params = target.getParameterTypes();
 113  9
     if (params.length != argumentList.size()) {
 114  0
         if (log.isErrorEnabled()) {
 115  0
             String message = MessageUtil.getMessageWithArgs(
 116  
                 Constants.INAPPROPRIATE_FUNCTION_ARG_COUNT,
 117  
                 functionName, new Integer(params.length),
 118  
                 new Integer(argumentList.size()));
 119  0
             log.error(message);
 120  0
             throw new ELException(message);
 121  
         }      
 122  
     }
 123  
 
 124  
     // now, walk through each parameter, evaluating and casting its argument
 125  9
     Object[] arguments = new Object[argumentList.size()];
 126  12
     for (int i = 0; i < params.length; i++) {
 127  
       // evaluate
 128  3
       arguments[i] = ((Expression) argumentList.get(i)).evaluate(pResolver,
 129  
                                                                  functions);
 130  
       // coerce
 131  3
       arguments[i] = Coercions.coerce(arguments[i], params[i]);
 132  
     }
 133  
 
 134  
     // finally, invoke the target method, which we know to be static
 135  
     try {
 136  9
       return (target.invoke(null, arguments));
 137  0
     } catch (InvocationTargetException ex) {
 138  0
         if (log.isErrorEnabled()) {
 139  0
             String message = MessageUtil.getMessageWithArgs(
 140  
                 Constants.FUNCTION_INVOCATION_ERROR,
 141  
                 functionName);
 142  0
             Throwable t = ex.getTargetException();
 143  0
             log.error(message, t);
 144  0
             throw new ELException(message, t);
 145  
         }      
 146  0
       return null;
 147  0
     } catch (Throwable t) {
 148  0
         if (log.isErrorEnabled()) {
 149  0
             String message = MessageUtil.getMessageWithArgs(
 150  
                 Constants.FUNCTION_INVOCATION_ERROR,
 151  
                 functionName);            
 152  0
             log.error(message, t);
 153  0
             throw new ELException(message, t); 
 154  
         }      
 155  0
       return null;
 156  
     }
 157  
   }
 158  
 
 159  
   /**
 160  
    * Returns the <code>Method</code> which is mapped to the function
 161  
    * name used by this <code>FunctionInvocation</code>.
 162  
    * @param functions The function mappings in use for this evaluation
 163  
    * @return the <code>Method</code> to execute 
 164  
    * @throws ELException
 165  
    */
 166  
   protected Method resolveFunction(FunctionMapper functions) throws ELException {
 167  
       // if the Map is null, then the function is invalid 
 168  6
       if (functions == null) { 
 169  0
           return null;
 170  
       }                    
 171  
 
 172  
       // normalize function name
 173  6
       String prefix = null; 
 174  6
       String localName = null; 
 175  6
       int index = functionName.indexOf( ':' );
 176  6
       if (index == -1) {
 177  6
         prefix = "";
 178  6
         localName = functionName;
 179  
       } else {
 180  0
         prefix = functionName.substring( 0, index );
 181  0
         localName = functionName.substring( index + 1 );
 182  
       }       
 183  
   
 184  
       // ensure that the function's name is mapped
 185  6
       Method target = (Method) functions.resolveFunction(prefix, localName);
 186  
    
 187  6
        return target; 
 188  
    }
 189  
 
 190  
    public Expression bindFunctions(final FunctionMapper functions)
 191  
            throws ELException {
 192  3
        final List argList = new ArrayList(argumentList.size());
 193  3
        for (Iterator argIter = argumentList.iterator(); argIter.hasNext();) {
 194  1
            Expression arg = (Expression) argIter.next();
 195  1
            argList.add(arg.bindFunctions(functions));
 196  1
        }
 197  3
        return new BoundFunctionInvocation(
 198  
                resolveFunction(functions),
 199  
                functionName,
 200  
                argList);
 201  
    }
 202  
 
 203  
   //-------------------------------------
 204  
 }