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