/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.lang.reflect; import java.lang.annotation.Annotation; import org.apache.harmony.lang.reflect.ReflectPermissionCollection; import org.jikesrvm.classloader.Atom; import org.jikesrvm.classloader.RVMMember; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.classloader.TypeReference; /** * This class must be implemented by the VM vendor. This class is the superclass * of all member reflect classes (Field, Constructor, Method). AccessibleObject * provides the ability to toggle access checks for these objects. By default * accessing a member (for example, setting a field or invoking a method) checks * the validity of the access (for example, invoking a private method from * outside the defining class is prohibited) and throws IllegalAccessException * if the operation is not permitted. If the accessible flag is set to true, * these checks are omitted. This allows privileged applications such as Java * Object Serialization, inspectors, and debuggers to have complete access to * objects. * * @see Field * @see Constructor * @see Method * @see ReflectPermission * @since 1.2 */ public class AccessibleObject implements AnnotatedElement { /** * Has the object been marked as accessible? */ private boolean isAccessible = false; /** * Attempts to set the value of the accessible flag for all the objects in * the array provided. Only one security check is performed. Setting this * flag to false will enable access checks, setting to true will disable * them. If there is a security manager, checkPermission is called with a * ReflectPermission("suppressAccessChecks"). * * @param objects the accessible objects * @param flag the new value for the accessible flag * @see #setAccessible(boolean) * @see ReflectPermission * @throws SecurityException if the request is denied */ public static void setAccessible(AccessibleObject[] objects, boolean flag) throws SecurityException { SecurityManager sc = System.getSecurityManager(); if (sc != null) { sc.checkPermission(ReflectPermissionCollection.SUPPRESS_ACCESS_CHECKS_PERMISSION); } for (int i = 0; i < objects.length; i++) { objects[i].setAccessible0(flag); } } /** * AccessibleObject constructor. AccessibleObjects can only be created by * the Virtual Machine. */ AccessibleObject() { super(); } /** * Returns the value of the accessible flag. This is false if access checks * are performed, true if they are skipped. * * @return the value of the accessible flag */ public boolean isAccessible() { return isAccessible; } /** * Attempts to set the value of the accessible flag. Setting this flag to * false will enable access checks, setting to true will disable them. If * there is a security manager, checkPermission is called with a * ReflectPermission("suppressAccessChecks"). * * @param flag the new value for the accessible flag * @see ReflectPermission * @throws SecurityException if the request is denied */ public void setAccessible(boolean flag) throws SecurityException { SecurityManager sc = System.getSecurityManager(); if (sc != null) { sc.checkPermission(ReflectPermissionCollection.SUPPRESS_ACCESS_CHECKS_PERMISSION); } setAccessible0(flag); } public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { return getVMMember().isAnnotationPresent(annotationType); } public Annotation[] getDeclaredAnnotations() { return getVMMember().getDeclaredAnnotations(); } public Annotation[] getAnnotations() { return getVMMember().getDeclaredAnnotations(); } public <T extends Annotation> T getAnnotation(Class<T> annotationType) { return getVMMember().getAnnotation(annotationType); } /* ---- Non-API Methods ---- */ /** * Set the accessibilty to the value of flag. Overridden in Constructor. */ void setAccessible0(boolean flag) { isAccessible = flag; } /** * Get the VM member implementation. Package protected to stop outside use. */ RVMMember getVMMember() { throw new Error("This method should always be overridden"); } /** * Get the VM method implementation, invalid for fields. Package protected to * stop outside use. */ RVMMethod getVMMethod() { throw new Error("This method should always be overridden"); } /** * <p> * Gets an array of arrays that represent the annotations of the formal * parameters of this RVMMethod. If there are no parameters on this * constructor, then an empty array is returned. If there are no annotations * set, then and array of empty arrays is returned. * </p> * * @return An array of arrays of {@link Annotation} instances. * @since 1.5 */ Annotation[][] getParameterAnnotations() { return getVMMethod().getDeclaredParameterAnnotations(); } /** * <p> * Indicates whether or not this RVMMethod takes a variable number * argument. * </p> * * @return A value of <code>true</code> if a vararg is declare, otherwise * <code>false</code>. */ boolean isVarArgs() { return (getVMMethod().getModifiers() & Modifier.VARARGS) != 0; } boolean isSynthetic() { return (getVMMethod().getModifiers() & Modifier.SYNTHETIC) != 0; } /** * Return the modifiers for the modeled method. The Modifier class * should be used to decode the result. * * @return the modifiers * @see java.lang.reflect.Modifier */ int getModifiers() { return getVMMember().getModifiers(); } /** * Return an array of the {@link Class} objects associated with the * exceptions declared to be thrown by this method. If the method * was not declared to throw any exceptions, the array returned will be * empty. * * @return the declared exception classes */ Class<?>[] getExceptionTypes() { TypeReference[] exceptionTypes = getVMMethod().getExceptionTypes(); if (exceptionTypes == null) { return new Class[0]; } else { return VMCommonLibrarySupport.typesToClasses(exceptionTypes); } } /** * Appends the specified class name to the buffer. The class may represent * a simple type, a reference type or an array type. * * @param sb buffer * @param obj the class which name should be appended to the buffer * @throws NullPointerException if any of the arguments is null */ static void appendArrayType(StringBuilder sb, Class<?> obj) { if (!obj.isArray()) { sb.append(obj.getName()); return; } int dimensions = 1; Class simplified = obj.getComponentType(); obj = simplified; while (simplified.isArray()) { obj = simplified; dimensions++; } sb.append(obj.getName()); switch (dimensions) { case 1: sb.append("[]"); break; case 2: sb.append("[][]"); break; case 3: sb.append("[][][]"); break; default: for (int i=0; i < dimensions; i++) { sb.append("[]"); } } } /** * Appends names of the specified array classes to the buffer. The array * elements may represent a simple type, a reference type or an array type. * Output format: java.lang.Object[], java.io.File, void * * @param sb buffer * @param objs array of classes to print the names * @throws NullPointerException if any of the arguments is null */ void appendArrayType(StringBuilder sb, Class[] objs) { if (objs.length > 0) { appendArrayType(sb, objs[0]); for (int i = 1; i < objs.length; i++) { sb.append(','); appendArrayType(sb, objs[i]); } } } /** * Appends names of the specified array classes to the buffer. The array * elements may represent a simple type, a reference type or an array type. * In case if the specified array element represents an array type its * internal will be appended to the buffer. * Output format: [Ljava.lang.Object;, java.io.File, void * * @param sb buffer * @param objs array of classes to print the names * @throws NullPointerException if any of the arguments is null */ static void appendSimpleType(StringBuilder sb, Class<?>[] objs) { if (objs.length > 0) { sb.append(objs[0].getName()); for (int i = 1; i < objs.length; i++) { sb.append(','); sb.append(objs[i].getName()); } } } /** * Return a descriptor for the member */ String getSignature() { return getVMMember().getDescriptor().toString(); } }