ReflectUtil.java revision 499346040d83c7103a67e776ae59b8057ce38aaa
1/* 2 * Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27package sun.reflect.misc; 28import java.lang.reflect.Proxy; 29 30public final class ReflectUtil { 31 32 private ReflectUtil() { 33 } 34 35 public static Class forName(String name) 36 throws ClassNotFoundException { 37 checkPackageAccess(name); 38 return Class.forName(name); 39 } 40 41 public static Object newInstance(Class cls) 42 throws InstantiationException, IllegalAccessException { 43 checkPackageAccess(cls); 44 return cls.newInstance(); 45 } 46 47 private static boolean isSubclassOf(Class queryClass, 48 Class ofClass) 49 { 50 while (queryClass != null) { 51 if (queryClass == ofClass) { 52 return true; 53 } 54 queryClass = queryClass.getSuperclass(); 55 } 56 return false; 57 } 58 59 /** 60 * Checks package access on the given class. 61 * 62 * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements 63 * a non-public interface (i.e. may be in a non-restricted package), 64 * also check the package access on the proxy interfaces. 65 */ 66 public static void checkPackageAccess(Class<?> clazz) { 67 checkPackageAccess(clazz.getName()); 68 if (isNonPublicProxyClass(clazz)) { 69 checkProxyPackageAccess(clazz); 70 } 71 } 72 73 /** 74 * Checks package access on the given classname. 75 * This method is typically called when the Class instance is not 76 * available and the caller attempts to load a class on behalf 77 * the true caller (application). 78 */ 79 public static void checkPackageAccess(String name) { 80 SecurityManager s = System.getSecurityManager(); 81 if (s != null) { 82 String cname = name.replace('/', '.'); 83 if (cname.startsWith("[")) { 84 int b = cname.lastIndexOf('[') + 2; 85 if (b > 1 && b < cname.length()) { 86 cname = cname.substring(b); 87 } 88 } 89 int i = cname.lastIndexOf('.'); 90 if (i != -1) { 91 s.checkPackageAccess(cname.substring(0, i)); 92 } 93 } 94 } 95 96 public static boolean isPackageAccessible(Class clazz) { 97 try { 98 checkPackageAccess(clazz); 99 } catch (SecurityException e) { 100 return false; 101 } 102 return true; 103 } 104 105 // Returns true if p is an ancestor of cl i.e. class loader 'p' can 106 // be found in the cl's delegation chain 107 private static boolean isAncestor(ClassLoader p, ClassLoader cl) { 108 ClassLoader acl = cl; 109 do { 110 acl = acl.getParent(); 111 if (p == acl) { 112 return true; 113 } 114 } while (acl != null); 115 return false; 116 } 117 118 /** 119 * Returns true if package access check is needed for reflective 120 * access from a class loader 'from' to classes or members in 121 * a class defined by class loader 'to'. This method returns true 122 * if 'from' is not the same as or an ancestor of 'to'. All code 123 * in a system domain are granted with all permission and so this 124 * method returns false if 'from' class loader is a class loader 125 * loading system classes. On the other hand, if a class loader 126 * attempts to access system domain classes, it requires package 127 * access check and this method will return true. 128 */ 129 public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { 130 if (from == null || from == to) 131 return false; 132 133 if (to == null) 134 return true; 135 136 return !isAncestor(from, to); 137 } 138 139 /** 140 * Check package access on the proxy interfaces that the given proxy class 141 * implements. 142 * 143 * @param clazz Proxy class object 144 */ 145 public static void checkProxyPackageAccess(Class<?> clazz) { 146 SecurityManager s = System.getSecurityManager(); 147 if (s != null) { 148 // check proxy interfaces if the given class is a proxy class 149 if (Proxy.isProxyClass(clazz)) { 150 for (Class<?> intf : clazz.getInterfaces()) { 151 checkPackageAccess(intf); 152 } 153 } 154 } 155 } 156 157 /** 158 * Access check on the interfaces that a proxy class implements and throw 159 * {@code SecurityException} if it accesses a restricted package from 160 * the caller's class loader. 161 * 162 * @param ccl the caller's class loader 163 * @param interfaces the list of interfaces that a proxy class implements 164 */ 165 public static void checkProxyPackageAccess(ClassLoader ccl, 166 Class<?>... interfaces) 167 { 168 SecurityManager sm = System.getSecurityManager(); 169 if (sm != null) { 170 for (Class<?> intf : interfaces) { 171 ClassLoader cl = intf.getClassLoader(); 172 if (needsPackageAccessCheck(ccl, cl)) { 173 checkPackageAccess(intf); 174 } 175 } 176 } 177 } 178 179 /** 180 * Test if the given class is a proxy class that implements 181 * non-public interface. Such proxy class may be in a non-restricted 182 * package that bypasses checkPackageAccess. 183 */ 184 public static boolean isNonPublicProxyClass(Class<?> cls) { 185 String name = cls.getName(); 186 int i = name.lastIndexOf('.'); 187 String pkg = (i != -1) ? name.substring(0, i) : ""; 188 189 // NOTE: Android creates proxies in the "default" package (and not com.sun.proxy), which 190 // makes this check imprecise. However, this function is only ever called if there's 191 // a security manager installed (which is the never case on android). 192 return Proxy.isProxyClass(cls) && !pkg.isEmpty(); 193 } 194} 195