1
14
15 package com.liferay.portal.kernel.util;
16
17 import com.liferay.portal.kernel.log.Log;
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
19
20 import java.lang.reflect.Array;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29
37 public class MethodInvoker {
38
39 public static Object invoke(MethodWrapper methodWrapper)
40 throws ClassNotFoundException, IllegalAccessException,
41 InstantiationException, InvocationTargetException,
42 NoSuchFieldException, NoSuchMethodException {
43
44 return invoke(methodWrapper, true);
45 }
46
47 public static Object invoke(
48 MethodWrapper methodWrapper, boolean newInstance)
49 throws ClassNotFoundException, IllegalAccessException,
50 InstantiationException, InvocationTargetException,
51 NoSuchFieldException, NoSuchMethodException {
52
53 Object targetObject = null;
54
55 if (newInstance) {
56 Thread currentThread = Thread.currentThread();
57
58 ClassLoader contextClassLoader =
59 currentThread.getContextClassLoader();
60
61 targetObject = contextClassLoader.loadClass(
62 methodWrapper.getClassName()).newInstance();
63 }
64
65 Object[] methodAndArguments = _lookupMethodAndArguments(
66 methodWrapper, targetObject);
67
68 Object returnObject = null;
69
70 if (methodAndArguments[0] != null) {
71 Method method = (Method)methodAndArguments[0];
72 Object[] arguments = (Object[])methodAndArguments[1];
73
74 returnObject = method.invoke(targetObject, arguments);
75 }
76
77 return returnObject;
78 }
79
80 public static Object invoke(
81 MethodWrapper methodWrapper, Object targetObject)
82 throws ClassNotFoundException, IllegalAccessException,
83 InvocationTargetException, NoSuchFieldException,
84 NoSuchMethodException {
85
86 Object[] methodAndArguments = _lookupMethodAndArguments(
87 methodWrapper, targetObject);
88
89 Object returnObject = null;
90
91 if (methodAndArguments[0] != null) {
92 Method method = (Method)methodAndArguments[0];
93 Object[] arguments = (Object[])methodAndArguments[1];
94
95 returnObject = method.invoke(targetObject, arguments);
96 }
97
98 return returnObject;
99 }
100
101 private static Object[] _lookupMethodAndArguments(
102 MethodWrapper methodWrapper, Object targetObject)
103 throws ClassNotFoundException, IllegalAccessException,
104 InvocationTargetException, NoSuchFieldException,
105 NoSuchMethodException {
106
107 Object[] methodAndArguments = new Object[2];
108
109 Thread currentThread = Thread.currentThread();
110
111 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
112
113 String className = methodWrapper.getClassName();
114 String methodName = methodWrapper.getMethodName();
115 Object[] arguments = methodWrapper.getArguments();
116 String[] argumentClassNames = methodWrapper.getArgumentClassNames();
117
118 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
119
120 for (int i = 0; i < arguments.length; i++) {
121 if (arguments[i] == null) {
122 _log.error(
123 "Cannot invoke " + className + " " + methodName +
124 " on position " + i + " because it is null");
125 }
126
127 Class<?> argClass = null;
128
129 if (argumentClassNames != null) {
130 argClass = _primitiveTypeMap.get(argumentClassNames[i]);
131
132 if (argClass == null) {
133 argClass = Class.forName(
134 argumentClassNames[i], true, contextClassLoader);
135 }
136 }
137 else {
138 argClass = arguments[i].getClass();
139 }
140
141 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
142 parameterTypes.add(
143 (Class<?>)argClass.getField("TYPE").get(arguments[i]));
144
145 MethodKey methodKey = new MethodKey(
146 argClass.getName(), "getValue");
147
148 Method method = MethodCache.get(methodKey);
149
150 arguments[i] = method.invoke(arguments[i], (Object[])null);
151 }
152 else if (arguments[i] instanceof NullWrapper) {
153 NullWrapper nullWrapper = (NullWrapper)arguments[i];
154
155 String wrappedClassName = nullWrapper.getClassName();
156
157 if (wrappedClassName.startsWith(StringPool.OPEN_BRACKET) &&
158 wrappedClassName.endsWith(StringPool.SEMICOLON)) {
159
160 wrappedClassName = wrappedClassName.substring(
161 2, wrappedClassName.length() - 1);
162
163 Class<?> wrappedClass = contextClassLoader.loadClass(
164 wrappedClassName);
165
166 parameterTypes.add(
167 Array.newInstance(wrappedClass, 0).getClass());
168 }
169 else {
170 Class<?> wrappedClass = contextClassLoader.loadClass(
171 wrappedClassName);
172
173 parameterTypes.add(wrappedClass);
174 }
175
176 arguments[i] = null;
177 }
178 else {
179 parameterTypes.add(argClass);
180 }
181 }
182
183 MethodKey methodKey = null;
184
185 Method method = null;
186
187 try {
188 methodKey = new MethodKey(
189 methodWrapper.getClassName(), methodWrapper.getMethodName(),
190 parameterTypes.toArray(new Class[parameterTypes.size()]));
191
192 method = MethodCache.get(methodKey);
193 }
194 catch (NoSuchMethodException nsme) {
195 Class<?> classObject = null;
196
197 if (targetObject == null) {
198 classObject = contextClassLoader.loadClass(className);
199 }
200 else {
201 classObject = targetObject.getClass();
202 }
203
204 Method[] methods = classObject.getMethods();
205
206 for (int i = 0; i < methods.length; i++) {
207 Class<?>[] methodParameterTypes =
208 methods[i].getParameterTypes();
209
210 if (methods[i].getName().equals(methodName) &&
211 methodParameterTypes.length == parameterTypes.size()) {
212
213 boolean correctParams = true;
214
215 for (int j = 0; j < parameterTypes.size(); j++) {
216 Class<?> a = parameterTypes.get(j);
217 Class<?> b = methodParameterTypes[j];
218
219 if (!ClassUtil.isSubclass(a, b)) {
220 correctParams = false;
221
222 break;
223 }
224 }
225
226 if (correctParams) {
227 method = methods[i];
228
229 MethodCache.put(methodKey, method);
230
231 break;
232 }
233 }
234 }
235
236 if (method == null) {
237 throw nsme;
238 }
239 }
240
241 methodAndArguments[0] = method;
242 methodAndArguments[1] = arguments;
243
244 return methodAndArguments;
245 }
246
247 private static Log _log = LogFactoryUtil.getLog(MethodInvoker.class);
248
249 private static Map<String, Class<?>> _primitiveTypeMap =
250 new HashMap<String, Class<?>>();
251
252 static {
253 _primitiveTypeMap.put("char", char.class);
254 _primitiveTypeMap.put("boolean", boolean.class);
255 _primitiveTypeMap.put("byte", byte.class);
256 _primitiveTypeMap.put("double", double.class);
257 _primitiveTypeMap.put("float", float.class);
258 _primitiveTypeMap.put("int", int.class);
259 _primitiveTypeMap.put("long", long.class);
260 _primitiveTypeMap.put("short", short.class);
261 }
262
263 }