diff options
Diffstat (limited to 'external/ikvm/openjdk/sun/reflect/misc/ReflectUtil.java')
-rw-r--r-- | external/ikvm/openjdk/sun/reflect/misc/ReflectUtil.java | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/external/ikvm/openjdk/sun/reflect/misc/ReflectUtil.java b/external/ikvm/openjdk/sun/reflect/misc/ReflectUtil.java new file mode 100644 index 0000000000..81468c2013 --- /dev/null +++ b/external/ikvm/openjdk/sun/reflect/misc/ReflectUtil.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package sun.reflect.misc; + +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import sun.reflect.Reflection; + +public final class ReflectUtil { + + private ReflectUtil() { + } + + public static Class forName(String name) + throws ClassNotFoundException { + checkPackageAccess(name); + return Class.forName(name); + } + + public static Object newInstance(Class cls) + throws InstantiationException, IllegalAccessException { + checkPackageAccess(cls); + return cls.newInstance(); + } + + /* + * Reflection.ensureMemberAccess is overly-restrictive + * due to a bug. We awkwardly work around it for now. + */ + public static void ensureMemberAccess(Class currentClass, + Class memberClass, + Object target, + int modifiers) + throws IllegalAccessException + { + if (target == null && Modifier.isProtected(modifiers)) { + int mods = modifiers; + mods = mods & (~Modifier.PROTECTED); + mods = mods | Modifier.PUBLIC; + + /* + * See if we fail because of class modifiers + */ + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + mods); + try { + /* + * We're still here so class access was ok. + * Now try with default field access. + */ + mods = mods & (~Modifier.PUBLIC); + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + mods); + /* + * We're still here so access is ok without + * checking for protected. + */ + return; + } catch (IllegalAccessException e) { + /* + * Access failed but we're 'protected' so + * if the test below succeeds then we're ok. + */ + if (isSubclassOf(currentClass, memberClass)) { + return; + } else { + throw e; + } + } + } else { + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + modifiers); + } + } + + private static boolean isSubclassOf(Class queryClass, + Class ofClass) + { + while (queryClass != null) { + if (queryClass == ofClass) { + return true; + } + queryClass = queryClass.getSuperclass(); + } + return false; + } + + + /** + * Checks package access on the given class. + * + * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements + * a non-public interface (i.e. may be in a non-restricted package), + * also check the package access on the proxy interfaces. + */ + public static void checkPackageAccess(Class<?> clazz) { + checkPackageAccess(clazz.getName()); + if (isNonPublicProxyClass(clazz)) { + checkProxyPackageAccess(clazz); + } + } + + /** + * Checks package access on the given classname. + * This method is typically called when the Class instance is not + * available and the caller attempts to load a class on behalf + * the true caller (application). + */ + public static void checkPackageAccess(String name) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + String cname = name.replace('/', '.'); + if (cname.startsWith("[")) { + int b = cname.lastIndexOf('[') + 2; + if (b > 1 && b < cname.length()) { + cname = cname.substring(b); + } + } + int i = cname.lastIndexOf('.'); + if (i != -1) { + s.checkPackageAccess(cname.substring(0, i)); + } + } + } + + public static boolean isPackageAccessible(Class clazz) { + try { + checkPackageAccess(clazz); + } catch (SecurityException e) { + return false; + } + return true; + } + + // Returns true if p is an ancestor of cl i.e. class loader 'p' can + // be found in the cl's delegation chain + private static boolean isAncestor(ClassLoader p, ClassLoader cl) { + ClassLoader acl = cl; + do { + acl = acl.getParent(); + if (p == acl) { + return true; + } + } while (acl != null); + return false; + } + + /** + * Returns true if package access check is needed for reflective + * access from a class loader 'from' to classes or members in + * a class defined by class loader 'to'. This method returns true + * if 'from' is not the same as or an ancestor of 'to'. All code + * in a system domain are granted with all permission and so this + * method returns false if 'from' class loader is a class loader + * loading system classes. On the other hand, if a class loader + * attempts to access system domain classes, it requires package + * access check and this method will return true. + */ + public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { + if (from == null || from == to) + return false; + + if (to == null) + return true; + + return !isAncestor(from, to); + } + + /** + * Check package access on the proxy interfaces that the given proxy class + * implements. + * + * @param clazz Proxy class object + */ + public static void checkProxyPackageAccess(Class<?> clazz) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + // check proxy interfaces if the given class is a proxy class + if (Proxy.isProxyClass(clazz)) { + for (Class<?> intf : clazz.getInterfaces()) { + checkPackageAccess(intf); + } + } + } + } + + /** + * Access check on the interfaces that a proxy class implements and throw + * {@code SecurityException} if it accesses a restricted package from + * the caller's class loader. + * + * @param ccl the caller's class loader + * @param interfaces the list of interfaces that a proxy class implements + */ + public static void checkProxyPackageAccess(ClassLoader ccl, + Class<?>... interfaces) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + for (Class<?> intf : interfaces) { + ClassLoader cl = intf.getClassLoader(); + if (needsPackageAccessCheck(ccl, cl)) { + checkPackageAccess(intf); + } + } + } + } + + public static final String PROXY_PACKAGE = "com.sun.proxy"; + + /** + * Test if the given class is a proxy class that implements + * non-public interface. Such proxy class may be in a non-restricted + * package that bypasses checkPackageAccess. + */ + public static boolean isNonPublicProxyClass(Class<?> cls) { + String name = cls.getName(); + int i = name.lastIndexOf('.'); + String pkg = (i != -1) ? name.substring(0, i) : ""; + return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); + } +} |