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 33 package java.lang.reflect; 34 35 import dalvik.system.VMStack; 36 37 import java.lang.annotation.Annotation; 38 39 import org.apache.harmony.kernel.vm.StringUtils; 40 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; 41 import org.apache.harmony.luni.lang.reflect.ListOfTypes; 42 import org.apache.harmony.luni.lang.reflect.Types; 43 44 /** 45 * This class represents a method. Information about the method can be accessed, 46 * and the method can be invoked dynamically. 47 * 48 * @since Android 1.0 49 */ 50 public final class Method extends AccessibleObject implements GenericDeclaration, Member { 51 52 private int slot; 53 54 private Class<?> declaringClass; 55 56 private String name; 57 58 private Class<?>[] parameterTypes; 59 60 private Class<?>[] exceptionTypes; 61 62 private Class<?> returnType; 63 64 private ListOfTypes genericExceptionTypes; 65 private ListOfTypes genericParameterTypes; 66 private Type genericReturnType; 67 private TypeVariable<Method>[] formalTypeParameters; 68 private volatile boolean genericTypesAreInitialized = false; 69 initGenericTypes()70 private synchronized void initGenericTypes() { 71 if (!genericTypesAreInitialized) { 72 String signatureAttribute = getSignatureAttribute(); 73 GenericSignatureParser parser = new GenericSignatureParser( 74 VMStack.getCallingClassLoader2()); 75 parser.parseForMethod(this, signatureAttribute); 76 formalTypeParameters = parser.formalTypeParameters; 77 genericParameterTypes = parser.parameterTypes; 78 genericExceptionTypes = parser.exceptionTypes; 79 genericReturnType = parser.returnType; 80 genericTypesAreInitialized = true; 81 } 82 } 83 84 /** 85 * Construct a clone of the given instance. 86 * 87 * @param orig non-null; the original instance to clone 88 */ Method(Method orig)89 /*package*/ Method(Method orig) { 90 this(orig.declaringClass, orig.parameterTypes, orig.exceptionTypes, 91 orig.returnType, orig.name, orig.slot); 92 93 // Copy the accessible flag. 94 if (orig.flag) { 95 this.flag = true; 96 } 97 } 98 Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot)99 private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot) 100 { 101 this.declaringClass = declaring; 102 this.name = name; 103 this.slot = slot; 104 this.parameterTypes = paramTypes; 105 this.exceptionTypes = exceptTypes; // may be null 106 this.returnType = returnType; 107 } 108 getTypeParameters()109 public TypeVariable<Method>[] getTypeParameters() { 110 initGenericTypes(); 111 return formalTypeParameters.clone(); 112 } 113 114 /** {@inheritDoc} */ getSignatureAttribute()115 @Override /*package*/ String getSignatureAttribute() { 116 Object[] annotation = getSignatureAnnotation(declaringClass, slot); 117 118 if (annotation == null) { 119 return null; 120 } 121 122 return StringUtils.combineStrings(annotation); 123 } 124 125 /** 126 * Returns the Signature annotation for this method. Returns {@code null} if 127 * not found. 128 */ getSignatureAnnotation(Class declaringClass, int slot)129 native private Object[] getSignatureAnnotation(Class declaringClass, 130 int slot); 131 132 /** 133 * Returns the string representation of the method's declaration, including 134 * the type parameters. 135 * 136 * @return the string representation of this method 137 * 138 * @since Android 1.0 139 */ toGenericString()140 public String toGenericString() { 141 StringBuilder sb = new StringBuilder(80); 142 143 initGenericTypes(); 144 145 // append modifiers if any 146 int modifier = getModifiers(); 147 if (modifier != 0) { 148 sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE + 149 Modifier.VARARGS))).append(' '); 150 } 151 // append type parameters 152 if (formalTypeParameters != null && formalTypeParameters.length > 0) { 153 sb.append('<'); 154 for (int i = 0; i < formalTypeParameters.length; i++) { 155 appendGenericType(sb, formalTypeParameters[i]); 156 if (i < formalTypeParameters.length - 1) { 157 sb.append(", "); 158 } 159 } 160 sb.append("> "); 161 } 162 // append return type 163 appendGenericType(sb, Types.getType(genericReturnType)); 164 sb.append(' '); 165 // append method name 166 appendArrayType(sb, getDeclaringClass()); 167 sb.append("."+getName()); 168 // append parameters 169 sb.append('('); 170 appendArrayGenericType(sb, 171 Types.getClonedTypeArray(genericParameterTypes)); 172 sb.append(')'); 173 // append exceptions if any 174 Type[] genericExceptionTypeArray = Types.getClonedTypeArray( 175 genericExceptionTypes); 176 if (genericExceptionTypeArray.length > 0) { 177 sb.append(" throws "); 178 appendArrayGenericType(sb, genericExceptionTypeArray); 179 } 180 return sb.toString(); 181 } 182 183 /** 184 * Returns the parameter types as an array of {@code Type} instances, in 185 * declaration order. If this method has no parameters, an empty array is 186 * returned. 187 * 188 * @return the parameter types 189 * 190 * @throws GenericSignatureFormatError 191 * if the generic method signature is invalid 192 * @throws TypeNotPresentException 193 * if any parameter type points to a missing type 194 * @throws MalformedParameterizedTypeException 195 * if any parameter type points to a type that cannot be 196 * instantiated for some reason 197 * 198 * @since Android 1.0 199 */ getGenericParameterTypes()200 public Type[] getGenericParameterTypes() { 201 initGenericTypes(); 202 return Types.getClonedTypeArray(genericParameterTypes); 203 } 204 205 /** 206 * Returns the exception types as an array of {@code Type} instances. If 207 * this method has no declared exceptions, an empty array will be returned. 208 * 209 * @return an array of generic exception types 210 * 211 * @throws GenericSignatureFormatError 212 * if the generic method signature is invalid 213 * @throws TypeNotPresentException 214 * if any exception type points to a missing type 215 * @throws MalformedParameterizedTypeException 216 * if any exception type points to a type that cannot be 217 * instantiated for some reason 218 * 219 * @since Android 1.0 220 */ getGenericExceptionTypes()221 public Type[] getGenericExceptionTypes() { 222 initGenericTypes(); 223 return Types.getClonedTypeArray(genericExceptionTypes); 224 } 225 226 /** 227 * Returns the return type of this method as a {@code Type} instance. 228 * 229 * @return the return type of this method 230 * 231 * @throws GenericSignatureFormatError 232 * if the generic method signature is invalid 233 * @throws TypeNotPresentException 234 * if the return type points to a missing type 235 * @throws MalformedParameterizedTypeException 236 * if the return type points to a type that cannot be 237 * instantiated for some reason 238 * 239 * @since Android 1.0 240 */ getGenericReturnType()241 public Type getGenericReturnType() { 242 initGenericTypes(); 243 return Types.getType(genericReturnType); 244 } 245 246 @Override getDeclaredAnnotations()247 public Annotation[] getDeclaredAnnotations() { 248 return getDeclaredAnnotations(declaringClass, slot); 249 } getDeclaredAnnotations(Class declaringClass, int slot)250 native private Annotation[] getDeclaredAnnotations(Class declaringClass, 251 int slot); 252 253 private static final Annotation[] NO_ANNOTATIONS = new Annotation[0]; 254 255 /** 256 * Creates an array of empty Annotation arrays. 257 */ noAnnotations(int size)258 /*package*/ static Annotation[][] noAnnotations(int size) { 259 Annotation[][] annotations = new Annotation[size][]; 260 for (int i = 0; i < size; i++) { 261 annotations[i] = NO_ANNOTATIONS; 262 } 263 return annotations; 264 } 265 266 /** 267 * Returns an array of arrays that represent the annotations of the formal 268 * parameters of this method. If there are no parameters on this method, 269 * then an empty array is returned. If there are no annotations set, then 270 * and array of empty arrays is returned. 271 * 272 * @return an array of arrays of {@code Annotation} instances 273 * 274 * @since Android 1.0 275 */ getParameterAnnotations()276 public Annotation[][] getParameterAnnotations() { 277 Annotation[][] parameterAnnotations 278 = getParameterAnnotations(declaringClass, slot); 279 if (parameterAnnotations.length == 0) { 280 return noAnnotations(parameterTypes.length); 281 } 282 return parameterAnnotations; 283 } 284 getParameterAnnotations(Class declaringClass, int slot)285 native private Annotation[][] getParameterAnnotations(Class declaringClass, 286 int slot); 287 288 /** 289 * Indicates whether or not this method takes a variable number argument. 290 * 291 * @return {@code true} if a vararg is declared, {@code false} otherwise 292 * 293 * @since Android 1.0 294 */ isVarArgs()295 public boolean isVarArgs() { 296 int modifiers = getMethodModifiers(declaringClass, slot); 297 return (modifiers & Modifier.VARARGS) != 0; 298 } 299 300 /** 301 * Indicates whether or not this method is a bridge. 302 * 303 * @return {@code true} if this method is a bridge, {@code false} otherwise 304 * 305 * @since Android 1.0 306 */ isBridge()307 public boolean isBridge() { 308 int modifiers = getMethodModifiers(declaringClass, slot); 309 return (modifiers & Modifier.BRIDGE) != 0; 310 } 311 312 /** 313 * Indicates whether or not this method is synthetic. 314 * 315 * @return {@code true} if this method is synthetic, {@code false} otherwise 316 * 317 * @since Android 1.0 318 */ isSynthetic()319 public boolean isSynthetic() { 320 int modifiers = getMethodModifiers(declaringClass, slot); 321 return (modifiers & Modifier.SYNTHETIC) != 0; 322 } 323 324 /** 325 * Returns the default value for the annotation member represented by this 326 * method. 327 * 328 * @return the default value, or {@code null} if none 329 * 330 * @throws TypeNotPresentException 331 * if this annotation member is of type {@code Class} and no 332 * definition can be found 333 * 334 * @since Android 1.0 335 */ getDefaultValue()336 public Object getDefaultValue() { 337 return getDefaultValue(declaringClass, slot); 338 } getDefaultValue(Class declaringClass, int slot)339 native private Object getDefaultValue(Class declaringClass, int slot); 340 341 /** 342 * Indicates whether or not the specified {@code object} is equal to this 343 * method. To be equal, the specified object must be an instance 344 * of {@code Method} with the same declaring class and parameter types 345 * as this method. 346 * 347 * @param object 348 * the object to compare 349 * 350 * @return {@code true} if the specified object is equal to this 351 * method, {@code false} otherwise 352 * 353 * @see #hashCode 354 * 355 * @since Android 1.0 356 */ 357 @Override equals(Object object)358 public boolean equals(Object object) { 359 return object instanceof Method && toString().equals(object.toString()); 360 } 361 362 /** 363 * Returns the class that declares this method. 364 * 365 * @return the declaring class 366 * 367 * @since Android 1.0 368 */ getDeclaringClass()369 public Class<?> getDeclaringClass() { 370 return declaringClass; 371 } 372 373 /** 374 * Returns the exception types as an array of {@code Class} instances. If 375 * this method has no declared exceptions, an empty array is returned. 376 * 377 * @return the declared exception classes 378 * 379 * @since Android 1.0 380 */ getExceptionTypes()381 public Class<?>[] getExceptionTypes() { 382 if (exceptionTypes == null) { 383 return new Class[0]; 384 } 385 386 return exceptionTypes; 387 } 388 389 /** 390 * Returns the modifiers for this method. The {@link Modifier} class should 391 * be used to decode the result. 392 * 393 * @return the modifiers for this method 394 * 395 * @see Modifier 396 * 397 * @since Android 1.0 398 */ getModifiers()399 public int getModifiers() { 400 return getMethodModifiers(declaringClass, slot); 401 } 402 getMethodModifiers(Class<?> decl_class, int slot)403 private native int getMethodModifiers(Class<?> decl_class, int slot); 404 405 /** 406 * Returns the name of the method represented by this {@code Method} 407 * instance. 408 * 409 * @return the name of this method 410 * 411 * @since Android 1.0 412 */ getName()413 public String getName() { 414 return name; 415 } 416 417 /** 418 * Returns an array of {@code Class} objects associated with the parameter 419 * types of this method. If the method was declared with no parameters, an 420 * empty array will be returned. 421 * 422 * @return the parameter types 423 * 424 * @since Android 1.0 425 */ getParameterTypes()426 public Class<?>[] getParameterTypes() { 427 return parameterTypes; 428 } 429 430 /** 431 * Returns the {@code Class} associated with the return type of this 432 * method. 433 * 434 * @return the return type 435 * 436 * @since Android 1.0 437 */ getReturnType()438 public Class<?> getReturnType() { 439 return returnType; 440 } 441 442 /** 443 * Returns an integer hash code for this method. Objects which are equal 444 * return the same value for this method. The hash code for this Method is 445 * the hash code of the name of this method. 446 * 447 * @return hash code for this method 448 * 449 * @see #equals 450 * 451 * @since Android 1.0 452 */ 453 @Override hashCode()454 public int hashCode() { 455 return name.hashCode(); 456 } 457 458 /** 459 * Returns the result of dynamically invoking this method. This reproduces 460 * the effect of {@code receiver.methodName(arg1, arg2, ... , argN)} This 461 * method performs the following: 462 * <ul> 463 * <li>If this method is static, the receiver argument is ignored.</li> 464 * <li>Otherwise, if the receiver is null, a NullPointerException is thrown. 465 * </li> 466 * <li>If the receiver is not an instance of the declaring class of the 467 * method, an IllegalArgumentException is thrown.</li> 468 * <li>If this Method object is enforcing access control (see 469 * AccessibleObject) and this method is not accessible from the current 470 * context, an IllegalAccessException is thrown.</li> 471 * <li>If the number of arguments passed and the number of parameters do not 472 * match, an IllegalArgumentException is thrown.</li> 473 * <li>For each argument passed: 474 * <ul> 475 * <li>If the corresponding parameter type is a primitive type, the argument 476 * is unwrapped. If the unwrapping fails, an IllegalArgumentException is 477 * thrown.</li> 478 * <li>If the resulting argument cannot be converted to the parameter type 479 * via a widening conversion, an IllegalArgumentException is thrown.</li> 480 * </ul> 481 * <li>If this method is static, it is invoked directly. If it is 482 * non-static, this method and the receiver are then used to perform a 483 * standard dynamic method lookup. The resulting method is then invoked.</li> 484 * <li>If an exception is thrown during the invocation it is caught and 485 * wrapped in an InvocationTargetException. This exception is then thrown.</li> 486 * <li>If the invocation completes normally, the return value itself is 487 * returned. If the method is declared to return a primitive type, the 488 * return value is first wrapped. If the return type is void, null is 489 * returned.</li> 490 * </ul> 491 * 492 * @param receiver 493 * the object on which to call this method 494 * @param args 495 * the arguments to the method 496 * 497 * @return the new, initialized, object 498 * 499 * @throws NullPointerException 500 * if the receiver is null for a non-static method 501 * @throws IllegalAccessException 502 * if this method is not accessible 503 * @throws IllegalArgumentException 504 * if an incorrect number of arguments are passed, the receiver 505 * is incompatible with the declaring class, or an argument 506 * could not be converted by a widening conversion 507 * @throws InvocationTargetException 508 * if an exception was thrown by the invoked method 509 * 510 * @see AccessibleObject 511 * 512 * @since Android 1.0 513 */ invoke(Object receiver, Object... args)514 public Object invoke(Object receiver, Object... args) 515 throws IllegalAccessException, IllegalArgumentException, 516 InvocationTargetException { 517 if (args == null) { 518 args = new Object[0]; 519 } 520 521 return invokeNative (receiver, args, declaringClass, parameterTypes, returnType, slot, flag); 522 } 523 invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTYpes, Class<?> returnType, int slot, boolean noAccessCheck)524 private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTYpes, Class<?> returnType, int slot, boolean noAccessCheck) 525 throws IllegalAccessException, 526 IllegalArgumentException, 527 InvocationTargetException; 528 529 /** 530 * Returns a string containing a concise, human-readable description of this 531 * method. The format of the string is: 532 * 533 * <ol> 534 * <li>modifiers (if any) 535 * <li>return type or 'void' 536 * <li>declaring class name 537 * <li>'(' 538 * <li>parameter types, separated by ',' (if any) 539 * <li>')' 540 * <li>'throws' plus exception types, separated by ',' (if any) 541 * </ol> 542 * 543 * For example: {@code public native Object 544 * java.lang.Method.invoke(Object,Object) throws 545 * IllegalAccessException,IllegalArgumentException 546 * ,InvocationTargetException} 547 * 548 * @return a printable representation for this method 549 * 550 * @since Android 1.0 551 */ 552 @Override toString()553 public String toString() { 554 StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); 555 556 if (result.length() != 0) 557 result.append(' '); 558 result.append(returnType.getName()); 559 result.append(' '); 560 result.append(declaringClass.getName()); 561 result.append('.'); 562 result.append(name); 563 result.append("("); 564 result.append(toString(parameterTypes)); 565 result.append(")"); 566 if (exceptionTypes != null && exceptionTypes.length != 0) { 567 result.append(" throws "); 568 result.append(toString(exceptionTypes)); 569 } 570 571 return result.toString(); 572 } 573 574 /** 575 * Returns the constructor's signature in non-printable form. This is called 576 * (only) from IO native code and needed for deriving the serialVersionUID 577 * of the class 578 * 579 * @return The constructor's signature. 580 */ 581 @SuppressWarnings("unused") getSignature()582 private String getSignature() { 583 StringBuilder result = new StringBuilder(); 584 585 result.append('('); 586 for(int i = 0; i < parameterTypes.length; i++) { 587 result.append(getSignature(parameterTypes[i])); 588 } 589 result.append(')'); 590 result.append(getSignature(returnType)); 591 592 return result.toString(); 593 } 594 595 } 596