001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 *****************************************************************************/ 009 010 package org.picocontainer.security; 011 012 import java.net.URL; 013 import java.net.URLClassLoader; 014 import java.security.AccessController; 015 import java.security.CodeSource; 016 import java.security.PermissionCollection; 017 import java.security.Permissions; 018 import java.security.PrivilegedAction; 019 import java.util.Map; 020 021 /** 022 * CustomPermissionsURLClassLoader extends URLClassLoader, adding the abilty to programatically add permissions easily. 023 * To be effective for permission management, it should be run in conjunction with a policy that restricts 024 * some of the classloaders, but not all. 025 * It's not ordinarily used by PicoContainer, but is here because PicoContainer is common 026 * to most classloader trees. 027 * 028 * @author Paul Hammant 029 */ 030 public class CustomPermissionsURLClassLoader extends URLClassLoader { 031 private final Map<URL, Permissions> permissionsMap; 032 033 public CustomPermissionsURLClassLoader(URL[] urls, Map<URL, Permissions> permissionsMap, ClassLoader parent) { 034 super(urls, parent); 035 this.permissionsMap = permissionsMap; 036 } 037 038 public Class<?> loadClass(String name) throws ClassNotFoundException { 039 try { 040 return super.loadClass(name); 041 } catch (ClassNotFoundException e) { 042 throw decorateException(name, e); 043 } 044 } 045 046 protected Class<?> findClass(String name) throws ClassNotFoundException { 047 try { 048 return super.findClass(name); 049 } catch (ClassNotFoundException e) { 050 throw decorateException(name, e); 051 } 052 } 053 054 private ClassNotFoundException decorateException(String name, ClassNotFoundException e) { 055 if (name.startsWith("class ")) { 056 return new ClassNotFoundException("Class '" + name + "' is not a classInstance.getName(). " + 057 "It's a classInstance.toString(). The clue is that it starts with 'class ', no classname contains a space."); 058 } 059 ClassLoader classLoader = this; 060 StringBuffer sb = new StringBuffer("'").append(name).append("' classloader stack ["); 061 while (classLoader != null) { 062 sb.append(classLoader.toString()).append("\n"); 063 final ClassLoader cl = classLoader; 064 classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { 065 public ClassLoader run() { 066 return cl.getParent(); 067 } 068 }); 069 070 } 071 return new ClassNotFoundException(sb.append("]").toString(), e); 072 } 073 074 public String toString() { 075 String result = CustomPermissionsURLClassLoader.class.getName() + " " + System.identityHashCode(this) + ":"; 076 URL[] urls = getURLs(); 077 for (URL url : urls) { 078 result += "\n\t" + url.toString(); 079 } 080 081 return result; 082 } 083 084 public PermissionCollection getPermissions(CodeSource codeSource) { 085 return (Permissions) permissionsMap.get(codeSource.getLocation()); 086 } 087 088 } 089