001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019
020 import java.lang.reflect.Array;
021 import java.lang.reflect.InvocationTargetException;
022 import java.lang.reflect.Method;
023
024 import java.util.ArrayList;
025 import java.util.HashMap;
026 import java.util.List;
027 import java.util.Map;
028
029
034 public class MethodInvoker {
035
036 public static Object invoke(MethodWrapper methodWrapper)
037 throws ClassNotFoundException, IllegalAccessException,
038 InstantiationException, InvocationTargetException,
039 NoSuchFieldException, NoSuchMethodException {
040
041 return invoke(methodWrapper, true);
042 }
043
044 public static Object invoke(
045 MethodWrapper methodWrapper, boolean newInstance)
046 throws ClassNotFoundException, IllegalAccessException,
047 InstantiationException, InvocationTargetException,
048 NoSuchFieldException, NoSuchMethodException {
049
050 Object targetObject = null;
051
052 if (newInstance) {
053 Thread currentThread = Thread.currentThread();
054
055 ClassLoader contextClassLoader =
056 currentThread.getContextClassLoader();
057
058 targetObject = contextClassLoader.loadClass(
059 methodWrapper.getClassName()).newInstance();
060 }
061
062 Object[] methodAndArguments = _lookupMethodAndArguments(
063 methodWrapper, targetObject);
064
065 Object returnObject = null;
066
067 if (methodAndArguments[0] != null) {
068 Method method = (Method)methodAndArguments[0];
069 Object[] arguments = (Object[])methodAndArguments[1];
070
071 returnObject = method.invoke(targetObject, arguments);
072 }
073
074 return returnObject;
075 }
076
077 public static Object invoke(
078 MethodWrapper methodWrapper, Object targetObject)
079 throws ClassNotFoundException, IllegalAccessException,
080 InvocationTargetException, NoSuchFieldException,
081 NoSuchMethodException {
082
083 Object[] methodAndArguments = _lookupMethodAndArguments(
084 methodWrapper, targetObject);
085
086 Object returnObject = null;
087
088 if (methodAndArguments[0] != null) {
089 Method method = (Method)methodAndArguments[0];
090 Object[] arguments = (Object[])methodAndArguments[1];
091
092 returnObject = method.invoke(targetObject, arguments);
093 }
094
095 return returnObject;
096 }
097
098 private static Object[] _lookupMethodAndArguments(
099 MethodWrapper methodWrapper, Object targetObject)
100 throws ClassNotFoundException, IllegalAccessException,
101 InvocationTargetException, NoSuchFieldException,
102 NoSuchMethodException {
103
104 Object[] methodAndArguments = new Object[2];
105
106 Thread currentThread = Thread.currentThread();
107
108 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
109
110 String className = methodWrapper.getClassName();
111 String methodName = methodWrapper.getMethodName();
112 Object[] arguments = methodWrapper.getArguments();
113 String[] argumentClassNames = methodWrapper.getArgumentClassNames();
114
115 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
116
117 for (int i = 0; i < arguments.length; i++) {
118 if (arguments[i] == null) {
119 _log.error(
120 "Cannot invoke " + className + " " + methodName +
121 " on position " + i + " because it is null");
122 }
123
124 Class<?> argClass = null;
125
126 if (argumentClassNames != null) {
127 argClass = _primitiveTypeMap.get(argumentClassNames[i]);
128
129 if (argClass == null) {
130 argClass = Class.forName(
131 argumentClassNames[i], true, contextClassLoader);
132 }
133 }
134 else {
135 argClass = arguments[i].getClass();
136 }
137
138 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
139 parameterTypes.add(
140 (Class<?>)argClass.getField("TYPE").get(arguments[i]));
141
142 MethodKey methodKey = new MethodKey(
143 argClass.getName(), "getValue", null);
144
145 Method method = MethodCache.get(methodKey);
146
147 arguments[i] = method.invoke(arguments[i], (Object[])null);
148 }
149 else if (arguments[i] instanceof NullWrapper) {
150 NullWrapper nullWrapper = (NullWrapper)arguments[i];
151
152 String wrappedClassName = nullWrapper.getClassName();
153
154 if (wrappedClassName.startsWith(StringPool.OPEN_BRACKET) &&
155 wrappedClassName.endsWith(StringPool.SEMICOLON)) {
156
157 wrappedClassName = wrappedClassName.substring(
158 2, wrappedClassName.length() - 1);
159
160 Class<?> wrappedClass = contextClassLoader.loadClass(
161 wrappedClassName);
162
163 parameterTypes.add(
164 Array.newInstance(wrappedClass, 0).getClass());
165 }
166 else {
167 Class<?> wrappedClass = contextClassLoader.loadClass(
168 wrappedClassName);
169
170 parameterTypes.add(wrappedClass);
171 }
172
173 arguments[i] = null;
174 }
175 else {
176 parameterTypes.add(argClass);
177 }
178 }
179
180 MethodKey methodKey = null;
181
182 Method method = null;
183
184 try {
185 methodKey = new MethodKey(
186 methodWrapper.getClassName(), methodWrapper.getMethodName(),
187 parameterTypes.toArray(new Class[parameterTypes.size()]));
188
189 method = MethodCache.get(methodKey);
190 }
191 catch (NoSuchMethodException nsme) {
192 Class<?> classObject = null;
193
194 if (targetObject == null) {
195 classObject = contextClassLoader.loadClass(className);
196 }
197 else {
198 classObject = targetObject.getClass();
199 }
200
201 Method[] methods = classObject.getMethods();
202
203 for (int i = 0; i < methods.length; i++) {
204 Class<?>[] methodParameterTypes =
205 methods[i].getParameterTypes();
206
207 if (methods[i].getName().equals(methodName) &&
208 methodParameterTypes.length == parameterTypes.size()) {
209
210 boolean correctParams = true;
211
212 for (int j = 0; j < parameterTypes.size(); j++) {
213 Class<?> a = parameterTypes.get(j);
214 Class<?> b = methodParameterTypes[j];
215
216 if (!ClassUtil.isSubclass(a, b)) {
217 correctParams = false;
218
219 break;
220 }
221 }
222
223 if (correctParams) {
224 method = methods[i];
225
226 MethodCache.put(methodKey, method);
227
228 break;
229 }
230 }
231 }
232
233 if (method == null) {
234 throw nsme;
235 }
236 }
237
238 methodAndArguments[0] = method;
239 methodAndArguments[1] = arguments;
240
241 return methodAndArguments;
242 }
243
244 private static Log _log = LogFactoryUtil.getLog(MethodInvoker.class);
245
246 private static Map<String, Class<?>> _primitiveTypeMap =
247 new HashMap<String, Class<?>>();
248
249 static {
250 _primitiveTypeMap.put("char", char.class);
251 _primitiveTypeMap.put("boolean", boolean.class);
252 _primitiveTypeMap.put("byte", byte.class);
253 _primitiveTypeMap.put("double", double.class);
254 _primitiveTypeMap.put("float", float.class);
255 _primitiveTypeMap.put("int", int.class);
256 _primitiveTypeMap.put("long", long.class);
257 _primitiveTypeMap.put("short", short.class);
258 }
259
260 }