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