001    /* java.lang.reflect.AccessibleObject
002       Copyright (C) 2001, 2005, 2006  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.lang.reflect;
040    
041    import java.lang.annotation.Annotation;
042    
043    /**
044     * This class is the superclass of various reflection classes, and
045     * allows sufficiently trusted code to bypass normal restrictions to
046     * do necessary things like invoke private methods outside of the
047     * class during Serialization.  If you don't have a good reason
048     * to mess with this, don't try. Fortunately, there are adequate
049     * security checks before you can set a reflection object as accessible.
050     *
051     * @author Tom Tromey (tromey@cygnus.com)
052     * @author Eric Blake (ebb9@email.byu.edu)
053     * @see Field
054     * @see Constructor
055     * @see Method
056     * @see ReflectPermission
057     * @since 1.2
058     * @status updated to 1.5
059     */
060    public class AccessibleObject
061        implements AnnotatedElement
062    {
063      /**
064       * True if this object is marked accessible, which means the reflected
065       * object bypasses normal security checks.
066       */
067      // default visibility for use by inherited classes
068      boolean flag = false;
069    
070      /**
071       * Only the three reflection classes that extend this can create an
072       * accessible object.  This is not serializable for security reasons.
073       */
074      protected AccessibleObject()
075      {
076      }
077    
078      /**
079       * Return the accessibility status of this object.
080       *
081       * @return true if this object bypasses security checks
082       */
083      public boolean isAccessible()
084      {
085        return flag;
086      }
087    
088      /**
089       * Convenience method to set the flag on a number of objects with a single
090       * security check. If a security manager exists, it is checked for
091       * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
092       *
093       * It is forbidden to set the accessibility flag to true on any constructor
094       * for java.lang.Class. This will result in a SecurityException. If the 
095       * SecurityException is thrown for any of the passed AccessibleObjects,
096       * the accessibility flag will be set on AccessibleObjects in the array prior 
097       * to the one which resulted in the exception.
098       *
099       * @param array the array of accessible objects
100       * @param flag the desired state of accessibility, true to bypass security
101       * @throws NullPointerException if array is null
102       * @throws SecurityException if the request is denied
103       * @see SecurityManager#checkPermission(java.security.Permission)
104       * @see RuntimePermission
105       */
106      public static void setAccessible(AccessibleObject[] array, boolean flag)
107      {
108        checkPermission();
109        for (int i = 0; i < array.length; i++)
110          array[i].secureSetAccessible(flag);
111      }
112    
113      /**
114       * Sets the accessibility flag for this reflection object. If a security
115       * manager exists, it is checked for
116       * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
117       *
118       * It is forbidden to set the accessibility flag to true on any constructor for 
119       * java.lang.Class. This will result in a SecurityException.
120       *
121       * @param flag the desired state of accessibility, true to bypass security
122       * @throws NullPointerException if array is null
123       * @throws SecurityException if the request is denied
124       * @see SecurityManager#checkPermission(java.security.Permission)
125       * @see RuntimePermission
126       */
127      public void setAccessible(boolean flag)
128      {
129        checkPermission();
130        secureSetAccessible(flag);
131      }
132    
133      /**
134       * Performs the specified security check, for
135       * <code>ReflectPermission("suppressAccessChecks")</code>.
136       *
137       * @throws SecurityException if permission is denied
138       */
139      private static void checkPermission()
140      {
141        SecurityManager sm = System.getSecurityManager();
142        if (sm != null)
143          sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
144      }
145    
146      /**
147       * Performs the actual accessibility change, this must always be invoked
148       * after calling checkPermission.
149       *
150       * @param flag the desired status
151       * @throws SecurityException if flag is true and this is a constructor
152       * for <code>java.lang.Class</code>.
153       */
154      private void secureSetAccessible(boolean flag)
155      {
156        if (flag &&
157            (this instanceof Constructor
158              && ((Constructor) this).getDeclaringClass() == Class.class))
159          throw new SecurityException("Cannot make object accessible: " + this);
160        this.flag = flag;
161      }
162    
163      public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
164      {
165        throw new AssertionError("Subclass must override this method");
166      }
167    
168      public Annotation[] getAnnotations()
169      {
170        return getDeclaredAnnotations();
171      }
172    
173      public Annotation[] getDeclaredAnnotations()
174      {
175        throw new AssertionError("Subclass must override this method");
176      }
177    
178      public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
179      {
180        return getAnnotation(annotationClass) != null;
181      }
182    }