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 methodHandler.invoke(_obj);
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 public Object invoke(String methodName, Object[] args) throws Throwable {
083 Thread currentThread = Thread.currentThread();
084
085 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
086
087 try {
088 currentThread.setContextClassLoader(_classLoader);
089
090 Class<?> classObj = Class.forName(_className, true, _classLoader);
091
092 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
093
094 for (int i = 0; i < args.length; i++) {
095 Object arg = args[i];
096
097 Class<?> argClass = Class.forName(
098 arg.getClass().getName(), true, _classLoader);
099
100 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
101 MethodKey methodKey = new MethodKey(
102 argClass.getName(), "getValue");
103
104 Method method = MethodCache.get(methodKey);
105
106 args[i] = method.invoke(arg, (Object[])null);
107
108 argClass = (Class<?>)argClass.getField("TYPE").get(arg);
109 }
110
111 if (ClassUtil.isSubclass(argClass, NullWrapper.class)) {
112 NullWrapper nullWrapper = (NullWrapper)arg;
113
114 argClass = Class.forName(
115 nullWrapper.getClassName(), true, _classLoader);
116
117 args[i] = null;
118 }
119
120 parameterTypes.add(argClass);
121 }
122
123 Method method = null;
124
125 try {
126 method = classObj.getMethod(
127 methodName,
128 parameterTypes.toArray(new Class[parameterTypes.size()]));
129 }
130 catch (NoSuchMethodException nsme) {
131 Method[] methods = ((Class<?>)classObj).getMethods();
132
133 for (int i = 0; i < methods.length; i++) {
134 Class<?>[] methodParameterTypes =
135 methods[i].getParameterTypes();
136
137 if (methods[i].getName().equals(methodName) &&
138 methodParameterTypes.length == parameterTypes.size()) {
139
140 boolean correctParams = true;
141
142 for (int j = 0; j < parameterTypes.size(); j++) {
143 Class<?> a = parameterTypes.get(j);
144 Class<?> b = methodParameterTypes[j];
145
146 if (!ClassUtil.isSubclass(a, b)) {
147 correctParams = false;
148
149 break;
150 }
151 }
152
153 if (correctParams) {
154 method = methods[i];
155
156 break;
157 }
158 }
159 }
160
161 if (method == null) {
162 throw nsme;
163 }
164 }
165
166 return method.invoke(_obj, args);
167 }
168 catch (InvocationTargetException ite) {
169 throw translateThrowable(ite.getCause(), contextClassLoader);
170 }
171 catch (Throwable t) {
172 _log.error(t, t);
173
174 throw t;
175 }
176 finally {
177 currentThread.setContextClassLoader(contextClassLoader);
178 }
179 }
180
181 protected Throwable translateThrowable(
182 Throwable t1, ClassLoader contextClassLoader) {
183
184 try {
185 UnsyncByteArrayOutputStream ubaos =
186 new UnsyncByteArrayOutputStream();
187 ObjectOutputStream oos = new ObjectOutputStream(ubaos);
188
189 oos.writeObject(t1);
190
191 oos.flush();
192 oos.close();
193
194 UnsyncByteArrayInputStream bais = new UnsyncByteArrayInputStream(
195 ubaos.unsafeGetByteArray(), 0, ubaos.size());
196 ObjectInputStream ois = new ClassLoaderObjectInputStream(
197 bais, contextClassLoader);
198
199 t1 = (Throwable)ois.readObject();
200
201 ois.close();
202
203 return t1;
204 }
205 catch (Throwable t2) {
206 _log.error(t2, t2);
207
208 return t2;
209 }
210 }
211
212 private static Log _log = LogFactoryUtil.getLog(ClassLoaderProxy.class);
213
214 private Object _obj;
215 private ClassLoader _classLoader;
216 private String _className;
217
218 }