1
14
15 package com.liferay.portal.kernel.util;
16
17 import com.liferay.portal.kernel.log.Log;
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
19
20 import java.lang.ref.WeakReference;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.List;
28
29
36 public class AggregateClassLoader extends ClassLoader {
37
38 public static ClassLoader getAggregateClassLoader(
39 ClassLoader parentClassLoader, ClassLoader[] classLoaders) {
40
41 if ((classLoaders == null) || (classLoaders.length == 0)) {
42 return null;
43 }
44
45 if (classLoaders.length == 1) {
46 return classLoaders[0];
47 }
48
49 AggregateClassLoader aggregateClassLoader = new AggregateClassLoader(
50 parentClassLoader);
51
52 for (ClassLoader classLoader : classLoaders) {
53 aggregateClassLoader.addClassLoader(classLoader);
54 }
55
56 return aggregateClassLoader;
57 }
58
59 public static ClassLoader getAggregateClassLoader(
60 ClassLoader[] classLoaders) {
61
62 if ((classLoaders == null) || (classLoaders.length == 0)) {
63 return null;
64 }
65
66 return getAggregateClassLoader(classLoaders[0], classLoaders);
67 }
68
69 public AggregateClassLoader(ClassLoader classLoader) {
70 _parentClassLoaderReference = new WeakReference<ClassLoader>(
71 classLoader);
72 }
73
74 public void addClassLoader(ClassLoader classLoader) {
75 if (getClassLoaders().contains(classLoader)) {
76 return;
77 }
78
79 if ((classLoader instanceof AggregateClassLoader) &&
80 (classLoader.getParent().equals(getParent()))){
81
82 AggregateClassLoader aggregateClassLoader =
83 (AggregateClassLoader)classLoader;
84
85 for (ClassLoader curClassLoader :
86 aggregateClassLoader.getClassLoaders()) {
87
88 addClassLoader(curClassLoader);
89 }
90 }
91 else {
92 _classLoaderReferences.add(
93 new WeakReference<ClassLoader>(classLoader));
94 }
95 }
96
97 public void addClassLoader(ClassLoader... classLoaders) {
98 for (ClassLoader classLoader : classLoaders) {
99 addClassLoader(classLoader);
100 }
101 }
102
103 public void addClassLoader(Collection<ClassLoader> classLoaders) {
104 for (ClassLoader classLoader : classLoaders) {
105 addClassLoader(classLoader);
106 }
107 }
108
109 public boolean equals(Object obj) {
110 if (this == obj) {
111 return true;
112 }
113
114 if (!(obj instanceof AggregateClassLoader)) {
115 return false;
116 }
117
118 AggregateClassLoader aggregateClassLoader = (AggregateClassLoader)obj;
119
120 if (_classLoaderReferences.equals(
121 aggregateClassLoader._classLoaderReferences) &&
122 (((getParent() == null) &&
123 (aggregateClassLoader.getParent() == null)) ||
124 ((getParent() != null) &&
125 (getParent().equals(aggregateClassLoader.getParent()))))) {
126
127 return true;
128 }
129
130 return false;
131 }
132
133 public List<ClassLoader> getClassLoaders() {
134 List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
135 _classLoaderReferences.size());
136
137 Iterator<WeakReference<ClassLoader>> itr =
138 _classLoaderReferences.iterator();
139
140 while (itr.hasNext()) {
141 WeakReference<ClassLoader> weakReference = itr.next();
142
143 ClassLoader classLoader = weakReference.get();
144
145 if (classLoader == null) {
146 itr.remove();
147 }
148 else {
149 classLoaders.add(classLoader);
150 }
151 }
152
153 return classLoaders;
154 }
155
156 public int hashCode() {
157 if (_classLoaderReferences != null) {
158 return _classLoaderReferences.hashCode();
159 }
160 else {
161 return 0;
162 }
163 }
164
165 protected Class<?> findClass(String name) throws ClassNotFoundException {
166 for (ClassLoader classLoader : getClassLoaders()) {
167 try {
168 return _findClass(classLoader, name);
169 }
170 catch (ClassNotFoundException cnfe) {
171 }
172 }
173
174 throw new ClassNotFoundException("Unable to find class " + name);
175 }
176
177 protected Class<?> loadClass(String name, boolean resolve)
178 throws ClassNotFoundException {
179
180 Class<?> loadedClass = null;
181
182 for (ClassLoader classLoader : getClassLoaders()) {
183 try {
184 loadedClass = _loadClass(classLoader, name, resolve);
185
186 break;
187 }
188 catch (ClassNotFoundException cnfe) {
189 }
190 }
191
192 if (loadedClass == null) {
193 ClassLoader parentClassLoader = _parentClassLoaderReference.get();
194
195 if (parentClassLoader == null) {
196 throw new ClassNotFoundException(
197 "Parent class loader has been garbage collected");
198 }
199
200 loadedClass = _loadClass(parentClassLoader, name, resolve);
201 }
202 else if (resolve) {
203 resolveClass(loadedClass);
204 }
205
206 return loadedClass;
207 }
208
209 private static Log _log = LogFactoryUtil.getLog(AggregateClassLoader.class);
210
211 private List<WeakReference<ClassLoader>> _classLoaderReferences =
212 new ArrayList<WeakReference<ClassLoader>>();
213
214 private static Class<?> _findClass(ClassLoader classLoader, String name)
215 throws ClassNotFoundException {
216
217 try {
218 return (Class<?>) _findClassMethod.invoke(classLoader, name);
219 }
220 catch (InvocationTargetException ite) {
221 throw new ClassNotFoundException(
222 "Unable to find class " + name, ite.getTargetException());
223 }
224 catch (Exception e) {
225 throw new ClassNotFoundException("Unable to find class " + name, e);
226 }
227 }
228
229 private static Class<?> _loadClass(
230 ClassLoader classLoader, String name, boolean resolve)
231 throws ClassNotFoundException {
232
233 try {
234 return (Class<?>) _loadClassMethod.invoke(
235 classLoader, name, resolve);
236 }
237 catch (InvocationTargetException ite) {
238 throw new ClassNotFoundException(
239 "Unable to load class " + name, ite.getTargetException());
240 }
241 catch (Exception e) {
242 throw new ClassNotFoundException(
243 "Unable to load class " + name, e);
244 }
245 }
246
247 private static Method _findClassMethod;
248 private static Method _loadClassMethod;
249
250 private WeakReference<ClassLoader> _parentClassLoaderReference;
251
252 static {
253 try {
254 _findClassMethod = ReflectionUtil.getDeclaredMethod(
255 ClassLoader.class, "findClass", String.class);
256 _loadClassMethod = ReflectionUtil.getDeclaredMethod(
257 ClassLoader.class, "loadClass", String.class, boolean.class);
258 }
259 catch (Exception e) {
260 if (_log.isErrorEnabled()) {
261 _log.error("Unable to locate required methods", e);
262 }
263 }
264 }
265
266 }