/* * 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. */ /* * Copyright (C) 2008 The Android Open Source Project * * Licensed 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 java.util.Hashtable; import org.apache.harmony.kernel.vm.StringUtils; /** * {@code AccessibleObject} is the superclass of all member reflection classes * (Field, Constructor, Method). AccessibleObject provides the ability to toggle * a flag controlling 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 code, such as Java object * serialization, object inspectors, and debuggers to have complete access to * objects. * * @see Field * @see Constructor * @see Method */ public class AccessibleObject implements AnnotatedElement { // If true, object is accessible, bypassing normal access checks boolean flag = false; // Holds a mapping from Java type names to native type codes. static Hashtable trans; static { trans = new Hashtable(9); trans.put("byte", "B"); trans.put("char", "C"); trans.put("short", "S"); trans.put("int", "I"); trans.put("long", "J"); trans.put("float", "F"); trans.put("double", "D"); trans.put("void", "V"); trans.put("boolean", "Z"); } /** * Attempts to set the value of the accessible flag for all the objects in * the array provided. Setting this * flag to {@code false} will enable access checks, setting to {@code true} * will disable them. * * @param objects * the accessible objects * @param flag * the new value for the accessible flag * * @see #setAccessible(boolean) */ public static void setAccessible(AccessibleObject[] objects, boolean flag) { synchronized(AccessibleObject.class) { for (AccessibleObject object : objects) { object.flag = flag; } } } /** * Constructs a new {@code AccessibleObject} instance. {@code * AccessibleObject} instances can only be constructed by the virtual * machine. */ protected AccessibleObject() { } /** * Indicates whether this object is accessible without access checks being * performed. Returns the accessible flag. * * @return {@code true} if this object is accessible without access * checks, {@code false} otherwise */ public boolean isAccessible() { return flag; } /** * Attempts to set the value of the accessible flag. Setting this flag to * {@code false} will enable access checks, setting to {@code true} will * disable them. * * @param flag * the new value for the accessible flag */ public void setAccessible(boolean flag) { this.flag = flag; } public boolean isAnnotationPresent(Class annotationType) { throw new UnsupportedOperationException(); } public Annotation[] getDeclaredAnnotations() { throw new UnsupportedOperationException(); } public Annotation[] getAnnotations() { // for all but Class, getAnnotations == getDeclaredAnnotations return getDeclaredAnnotations(); } public T getAnnotation(Class annotationType) { throw new UnsupportedOperationException(); } /** * Returns the signature for a class. This is the kind of signature used * internally by the JVM, with one-character codes representing the basic * types. It is not suitable for printing. * * @param clazz * the class for which a signature is required * * @return The signature as a string */ String getSignature(Class clazz) { String result = ""; String nextType = clazz.getName(); if(trans.containsKey(nextType)) { result = trans.get(nextType); } else { if(clazz.isArray()) { result = "[" + getSignature(clazz.getComponentType()); } else { result = "L" + nextType + ";"; } } return result; } /** * Returns a printable String consisting of the canonical names of the * classes contained in an array. The form is that used in parameter and * exception lists, that is, the class or type names are separated by * commas. * * @param types * the array of classes * * @return The String of names */ String toString(Class[] types) { StringBuilder result = new StringBuilder(); if (types.length != 0) { result.append(types[0].getName()); for (int i = 1; i < types.length; i++) { result.append(','); result.append(types[i].getName()); } } return result.toString(); } /** * Gets the Signature attribute for this instance. Returns {@code null} * if not found. */ /*package*/ String getSignatureAttribute() { /* * Note: This method would have been declared abstract, but the * standard API lists this class as concrete. */ throw new UnsupportedOperationException(); } /** * Retrieve the signature attribute from an arbitrary class. This is * the same as Class.getSignatureAttribute(), but it can be used from * the java.lang.reflect package. */ /*package*/ static String getClassSignatureAttribute(Class clazz) { Object[] annotation = getClassSignatureAnnotation(clazz); if (annotation == null) { return null; } return StringUtils.combineStrings(annotation); } /** * Retrieve the signature annotation from an arbitrary class. This is * the same as Class.getSignatureAttribute(), but it can be used from * the java.lang.reflect package. */ private static native Object[] getClassSignatureAnnotation(Class clazz); /** * 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 */ void appendArrayType(StringBuilder sb, Class obj) { int dimensions = 0; while (obj.isArray()) { obj = obj.getComponentType(); dimensions++; } sb.append(obj.getName()); for (int d = 0; d < dimensions; d++) { 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 types array of classes to print the names * @throws NullPointerException if any of the arguments is null */ void appendArrayGenericType(StringBuilder sb, Type[] types) { if (types.length > 0) { appendGenericType(sb, types[0]); for (int i = 1; i < types.length; i++) { sb.append(','); appendGenericType(sb, types[i]); } } } /** * Appends the generic type representation to the buffer. * * @param sb buffer * @param obj the generic type which representation should be appended to the buffer * * @throws NullPointerException if any of the arguments is null */ void appendGenericType(StringBuilder sb, Type obj) { if (obj instanceof TypeVariable) { sb.append(((TypeVariable)obj).getName()); } else if (obj instanceof ParameterizedType) { sb.append(obj.toString()); } else if (obj instanceof GenericArrayType) { //XXX: is it a working branch? Type simplified = ((GenericArrayType)obj).getGenericComponentType(); appendGenericType(sb, simplified); sb.append("[]"); } else if (obj instanceof Class) { Class c = ((Class)obj); if (c.isArray()){ String as[] = c.getName().split("\\["); int len = as.length-1; if (as[len].length() > 1){ sb.append(as[len].substring(1, as[len].length()-1)); } else { char ch = as[len].charAt(0); if (ch == 'I') sb.append("int"); else if (ch == 'B') sb.append("byte"); else if (ch == 'J') sb.append("long"); else if (ch == 'F') sb.append("float"); else if (ch == 'D') sb.append("double"); else if (ch == 'S') sb.append("short"); else if (ch == 'C') sb.append("char"); else if (ch == 'Z') sb.append("boolean"); else if (ch == 'V') //XXX: is it a working branch? sb.append("void"); } for (int i = 0; i < len; i++){ sb.append("[]"); } } else { sb.append(c.getName()); } } } }