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