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
039 public ClassLoaderProxy(Object obj, ClassLoader classLoader) {
040 this(obj, obj.getClass().getName(), classLoader);
041 }
042
043 public ClassLoaderProxy(
044 Object obj, String className, ClassLoader classLoader) {
045
046 _obj = obj;
047 _className = className;
048 _classLoader = classLoader;
049 }
050
051 public ClassLoader getClassLoader() {
052 return _classLoader;
053 }
054
055 public String getClassName() {
056 return _className;
057 }
058
059 public Object invoke(MethodHandler methodHandler) throws Throwable {
060 Thread currentThread = Thread.currentThread();
061
062 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
063
064 try {
065 currentThread.setContextClassLoader(_classLoader);
066
067 return methodHandler.invoke(_obj);
068 }
069 catch (InvocationTargetException ite) {
070 throw translateThrowable(ite.getCause(), contextClassLoader);
071 }
072 catch (Throwable t) {
073 _log.error(t, t);
074
075 throw t;
076 }
077 finally {
078 currentThread.setContextClassLoader(contextClassLoader);
079 }
080 }
081
082
085 public Object invoke(String methodName, Object[] args) throws Throwable {
086 Thread currentThread = Thread.currentThread();
087
088 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
089
090 try {
091 currentThread.setContextClassLoader(_classLoader);
092
093 Class<?> classObj = Class.forName(_className, true, _classLoader);
094
095 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
096
097 for (int i = 0; i < args.length; i++) {
098 Object arg = args[i];
099
100 Class<?> argClass = Class.forName(
101 arg.getClass().getName(), true, _classLoader);
102
103 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
104 MethodKey methodKey = new MethodKey(
105 argClass.getName(), "getValue");
106
107 Method method = MethodCache.get(methodKey);
108
109 args[i] = method.invoke(arg, (Object[])null);
110
111 argClass = (Class<?>)argClass.getField("TYPE").get(arg);
112 }
113
114 if (ClassUtil.isSubclass(argClass, NullWrapper.class)) {
115 NullWrapper nullWrapper = (NullWrapper)arg;
116
117 argClass = Class.forName(
118 nullWrapper.getClassName(), true, _classLoader);
119
120 args[i] = null;
121 }
122
123 parameterTypes.add(argClass);
124 }
125
126 Method method = null;
127
128 try {
129 method = classObj.getMethod(
130 methodName,
131 parameterTypes.toArray(new Class[parameterTypes.size()]));
132 }
133 catch (NoSuchMethodException nsme) {
134 Method[] methods = ((Class<?>)classObj).getMethods();
135
136 for (int i = 0; i < methods.length; i++) {
137 Class<?>[] methodParameterTypes =
138 methods[i].getParameterTypes();
139
140 if (methods[i].getName().equals(methodName) &&
141 methodParameterTypes.length == 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 t1, ClassLoader contextClassLoader) {
186
187 try {
188 UnsyncByteArrayOutputStream ubaos =
189 new UnsyncByteArrayOutputStream();
190 ObjectOutputStream oos = new ObjectOutputStream(ubaos);
191
192 oos.writeObject(t1);
193
194 oos.flush();
195 oos.close();
196
197 UnsyncByteArrayInputStream bais = new UnsyncByteArrayInputStream(
198 ubaos.unsafeGetByteArray(), 0, ubaos.size());
199 ObjectInputStream ois = new ClassLoaderObjectInputStream(
200 bais, contextClassLoader);
201
202 t1 = (Throwable)ois.readObject();
203
204 ois.close();
205
206 return t1;
207 }
208 catch (Throwable t2) {
209 _log.error(t2, t2);
210
211 return t2;
212 }
213 }
214
215 private static Log _log = LogFactoryUtil.getLog(ClassLoaderProxy.class);
216
217 private Object _obj;
218 private ClassLoader _classLoader;
219 private String _className;
220
221 }