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