1
19
20 package com.liferay.portal.kernel.util;
21
22 import com.liferay.portal.kernel.log.Log;
23 import com.liferay.portal.kernel.log.LogFactoryUtil;
24
25 import java.lang.reflect.Array;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28
29 import java.util.ArrayList;
30 import java.util.List;
31
32
39 public class MethodInvoker {
40
41 public static Object invoke(MethodWrapper methodWrapper)
42 throws ClassNotFoundException, IllegalAccessException,
43 InstantiationException, InvocationTargetException,
44 NoSuchFieldException, NoSuchMethodException {
45
46 return invoke(methodWrapper, true);
47 }
48
49 public static Object invoke(
50 MethodWrapper methodWrapper, boolean newInstance)
51 throws ClassNotFoundException, IllegalAccessException,
52 InstantiationException, InvocationTargetException,
53 NoSuchFieldException, NoSuchMethodException {
54
55 Thread currentThread = Thread.currentThread();
56
57 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
58
59 String className = methodWrapper.getClassName();
60 String methodName = methodWrapper.getMethodName();
61 Object[] args = methodWrapper.getArgs();
62
63 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
64
65 for (int i = 0; i < args.length; i++) {
66 if (args[i] == null) {
67 _log.error(
68 "Cannot invoke " + className + " " + methodName +
69 " on position " + i + " because it is null");
70 }
71
72 Class<?> argClass = args[i].getClass();
73
74 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
75 parameterTypes.add(
76 (Class<?>)argClass.getField("TYPE").get(args[i]));
77
78 MethodKey methodKey = new MethodKey(
79 argClass.getName(), "getValue", null);
80
81 Method method = MethodCache.get(methodKey);
82
83 args[i] = method.invoke(args[i], (Object[])null);
84 }
85 else if (args[i] instanceof NullWrapper) {
86 NullWrapper nullWrapper = (NullWrapper)args[i];
87
88 String wrappedClassName = nullWrapper.getClassName();
89
90 if (wrappedClassName.startsWith(StringPool.OPEN_BRACKET) &&
91 wrappedClassName.endsWith(StringPool.SEMICOLON)) {
92
93 wrappedClassName = wrappedClassName.substring(
94 2, wrappedClassName.length() - 1);
95
96 Class<?> wrappedClass = contextClassLoader.loadClass(
97 wrappedClassName);
98
99 parameterTypes.add(
100 Array.newInstance(wrappedClass, 0).getClass());
101 }
102 else {
103 Class<?> wrappedClass = contextClassLoader.loadClass(
104 wrappedClassName);
105
106 parameterTypes.add(wrappedClass);
107 }
108
109 args[i] = null;
110 }
111 else {
112 parameterTypes.add(argClass);
113 }
114 }
115
116 Object classObj = contextClassLoader.loadClass(className);
117
118 if (newInstance) {
119 classObj = ((Class<?>)classObj).newInstance();
120 }
121
122 Method method = null;
123
124 try {
125 MethodKey methodKey = new MethodKey(
126 methodWrapper.getClassName(), methodWrapper.getMethodName(),
127 parameterTypes.toArray(new Class[parameterTypes.size()]));
128
129 method = MethodCache.get(methodKey);
130 }
131 catch (NoSuchMethodException nsme) {
132 Method[] methods = null;
133
134 if (newInstance) {
135 methods = classObj.getClass().getMethods();
136 }
137 else {
138 methods = ((Class<?>)classObj).getMethods();
139 }
140
141 for (int i = 0; i < methods.length; i++) {
142 Class<?>[] methodParameterTypes =
143 methods[i].getParameterTypes();
144
145 if (methods[i].getName().equals(methodName) &&
146 methodParameterTypes.length == parameterTypes.size()) {
147
148 boolean correctParams = true;
149
150 for (int j = 0; j < parameterTypes.size(); j++) {
151 Class<?> a = parameterTypes.get(j);
152 Class<?> b = methodParameterTypes[j];
153
154 if (!ClassUtil.isSubclass(a, b)) {
155 correctParams = false;
156
157 break;
158 }
159 }
160
161 if (correctParams) {
162 method = methods[i];
163
164 break;
165 }
166 }
167 }
168
169 if (method == null) {
170 throw nsme;
171 }
172 }
173
174 Object returnObj = null;
175
176 if (method != null) {
177 returnObj = method.invoke(classObj, args);
178 }
179
180 return returnObj;
181 }
182
183 private static Log _log = LogFactoryUtil.getLog(MethodInvoker.class);
184
185 }