001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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    /**
030     * @author     Brian Wing Shun Chan
031     * @author     Harry Mark
032     * @author     Shuyang Zhou
033     * @deprecated
034     */
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    }