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