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