001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.lib.util;
020:
021: import java.io.IOException;
022: import java.net.URL;
023: import java.security.AccessController;
024: import java.security.PrivilegedActionException;
025: import java.util.ArrayList;
026: import java.util.Enumeration;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Vector;
030:
031: /**
032: * Class loader type that can be configured to delegate to multiple
033: * internal class loaders.
034: * The {@link #THREAD_LOADER} constant is a marker that will be replaced
035: * with the context loader of the current thread.
036: *
037: * @author Abe White
038: */
039: public class MultiClassLoader extends ClassLoader {
040:
041: /**
042: * Marker that will be replaced with the context loader of the current
043: * thread whenever it is discovered in the class loader list.
044: */
045: public static final ClassLoader THREAD_LOADER = null;
046:
047: /**
048: * The standard system class loader.
049: */
050: public static final ClassLoader SYSTEM_LOADER = (ClassLoader) AccessController
051: .doPrivileged(J2DoPrivHelper.getSystemClassLoaderAction());
052:
053: private List _loaders = new ArrayList(5);
054:
055: /**
056: * Constructor; initializes the loader with an empty list of delegates.
057: */
058: public MultiClassLoader() {
059: super (null);
060: }
061:
062: /**
063: * Construct with the class loaders of another multi loader.
064: */
065: public MultiClassLoader(MultiClassLoader other) {
066: super (null);
067: addClassLoaders(other);
068: }
069:
070: /**
071: * Returns true if the list contains the given class loader or marker.
072: */
073: public boolean containsClassLoader(ClassLoader loader) {
074: return _loaders.contains(loader);
075: }
076:
077: /**
078: * Return an array of all contained class loaders.
079: */
080: public ClassLoader[] getClassLoaders() {
081: ClassLoader[] loaders = new ClassLoader[size()];
082: ClassLoader loader;
083: Iterator itr = _loaders.iterator();
084: for (int i = 0; i < loaders.length; i++) {
085: loader = (ClassLoader) itr.next();
086: if (loader == THREAD_LOADER)
087: loader = (ClassLoader) AccessController
088: .doPrivileged(J2DoPrivHelper
089: .getContextClassLoaderAction());
090: loaders[i] = loader;
091: }
092: return loaders;
093: }
094:
095: /**
096: * Return the class loader at the given index.
097: */
098: public ClassLoader getClassLoader(int index) {
099: ClassLoader loader = (ClassLoader) _loaders.get(index);
100: if (loader == THREAD_LOADER)
101: loader = (ClassLoader) AccessController
102: .doPrivileged(J2DoPrivHelper
103: .getContextClassLoaderAction());
104: return loader;
105: }
106:
107: /**
108: * Add the given class loader to the set of loaders that will be tried.
109: *
110: * @return true if the loader was added, false if already in the list
111: */
112: public boolean addClassLoader(ClassLoader loader) {
113: if (_loaders.contains(loader))
114: return false;
115: return _loaders.add(loader);
116: }
117:
118: /**
119: * Add the given class loader at the specified index.
120: *
121: * @return true if the loader was added, false if already in the list
122: */
123: public boolean addClassLoader(int index, ClassLoader loader) {
124: if (_loaders.contains(loader))
125: return false;
126: _loaders.add(index, loader);
127: return true;
128: }
129:
130: /**
131: * Set the class loaders of this loader to those of the given loader.
132: */
133: public void setClassLoaders(MultiClassLoader multi) {
134: clear();
135: addClassLoaders(multi);
136: }
137:
138: /**
139: * Adds all class loaders from the given multi loader starting at the
140: * given index.
141: *
142: * @return true if any loaders were added, false if all already in list
143: */
144: public boolean addClassLoaders(int index, MultiClassLoader multi) {
145: if (multi == null)
146: return false;
147:
148: // use iterator so that the thread loader is not resolved
149: boolean added = false;
150: for (Iterator itr = multi._loaders.iterator(); itr.hasNext();) {
151: if (addClassLoader(index, (ClassLoader) itr.next())) {
152: index++;
153: added = true;
154: }
155: }
156: return added;
157: }
158:
159: /**
160: * Adds all the class loaders from the given multi loader.
161: *
162: * @return true if any loaders were added, false if all already in list
163: */
164: public boolean addClassLoaders(MultiClassLoader multi) {
165: if (multi == null)
166: return false;
167:
168: // use iterator so that the thread loader is not resolved
169: boolean added = false;
170: for (Iterator itr = multi._loaders.iterator(); itr.hasNext();)
171: added = addClassLoader((ClassLoader) itr.next()) || added;
172: return added;
173: }
174:
175: /**
176: * Remove the given loader from the list.
177: *
178: * @return true if removed, false if not in list
179: */
180: public boolean removeClassLoader(ClassLoader loader) {
181: return _loaders.remove(loader);
182: }
183:
184: /**
185: * Clear the list of class loaders.
186: */
187: public void clear() {
188: _loaders.clear();
189: }
190:
191: /**
192: * Return the number of internal class loaders.
193: */
194: public int size() {
195: return _loaders.size();
196: }
197:
198: /**
199: * Return true if there are no internal class laoders.
200: */
201: public boolean isEmpty() {
202: return _loaders.isEmpty();
203: }
204:
205: protected Class findClass(String name)
206: throws ClassNotFoundException {
207: ClassLoader loader;
208: for (Iterator itr = _loaders.iterator(); itr.hasNext();) {
209: loader = (ClassLoader) itr.next();
210: if (loader == THREAD_LOADER)
211: loader = (ClassLoader) AccessController
212: .doPrivileged(J2DoPrivHelper
213: .getContextClassLoaderAction());
214: try {
215: return Class.forName(name, false, loader);
216: } catch (Throwable t) {
217: }
218: }
219: throw new ClassNotFoundException(name);
220: }
221:
222: protected URL findResource(String name) {
223: ClassLoader loader;
224: URL rsrc;
225: for (Iterator itr = _loaders.iterator(); itr.hasNext();) {
226: loader = (ClassLoader) itr.next();
227: if (loader == THREAD_LOADER)
228: loader = (ClassLoader) AccessController
229: .doPrivileged(J2DoPrivHelper
230: .getContextClassLoaderAction());
231:
232: if (loader == null) // skip
233: continue;
234:
235: rsrc = (URL) AccessController.doPrivileged(J2DoPrivHelper
236: .getResourceAction(loader, name));
237: if (rsrc != null)
238: return rsrc;
239: }
240: return null;
241: }
242:
243: protected Enumeration findResources(String name) throws IOException {
244: ClassLoader loader;
245: Enumeration rsrcs;
246: Object rsrc;
247: Vector all = new Vector();
248: for (Iterator itr = _loaders.iterator(); itr.hasNext();) {
249: loader = (ClassLoader) itr.next();
250: if (loader == THREAD_LOADER)
251: loader = (ClassLoader) AccessController
252: .doPrivileged(J2DoPrivHelper
253: .getContextClassLoaderAction());
254:
255: if (loader == null) // skip
256: continue;
257:
258: try {
259: rsrcs = (Enumeration) AccessController
260: .doPrivileged(J2DoPrivHelper
261: .getResourcesAction(loader, name));
262: while (rsrcs.hasMoreElements()) {
263: rsrc = rsrcs.nextElement();
264: if (!all.contains(rsrc))
265: all.addElement(rsrc);
266: }
267: } catch (PrivilegedActionException pae) {
268: throw (IOException) pae.getException();
269: }
270: }
271: return all.elements();
272: }
273:
274: public boolean equals(Object other) {
275: if (other == this )
276: return true;
277: if (!(other instanceof MultiClassLoader))
278: return false;
279: return ((MultiClassLoader) other)._loaders.equals(_loaders);
280: }
281:
282: public int hashCode() {
283: return _loaders.hashCode();
284: }
285: }
|