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.List;
34
35
42 public class MethodInvoker {
43
44 public static Object invoke(MethodWrapper methodWrapper)
45 throws ClassNotFoundException, IllegalAccessException,
46 InstantiationException, InvocationTargetException,
47 NoSuchFieldException, NoSuchMethodException {
48
49 return invoke(methodWrapper, true);
50 }
51
52 public static Object invoke(
53 MethodWrapper methodWrapper, boolean newInstance)
54 throws ClassNotFoundException, IllegalAccessException,
55 InstantiationException, InvocationTargetException,
56 NoSuchFieldException, NoSuchMethodException {
57
58 Thread currentThread = Thread.currentThread();
59
60 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
61
62 String className = methodWrapper.getClassName();
63 String methodName = methodWrapper.getMethodName();
64 Object[] args = methodWrapper.getArgs();
65
66 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
67
68 for (int i = 0; i < args.length; i++) {
69 if (args[i] == null) {
70 _log.error(
71 "Cannot invoke " + className + " " + methodName +
72 " on position " + i + " because it is null");
73 }
74
75 Class<?> argClass = args[i].getClass();
76
77 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
78 parameterTypes.add(
79 (Class<?>)argClass.getField("TYPE").get(args[i]));
80
81 MethodKey methodKey = new MethodKey(
82 argClass.getName(), "getValue", null);
83
84 Method method = MethodCache.get(methodKey);
85
86 args[i] = method.invoke(args[i], (Object[])null);
87 }
88 else if (args[i] instanceof NullWrapper) {
89 NullWrapper nullWrapper = (NullWrapper)args[i];
90
91 String wrappedClassName = nullWrapper.getClassName();
92
93 if (wrappedClassName.startsWith(StringPool.OPEN_BRACKET) &&
94 wrappedClassName.endsWith(StringPool.SEMICOLON)) {
95
96 wrappedClassName = wrappedClassName.substring(
97 2, wrappedClassName.length() - 1);
98
99 Class<?> wrappedClass = contextClassLoader.loadClass(
100 wrappedClassName);
101
102 parameterTypes.add(
103 Array.newInstance(wrappedClass, 0).getClass());
104 }
105 else {
106 Class<?> wrappedClass = contextClassLoader.loadClass(
107 wrappedClassName);
108
109 parameterTypes.add(wrappedClass);
110 }
111
112 args[i] = null;
113 }
114 else {
115 parameterTypes.add(argClass);
116 }
117 }
118
119 Object classObj = contextClassLoader.loadClass(className);
120
121 if (newInstance) {
122 classObj = ((Class<?>)classObj).newInstance();
123 }
124
125 Method method = null;
126
127 try {
128 MethodKey methodKey = new MethodKey(
129 methodWrapper.getClassName(), methodWrapper.getMethodName(),
130 parameterTypes.toArray(new Class[parameterTypes.size()]));
131
132 method = MethodCache.get(methodKey);
133 }
134 catch (NoSuchMethodException nsme) {
135 Method[] methods = null;
136
137 if (newInstance) {
138 methods = classObj.getClass().getMethods();
139 }
140 else {
141 methods = ((Class<?>)classObj).getMethods();
142 }
143
144 for (int i = 0; i < methods.length; i++) {
145 Class<?>[] methodParameterTypes =
146 methods[i].getParameterTypes();
147
148 if (methods[i].getName().equals(methodName) &&
149 methodParameterTypes.length == parameterTypes.size()) {
150
151 boolean correctParams = true;
152
153 for (int j = 0; j < parameterTypes.size(); j++) {
154 Class<?> a = parameterTypes.get(j);
155 Class<?> b = methodParameterTypes[j];
156
157 if (!ClassUtil.isSubclass(a, b)) {
158 correctParams = false;
159
160 break;
161 }
162 }
163
164 if (correctParams) {
165 method = methods[i];
166
167 break;
168 }
169 }
170 }
171
172 if (method == null) {
173 throw nsme;
174 }
175 }
176
177 Object returnObj = null;
178
179 if (method != null) {
180 returnObj = method.invoke(classObj, args);
181 }
182
183 return returnObj;
184 }
185
186 private static Log _log = LogFactoryUtil.getLog(MethodInvoker.class);
187
188 }