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.io.ByteArrayInputStream;
29 import java.io.ByteArrayOutputStream;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32
33 import java.lang.Object;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Method;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40
46 public class ClassLoaderProxy {
47
48 public ClassLoaderProxy(Object obj, ClassLoader classLoader) {
49 _obj = obj;
50 _classLoader = classLoader;
51 }
52
53 public ClassLoader getClassLoader() {
54 return _classLoader;
55 }
56
57 public Object invoke(String methodName, Object[] args) throws Throwable {
58 Thread currentThread = Thread.currentThread();
59
60 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
61
62 try {
63 currentThread.setContextClassLoader(_classLoader);
64
65 Class<?> classObj = Class.forName(
66 _obj.getClass().getName(), true, _classLoader);
67
68 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
69
70 for (int i = 0; i < args.length; i++) {
71 Object arg = args[i];
72
73 Class<?> argClass = Class.forName(
74 arg.getClass().getName(), true, _classLoader);
75
76 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
77 MethodKey methodKey = new MethodKey(
78 argClass.getName(), "getValue", null);
79
80 Method method = MethodCache.get(methodKey);
81
82 args[i] = method.invoke(arg, (Object[])null);
83
84 argClass = (Class<?>)argClass.getField("TYPE").get(arg);
85 }
86
87 if (ClassUtil.isSubclass(argClass, NullWrapper.class)) {
88 NullWrapper nullWrapper = (NullWrapper)arg;
89
90 argClass = Class.forName(
91 nullWrapper.getClassName(), true, _classLoader);
92
93 args[i] = null;
94 }
95
96 parameterTypes.add(argClass);
97 }
98
99 Method method = null;
100
101 try {
102 method = classObj.getMethod(
103 methodName,
104 parameterTypes.toArray(new Class[parameterTypes.size()]));
105 }
106 catch (NoSuchMethodException nsme) {
107 Method[] methods = ((Class<?>)classObj).getMethods();
108
109 for (int i = 0; i < methods.length; i++) {
110 Class<?>[] methodParameterTypes =
111 methods[i].getParameterTypes();
112
113 if (methods[i].getName().equals(methodName) &&
114 methodParameterTypes.length == parameterTypes.size()) {
115
116 boolean correctParams = true;
117
118 for (int j = 0; j < parameterTypes.size(); j++) {
119 Class<?> a = parameterTypes.get(j);
120 Class<?> b = methodParameterTypes[j];
121
122 if (!ClassUtil.isSubclass(a, b)) {
123 correctParams = false;
124
125 break;
126 }
127 }
128
129 if (correctParams) {
130 method = methods[i];
131
132 break;
133 }
134 }
135 }
136
137 if (method == null) {
138 throw nsme;
139 }
140 }
141
142 return method.invoke(_obj, args);
143 }
144 catch (InvocationTargetException ite) {
145 throw translateThrowable(ite.getCause(), contextClassLoader);
146 }
147 catch (Throwable t) {
148 _log.error(t, t);
149
150 throw t;
151 }
152 finally {
153 currentThread.setContextClassLoader(contextClassLoader);
154 }
155 }
156
157 protected Throwable translateThrowable(
158 Throwable t1, ClassLoader contextClassLoader) {
159
160 try {
161 ByteArrayOutputStream baos = new ByteArrayOutputStream();
162 ObjectOutputStream oos = new ObjectOutputStream(baos);
163
164 oos.writeObject(t1);
165
166 oos.flush();
167 oos.close();
168
169 byte[] bytes = baos.toByteArray();
170
171 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
172 ObjectInputStream ois = new ClassLoaderObjectInputStream(
173 bais, contextClassLoader);
174
175 t1 = (Throwable)ois.readObject();
176
177 ois.close();
178
179 return t1;
180 }
181 catch (Throwable t2) {
182 _log.error(t2, t2);
183
184 return t2;
185 }
186 }
187
188 private static Log _log = LogFactoryUtil.getLog(ClassLoaderProxy.class);
189
190 private Object _obj;
191 private ClassLoader _classLoader;
192
193 }