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.Object;
026 import java.lang.reflect.InvocationTargetException;
027 import java.lang.reflect.Method;
028
029 import java.util.ArrayList;
030 import java.util.List;
031
032
035 public class ClassLoaderProxy {
036
037
040 public ClassLoaderProxy(Object obj, ClassLoader classLoader) {
041 this(obj, obj.getClass().getName(), classLoader);
042 }
043
044 public ClassLoaderProxy(
045 Object obj, String className, ClassLoader classLoader) {
046
047 _obj = obj;
048 _className = className;
049 _classLoader = classLoader;
050 }
051
052 public ClassLoader getClassLoader() {
053 return _classLoader;
054 }
055
056 public Object invoke(String methodName, Object[] args) throws Throwable {
057 Thread currentThread = Thread.currentThread();
058
059 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
060
061 try {
062 currentThread.setContextClassLoader(_classLoader);
063
064 Class<?> classObj = Class.forName(_className, true, _classLoader);
065
066 List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
067
068 for (int i = 0; i < args.length; i++) {
069 Object arg = args[i];
070
071 Class<?> argClass = Class.forName(
072 arg.getClass().getName(), true, _classLoader);
073
074 if (ClassUtil.isSubclass(argClass, PrimitiveWrapper.class)) {
075 MethodKey methodKey = new MethodKey(
076 argClass.getName(), "getValue", null);
077
078 Method method = MethodCache.get(methodKey);
079
080 args[i] = method.invoke(arg, (Object[])null);
081
082 argClass = (Class<?>)argClass.getField("TYPE").get(arg);
083 }
084
085 if (ClassUtil.isSubclass(argClass, NullWrapper.class)) {
086 NullWrapper nullWrapper = (NullWrapper)arg;
087
088 argClass = Class.forName(
089 nullWrapper.getClassName(), true, _classLoader);
090
091 args[i] = null;
092 }
093
094 parameterTypes.add(argClass);
095 }
096
097 Method method = null;
098
099 try {
100 method = classObj.getMethod(
101 methodName,
102 parameterTypes.toArray(new Class[parameterTypes.size()]));
103 }
104 catch (NoSuchMethodException nsme) {
105 Method[] methods = ((Class<?>)classObj).getMethods();
106
107 for (int i = 0; i < methods.length; i++) {
108 Class<?>[] methodParameterTypes =
109 methods[i].getParameterTypes();
110
111 if (methods[i].getName().equals(methodName) &&
112 methodParameterTypes.length == parameterTypes.size()) {
113
114 boolean correctParams = true;
115
116 for (int j = 0; j < parameterTypes.size(); j++) {
117 Class<?> a = parameterTypes.get(j);
118 Class<?> b = methodParameterTypes[j];
119
120 if (!ClassUtil.isSubclass(a, b)) {
121 correctParams = false;
122
123 break;
124 }
125 }
126
127 if (correctParams) {
128 method = methods[i];
129
130 break;
131 }
132 }
133 }
134
135 if (method == null) {
136 throw nsme;
137 }
138 }
139
140 return method.invoke(_obj, args);
141 }
142 catch (InvocationTargetException ite) {
143 throw translateThrowable(ite.getCause(), contextClassLoader);
144 }
145 catch (Throwable t) {
146 _log.error(t, t);
147
148 throw t;
149 }
150 finally {
151 currentThread.setContextClassLoader(contextClassLoader);
152 }
153 }
154
155 protected Throwable translateThrowable(
156 Throwable t1, ClassLoader contextClassLoader) {
157
158 try {
159 UnsyncByteArrayOutputStream ubaos =
160 new UnsyncByteArrayOutputStream();
161 ObjectOutputStream oos = new ObjectOutputStream(ubaos);
162
163 oos.writeObject(t1);
164
165 oos.flush();
166 oos.close();
167
168 UnsyncByteArrayInputStream bais = new UnsyncByteArrayInputStream(
169 ubaos.unsafeGetByteArray(), 0, ubaos.size());
170 ObjectInputStream ois = new ClassLoaderObjectInputStream(
171 bais, contextClassLoader);
172
173 t1 = (Throwable)ois.readObject();
174
175 ois.close();
176
177 return t1;
178 }
179 catch (Throwable t2) {
180 _log.error(t2, t2);
181
182 return t2;
183 }
184 }
185
186 private static Log _log = LogFactoryUtil.getLog(ClassLoaderProxy.class);
187
188 private Object _obj;
189 private ClassLoader _classLoader;
190 private String _className;
191
192 }