View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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;  // ignore
93          }
94          
95          // Return the selected class loader
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         // 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 }