View Javadoc

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  package org.apache.commons.jxpath.functions;
17  
18  import java.lang.reflect.InvocationTargetException;
19  import java.lang.reflect.Method;
20  import java.lang.reflect.Modifier;
21  
22  import org.apache.commons.jxpath.ExpressionContext;
23  import org.apache.commons.jxpath.Function;
24  import org.apache.commons.jxpath.JXPathException;
25  import org.apache.commons.jxpath.util.TypeUtils;
26  import org.apache.commons.jxpath.util.ValueUtils;
27  
28  /***
29   * An XPath extension function implemented as an individual Java method.
30   * 
31   * @author Dmitri Plotnikov
32   * @version $Revision: 1.11 $ $Date: 2004/02/29 14:17:44 $
33   */
34  public class MethodFunction implements Function {
35  
36      private Method method;
37      private static final Object EMPTY_ARRAY[] = new Object[0];
38  
39      public MethodFunction(Method method) {
40          this.method = ValueUtils.getAccessibleMethod(method);
41      }
42  
43      public Object invoke(ExpressionContext context, Object[] parameters) {
44          try {
45              Object target;
46              Object[] args;
47              if (Modifier.isStatic(method.getModifiers())) {
48                  target = null;
49                  if (parameters == null) {
50                      parameters = EMPTY_ARRAY;
51                  }
52                  int pi = 0;
53                  Class types[] = method.getParameterTypes();
54                  if (types.length >= 1
55                      && ExpressionContext.class.isAssignableFrom(types[0])) {
56                      pi = 1;
57                  }
58                  args = new Object[parameters.length + pi];
59                  if (pi == 1) {
60                      args[0] = context;
61                  }
62                  for (int i = 0; i < parameters.length; i++) {
63                      args[i + pi] =
64                          TypeUtils.convert(parameters[i], types[i + pi]);
65                  }
66              }
67              else {
68                  int pi = 0;
69                  Class types[] = method.getParameterTypes();
70                  if (types.length >= 1
71                      && ExpressionContext.class.isAssignableFrom(types[0])) {
72                      pi = 1;
73                  }
74                  target =
75                      TypeUtils.convert(
76                          parameters[0],
77                          method.getDeclaringClass());
78                  args = new Object[parameters.length - 1 + pi];
79                  if (pi == 1) {
80                      args[0] = context;
81                  }
82                  for (int i = 1; i < parameters.length; i++) {
83                      args[pi + i - 1] =
84                          TypeUtils.convert(parameters[i], types[i + pi - 1]);
85                  }
86              }
87  
88              return method.invoke(target, args);
89          }
90          catch (Throwable ex) {
91              if (ex instanceof InvocationTargetException) {
92                  ex = ((InvocationTargetException) ex).getTargetException();
93              }
94              throw new JXPathException("Cannot invoke " + method, ex);
95          }
96      }
97      
98      public String toString() {
99          return method.toString();
100     }
101 }