001/* java.lang.reflect.AccessibleObject
002   Copyright (C) 2001, 2005, 2006  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.lang.reflect;
040
041import 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 */
060public 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  /**
164   * <p>
165   * Returns the element's annotation for the specified annotation type,
166   * or <code>null</code> if no such annotation exists.
167   * </p>
168   * <p>
169   * <strong>This method must be overridden by subclasses to provide
170   * appropriate behaviour.</strong>
171   * </p>
172   *
173   * @param annotationClass the type of annotation to look for.
174   * @return this element's annotation for the specified type, or
175   *         <code>null</code> if no such annotation exists.
176   * @throws NullPointerException if the annotation class is <code>null</code>.
177   */
178  public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
179  {
180    throw new AssertionError("Subclass must override this method");
181  }
182
183  /**
184   * Returns all annotations associated with the element.  If there are
185   * no annotations associated with the element, then a zero-length array
186   * will be returned.  The returned array may be modified by the client
187   * code, but this will have no effect on the annotation content of the
188   * element, and hence no effect on the return value of this method for
189   * future callers.
190   *
191   * @return this element's annotations.
192   */
193  public Annotation[] getAnnotations()
194  {
195    return getDeclaredAnnotations();
196  }
197
198  /**
199   * <p>
200   * Returns all annotations directly defined by the element.  If there are
201   * no annotations directly associated with the element, then a zero-length
202   * array will be returned.  The returned array may be modified by the client
203   * code, but this will have no effect on the annotation content of this
204   * class, and hence no effect on the return value of this method for
205   * future callers.
206   * </p>
207   * <p>
208   * <strong>This method must be overridden by subclasses to provide
209   * appropriate behaviour.</strong>
210   * </p>
211   *
212   * @return the annotations directly defined by the element.
213   * @since 1.5
214   */
215  public Annotation[] getDeclaredAnnotations()
216  {
217    throw new AssertionError("Subclass must override this method");
218  }
219
220  /**
221   * Returns true if an annotation for the specified type is associated
222   * with the element.  This is primarily a short-hand for using marker
223   * annotations.
224   *
225   * @param annotationClass the type of annotation to look for.
226   * @return true if an annotation exists for the specified type.
227   * @since 1.5
228   */
229  public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
230  {
231    return getAnnotation(annotationClass) != null;
232  }
233}