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