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 }