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