6378384: (reflect) subclass can’t access superclass’s protected fields and methods by reflection
Reviewed-by: mchung
This commit is contained in:
parent
8233dc0e08
commit
f160991436
@ -557,7 +557,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (newInstanceCallerCache != caller) {
|
||||
int modifiers = tmpConstructor.getModifiers();
|
||||
Reflection.ensureMemberAccess(caller, this, null, modifiers);
|
||||
Reflection.ensureMemberAccess(caller, this, this, modifiers);
|
||||
newInstanceCallerCache = caller;
|
||||
}
|
||||
// Run constructor
|
||||
|
@ -312,22 +312,22 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
// (See also Class.newInstance(), which uses a similar method.)
|
||||
//
|
||||
// A more complicated security check cache is needed for Method and Field
|
||||
// The cache can be either null (empty cache), a 2-array of {caller,target},
|
||||
// or a caller (with target implicitly equal to this.clazz).
|
||||
// In the 2-array case, the target is always different from the clazz.
|
||||
// The cache can be either null (empty cache), a 2-array of {caller,targetClass},
|
||||
// or a caller (with targetClass implicitly equal to memberClass).
|
||||
// In the 2-array case, the targetClass is always different from the memberClass.
|
||||
volatile Object securityCheckCache;
|
||||
|
||||
void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers)
|
||||
final void checkAccess(Class<?> caller, Class<?> memberClass,
|
||||
Class<?> targetClass, int modifiers)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
if (caller == clazz) { // quick check
|
||||
if (caller == memberClass) { // quick check
|
||||
return; // ACCESS IS OK
|
||||
}
|
||||
Object cache = securityCheckCache; // read volatile
|
||||
Class<?> targetClass = clazz;
|
||||
if (obj != null
|
||||
if (targetClass != null // instance member or constructor
|
||||
&& Modifier.isProtected(modifiers)
|
||||
&& ((targetClass = obj.getClass()) != clazz)) {
|
||||
&& targetClass != memberClass) {
|
||||
// Must match a 2-list of { caller, targetClass }.
|
||||
if (cache instanceof Class[]) {
|
||||
Class<?>[] cache2 = (Class<?>[]) cache;
|
||||
@ -339,25 +339,27 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
// subsumes range check for [0].)
|
||||
}
|
||||
} else if (cache == caller) {
|
||||
// Non-protected case (or obj.class == this.clazz).
|
||||
// Non-protected case (or targetClass == memberClass or static member).
|
||||
return; // ACCESS IS OK
|
||||
}
|
||||
|
||||
// If no return, fall through to the slow path.
|
||||
slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
|
||||
slowCheckMemberAccess(caller, memberClass, targetClass, modifiers);
|
||||
}
|
||||
|
||||
// Keep all this slow stuff out of line:
|
||||
void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers,
|
||||
Class<?> targetClass)
|
||||
void slowCheckMemberAccess(Class<?> caller, Class<?> memberClass,
|
||||
Class<?> targetClass, int modifiers)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
|
||||
Reflection.ensureMemberAccess(caller, memberClass, targetClass, modifiers);
|
||||
|
||||
// Success: Update the cache.
|
||||
Object cache = ((targetClass == clazz)
|
||||
? caller
|
||||
: new Class<?>[] { caller, targetClass });
|
||||
Object cache = (targetClass != null
|
||||
&& Modifier.isProtected(modifiers)
|
||||
&& targetClass != memberClass)
|
||||
? new Class<?>[] { caller, targetClass }
|
||||
: caller;
|
||||
|
||||
// Note: The two cache elements are not volatile,
|
||||
// but they are effectively final. The Java memory model
|
||||
|
@ -443,7 +443,7 @@ public final class Constructor<T> extends Executable {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, null, modifiers);
|
||||
checkAccess(caller, clazz, clazz, modifiers);
|
||||
}
|
||||
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
|
||||
throw new IllegalArgumentException("Cannot reflectively create enum objects");
|
||||
|
@ -403,7 +403,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).get(obj);
|
||||
}
|
||||
@ -437,7 +437,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getBoolean(obj);
|
||||
}
|
||||
@ -471,7 +471,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getByte(obj);
|
||||
}
|
||||
@ -507,7 +507,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getChar(obj);
|
||||
}
|
||||
@ -543,7 +543,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getShort(obj);
|
||||
}
|
||||
@ -579,7 +579,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getInt(obj);
|
||||
}
|
||||
@ -615,7 +615,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getLong(obj);
|
||||
}
|
||||
@ -651,7 +651,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getFloat(obj);
|
||||
}
|
||||
@ -687,7 +687,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
return getFieldAccessor(obj).getDouble(obj);
|
||||
}
|
||||
@ -765,7 +765,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).set(obj, value);
|
||||
}
|
||||
@ -801,7 +801,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setBoolean(obj, z);
|
||||
}
|
||||
@ -837,7 +837,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setByte(obj, b);
|
||||
}
|
||||
@ -873,7 +873,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setChar(obj, c);
|
||||
}
|
||||
@ -909,7 +909,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setShort(obj, s);
|
||||
}
|
||||
@ -945,7 +945,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setInt(obj, i);
|
||||
}
|
||||
@ -981,7 +981,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setLong(obj, l);
|
||||
}
|
||||
@ -1017,7 +1017,7 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setFloat(obj, f);
|
||||
}
|
||||
@ -1053,11 +1053,20 @@ class Field extends AccessibleObject implements Member {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, obj);
|
||||
}
|
||||
getFieldAccessor(obj).setDouble(obj, d);
|
||||
}
|
||||
|
||||
// check access to field
|
||||
private void checkAccess(Class<?> caller, Object obj)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
checkAccess(caller, clazz,
|
||||
Modifier.isStatic(modifiers) ? null : obj.getClass(),
|
||||
modifiers);
|
||||
}
|
||||
|
||||
// security check is done before calling this method
|
||||
private FieldAccessor getFieldAccessor(Object obj)
|
||||
throws IllegalAccessException
|
||||
|
@ -526,7 +526,9 @@ public final class Method extends Executable {
|
||||
{
|
||||
if (!override) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
checkAccess(caller, clazz,
|
||||
Modifier.isStatic(modifiers) ? null : obj.getClass(),
|
||||
modifiers);
|
||||
}
|
||||
MethodAccessor ma = methodAccessor; // read volatile
|
||||
if (ma == null) {
|
||||
|
@ -84,9 +84,22 @@ public class Reflection {
|
||||
public static native int getClassAccessFlags(Class<?> c);
|
||||
|
||||
|
||||
/**
|
||||
* Ensures that access to a member is granted and throws
|
||||
* IllegalAccessException if not.
|
||||
*
|
||||
* @param currentClass the class performing the access
|
||||
* @param memberClass the declaring class of the member being accessed
|
||||
* @param targetClass the class of target object if accessing instance
|
||||
* field or method;
|
||||
* or the declaring class if accessing constructor;
|
||||
* or null if accessing static field or method
|
||||
* @param modifiers the member's access modifiers
|
||||
* @throws IllegalAccessException if access to member is denied
|
||||
*/
|
||||
public static void ensureMemberAccess(Class<?> currentClass,
|
||||
Class<?> memberClass,
|
||||
Object target,
|
||||
Class<?> targetClass,
|
||||
int modifiers)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
@ -94,18 +107,15 @@ public class Reflection {
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {
|
||||
throwIllegalAccessException(currentClass, memberClass, target, modifiers);
|
||||
if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) {
|
||||
throwIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verifyMemberAccess(Class<?> currentClass,
|
||||
// Declaring class of field
|
||||
// or method
|
||||
Class<?> memberClass,
|
||||
// May be NULL in case of statics
|
||||
Object target,
|
||||
int modifiers)
|
||||
private static boolean verifyMemberAccess(Class<?> currentClass,
|
||||
Class<?> memberClass,
|
||||
Class<?> targetClass,
|
||||
int modifiers)
|
||||
{
|
||||
// Verify that currentClass can access a field, method, or
|
||||
// constructor of memberClass, where that member's access bits are
|
||||
@ -162,18 +172,18 @@ public class Reflection {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Modifier.isProtected(modifiers)) {
|
||||
// Additional test for protected members: JLS 6.6.2
|
||||
Class<?> targetClass = (target == null ? memberClass : target.getClass());
|
||||
if (targetClass != currentClass) {
|
||||
if (!gotIsSameClassPackage) {
|
||||
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
|
||||
gotIsSameClassPackage = true;
|
||||
}
|
||||
if (!isSameClassPackage) {
|
||||
if (!isSubclassOf(targetClass, currentClass)) {
|
||||
return false;
|
||||
}
|
||||
// Additional test for protected instance members
|
||||
// and protected constructors: JLS 6.6.2
|
||||
if (targetClass != null && Modifier.isProtected(modifiers) &&
|
||||
targetClass != currentClass)
|
||||
{
|
||||
if (!gotIsSameClassPackage) {
|
||||
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
|
||||
gotIsSameClassPackage = true;
|
||||
}
|
||||
if (!isSameClassPackage) {
|
||||
if (!isSubclassOf(targetClass, currentClass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +44,21 @@ public final class ReflectUtil {
|
||||
return Class.forName(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reflection.ensureMemberAccess is overly-restrictive
|
||||
* due to a bug. We awkwardly work around it for now.
|
||||
/**
|
||||
* Ensures that access to a method or field is granted and throws
|
||||
* IllegalAccessException if not. This method is not suitable for checking
|
||||
* access to constructors.
|
||||
*
|
||||
* @param currentClass the class performing the access
|
||||
* @param memberClass the declaring class of the member being accessed
|
||||
* @param target the target object if accessing instance field or method;
|
||||
* or null if accessing static field or method or if target
|
||||
* object access rights will be checked later
|
||||
* @param modifiers the member's access modifiers
|
||||
* @throws IllegalAccessException if access to member is denied
|
||||
* @implNote Delegates directly to
|
||||
* {@link Reflection#ensureMemberAccess(Class, Class, Class, int)}
|
||||
* which should be used instead.
|
||||
*/
|
||||
public static void ensureMemberAccess(Class<?> currentClass,
|
||||
Class<?> memberClass,
|
||||
@ -54,62 +66,10 @@ public final class ReflectUtil {
|
||||
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;
|
||||
Reflection.ensureMemberAccess(currentClass,
|
||||
memberClass,
|
||||
target == null ? null : target.getClass(),
|
||||
modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
454
jdk/test/java/lang/reflect/AccessControl/AccessControlTest.java
Normal file
454
jdk/test/java/lang/reflect/AccessControl/AccessControlTest.java
Normal file
@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import util.ClassSupplier;
|
||||
import util.MemberFactory;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.util.stream.Collectors.mapping;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import static util.MemberFactory.*;
|
||||
import static util.MemberFactory.Group.*;
|
||||
import static util.ClassSupplier.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary An exhaustive test of reflective access controls
|
||||
* @bug 6378384
|
||||
* @build a.PublicSuper a.Package b.PublicSub b.Package
|
||||
* util.MemberFactory util.ClassSupplier
|
||||
* @run main AccessControlTest
|
||||
*/
|
||||
public class AccessControlTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
boolean ok = true;
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_A)
|
||||
.member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A)
|
||||
.allowed(ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_A)
|
||||
.member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B)
|
||||
.denied (ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A)
|
||||
.allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.allowed(ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B)
|
||||
.denied (ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_B)
|
||||
.member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A)
|
||||
.denied (ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.allowed(PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_B)
|
||||
.member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B)
|
||||
.allowed(ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PACKAGE_CLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A)
|
||||
.denied (ALL)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A)
|
||||
.allowed(PUBLIC_MEMBERS, PROTECTED_STATIC_F_M)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_INSTANCE_F_M,
|
||||
PROTECTED_C)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(PUBLIC_MEMBERS, PROTECTED_INSTANCE_F_M, PROTECTED_STATIC_F_M)
|
||||
.denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_C)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B)
|
||||
.allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS)
|
||||
.denied (PRIVATE_MEMBERS)
|
||||
.perform();
|
||||
|
||||
ok &= new Test()
|
||||
.current(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B)
|
||||
.allowed(ALL)
|
||||
.perform();
|
||||
|
||||
if (ok) {
|
||||
System.out.println("\nAll cases passed.");
|
||||
} else {
|
||||
throw new RuntimeException("Some cases failed - see log.");
|
||||
}
|
||||
}
|
||||
|
||||
// use this for generating an exhaustive set of test cases on stdout
|
||||
public static class Generate {
|
||||
public static void main(String[] args) {
|
||||
for (ClassSupplier current : ClassSupplier.values()) {
|
||||
for (ClassSupplier member : ClassSupplier.values()) {
|
||||
for (ClassSupplier target : ClassSupplier.values()) {
|
||||
if (member.get().isAssignableFrom(target.get())) {
|
||||
new Test()
|
||||
.current(current).member(member).target(target)
|
||||
.allowed(ALL)
|
||||
.perform(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Test {
|
||||
|
||||
ClassSupplier currentClassSupplier, memberClassSupplier, targetClassSupplier;
|
||||
EnumSet<MemberFactory> expectAllowedMembers = EnumSet.noneOf(MemberFactory.class);
|
||||
EnumSet<MemberFactory> expectDeniedMembers = EnumSet.noneOf(MemberFactory.class);
|
||||
|
||||
Test current(ClassSupplier current) {
|
||||
currentClassSupplier = current;
|
||||
return this;
|
||||
}
|
||||
|
||||
Test member(ClassSupplier member) {
|
||||
memberClassSupplier = member;
|
||||
return this;
|
||||
}
|
||||
|
||||
Test target(ClassSupplier target) {
|
||||
targetClassSupplier = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
Test allowed(MemberFactory... allowed) {
|
||||
expectAllowedMembers = MemberFactory.asSet(allowed);
|
||||
return this;
|
||||
}
|
||||
|
||||
Test allowed(MemberFactory.Group... allowedGroups) {
|
||||
expectAllowedMembers = MemberFactory.groupsToMembers(
|
||||
MemberFactory.Group.asSet(allowedGroups));
|
||||
return this;
|
||||
}
|
||||
|
||||
Test denied(MemberFactory... denied) {
|
||||
expectDeniedMembers = MemberFactory.asSet(denied);
|
||||
return this;
|
||||
}
|
||||
|
||||
Test denied(MemberFactory.Group... deniedGroups) {
|
||||
expectDeniedMembers = MemberFactory.groupsToMembers(
|
||||
MemberFactory.Group.asSet(deniedGroups));
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean perform() {
|
||||
return perform(false);
|
||||
}
|
||||
|
||||
boolean perform(boolean generateCases) {
|
||||
|
||||
// some validation 1st
|
||||
EnumSet<MemberFactory> intersection = EnumSet.copyOf(expectAllowedMembers);
|
||||
intersection.retainAll(expectDeniedMembers);
|
||||
if (!intersection.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Expected allowed and denied MemberFactories have non-empty intersection: " +
|
||||
intersection);
|
||||
}
|
||||
|
||||
EnumSet<MemberFactory> missing = EnumSet.allOf(MemberFactory.class);
|
||||
missing.removeAll(expectAllowedMembers);
|
||||
missing.removeAll(expectDeniedMembers);
|
||||
if (!missing.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Union of expected allowed and denied MemberFactories is missing elements: " +
|
||||
missing);
|
||||
}
|
||||
|
||||
// retrieve method that will perform reflective access
|
||||
Method checkAccessMethod;
|
||||
try {
|
||||
checkAccessMethod = currentClassSupplier.get().getDeclaredMethod(
|
||||
"checkAccess", AccessibleObject.class, Object.class);
|
||||
// in case of inaccessible currentClass
|
||||
checkAccessMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// construct a target object (for instance field/method)
|
||||
Object target;
|
||||
Constructor<?> targetConstructor =
|
||||
(Constructor<?>) PUBLIC_CONSTRUCTOR.apply(targetClassSupplier.get());
|
||||
// in case of inaccessible targetClass
|
||||
targetConstructor.setAccessible(true);
|
||||
try {
|
||||
target = targetConstructor.newInstance(
|
||||
new Object[targetConstructor.getParameterCount()]);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Class<?> memberClass = memberClassSupplier.get();
|
||||
|
||||
Map<Boolean, EnumSet<MemberFactory>> actualMembers = Stream.concat(
|
||||
|
||||
expectAllowedMembers.stream().map(member -> new Trial(member, true)),
|
||||
expectDeniedMembers.stream().map(member -> new Trial(member, false))
|
||||
|
||||
).map(trial -> {
|
||||
|
||||
// obtain AccessibleObject to be used to perform reflective access
|
||||
AccessibleObject accessibleObject = trial.member.apply(memberClass);
|
||||
|
||||
// only need target 'obj' for instance fields and methods
|
||||
Object obj =
|
||||
(accessibleObject instanceof Field &&
|
||||
!Modifier.isStatic(((Field) accessibleObject).getModifiers())
|
||||
||
|
||||
accessibleObject instanceof Method &&
|
||||
!Modifier.isStatic(((Method) accessibleObject).getModifiers())
|
||||
)
|
||||
? target : null;
|
||||
|
||||
// invoke checkAccess method and let it perform the reflective access
|
||||
try {
|
||||
checkAccessMethod.invoke(null, accessibleObject, obj);
|
||||
trial.actualAllowed = true;
|
||||
} catch (IllegalAccessException e) {
|
||||
// should not happen as checkAccessMethod.isAccessible()
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getTargetException() instanceof IllegalAccessException) {
|
||||
trial.actualAllowed = false;
|
||||
} else {
|
||||
// any other Exception is a fault in test or infrastructure - fail fast
|
||||
throw new RuntimeException(e.getTargetException());
|
||||
}
|
||||
}
|
||||
|
||||
if (!generateCases) {
|
||||
System.out.printf(
|
||||
"%-26s accessing %26s's %-25s %-43s - expected %s, actual %s: %s\n",
|
||||
currentClassSupplier, memberClassSupplier, trial.member.name(),
|
||||
(obj == null ? "" : "with instance of " + targetClassSupplier),
|
||||
(trial.expectAllowed ? "allowed" : "denied "),
|
||||
(trial.actualAllowed ? "allowed" : "denied "),
|
||||
(trial.expectAllowed == trial.actualAllowed ? "OK" : "FAILURE")
|
||||
);
|
||||
}
|
||||
|
||||
return trial;
|
||||
|
||||
}).collect(
|
||||
groupingBy(
|
||||
Trial::isActualAllowed,
|
||||
mapping(
|
||||
Trial::getMember,
|
||||
toCollection(() -> EnumSet.noneOf(MemberFactory.class))))
|
||||
);
|
||||
|
||||
EnumSet<MemberFactory> actualAllowedMembers =
|
||||
Optional.ofNullable(actualMembers.get(true))
|
||||
.orElse(EnumSet.noneOf(MemberFactory.class));
|
||||
EnumSet<MemberFactory> actualDeniedMembers =
|
||||
Optional.ofNullable(actualMembers.get(false))
|
||||
.orElse(EnumSet.noneOf(MemberFactory.class));
|
||||
|
||||
if (generateCases) {
|
||||
System.out.printf(
|
||||
" ok &= new Test()\n" +
|
||||
" .current(%s)\n" +
|
||||
" .member (%s).target(%s)\n",
|
||||
currentClassSupplier,
|
||||
memberClassSupplier, targetClassSupplier
|
||||
);
|
||||
|
||||
if (!actualAllowedMembers.isEmpty()) {
|
||||
EnumSet<? extends Enum> actualAllowed =
|
||||
MemberFactory.membersToGroupsOrNull(actualAllowedMembers);
|
||||
if (actualAllowed == null)
|
||||
actualAllowed = actualAllowedMembers;
|
||||
System.out.print(
|
||||
chunkBy(3, actualAllowed.stream().map(Enum::name))
|
||||
.map(chunk -> chunk.collect(joining(", ")))
|
||||
.collect(joining(",\n" +
|
||||
" ",
|
||||
" .allowed(",
|
||||
")\n"))
|
||||
);
|
||||
}
|
||||
|
||||
if (!actualDeniedMembers.isEmpty()) {
|
||||
EnumSet<? extends Enum> actualDenied =
|
||||
MemberFactory.membersToGroupsOrNull(actualDeniedMembers);
|
||||
if (actualDenied == null)
|
||||
actualDenied = actualAllowedMembers;
|
||||
System.out.print(
|
||||
chunkBy(3, actualDenied.stream().map(Enum::name))
|
||||
.map(chunk -> chunk.collect(joining(", ")))
|
||||
.collect(joining(",\n" +
|
||||
" ",
|
||||
" .denied (",
|
||||
")\n"))
|
||||
);
|
||||
}
|
||||
|
||||
System.out.print(
|
||||
" .perform();\n"
|
||||
);
|
||||
}
|
||||
|
||||
return expectAllowedMembers.equals(actualAllowedMembers) &&
|
||||
expectDeniedMembers.equals(actualDeniedMembers);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Stream<Stream<T>> chunkBy(int chunkSize, Stream<T> stream) {
|
||||
Iterator<T> elements = stream.iterator();
|
||||
Stream.Builder<Stream<T>> b1 = Stream.builder();
|
||||
while (elements.hasNext()) {
|
||||
Stream.Builder<T> b2 = Stream.builder();
|
||||
for (int i = 0; i < chunkSize && elements.hasNext(); i++) {
|
||||
b2.accept(elements.next());
|
||||
}
|
||||
b1.accept(b2.build());
|
||||
}
|
||||
return b1.build();
|
||||
}
|
||||
|
||||
private static class Trial {
|
||||
final MemberFactory member;
|
||||
final boolean expectAllowed;
|
||||
boolean actualAllowed;
|
||||
|
||||
Trial(MemberFactory member, boolean expectAllowed) {
|
||||
this.member = member;
|
||||
this.expectAllowed = expectAllowed;
|
||||
}
|
||||
|
||||
MemberFactory getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
boolean isActualAllowed() {
|
||||
return actualAllowed;
|
||||
}
|
||||
}
|
||||
}
|
82
jdk/test/java/lang/reflect/AccessControl/a/Package.java
Normal file
82
jdk/test/java/lang/reflect/AccessControl/a/Package.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 a;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A package-private class in a.
|
||||
*/
|
||||
class Package {
|
||||
|
||||
// fields
|
||||
private static int privateStatic;
|
||||
private int privateInstance;
|
||||
static int packageStatic;
|
||||
int packageInstance;
|
||||
protected static int protectedStatic;
|
||||
protected int protectedInstance;
|
||||
public static int publicStatic;
|
||||
public int publicInstance;
|
||||
|
||||
// methods
|
||||
private static int privateStatic() { return 42; }
|
||||
private int privateInstance() { return 42; }
|
||||
static int packageStatic() { return 42; }
|
||||
int packageInstance() { return 42; }
|
||||
protected static int protectedStatic() { return 42; }
|
||||
protected int protectedInstance() { return 42; }
|
||||
public static int publicStatic() { return 42; }
|
||||
public int publicInstance() { return 42; }
|
||||
|
||||
// constructors
|
||||
private Package(Void _1, Void _2, Void _3) {}
|
||||
Package(Void _1, Void _2) {}
|
||||
protected Package(Void _1) {}
|
||||
public Package() {}
|
||||
|
||||
|
||||
// testing method
|
||||
public static void checkAccess(AccessibleObject accessibleObject, Object obj)
|
||||
throws IllegalAccessException,
|
||||
InvocationTargetException,
|
||||
InstantiationException
|
||||
{
|
||||
if (accessibleObject instanceof Field) {
|
||||
Field field = (Field) accessibleObject;
|
||||
field.set(obj, 42);
|
||||
field.get(obj);
|
||||
} else if (accessibleObject instanceof Method) {
|
||||
Method method = (Method) accessibleObject;
|
||||
method.invoke(obj);
|
||||
} else if (accessibleObject instanceof Constructor) {
|
||||
Constructor<?> constructor = (Constructor<?>) accessibleObject;
|
||||
Object[] params = new Object[constructor.getParameterCount()];
|
||||
constructor.newInstance(params);
|
||||
}
|
||||
}
|
||||
}
|
82
jdk/test/java/lang/reflect/AccessControl/a/PublicSuper.java
Normal file
82
jdk/test/java/lang/reflect/AccessControl/a/PublicSuper.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 a;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A public class in a which is a superclass of public class in b.
|
||||
*/
|
||||
public class PublicSuper {
|
||||
|
||||
// fields
|
||||
private static int privateStatic;
|
||||
private int privateInstance;
|
||||
static int packageStatic;
|
||||
int packageInstance;
|
||||
protected static int protectedStatic;
|
||||
protected int protectedInstance;
|
||||
public static int publicStatic;
|
||||
public int publicInstance;
|
||||
|
||||
// methods
|
||||
private static int privateStatic() { return 42; }
|
||||
private int privateInstance() { return 42; }
|
||||
static int packageStatic() { return 42; }
|
||||
int packageInstance() { return 42; }
|
||||
protected static int protectedStatic() { return 42; }
|
||||
protected int protectedInstance() { return 42; }
|
||||
public static int publicStatic() { return 42; }
|
||||
public int publicInstance() { return 42; }
|
||||
|
||||
// constructors
|
||||
private PublicSuper(Void _1, Void _2, Void _3) {}
|
||||
PublicSuper(Void _1, Void _2) {}
|
||||
protected PublicSuper(Void _1) {}
|
||||
public PublicSuper() {}
|
||||
|
||||
|
||||
// testing method
|
||||
public static void checkAccess(AccessibleObject accessibleObject, Object obj)
|
||||
throws IllegalAccessException,
|
||||
InvocationTargetException,
|
||||
InstantiationException
|
||||
{
|
||||
if (accessibleObject instanceof Field) {
|
||||
Field field = (Field) accessibleObject;
|
||||
field.set(obj, 42);
|
||||
field.get(obj);
|
||||
} else if (accessibleObject instanceof Method) {
|
||||
Method method = (Method) accessibleObject;
|
||||
method.invoke(obj);
|
||||
} else if (accessibleObject instanceof Constructor) {
|
||||
Constructor<?> constructor = (Constructor<?>) accessibleObject;
|
||||
Object[] params = new Object[constructor.getParameterCount()];
|
||||
constructor.newInstance(params);
|
||||
}
|
||||
}
|
||||
}
|
82
jdk/test/java/lang/reflect/AccessControl/b/Package.java
Normal file
82
jdk/test/java/lang/reflect/AccessControl/b/Package.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 b;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A package-private class in b.
|
||||
*/
|
||||
class Package {
|
||||
|
||||
// fields
|
||||
private static int privateStatic;
|
||||
private int privateInstance;
|
||||
static int packageStatic;
|
||||
int packageInstance;
|
||||
protected static int protectedStatic;
|
||||
protected int protectedInstance;
|
||||
public static int publicStatic;
|
||||
public int publicInstance;
|
||||
|
||||
// methods
|
||||
private static int privateStatic() { return 42; }
|
||||
private int privateInstance() { return 42; }
|
||||
static int packageStatic() { return 42; }
|
||||
int packageInstance() { return 42; }
|
||||
protected static int protectedStatic() { return 42; }
|
||||
protected int protectedInstance() { return 42; }
|
||||
public static int publicStatic() { return 42; }
|
||||
public int publicInstance() { return 42; }
|
||||
|
||||
// constructors
|
||||
private Package(Void _1, Void _2, Void _3) {}
|
||||
Package(Void _1, Void _2) {}
|
||||
protected Package(Void _1) {}
|
||||
public Package() {}
|
||||
|
||||
|
||||
// testing method
|
||||
public static void checkAccess(AccessibleObject accessibleObject, Object obj)
|
||||
throws IllegalAccessException,
|
||||
InvocationTargetException,
|
||||
InstantiationException
|
||||
{
|
||||
if (accessibleObject instanceof Field) {
|
||||
Field field = (Field) accessibleObject;
|
||||
field.set(obj, 42);
|
||||
field.get(obj);
|
||||
} else if (accessibleObject instanceof Method) {
|
||||
Method method = (Method) accessibleObject;
|
||||
method.invoke(obj);
|
||||
} else if (accessibleObject instanceof Constructor) {
|
||||
Constructor<?> constructor = (Constructor<?>) accessibleObject;
|
||||
Object[] params = new Object[constructor.getParameterCount()];
|
||||
constructor.newInstance(params);
|
||||
}
|
||||
}
|
||||
}
|
82
jdk/test/java/lang/reflect/AccessControl/b/PublicSub.java
Normal file
82
jdk/test/java/lang/reflect/AccessControl/b/PublicSub.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 b;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A public class in b which is a subclass of public class in a.
|
||||
*/
|
||||
public class PublicSub extends a.PublicSuper {
|
||||
|
||||
// fields
|
||||
private static int privateStatic;
|
||||
private int privateInstance;
|
||||
static int packageStatic;
|
||||
int packageInstance;
|
||||
protected static int protectedStatic;
|
||||
protected int protectedInstance;
|
||||
public static int publicStatic;
|
||||
public int publicInstance;
|
||||
|
||||
// methods
|
||||
private static int privateStatic() { return 42; }
|
||||
private int privateInstance() { return 42; }
|
||||
static int packageStatic() { return 42; }
|
||||
int packageInstance() { return 42; }
|
||||
protected static int protectedStatic() { return 42; }
|
||||
protected int protectedInstance() { return 42; }
|
||||
public static int publicStatic() { return 42; }
|
||||
public int publicInstance() { return 42; }
|
||||
|
||||
// constructors
|
||||
private PublicSub(Void _1, Void _2, Void _3) {}
|
||||
PublicSub(Void _1, Void _2) {}
|
||||
protected PublicSub(Void _1) {}
|
||||
public PublicSub() {}
|
||||
|
||||
|
||||
// testing method
|
||||
public static void checkAccess(AccessibleObject accessibleObject, Object obj)
|
||||
throws IllegalAccessException,
|
||||
InvocationTargetException,
|
||||
InstantiationException
|
||||
{
|
||||
if (accessibleObject instanceof Field) {
|
||||
Field field = (Field) accessibleObject;
|
||||
field.set(obj, 42);
|
||||
field.get(obj);
|
||||
} else if (accessibleObject instanceof Method) {
|
||||
Method method = (Method) accessibleObject;
|
||||
method.invoke(obj);
|
||||
} else if (accessibleObject instanceof Constructor) {
|
||||
Constructor<?> constructor = (Constructor<?>) accessibleObject;
|
||||
Object[] params = new Object[constructor.getParameterCount()];
|
||||
constructor.newInstance(params);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 util;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* An enumeration of suppliers of test classes.
|
||||
*/
|
||||
public enum ClassSupplier implements Supplier<Class<?>> {
|
||||
PACKAGE_CLASS_IN_PKG_A("a.Package"),
|
||||
PUBLIC_SUPERCLASS_IN_PKG_A("a.PublicSuper"),
|
||||
PACKAGE_CLASS_IN_PKG_B("b.Package"),
|
||||
PUBLIC_SUBCLASS_IN_PKG_B("b.PublicSub");
|
||||
|
||||
private final String className;
|
||||
|
||||
ClassSupplier(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> get() {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw (Error) new NoClassDefFoundError(className).initCause(e);
|
||||
}
|
||||
}
|
||||
}
|
220
jdk/test/java/lang/reflect/AccessControl/util/MemberFactory.java
Normal file
220
jdk/test/java/lang/reflect/AccessControl/util/MemberFactory.java
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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 util;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static util.MemberFactory.Kind.CONSTRUCTOR;
|
||||
import static util.MemberFactory.Kind.FIELD;
|
||||
import static util.MemberFactory.Kind.METHOD;
|
||||
|
||||
/**
|
||||
* Enumeration of:
|
||||
* <p>
|
||||
* {private, package, protected, public} x {instance, static} x {field, method}
|
||||
* <p>
|
||||
* and:
|
||||
* <p>
|
||||
* {private, package, protected, public} x {constructor},
|
||||
* <p>
|
||||
* with each element acting as a factory of AccessibleObject(s)
|
||||
* declared by given declaringClass(es).
|
||||
*/
|
||||
public enum MemberFactory implements Function<Class<?>, AccessibleObject> {
|
||||
// instance fields
|
||||
PRIVATE_INSTANCE_FIELD(FIELD, "privateInstance"),
|
||||
PACKAGE_INSTANCE_FIELD(FIELD, "packageInstance"),
|
||||
PROTECTED_INSTANCE_FIELD(FIELD, "protectedInstance"),
|
||||
PUBLIC_INSTANCE_FIELD(FIELD, "publicInstance"),
|
||||
// instance methods
|
||||
PRIVATE_INSTANCE_METHOD(METHOD, "privateInstance"),
|
||||
PACKAGE_INSTANCE_METHOD(METHOD, "packageInstance"),
|
||||
PROTECTED_INSTANCE_METHOD(METHOD, "protectedInstance"),
|
||||
PUBLIC_INSTANCE_METHOD(METHOD, "publicInstance"),
|
||||
// static fields
|
||||
PRIVATE_STATIC_FIELD(FIELD, "privateStatic"),
|
||||
PACKAGE_STATIC_FIELD(FIELD, "packageStatic"),
|
||||
PROTECTED_STATIC_FIELD(FIELD, "protectedStatic"),
|
||||
PUBLIC_STATIC_FIELD(FIELD, "publicStatic"),
|
||||
// static methods
|
||||
PRIVATE_STATIC_METHOD(METHOD, "privateStatic"),
|
||||
PACKAGE_STATIC_METHOD(METHOD, "packageStatic"),
|
||||
PROTECTED_STATIC_METHOD(METHOD, "protectedStatic"),
|
||||
PUBLIC_STATIC_METHOD(METHOD, "publicStatic"),
|
||||
// constructors
|
||||
PRIVATE_CONSTRUCTOR(CONSTRUCTOR, null, Void.class, Void.class, Void.class),
|
||||
PACKAGE_CONSTRUCTOR(CONSTRUCTOR, null, Void.class, Void.class),
|
||||
PROTECTED_CONSTRUCTOR(CONSTRUCTOR, null, Void.class),
|
||||
PUBLIC_CONSTRUCTOR(CONSTRUCTOR, null),;
|
||||
|
||||
final Kind kind;
|
||||
final String name;
|
||||
final Class<?>[] parameterTypes;
|
||||
|
||||
MemberFactory(Kind kind, String name, Class<?>... parameterTypes) {
|
||||
this.kind = kind;
|
||||
this.name = name;
|
||||
this.parameterTypes = parameterTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleObject apply(Class<?> declaringClass) {
|
||||
return kind.apply(declaringClass, this);
|
||||
}
|
||||
|
||||
public static EnumSet<MemberFactory> asSet(MemberFactory... members) {
|
||||
return members.length == 0 ? EnumSet.noneOf(MemberFactory.class)
|
||||
: EnumSet.copyOf(Arrays.asList(members));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param members the set of MemberFactory(s) to convert to set of
|
||||
* MemberFactory.Group(s).
|
||||
* @return a set of groups that cover all elements of the members set if
|
||||
* such set of groups exists or null if it doesn't.
|
||||
*/
|
||||
public static EnumSet<Group> membersToGroupsOrNull(EnumSet<MemberFactory> members) {
|
||||
EnumSet<MemberFactory> mSet = members.clone();
|
||||
EnumSet<Group> gSet = EnumSet.allOf(Group.class);
|
||||
Iterator<Group> gIter = gSet.iterator();
|
||||
while (gIter.hasNext()) {
|
||||
Group g = gIter.next();
|
||||
if (mSet.containsAll(g.members)) {
|
||||
mSet.removeAll(g.members);
|
||||
} else {
|
||||
gIter.remove();
|
||||
}
|
||||
}
|
||||
return mSet.isEmpty() ? gSet : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groups the set of MemberFactory.Group(s) to convert to set of
|
||||
* MemberFactory(s).
|
||||
* @return a set of members as a union of members of all groups.
|
||||
*/
|
||||
public static EnumSet<MemberFactory> groupsToMembers(EnumSet<Group> groups) {
|
||||
EnumSet<MemberFactory> mSet = EnumSet.noneOf(MemberFactory.class);
|
||||
for (Group g : groups) {
|
||||
mSet.addAll(g.members);
|
||||
}
|
||||
return mSet;
|
||||
}
|
||||
|
||||
enum Kind implements BiFunction<Class<?>, MemberFactory, AccessibleObject> {
|
||||
FIELD {
|
||||
@Override
|
||||
public AccessibleObject apply(Class<?> declaringClass, MemberFactory factory) {
|
||||
assert factory.kind == this;
|
||||
try {
|
||||
return declaringClass.getDeclaredField(factory.name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// a fault in test - fail fast
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
},
|
||||
METHOD {
|
||||
@Override
|
||||
public AccessibleObject apply(Class<?> declaringClass, MemberFactory factory) {
|
||||
assert factory.kind == this;
|
||||
try {
|
||||
return declaringClass.getDeclaredMethod(factory.name, factory.parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// a fault in test - fail fast
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
},
|
||||
CONSTRUCTOR {
|
||||
@Override
|
||||
public AccessibleObject apply(Class<?> declaringClass, MemberFactory factory) {
|
||||
assert factory.kind == this;
|
||||
try {
|
||||
return declaringClass.getDeclaredConstructor(factory.parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// a fault in test - fail fast
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We define groups of MemberFactory(s) for members that commonly
|
||||
* exhibit same access restrictions in various cases in order to allow
|
||||
* specifying groups instead of individual members in the test cases,
|
||||
* making them less verbose.
|
||||
*/
|
||||
public enum Group {
|
||||
// all members
|
||||
ALL(MemberFactory.values()),
|
||||
// all private members
|
||||
PRIVATE_MEMBERS(PRIVATE_INSTANCE_FIELD, PRIVATE_INSTANCE_METHOD,
|
||||
PRIVATE_STATIC_FIELD, PRIVATE_STATIC_METHOD,
|
||||
PRIVATE_CONSTRUCTOR),
|
||||
// all package members
|
||||
PACKAGE_MEMBERS(PACKAGE_INSTANCE_FIELD, PACKAGE_INSTANCE_METHOD,
|
||||
PACKAGE_STATIC_FIELD, PACKAGE_STATIC_METHOD,
|
||||
PACKAGE_CONSTRUCTOR),
|
||||
// all protected members
|
||||
PROTECTED_MEMBERS(PROTECTED_INSTANCE_FIELD, PROTECTED_INSTANCE_METHOD,
|
||||
PROTECTED_STATIC_FIELD, PROTECTED_STATIC_METHOD,
|
||||
PROTECTED_CONSTRUCTOR),
|
||||
// all public members
|
||||
PUBLIC_MEMBERS(PUBLIC_INSTANCE_FIELD, PUBLIC_INSTANCE_METHOD,
|
||||
PUBLIC_STATIC_FIELD, PUBLIC_STATIC_METHOD,
|
||||
PUBLIC_CONSTRUCTOR),
|
||||
// instance field and method pairs
|
||||
PRIVATE_INSTANCE_F_M(PRIVATE_INSTANCE_FIELD, PRIVATE_INSTANCE_METHOD),
|
||||
PACKAGE_INSTANCE_F_M(PACKAGE_INSTANCE_FIELD, PACKAGE_INSTANCE_METHOD),
|
||||
PROTECTED_INSTANCE_F_M(PROTECTED_INSTANCE_FIELD, PROTECTED_INSTANCE_METHOD),
|
||||
PUBLIC_INSTANCE_F_M(PUBLIC_INSTANCE_FIELD, PUBLIC_INSTANCE_METHOD),
|
||||
// static field and method pairs
|
||||
PRIVATE_STATIC_F_M(PRIVATE_STATIC_FIELD, PRIVATE_STATIC_METHOD),
|
||||
PACKAGE_STATIC_F_M(PACKAGE_STATIC_FIELD, PACKAGE_STATIC_METHOD),
|
||||
PROTECTED_STATIC_F_M(PROTECTED_STATIC_FIELD, PROTECTED_STATIC_METHOD),
|
||||
PUBLIC_STATIC_F_M(PUBLIC_STATIC_FIELD, PUBLIC_STATIC_METHOD),
|
||||
// constructor singles
|
||||
PRIVATE_C(PRIVATE_CONSTRUCTOR),
|
||||
PACKAGE_C(PACKAGE_CONSTRUCTOR),
|
||||
PROTECTED_C(PROTECTED_CONSTRUCTOR),
|
||||
PUBLIC_C(PUBLIC_CONSTRUCTOR);
|
||||
|
||||
final EnumSet<MemberFactory> members;
|
||||
|
||||
Group(MemberFactory... members) {
|
||||
this.members = EnumSet.copyOf(Arrays.asList(members));
|
||||
}
|
||||
|
||||
public static EnumSet<Group> asSet(Group... groups) {
|
||||
return groups.length == 0 ? EnumSet.noneOf(Group.class)
|
||||
: EnumSet.copyOf(Arrays.asList(groups));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user