1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.discovery.jdk;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.util.Collections;
22 import java.util.Enumeration;
23
24 import org.apache.commons.discovery.log.DiscoveryLogFactory;
25 import org.apache.commons.logging.Log;
26
27
28 /***
29 * @author Richard A. Sitze
30 */
31 public class JDK12Hooks extends JDKHooks {
32
33 /***
34 * Logger
35 */
36 private static Log log = DiscoveryLogFactory.newLog(JDK12Hooks.class);
37
38
39 private static final ClassLoader systemClassLoader
40 = findSystemClassLoader();
41
42 /***
43 * Must be implemented to use DiscoveryLogFactory
44 */
45 public static void setLog(Log _log) {
46 log = _log;
47 }
48
49 /***
50 * Get the system property
51 *
52 * @param propName name of the property
53 * @return value of the property
54 */
55 public String getSystemProperty(final String propName) {
56 return (String)
57 java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
58 public Object run() {
59 try {
60 return System.getProperty(propName);
61 } catch (SecurityException se){
62 return null;
63 }
64 }
65 });
66 }
67
68 /***
69 * The thread context class loader is available for JDK 1.2
70 * or later, if certain security conditions are met.
71 *
72 * @return The thread context class loader, if available.
73 * Otherwise return null.
74 */
75 public ClassLoader getThreadContextClassLoader() {
76 ClassLoader classLoader;
77
78 try {
79 classLoader = Thread.currentThread().getContextClassLoader();
80 } catch (SecurityException e) {
81 /***
82 * SecurityException is thrown when
83 * a) the context class loader isn't an ancestor of the
84 * calling class's class loader, or
85 * b) if security permissions are restricted.
86 *
87 * For (a), ignore and keep going. We cannot help but also
88 * ignore (b) with the logic below, but other calls elsewhere
89 * (to obtain a class loader) will re-trigger this exception
90 * where we can make a distinction.
91 */
92 classLoader = null;
93 }
94
95
96 return classLoader;
97 }
98
99 /***
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
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
244 return classLoader;
245 }
246 }