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