001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
018 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021
022 import java.io.ObjectInputStream;
023 import java.io.ObjectOutputStream;
024
025 import java.lang.reflect.InvocationTargetException;
026 import java.lang.reflect.Method;
027
028 import java.util.ArrayList;
029 import java.util.List;
030
031
034 public class ClassLoaderProxy {
035
036 public ClassLoaderProxy(Object obj, ClassLoader classLoader) {
037 this(obj, obj.getClass().getName(), classLoader);
038 }
039
040 public ClassLoaderProxy(
041 Object obj, String className, ClassLoader classLoader) {
042
043 _obj = obj;
044 _className = className;
045 _classLoader = classLoader;
046 }
047
048 public ClassLoader getClassLoader() {
049 return _classLoader;
050 }
051
052 public String getClassName() {
053 return _className;
054 }
055
056 public Object invoke(MethodHandler methodHandler) throws Throwable {
057 Thread currentThread = Thread.currentThread();
058
059 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
060
061 try {
062 currentThread.setContextClassLoader(_classLoader);
063
064 return _invoke(methodHandler);
065 }
066 catch (InvocationTargetException ite) {
067 throw translateThrowable(ite.getCause(), contextClassLoader);
068 }
069 catch (Throwable t) {
070 _log.error(t, t);
071
072 throw t;
073 }
074 finally {
075 currentThread.setContextClassLoader(contextClassLoader);
076 }
077 }
078
079
082 @Deprecated
083 public Object invoke(String methodName, Object[] args) throws Throwable {
084 Thread currentThread = Thread.currentThread();
085
086 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
087
088 try {
089 currentThread.setContextClassLoader(_classLoader);
090
091 Class<?> clazz = Class.forName(_className, true, _classLoader);
092
093 List<Class<?>> parameterTypes = new ArrayList<>();
094
095 for (int i = 0; i < args.length; i++) {
096 Object arg = args[i];
097
098 Class<?> argClazz = arg.getClass();
099
100 Class<?> argClass = Class.forName(
101 argClazz.getName(), true, _classLoader);
102
103 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
104 MethodKey methodKey = new MethodKey(argClass, "getValue");
105
106 Method method = methodKey.getMethod();
107
108 args[i] = method.invoke(arg, (Object[])null);
109
110 argClass = (Class<?>)argClass.getField("TYPE").get(arg);
111 }
112
113 if (ClassUtil.isSubclass(argClass, NullWrapper.class)) {
114 NullWrapper nullWrapper = (NullWrapper)arg;
115
116 argClass = Class.forName(
117 nullWrapper.getClassName(), true, _classLoader);
118
119 args[i] = null;
120 }
121
122 parameterTypes.add(argClass);
123 }
124
125 Method method = null;
126
127 try {
128 method = clazz.getMethod(
129 methodName,
130 parameterTypes.toArray(new Class[parameterTypes.size()]));
131 }
132 catch (NoSuchMethodException nsme) {
133 Method[] methods = ((Class<?>)clazz).getMethods();
134
135 for (int i = 0; i < methods.length; i++) {
136 Class<?>[] methodParameterTypes =
137 methods[i].getParameterTypes();
138
139 if (methods[i].getName().equals(methodName) &&
140 (methodParameterTypes.length ==
141 parameterTypes.size())) {
142
143 boolean correctParams = true;
144
145 for (int j = 0; j < parameterTypes.size(); j++) {
146 Class<?> a = parameterTypes.get(j);
147 Class<?> b = methodParameterTypes[j];
148
149 if (!ClassUtil.isSubclass(a, b)) {
150 correctParams = false;
151
152 break;
153 }
154 }
155
156 if (correctParams) {
157 method = methods[i];
158
159 break;
160 }
161 }
162 }
163
164 if (method == null) {
165 throw nsme;
166 }
167 }
168
169 return method.invoke(_obj, args);
170 }
171 catch (InvocationTargetException ite) {
172 throw translateThrowable(ite.getCause(), contextClassLoader);
173 }
174 catch (Throwable t) {
175 _log.error(t, t);
176
177 throw t;
178 }
179 finally {
180 currentThread.setContextClassLoader(contextClassLoader);
181 }
182 }
183
184 protected Throwable translateThrowable(
185 Throwable throwable, ClassLoader contextClassLoader) {
186
187 try {
188 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
189 new UnsyncByteArrayOutputStream();
190
191 try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(
192 unsyncByteArrayOutputStream)) {
193
194 objectOutputStream.writeObject(throwable);
195
196 objectOutputStream.flush();
197 }
198
199 UnsyncByteArrayInputStream unsyncByteArrayInputStream =
200 new UnsyncByteArrayInputStream(
201 unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
202 unsyncByteArrayOutputStream.size());
203
204 try (ObjectInputStream objectInputStream =
205 new ClassLoaderObjectInputStream(
206 unsyncByteArrayInputStream, contextClassLoader)) {
207
208 return (Throwable)objectInputStream.readObject();
209 }
210 }
211 catch (Throwable throwable2) {
212 _log.error(throwable2, throwable2);
213
214 return throwable2;
215 }
216 }
217
218 private Object _invoke(MethodHandler methodHandler) throws Exception {
219 try {
220 return methodHandler.invoke(_obj);
221 }
222 catch (NoSuchMethodException nsme) {
223 MethodKey methodKey = methodHandler.getMethodKey();
224
225 String name = methodKey.getMethodName();
226
227 Class<?>[] parameterTypes = methodKey.getParameterTypes();
228
229 Class<?> clazz = Class.forName(_className, true, _classLoader);
230
231 for (Method method : clazz.getMethods()) {
232 String curName = method.getName();
233 Class<?>[] curParameterTypes = method.getParameterTypes();
234
235 if (!curName.equals(name) ||
236 (curParameterTypes.length != parameterTypes.length)) {
237
238 continue;
239 }
240
241 boolean correctParams = true;
242
243 for (int j = 0; j < parameterTypes.length; j++) {
244 Class<?> a = parameterTypes[j];
245 Class<?> b = curParameterTypes[j];
246
247 if (!ClassUtil.isSubclass(a, b.getName())) {
248 correctParams = false;
249
250 break;
251 }
252 }
253
254 if (correctParams) {
255 return method.invoke(_obj, methodHandler.getArguments());
256 }
257 }
258
259 throw nsme;
260 }
261 }
262
263 private static final Log _log = LogFactoryUtil.getLog(
264 ClassLoaderProxy.class);
265
266 private final ClassLoader _classLoader;
267 private final String _className;
268 private final Object _obj;
269
270 }