1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/* 18 * Copyright (C) 2008 The Android Open Source Project 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33package java.lang.reflect; 34 35import java.lang.annotation.Annotation; 36import java.util.Hashtable; 37import org.apache.harmony.kernel.vm.StringUtils; 38 39/** 40 * {@code AccessibleObject} is the superclass of all member reflection classes 41 * (Field, Constructor, Method). AccessibleObject provides the ability to toggle 42 * a flag controlling access checks for these objects. By default, accessing a 43 * member (for example, setting a field or invoking a method) checks the 44 * validity of the access (for example, invoking a private method from outside 45 * the defining class is prohibited) and throws IllegalAccessException if the 46 * operation is not permitted. If the accessible flag is set to true, these 47 * checks are omitted. This allows privileged code, such as Java object 48 * serialization, object inspectors, and debuggers to have complete access to 49 * objects. 50 * 51 * @see Field 52 * @see Constructor 53 * @see Method 54 */ 55public class AccessibleObject implements AnnotatedElement { 56 57 // If true, object is accessible, bypassing normal access checks 58 boolean flag = false; 59 60 // Holds a mapping from Java type names to native type codes. 61 static Hashtable<String, String> trans; 62 63 static { 64 trans = new Hashtable<String, String>(9); 65 trans.put("byte", "B"); 66 trans.put("char", "C"); 67 trans.put("short", "S"); 68 trans.put("int", "I"); 69 trans.put("long", "J"); 70 trans.put("float", "F"); 71 trans.put("double", "D"); 72 trans.put("void", "V"); 73 trans.put("boolean", "Z"); 74 } 75 76 /** 77 * Attempts to set the value of the accessible flag for all the objects in 78 * the array provided. Setting this 79 * flag to {@code false} will enable access checks, setting to {@code true} 80 * will disable them. 81 * 82 * @param objects 83 * the accessible objects 84 * @param flag 85 * the new value for the accessible flag 86 * 87 * @see #setAccessible(boolean) 88 */ 89 public static void setAccessible(AccessibleObject[] objects, boolean flag) { 90 synchronized(AccessibleObject.class) { 91 for (AccessibleObject object : objects) { 92 object.flag = flag; 93 } 94 } 95 } 96 97 /** 98 * Constructs a new {@code AccessibleObject} instance. {@code 99 * AccessibleObject} instances can only be constructed by the virtual 100 * machine. 101 */ 102 protected AccessibleObject() { 103 } 104 105 /** 106 * Indicates whether this object is accessible without access checks being 107 * performed. Returns the accessible flag. 108 * 109 * @return {@code true} if this object is accessible without access 110 * checks, {@code false} otherwise 111 */ 112 public boolean isAccessible() { 113 return flag; 114 } 115 116 /** 117 * Attempts to set the value of the accessible flag. Setting this flag to 118 * {@code false} will enable access checks, setting to {@code true} will 119 * disable them. 120 * 121 * @param flag 122 * the new value for the accessible flag 123 */ 124 public void setAccessible(boolean flag) { 125 this.flag = flag; 126 } 127 128 public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 129 throw new UnsupportedOperationException(); 130 } 131 132 public Annotation[] getDeclaredAnnotations() { 133 throw new UnsupportedOperationException(); 134 } 135 136 public Annotation[] getAnnotations() { 137 // for all but Class, getAnnotations == getDeclaredAnnotations 138 return getDeclaredAnnotations(); 139 } 140 141 public <T extends Annotation> T getAnnotation(Class<T> annotationType) { 142 throw new UnsupportedOperationException(); 143 } 144 145 /** 146 * Returns the signature for a class. This is the kind of signature used 147 * internally by the JVM, with one-character codes representing the basic 148 * types. It is not suitable for printing. 149 * 150 * @param clazz 151 * the class for which a signature is required 152 * 153 * @return The signature as a string 154 */ 155 String getSignature(Class<?> clazz) { 156 String result = ""; 157 String nextType = clazz.getName(); 158 159 if(trans.containsKey(nextType)) { 160 result = trans.get(nextType); 161 } else { 162 if(clazz.isArray()) { 163 result = "[" + getSignature(clazz.getComponentType()); 164 } else { 165 result = "L" + nextType + ";"; 166 } 167 } 168 return result; 169 } 170 171 /** 172 * Returns a printable String consisting of the canonical names of the 173 * classes contained in an array. The form is that used in parameter and 174 * exception lists, that is, the class or type names are separated by 175 * commas. 176 * 177 * @param types 178 * the array of classes 179 * 180 * @return The String of names 181 */ 182 String toString(Class<?>[] types) { 183 StringBuilder result = new StringBuilder(); 184 185 if (types.length != 0) { 186 appendTypeName(result, types[0]); 187 for (int i = 1; i < types.length; i++) { 188 result.append(','); 189 appendTypeName(result, types[i]); 190 } 191 } 192 193 return result.toString(); 194 } 195 196 /** 197 * Gets the Signature attribute for this instance. Returns {@code null} 198 * if not found. 199 */ 200 /*package*/ String getSignatureAttribute() { 201 /* 202 * Note: This method would have been declared abstract, but the 203 * standard API lists this class as concrete. 204 */ 205 throw new UnsupportedOperationException(); 206 } 207 208 /** 209 * Retrieve the signature attribute from an arbitrary class. This is 210 * the same as Class.getSignatureAttribute(), but it can be used from 211 * the java.lang.reflect package. 212 */ 213 /*package*/ static String getClassSignatureAttribute(Class clazz) { 214 Object[] annotation = getClassSignatureAnnotation(clazz); 215 216 if (annotation == null) { 217 return null; 218 } 219 220 return StringUtils.combineStrings(annotation); 221 } 222 223 /** 224 * Retrieve the signature annotation from an arbitrary class. This is 225 * the same as Class.getSignatureAttribute(), but it can be used from 226 * the java.lang.reflect package. 227 */ 228 private static native Object[] getClassSignatureAnnotation(Class clazz); 229 230 /** 231 * Appends the best {@link #toString} name for {@code c} to {@code out}. 232 * This works around the fact that {@link Class#getName} is lousy for 233 * primitive arrays (it writes "[C" instead of "char[]") and {@link 234 * Class#getCanonicalName()} is lousy for nested classes (it uses a "." 235 * separator rather than a "$" separator). 236 */ 237 void appendTypeName(StringBuilder out, Class<?> c) { 238 int dimensions = 0; 239 while (c.isArray()) { 240 c = c.getComponentType(); 241 dimensions++; 242 } 243 out.append(c.getName()); 244 for (int d = 0; d < dimensions; d++) { 245 out.append("[]"); 246 } 247 } 248 249 /** 250 * Appends names of the specified array classes to the buffer. The array 251 * elements may represent a simple type, a reference type or an array type. 252 * Output format: java.lang.Object[], java.io.File, void 253 * 254 * @param types array of classes to print the names 255 * @throws NullPointerException if any of the arguments is null 256 */ 257 void appendArrayGenericType(StringBuilder sb, Type[] types) { 258 if (types.length > 0) { 259 appendGenericType(sb, types[0]); 260 for (int i = 1; i < types.length; i++) { 261 sb.append(','); 262 appendGenericType(sb, types[i]); 263 } 264 } 265 } 266 267 /** 268 * Appends the generic type representation to the buffer. 269 * 270 * @param sb buffer 271 * @param obj the generic type which representation should be appended to the buffer 272 * 273 * @throws NullPointerException if any of the arguments is null 274 */ 275 void appendGenericType(StringBuilder sb, Type obj) { 276 if (obj instanceof TypeVariable) { 277 sb.append(((TypeVariable)obj).getName()); 278 } else if (obj instanceof ParameterizedType) { 279 sb.append(obj.toString()); 280 } else if (obj instanceof GenericArrayType) { //XXX: is it a working branch? 281 Type simplified = ((GenericArrayType)obj).getGenericComponentType(); 282 appendGenericType(sb, simplified); 283 sb.append("[]"); 284 } else if (obj instanceof Class) { 285 Class c = ((Class<?>)obj); 286 if (c.isArray()){ 287 String as[] = c.getName().split("\\["); 288 int len = as.length-1; 289 if (as[len].length() > 1){ 290 sb.append(as[len].substring(1, as[len].length()-1)); 291 } else { 292 char ch = as[len].charAt(0); 293 if (ch == 'I') 294 sb.append("int"); 295 else if (ch == 'B') 296 sb.append("byte"); 297 else if (ch == 'J') 298 sb.append("long"); 299 else if (ch == 'F') 300 sb.append("float"); 301 else if (ch == 'D') 302 sb.append("double"); 303 else if (ch == 'S') 304 sb.append("short"); 305 else if (ch == 'C') 306 sb.append("char"); 307 else if (ch == 'Z') 308 sb.append("boolean"); 309 else if (ch == 'V') //XXX: is it a working branch? 310 sb.append("void"); 311 } 312 for (int i = 0; i < len; i++){ 313 sb.append("[]"); 314 } 315 } else { 316 sb.append(c.getName()); 317 } 318 } 319 } 320} 321