001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.util; 015 016import java.io.IOException; 017import java.net.URL; 018import java.security.AccessController; 019import java.security.PrivilegedAction; 020import java.util.Enumeration; 021import java.util.Set; 022import java.util.HashSet; 023 024import ch.qos.logback.core.Context; 025 026/** 027 * Load resources (or images) from various sources. 028 * 029 * @author Ceki Gülcü 030 */ 031public class Loader { 032 static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous."; 033 034 private static boolean ignoreTCL = false; 035 public static final String IGNORE_TCL_PROPERTY_NAME = "logback.ignoreTCL"; 036 private static boolean HAS_GET_CLASS_LOADER_PERMISSION = false; 037 038 static { 039 String ignoreTCLProp = OptionHelper.getSystemProperty(IGNORE_TCL_PROPERTY_NAME, null); 040 041 if (ignoreTCLProp != null) { 042 ignoreTCL = OptionHelper.toBoolean(ignoreTCLProp, true); 043 } 044 045 HAS_GET_CLASS_LOADER_PERMISSION = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 046 public Boolean run() { 047 try { 048 AccessController.checkPermission(new RuntimePermission("getClassLoader")); 049 return true; 050 } catch (SecurityException e) { 051 // Using SecurityException instead of AccessControlException. 052 // See bug LOGBACK-760. 053 return false; 054 } 055 } 056 }); 057 } 058 059 /** 060 * Compute the number of occurrences a resource can be found by a class loader. 061 * 062 * @param resource 063 * @param classLoader 064 * @return 065 * @throws IOException 066 */ 067 068 public static Set<URL> getResources(String resource, ClassLoader classLoader) throws IOException { 069 // See LBCLASSIC-159 070 Set<URL> urlSet = new HashSet<URL>(); 071 Enumeration<URL> urlEnum = classLoader.getResources(resource); 072 while (urlEnum.hasMoreElements()) { 073 URL url = urlEnum.nextElement(); 074 urlSet.add(url); 075 } 076 return urlSet; 077 } 078 079 /** 080 * Search for a resource using the classloader passed as parameter. 081 * 082 * @param resource the resource name to look for 083 * @param classLoader the classloader used for the search 084 */ 085 public static URL getResource(String resource, ClassLoader classLoader) { 086 try { 087 return classLoader.getResource(resource); 088 } catch (Throwable t) { 089 return null; 090 } 091 } 092 093 /** 094 * Attempt to find a resource by using the classloader that loaded this class, 095 * namely Loader.class. 096 * 097 * @param resource 098 * @return 099 */ 100 public static URL getResourceBySelfClassLoader(String resource) { 101 return getResource(resource, getClassLoaderOfClass(Loader.class)); 102 } 103 104 // private static URL getResourceByTCL(String resource) { 105 // return getResource(resource, getTCL()); 106 // } 107 108 /** 109 * Get the Thread Context Loader which is a JDK 1.2 feature. If we are running 110 * under JDK 1.1 or anything else goes wrong the method returns {@code null}. 111 */ 112 public static ClassLoader getTCL() { 113 return Thread.currentThread().getContextClassLoader(); 114 } 115 116 public static Class<?> loadClass(String clazz, Context context) throws ClassNotFoundException { 117 ClassLoader cl = getClassLoaderOfObject(context); 118 return cl.loadClass(clazz); 119 } 120 121 /** 122 * Get the class loader of the object passed as argument. Return the system 123 * class loader if appropriate. 124 * 125 * @param o 126 * @return 127 */ 128 public static ClassLoader getClassLoaderOfObject(Object o) { 129 if (o == null) { 130 throw new NullPointerException("Argument cannot be null"); 131 } 132 return getClassLoaderOfClass(o.getClass()); 133 } 134 135 /** 136 * Returns the class loader of clazz in an access privileged section. 137 * 138 * @param clazz 139 * @return 140 */ 141 public static ClassLoader getClassLoaderAsPrivileged(final Class<?> clazz) { 142 if (!HAS_GET_CLASS_LOADER_PERMISSION) 143 return null; 144 else 145 return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { 146 public ClassLoader run() { 147 return clazz.getClassLoader(); 148 } 149 }); 150 } 151 152 /** 153 * Return the class loader which loaded the class passed as argument. Return the 154 * system class loader if appropriate. 155 * 156 * @param clazz 157 * @return 158 */ 159 public static ClassLoader getClassLoaderOfClass(final Class<?> clazz) { 160 ClassLoader cl = clazz.getClassLoader(); 161 if (cl == null) { 162 return ClassLoader.getSystemClassLoader(); 163 } else { 164 return cl; 165 } 166 } 167 168 /** 169 * If running under JDK 1.2 load the specified class using the 170 * <code>Thread</code> <code>contextClassLoader</code> if that fails try 171 * Class.forname. Under JDK 1.1 only Class.forName is used. 172 */ 173 public static Class<?> loadClass(String clazz) throws ClassNotFoundException { 174 // Just call Class.forName(clazz) if we are running under JDK 1.1 175 // or if we are instructed to ignore the TCL. 176 if (ignoreTCL) { 177 return Class.forName(clazz); 178 } else { 179 try { 180 return getTCL().loadClass(clazz); 181 } catch (Throwable e) { 182 // we reached here because tcl was null or because of a 183 // security exception, or because clazz could not be loaded... 184 // In any case we now try one more time 185 return Class.forName(clazz); 186 } 187 } 188 } 189}