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