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.jdk;
018:
019: import java.io.IOException;
020: import java.net.URL;
021: import java.util.Collections;
022: import java.util.Enumeration;
023:
024: import org.apache.commons.discovery.log.DiscoveryLogFactory;
025: import org.apache.commons.logging.Log;
026:
027: /**
028: * @author Richard A. Sitze
029: */
030: public class JDK12Hooks extends JDKHooks {
031:
032: /**
033: * Logger
034: */
035: private static Log log = DiscoveryLogFactory
036: .newLog(JDK12Hooks.class);
037:
038: private static final ClassLoader systemClassLoader = findSystemClassLoader();
039:
040: /**
041: * Must be implemented to use DiscoveryLogFactory
042: */
043: public static void setLog(Log _log) {
044: log = _log;
045: }
046:
047: /**
048: * Get the system property
049: *
050: * @param propName name of the property
051: * @return value of the property
052: */
053: public String getSystemProperty(final String propName) {
054: return (String) java.security.AccessController
055: .doPrivileged(new java.security.PrivilegedAction() {
056: public Object run() {
057: try {
058: return System.getProperty(propName);
059: } catch (SecurityException se) {
060: return null;
061: }
062: }
063: });
064: }
065:
066: /**
067: * The thread context class loader is available for JDK 1.2
068: * or later, if certain security conditions are met.
069: *
070: * @return The thread context class loader, if available.
071: * Otherwise return null.
072: */
073: public ClassLoader getThreadContextClassLoader() {
074: ClassLoader classLoader;
075:
076: try {
077: classLoader = Thread.currentThread()
078: .getContextClassLoader();
079: } catch (SecurityException e) {
080: /**
081: * SecurityException is thrown when
082: * a) the context class loader isn't an ancestor of the
083: * calling class's class loader, or
084: * b) if security permissions are restricted.
085: *
086: * For (a), ignore and keep going. We cannot help but also
087: * ignore (b) with the logic below, but other calls elsewhere
088: * (to obtain a class loader) will re-trigger this exception
089: * where we can make a distinction.
090: */
091: classLoader = null; // ignore
092: }
093:
094: // Return the selected class loader
095: return classLoader;
096: }
097:
098: /**
099: * The system class loader is available for JDK 1.2
100: * or later, if certain security conditions are met.
101: *
102: * @return The system class loader, if available.
103: * Otherwise return null.
104: */
105: public ClassLoader getSystemClassLoader() {
106: return systemClassLoader;
107: }
108:
109: /**
110: * Implement ClassLoader.getResources for JDK 1.2
111: */
112: public Enumeration getResources(ClassLoader loader,
113: String resourceName) throws IOException {
114: /**
115: * The simple answer is/was:
116: * return loader.getResources(resourceName);
117: *
118: * However, some classloaders overload the behavior of getResource
119: * (loadClass, etc) such that the order of returned results changes
120: * from normally expected behavior.
121: *
122: * Example: locate classes/resources from child ClassLoaders first,
123: * parents last (in some J2EE environs).
124: *
125: * The resource returned by getResource() should be the same as the
126: * first resource returned by getResources(). Unfortunately, this
127: * is not, and cannot be: getResources() is 'final' in the current
128: * JDK's (1.2, 1.3, 1.4).
129: *
130: * To address this, the implementation of this method will
131: * return an Enumeration such that the first element is the
132: * results of getResource, and all trailing elements are
133: * from getResources. On each iteration, we check so see
134: * if the resource (from getResources) matches the first resource,
135: * and eliminate the redundent element.
136: */
137:
138: final URL first = loader.getResource(resourceName);
139:
140: // XXX: Trying to avoid JBoss UnifiedClassLoader problem
141:
142: Enumeration resources;
143:
144: if (first == null) {
145: log.debug("Could not find resource: " + resourceName);
146: resources = Collections.enumeration(Collections.EMPTY_LIST);
147:
148: } else {
149:
150: try {
151:
152: resources = loader.getResources(resourceName);
153:
154: } catch (RuntimeException ex) {
155: log.error("Exception occured during attept to get "
156: + resourceName + " from " + first, ex);
157: resources = Collections
158: .enumeration(Collections.EMPTY_LIST);
159: }
160:
161: resources = getResourcesFromUrl(first, resources);
162: }
163:
164: return resources;
165: }
166:
167: private static Enumeration getResourcesFromUrl(final URL first,
168: final Enumeration rest) {
169: return new Enumeration() {
170: private boolean firstDone = (first == null);
171: private URL next = getNext();
172:
173: public Object nextElement() {
174: URL o = next;
175: next = getNext();
176: return o;
177: }
178:
179: public boolean hasMoreElements() {
180: return next != null;
181: }
182:
183: private URL getNext() {
184: URL n;
185:
186: if (!firstDone) {
187: /**
188: * First time through, use results of getReference()
189: * if they were non-null.
190: */
191: firstDone = true;
192: n = first;
193: } else {
194: /**
195: * Subsequent times through,
196: * use results of getReferences()
197: * but take out anything that matches 'first'.
198: *
199: * Iterate through list until we find one that
200: * doesn't match 'first'.
201: */
202: n = null;
203: while (rest.hasMoreElements() && n == null) {
204: n = (URL) rest.nextElement();
205: if (first != null && n != null
206: && n.equals(first)) {
207: n = null;
208: }
209: }
210: }
211:
212: return n;
213: }
214: };
215: }
216:
217: static private ClassLoader findSystemClassLoader() {
218: ClassLoader classLoader;
219:
220: try {
221: classLoader = ClassLoader.getSystemClassLoader();
222: } catch (SecurityException e) {
223: /**
224: * Ignore and keep going.
225: */
226: classLoader = null;
227: }
228:
229: if (classLoader == null) {
230: SecurityManager security = System.getSecurityManager();
231: if (security != null) {
232: try {
233: security.checkCreateClassLoader();
234: classLoader = new PsuedoSystemClassLoader();
235: } catch (SecurityException se) {
236: }
237: }
238: }
239:
240: // Return the selected class loader
241: return classLoader;
242: }
243: }
|