001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.discovery.resource;
018:
019: import java.util.Vector;
020:
021: import org.apache.commons.discovery.jdk.JDKHooks;
022:
023: /**
024: * There are many different contexts in which
025: * loaders can be used. This provides a holder
026: * for a set of class loaders, so that they
027: * don't have to be build back up everytime...
028: *
029: * @author Richard A. Sitze
030: * @author Craig R. McClanahan
031: * @author Costin Manolache
032: */
033: public class ClassLoaders {
034: protected Vector classLoaders = new Vector();
035:
036: /** Construct a new class loader set
037: */
038: public ClassLoaders() {
039: }
040:
041: public int size() {
042: return classLoaders.size();
043: }
044:
045: public ClassLoader get(int idx) {
046: return (ClassLoader) classLoaders.elementAt(idx);
047: }
048:
049: /**
050: * Specify a new class loader to be used in searching.
051: * The order of loaders determines the order of the result.
052: * It is recommended to add the most specific loaders first.
053: */
054: public void put(ClassLoader classLoader) {
055: if (classLoader != null) {
056: classLoaders.addElement(classLoader);
057: }
058: }
059:
060: /**
061: * Specify a new class loader to be used in searching.
062: * The order of loaders determines the order of the result.
063: * It is recommended to add the most specific loaders first.
064: *
065: * @param prune if true, verify that the class loader is
066: * not an Ancestor (@see isAncestor) before
067: * adding it to our list.
068: */
069: public void put(ClassLoader classLoader, boolean prune) {
070: if (classLoader != null && !(prune && isAncestor(classLoader))) {
071: classLoaders.addElement(classLoader);
072: }
073: }
074:
075: /**
076: * Check to see if <code>classLoader</code> is an
077: * ancestor of any contained class loader.
078: *
079: * This can be used to eliminate redundant class loaders
080: * IF all class loaders defer to parent class loaders
081: * before resolving a class.
082: *
083: * It may be that this is not always true. Therefore,
084: * this check is not done internally to eliminate
085: * redundant class loaders, but left to the discretion
086: * of the user.
087: */
088: public boolean isAncestor(final ClassLoader classLoader) {
089: /* bootstrap classloader, at root of all trees! */
090: if (classLoader == null)
091: return true;
092:
093: for (int idx = 0; idx < size(); idx++) {
094: for (ClassLoader walker = get(idx); walker != null; walker = walker
095: .getParent()) {
096: if (walker == classLoader) {
097: return true;
098: }
099: }
100: }
101: return false;
102: }
103:
104: /**
105: * Utility method. Returns a preloaded ClassLoaders instance
106: * containing the following class loaders, in order:
107: *
108: * <ul>
109: * <li>spi.getClassLoader</li>
110: * <li>seeker.getClassLoader</li>
111: * <li>System Class Loader</li>
112: * </ul>
113: *
114: * Note that the thread context class loader is NOT present.
115: * This is a reasonable set of loaders to try if the resource to be found
116: * should be restricted to a libraries containing the SPI and Factory.
117: *
118: * @param spi WHAT is being looked for (an implementation of this class,
119: * a default property file related to this class).
120: * @param factory WHO is performing the lookup.
121: * @param prune Determines if ancestors are allowed to be loaded or not.
122: */
123: public static ClassLoaders getLibLoaders(Class spi, Class factory,
124: boolean prune) {
125: ClassLoaders loaders = new ClassLoaders();
126:
127: if (spi != null)
128: loaders.put(spi.getClassLoader());
129: if (factory != null)
130: loaders.put(factory.getClassLoader(), prune);
131: loaders.put(JDKHooks.getJDKHooks().getSystemClassLoader(),
132: prune);
133:
134: return loaders;
135: }
136:
137: /**
138: * Utility method. Returns a preloaded ClassLoaders instance
139: * containing the following class loaders, in order:
140: *
141: * <ul>
142: * <li>Thread Context Class Loader</li>
143: * <li>spi.getClassLoader</li>
144: * <li>seeker.getClassLoader</li>
145: * <li>System Class Loader</li>
146: * </ul>
147: *
148: * Note that the thread context class loader IS present.
149: * This is a reasonable set of loaders to try if the resource to be found
150: * may be provided by an application.
151: *
152: * @param spi WHAT is being looked for (an implementation of this class,
153: * a default property file related to this class).
154: * @param factory WHO is performing the lookup (factory).
155: * @param prune Determines if ancestors are allowed to be loaded or not.
156: */
157: public static ClassLoaders getAppLoaders(Class spi, Class factory,
158: boolean prune) {
159: ClassLoaders loaders = new ClassLoaders();
160:
161: loaders.put(JDKHooks.getJDKHooks()
162: .getThreadContextClassLoader());
163: if (spi != null)
164: loaders.put(spi.getClassLoader(), prune);
165: if (factory != null)
166: loaders.put(factory.getClassLoader(), prune);
167: loaders.put(JDKHooks.getJDKHooks().getSystemClassLoader(),
168: prune);
169:
170: return loaders;
171: }
172: }
|