jtulach@258: /* jtulach@258: * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. jtulach@258: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@258: * jtulach@258: * This code is free software; you can redistribute it and/or modify it jtulach@258: * under the terms of the GNU General Public License version 2 only, as jtulach@258: * published by the Free Software Foundation. Oracle designates this jtulach@258: * particular file as subject to the "Classpath" exception as provided jtulach@258: * by Oracle in the LICENSE file that accompanied this code. jtulach@258: * jtulach@258: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@258: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@258: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@258: * version 2 for more details (a copy is included in the LICENSE file that jtulach@258: * accompanied this code). jtulach@258: * jtulach@258: * You should have received a copy of the GNU General Public License version jtulach@258: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@258: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@258: * jtulach@258: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@258: * or visit www.oracle.com if you need additional information or have any jtulach@258: * questions. jtulach@258: */ jtulach@258: jtulach@258: package java.lang.reflect; jtulach@258: jtulach@258: import java.security.AccessController; jtulach@258: import sun.reflect.Reflection; jtulach@258: import sun.reflect.ReflectionFactory; jtulach@258: import java.lang.annotation.Annotation; jtulach@258: jtulach@258: /** jtulach@258: * The AccessibleObject class is the base class for Field, Method and jtulach@258: * Constructor objects. It provides the ability to flag a reflected jtulach@258: * object as suppressing default Java language access control checks jtulach@258: * when it is used. The access checks--for public, default (package) jtulach@258: * access, protected, and private members--are performed when Fields, jtulach@258: * Methods or Constructors are used to set or get fields, to invoke jtulach@258: * methods, or to create and initialize new instances of classes, jtulach@258: * respectively. jtulach@258: * jtulach@258: *

Setting the {@code accessible} flag in a reflected object jtulach@258: * permits sophisticated applications with sufficient privilege, such jtulach@258: * as Java Object Serialization or other persistence mechanisms, to jtulach@258: * manipulate objects in a manner that would normally be prohibited. jtulach@258: * jtulach@258: *

By default, a reflected object is not accessible. jtulach@258: * jtulach@258: * @see Field jtulach@258: * @see Method jtulach@258: * @see Constructor jtulach@258: * @see ReflectPermission jtulach@258: * jtulach@258: * @since 1.2 jtulach@258: */ jtulach@258: public class AccessibleObject implements AnnotatedElement { jtulach@258: jtulach@258: /** jtulach@258: * The Permission object that is used to check whether a client jtulach@258: * has sufficient privilege to defeat Java language access jtulach@258: * control checks. jtulach@258: */ jtulach@258: static final private java.security.Permission ACCESS_PERMISSION = jtulach@258: new ReflectPermission("suppressAccessChecks"); jtulach@258: jtulach@258: /** jtulach@258: * Convenience method to set the {@code accessible} flag for an jtulach@258: * array of objects with a single security check (for efficiency). jtulach@258: * jtulach@258: *

First, if there is a security manager, its jtulach@258: * {@code checkPermission} method is called with a jtulach@258: * {@code ReflectPermission("suppressAccessChecks")} permission. jtulach@258: * jtulach@258: *

A {@code SecurityException} is raised if {@code flag} is jtulach@258: * {@code true} but accessibility of any of the elements of the input jtulach@258: * {@code array} may not be changed (for example, if the element jtulach@258: * object is a {@link Constructor} object for the class {@link jtulach@258: * java.lang.Class}). In the event of such a SecurityException, the jtulach@258: * accessibility of objects is set to {@code flag} for array elements jtulach@258: * upto (and excluding) the element for which the exception occurred; the jtulach@258: * accessibility of elements beyond (and including) the element for which jtulach@258: * the exception occurred is unchanged. jtulach@258: * jtulach@258: * @param array the array of AccessibleObjects jtulach@258: * @param flag the new value for the {@code accessible} flag jtulach@258: * in each object jtulach@258: * @throws SecurityException if the request is denied. jtulach@258: * @see SecurityManager#checkPermission jtulach@258: * @see java.lang.RuntimePermission jtulach@258: */ jtulach@258: public static void setAccessible(AccessibleObject[] array, boolean flag) jtulach@258: throws SecurityException { jtulach@258: SecurityManager sm = System.getSecurityManager(); jtulach@258: if (sm != null) sm.checkPermission(ACCESS_PERMISSION); jtulach@258: for (int i = 0; i < array.length; i++) { jtulach@258: setAccessible0(array[i], flag); jtulach@258: } jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Set the {@code accessible} flag for this object to jtulach@258: * the indicated boolean value. A value of {@code true} indicates that jtulach@258: * the reflected object should suppress Java language access jtulach@258: * checking when it is used. A value of {@code false} indicates jtulach@258: * that the reflected object should enforce Java language access checks. jtulach@258: * jtulach@258: *

First, if there is a security manager, its jtulach@258: * {@code checkPermission} method is called with a jtulach@258: * {@code ReflectPermission("suppressAccessChecks")} permission. jtulach@258: * jtulach@258: *

A {@code SecurityException} is raised if {@code flag} is jtulach@258: * {@code true} but accessibility of this object may not be changed jtulach@258: * (for example, if this element object is a {@link Constructor} object for jtulach@258: * the class {@link java.lang.Class}). jtulach@258: * jtulach@258: *

A {@code SecurityException} is raised if this object is a {@link jtulach@258: * java.lang.reflect.Constructor} object for the class jtulach@258: * {@code java.lang.Class}, and {@code flag} is true. jtulach@258: * jtulach@258: * @param flag the new value for the {@code accessible} flag jtulach@258: * @throws SecurityException if the request is denied. jtulach@258: * @see SecurityManager#checkPermission jtulach@258: * @see java.lang.RuntimePermission jtulach@258: */ jtulach@258: public void setAccessible(boolean flag) throws SecurityException { jtulach@258: SecurityManager sm = System.getSecurityManager(); jtulach@258: if (sm != null) sm.checkPermission(ACCESS_PERMISSION); jtulach@258: setAccessible0(this, flag); jtulach@258: } jtulach@258: jtulach@258: /* Check that you aren't exposing java.lang.Class.. */ jtulach@258: private static void setAccessible0(AccessibleObject obj, boolean flag) jtulach@258: throws SecurityException jtulach@258: { jtulach@258: if (obj instanceof Constructor && flag == true) { jtulach@258: Constructor c = (Constructor)obj; jtulach@258: if (c.getDeclaringClass() == Class.class) { jtulach@258: throw new SecurityException("Can not make a java.lang.Class" + jtulach@258: " constructor accessible"); jtulach@258: } jtulach@258: } jtulach@258: obj.override = flag; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Get the value of the {@code accessible} flag for this object. jtulach@258: * jtulach@258: * @return the value of the object's {@code accessible} flag jtulach@258: */ jtulach@258: public boolean isAccessible() { jtulach@258: return override; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Constructor: only used by the Java Virtual Machine. jtulach@258: */ jtulach@258: protected AccessibleObject() {} jtulach@258: jtulach@258: // Indicates whether language-level access checks are overridden jtulach@258: // by this object. Initializes to "false". This field is used by jtulach@258: // Field, Method, and Constructor. jtulach@258: // jtulach@258: // NOTE: for security purposes, this field must not be visible jtulach@258: // outside this package. jtulach@258: boolean override; jtulach@258: jtulach@258: // Reflection factory used by subclasses for creating field, jtulach@258: // method, and constructor accessors. Note that this is called jtulach@258: // very early in the bootstrapping process. jtulach@258: static final ReflectionFactory reflectionFactory = jtulach@258: AccessController.doPrivileged( jtulach@258: new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); jtulach@258: jtulach@258: /** jtulach@258: * @throws NullPointerException {@inheritDoc} jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public T getAnnotation(Class annotationClass) { jtulach@258: throw new AssertionError("All subclasses should override this method"); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * @throws NullPointerException {@inheritDoc} jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public boolean isAnnotationPresent( jtulach@258: Class annotationClass) { jtulach@258: return getAnnotation(annotationClass) != null; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public Annotation[] getAnnotations() { jtulach@258: return getDeclaredAnnotations(); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public Annotation[] getDeclaredAnnotations() { jtulach@258: throw new AssertionError("All subclasses should override this method"); jtulach@258: } jtulach@258: jtulach@258: jtulach@258: // Shared access checking logic. jtulach@258: jtulach@258: // For non-public members or members in package-private classes, jtulach@258: // it is necessary to perform somewhat expensive security checks. jtulach@258: // If the security check succeeds for a given class, it will jtulach@258: // always succeed (it is not affected by the granting or revoking jtulach@258: // of permissions); we speed up the check in the common case by jtulach@258: // remembering the last Class for which the check succeeded. jtulach@258: // jtulach@258: // The simple security check for Constructor is to see if jtulach@258: // the caller has already been seen, verified, and cached. jtulach@258: // (See also Class.newInstance(), which uses a similar method.) jtulach@258: // jtulach@258: // A more complicated security check cache is needed for Method and Field jtulach@258: // The cache can be either null (empty cache), a 2-array of {caller,target}, jtulach@258: // or a caller (with target implicitly equal to this.clazz). jtulach@258: // In the 2-array case, the target is always different from the clazz. jtulach@258: volatile Object securityCheckCache; jtulach@258: jtulach@258: void checkAccess(Class caller, Class clazz, Object obj, int modifiers) jtulach@258: throws IllegalAccessException jtulach@258: { jtulach@258: if (caller == clazz) { // quick check jtulach@258: return; // ACCESS IS OK jtulach@258: } jtulach@258: Object cache = securityCheckCache; // read volatile jtulach@258: Class targetClass = clazz; jtulach@258: if (obj != null jtulach@258: && Modifier.isProtected(modifiers) jtulach@258: && ((targetClass = obj.getClass()) != clazz)) { jtulach@258: // Must match a 2-list of { caller, targetClass }. jtulach@258: if (cache instanceof Class[]) { jtulach@258: Class[] cache2 = (Class[]) cache; jtulach@258: if (cache2[1] == targetClass && jtulach@258: cache2[0] == caller) { jtulach@258: return; // ACCESS IS OK jtulach@258: } jtulach@258: // (Test cache[1] first since range check for [1] jtulach@258: // subsumes range check for [0].) jtulach@258: } jtulach@258: } else if (cache == caller) { jtulach@258: // Non-protected case (or obj.class == this.clazz). jtulach@258: return; // ACCESS IS OK jtulach@258: } jtulach@258: jtulach@258: // If no return, fall through to the slow path. jtulach@258: slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass); jtulach@258: } jtulach@258: jtulach@258: // Keep all this slow stuff out of line: jtulach@258: void slowCheckMemberAccess(Class caller, Class clazz, Object obj, int modifiers, jtulach@258: Class targetClass) jtulach@258: throws IllegalAccessException jtulach@258: { jtulach@258: Reflection.ensureMemberAccess(caller, clazz, obj, modifiers); jtulach@258: jtulach@258: // Success: Update the cache. jtulach@258: Object cache = ((targetClass == clazz) jtulach@258: ? caller jtulach@258: : new Class[] { caller, targetClass }); jtulach@258: jtulach@258: // Note: The two cache elements are not volatile, jtulach@258: // but they are effectively final. The Java memory model jtulach@258: // guarantees that the initializing stores for the cache jtulach@258: // elements will occur before the volatile write. jtulach@258: securityCheckCache = cache; // write volatile jtulach@258: } jtulach@258: }