1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.kernel.util;
21  
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  
25  import java.lang.reflect.Array;
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  /**
33   * <a href="MethodInvoker.java.html"><b><i>View Source</i></b></a>
34   *
35   * @author Brian Wing Shun Chan
36   * @author Harry Mark
37   *
38   */
39  public class MethodInvoker {
40  
41      public static Object invoke(MethodWrapper methodWrapper)
42          throws ClassNotFoundException, IllegalAccessException,
43                 InstantiationException, InvocationTargetException,
44                 NoSuchFieldException, NoSuchMethodException {
45  
46          return invoke(methodWrapper, true);
47      }
48  
49      public static Object invoke(
50              MethodWrapper methodWrapper, boolean newInstance)
51          throws ClassNotFoundException, IllegalAccessException,
52                 InstantiationException, InvocationTargetException,
53                 NoSuchFieldException, NoSuchMethodException {
54  
55          Thread currentThread = Thread.currentThread();
56  
57          ClassLoader contextClassLoader = currentThread.getContextClassLoader();
58  
59          String className = methodWrapper.getClassName();
60          String methodName = methodWrapper.getMethodName();
61          Object[] args = methodWrapper.getArgs();
62  
63          List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
64  
65          for (int i = 0; i < args.length; i++) {
66              if (args[i] == null) {
67                  _log.error(
68                      "Cannot invoke " + className + " " + methodName +
69                          " on position " + i + " because it is null");
70              }
71  
72              Class<?> argClass = args[i].getClass();
73  
74              if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
75                  parameterTypes.add(
76                      (Class<?>)argClass.getField("TYPE").get(args[i]));
77  
78                  MethodKey methodKey = new MethodKey(
79                      argClass.getName(), "getValue", null);
80  
81                  Method method = MethodCache.get(methodKey);
82  
83                  args[i] = method.invoke(args[i], (Object[])null);
84              }
85              else if (args[i] instanceof NullWrapper) {
86                  NullWrapper nullWrapper = (NullWrapper)args[i];
87  
88                  String wrappedClassName = nullWrapper.getClassName();
89  
90                  if (wrappedClassName.startsWith(StringPool.OPEN_BRACKET) &&
91                      wrappedClassName.endsWith(StringPool.SEMICOLON)) {
92  
93                      wrappedClassName = wrappedClassName.substring(
94                          2, wrappedClassName.length() - 1);
95  
96                      Class<?> wrappedClass = contextClassLoader.loadClass(
97                          wrappedClassName);
98  
99                      parameterTypes.add(
100                         Array.newInstance(wrappedClass, 0).getClass());
101                 }
102                 else {
103                     Class<?> wrappedClass = contextClassLoader.loadClass(
104                         wrappedClassName);
105 
106                     parameterTypes.add(wrappedClass);
107                 }
108 
109                 args[i] = null;
110             }
111             else {
112                 parameterTypes.add(argClass);
113             }
114         }
115 
116         Object classObj = contextClassLoader.loadClass(className);
117 
118         if (newInstance) {
119             classObj = ((Class<?>)classObj).newInstance();
120         }
121 
122         Method method = null;
123 
124         try {
125             MethodKey methodKey = new MethodKey(
126                 methodWrapper.getClassName(), methodWrapper.getMethodName(),
127                 parameterTypes.toArray(new Class[parameterTypes.size()]));
128 
129             method = MethodCache.get(methodKey);
130         }
131         catch (NoSuchMethodException nsme) {
132             Method[] methods = null;
133 
134             if (newInstance) {
135                 methods = classObj.getClass().getMethods();
136             }
137             else {
138                 methods = ((Class<?>)classObj).getMethods();
139             }
140 
141             for (int i = 0; i < methods.length; i++) {
142                 Class<?>[] methodParameterTypes =
143                     methods[i].getParameterTypes();
144 
145                 if (methods[i].getName().equals(methodName) &&
146                     methodParameterTypes.length == parameterTypes.size()) {
147 
148                     boolean correctParams = true;
149 
150                     for (int j = 0; j < parameterTypes.size(); j++) {
151                         Class<?> a = parameterTypes.get(j);
152                         Class<?> b = methodParameterTypes[j];
153 
154                         if (!ClassUtil.isSubclass(a, b)) {
155                             correctParams = false;
156 
157                             break;
158                         }
159                     }
160 
161                     if (correctParams) {
162                         method = methods[i];
163 
164                         break;
165                     }
166                 }
167             }
168 
169             if (method == null) {
170                 throw nsme;
171             }
172         }
173 
174         Object returnObj = null;
175 
176         if (method != null) {
177             returnObj = method.invoke(classObj, args);
178         }
179 
180         return returnObj;
181     }
182 
183     private static Log _log = LogFactoryUtil.getLog(MethodInvoker.class);
184 
185 }