changeset 6331:6c00e5d483b9

8011557: Improve reflection utility classes Reviewed-by: ahgross, alanb
author mchung
date Fri, 05 Apr 2013 08:43:00 -0700
parents 845c9121b16d
children 41529646ab84
files src/share/classes/java/lang/Class.java src/share/classes/java/lang/reflect/Proxy.java src/share/classes/sun/reflect/misc/ReflectUtil.java
diffstat 3 files changed, 56 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/Class.java	Fri Apr 05 08:49:33 2013 -0400
+++ b/src/share/classes/java/lang/Class.java	Fri Apr 05 08:43:00 2013 -0700
@@ -2209,7 +2209,7 @@
                 if (i != -1) {
                     // skip the package access check on a proxy class in default proxy package
                     String pkg = name.substring(0, i);
-                    if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) {
+                    if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
                         s.checkPackageAccess(pkg);
                     }
                 }
--- a/src/share/classes/java/lang/reflect/Proxy.java	Fri Apr 05 08:49:33 2013 -0400
+++ b/src/share/classes/java/lang/reflect/Proxy.java	Fri Apr 05 08:43:00 2013 -0700
@@ -302,13 +302,11 @@
                 return false;
             }
 
-            if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
-                // all proxy interfaces are public
-                return false;
-            }
-            for (Class<?> intf : proxyClass.getInterfaces()) {
-                if (!Modifier.isPublic(intf.getModifiers())) {
-                    return true;
+            if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
+                for (Class<?> intf : proxyClass.getInterfaces()) {
+                    if (!Modifier.isPublic(intf.getModifiers())) {
+                        return true;
+                    }
                 }
             }
             return false;
--- a/src/share/classes/sun/reflect/misc/ReflectUtil.java	Fri Apr 05 08:49:33 2013 -0400
+++ b/src/share/classes/sun/reflect/misc/ReflectUtil.java	Fri Apr 05 08:43:00 2013 -0700
@@ -27,6 +27,7 @@
 package sun.reflect.misc;
 
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import sun.reflect.Reflection;
 
 public final class ReflectUtil {
@@ -115,10 +116,26 @@
     }
 
 
-    public static void checkPackageAccess(Class clazz) {
+    /**
+     * 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) {
@@ -180,13 +197,30 @@
     }
 
     /**
+     * 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.
+     * {@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
-     *
-     * @see Proxy#checkProxyAccess
      */
     public static void checkProxyPackageAccess(ClassLoader ccl,
                                                Class<?>... interfaces)
@@ -203,4 +237,16 @@
     }
 
     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);
+    }
 }