1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.reflect;
  27 
  28 import java.lang.annotation.*;
  29 import java.util.Map;
  30 import java.util.Objects;
  31 import sun.reflect.annotation.AnnotationParser;
  32 import sun.reflect.annotation.AnnotationSupport;
  33 import sun.reflect.annotation.TypeAnnotationParser;
  34 import sun.reflect.annotation.TypeAnnotation;
  35 import sun.reflect.generics.repository.ConstructorRepository;
  36 
  37 /**
  38  * A shared superclass for the common functionality of {@link Method}
  39  * and {@link Constructor}.
  40  *
  41  * @since 1.8
  42  */
  43 public abstract class Executable extends AccessibleObject
  44     implements Member, GenericDeclaration {
  45     /*
  46      * Only grant package-visibility to the constructor.
  47      */
  48     Executable() {}
  49 
  50     /**
  51      * Accessor method to allow code sharing
  52      */
  53     abstract byte[] getAnnotationBytes();
  54     abstract byte[] getTypeAnnotationBytes();
  55 
  56     /**
  57      * Does the Executable have generic information.
  58      */
  59     abstract boolean hasGenericInformation();
  60 
  61     abstract ConstructorRepository getGenericInfo();
  62 
  63     boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
  64         /* Avoid unnecessary cloning */
  65         if (params1.length == params2.length) {
  66             for (int i = 0; i < params1.length; i++) {
  67                 if (params1[i] != params2[i])
  68                     return false;
  69             }
  70             return true;
  71         }
  72         return false;
  73     }
  74 
  75     Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) {
  76         return AnnotationParser.parseParameterAnnotations(
  77                parameterAnnotations,
  78                sun.misc.SharedSecrets.getJavaLangAccess().
  79                getConstantPool(getDeclaringClass()),
  80                getDeclaringClass());
  81     }
  82 
  83     void separateWithCommas(Class<?>[] types, StringBuilder sb) {
  84         for (int j = 0; j < types.length; j++) {
  85             sb.append(Field.getTypeName(types[j]));
  86             if (j < (types.length - 1))
  87                 sb.append(",");
  88         }
  89 
  90     }
  91 
  92     void printModifiersIfNonzero(StringBuilder sb, int mask) {
  93         int mod = getModifiers() & mask;
  94         if (mod != 0) {
  95             sb.append(Modifier.toString(mod)).append(' ');
  96         }
  97     }
  98 
  99     String sharedToString(int modifierMask,
 100                           Class<?>[] parameterTypes,
 101                           Class<?>[] exceptionTypes) {
 102         try {
 103             StringBuilder sb = new StringBuilder();
 104 
 105             printModifiersIfNonzero(sb, modifierMask);
 106             specificToStringHeader(sb);
 107 
 108             sb.append('(');
 109             separateWithCommas(parameterTypes, sb);
 110             sb.append(')');
 111             if (exceptionTypes.length > 0) {
 112                 sb.append(" throws ");
 113                 separateWithCommas(exceptionTypes, sb);
 114             }
 115             return sb.toString();
 116         } catch (Exception e) {
 117             return "<" + e + ">";
 118         }
 119     }
 120 
 121     /**
 122      * Generate toString header information specific to a method or
 123      * constructor.
 124      */
 125     abstract void specificToStringHeader(StringBuilder sb);
 126 
 127     String sharedToGenericString(int modifierMask) {
 128         try {
 129             StringBuilder sb = new StringBuilder();
 130 
 131             printModifiersIfNonzero(sb, modifierMask);
 132 
 133             TypeVariable<?>[] typeparms = getTypeParameters();
 134             if (typeparms.length > 0) {
 135                 boolean first = true;
 136                 sb.append('<');
 137                 for(TypeVariable<?> typeparm: typeparms) {
 138                     if (!first)
 139                         sb.append(',');
 140                     // Class objects can't occur here; no need to test
 141                     // and call Class.getName().
 142                     sb.append(typeparm.toString());
 143                     first = false;
 144                 }
 145                 sb.append("> ");
 146             }
 147 
 148             specificToGenericStringHeader(sb);
 149 
 150             sb.append('(');
 151             Type[] params = getGenericParameterTypes();
 152             for (int j = 0; j < params.length; j++) {
 153                 String param = (params[j] instanceof Class)?
 154                     Field.getTypeName((Class)params[j]):
 155                     (params[j].toString());
 156                 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
 157                     param = param.replaceFirst("\\[\\]$", "...");
 158                 sb.append(param);
 159                 if (j < (params.length - 1))
 160                     sb.append(',');
 161             }
 162             sb.append(')');
 163             Type[] exceptions = getGenericExceptionTypes();
 164             if (exceptions.length > 0) {
 165                 sb.append(" throws ");
 166                 for (int k = 0; k < exceptions.length; k++) {
 167                     sb.append((exceptions[k] instanceof Class)?
 168                               ((Class)exceptions[k]).getName():
 169                               exceptions[k].toString());
 170                     if (k < (exceptions.length - 1))
 171                         sb.append(',');
 172                 }
 173             }
 174             return sb.toString();
 175         } catch (Exception e) {
 176             return "<" + e + ">";
 177         }
 178     }
 179 
 180     /**
 181      * Generate toGenericString header information specific to a
 182      * method or constructor.
 183      */
 184     abstract void specificToGenericStringHeader(StringBuilder sb);
 185 
 186     /**
 187      * Returns the {@code Class} object representing the class or interface
 188      * that declares the executable represented by this object.
 189      */
 190     public abstract Class<?> getDeclaringClass();
 191 
 192     /**
 193      * Returns the name of the executable represented by this object.
 194      */
 195     public abstract String getName();
 196 
 197     /**
 198      * Returns the Java language {@linkplain Modifier modifiers} for
 199      * the executable represented by this object.
 200      */
 201     public abstract int getModifiers();
 202 
 203     /**
 204      * Returns an array of {@code TypeVariable} objects that represent the
 205      * type variables declared by the generic declaration represented by this
 206      * {@code GenericDeclaration} object, in declaration order.  Returns an
 207      * array of length 0 if the underlying generic declaration declares no type
 208      * variables.
 209      *
 210      * @return an array of {@code TypeVariable} objects that represent
 211      *     the type variables declared by this generic declaration
 212      * @throws GenericSignatureFormatError if the generic
 213      *     signature of this generic declaration does not conform to
 214      *     the format specified in
 215      *     <cite>The Java&trade; Virtual Machine Specification</cite>
 216      */
 217     public abstract TypeVariable<?>[] getTypeParameters();
 218 
 219     /**
 220      * Returns an array of {@code Class} objects that represent the formal
 221      * parameter types, in declaration order, of the executable
 222      * represented by this object.  Returns an array of length
 223      * 0 if the underlying executable takes no parameters.
 224      *
 225      * @return the parameter types for the executable this object
 226      * represents
 227      */
 228     public abstract Class<?>[] getParameterTypes();
 229 
 230     /**
 231      * Returns the number of formal parameters (including any
 232      * synthetic or synthesized parameters) for the executable
 233      * represented by this object.
 234      *
 235      * @return The number of formal parameters for the executable this
 236      * object represents
 237      */
 238     public int getParameterCount() {
 239         throw new AbstractMethodError();
 240     }
 241 
 242     /**
 243      * Returns an array of {@code Type} objects that represent the formal
 244      * parameter types, in declaration order, of the executable represented by
 245      * this object. Returns an array of length 0 if the
 246      * underlying executable takes no parameters.
 247      *
 248      * <p>If a formal parameter type is a parameterized type,
 249      * the {@code Type} object returned for it must accurately reflect
 250      * the actual type parameters used in the source code.
 251      *
 252      * <p>If a formal parameter type is a type variable or a parameterized
 253      * type, it is created. Otherwise, it is resolved.
 254      *
 255      * @return an array of {@code Type}s that represent the formal
 256      *     parameter types of the underlying executable, in declaration order
 257      * @throws GenericSignatureFormatError
 258      *     if the generic method signature does not conform to the format
 259      *     specified in
 260      *     <cite>The Java&trade; Virtual Machine Specification</cite>
 261      * @throws TypeNotPresentException if any of the parameter
 262      *     types of the underlying executable refers to a non-existent type
 263      *     declaration
 264      * @throws MalformedParameterizedTypeException if any of
 265      *     the underlying executable's parameter types refer to a parameterized
 266      *     type that cannot be instantiated for any reason
 267      */
 268     public Type[] getGenericParameterTypes() {
 269         if (hasGenericInformation())
 270             return getGenericInfo().getParameterTypes();
 271         else
 272             return getParameterTypes();
 273     }
 274 
 275     /**
 276      * Returns an array of {@code Parameter} objects that represent
 277      * all the parameters to the underlying executable represented by
 278      * this object.  Returns an array of length 0 if the executable
 279      * has no parameters.
 280      *
 281      * The parameters of the underlying executable do not necessarily
 282      * have unique names, or names that are legal identifiers in the
 283      * Java programming language (JLS 3.8).
 284      *
 285      * @return an array of {@code Parameter} objects representing all
 286      * the parameters to the executable this object represents
 287      */
 288     public Parameter[] getParameters() {
 289         // TODO: This may eventually need to be guarded by security
 290         // mechanisms similar to those in Field, Method, etc.
 291         //
 292         // Need to copy the cached array to prevent users from messing
 293         // with it.  Since parameters are immutable, we can
 294         // shallow-copy.
 295         return privateGetParameters().clone();
 296     }
 297 
 298     private Parameter[] synthesizeAllParams() {
 299         final int realparams = getParameterCount();
 300         final Parameter[] out = new Parameter[realparams];
 301         for (int i = 0; i < realparams; i++)
 302             // TODO: is there a way to synthetically derive the
 303             // modifiers?  Probably not in the general case, since
 304             // we'd have no way of knowing about them, but there
 305             // may be specific cases.
 306             out[i] = new Parameter("arg" + i, 0, this, i);
 307         return out;
 308     }
 309 
 310     private Parameter[] privateGetParameters() {
 311         // Use tmp to avoid multiple writes to a volatile.
 312         Parameter[] tmp = parameters;
 313 
 314         if (tmp == null) {
 315 
 316             // Otherwise, go to the JVM to get them
 317             tmp = getParameters0();
 318 
 319             // If we get back nothing, then synthesize parameters
 320             if (tmp == null)
 321                 tmp = synthesizeAllParams();
 322 
 323             parameters = tmp;
 324         }
 325 
 326         return tmp;
 327     }
 328 
 329     private transient volatile Parameter[] parameters;
 330 
 331     private native Parameter[] getParameters0();
 332 
 333     /**
 334      * Returns an array of {@code Class} objects that represent the
 335      * types of exceptions declared to be thrown by the underlying
 336      * executable represented by this object.  Returns an array of
 337      * length 0 if the executable declares no exceptions in its {@code
 338      * throws} clause.
 339      *
 340      * @return the exception types declared as being thrown by the
 341      * executable this object represents
 342      */
 343     public abstract Class<?>[] getExceptionTypes();
 344 
 345     /**
 346      * Returns an array of {@code Type} objects that represent the
 347      * exceptions declared to be thrown by this executable object.
 348      * Returns an array of length 0 if the underlying executable declares
 349      * no exceptions in its {@code throws} clause.
 350      *
 351      * <p>If an exception type is a type variable or a parameterized
 352      * type, it is created. Otherwise, it is resolved.
 353      *
 354      * @return an array of Types that represent the exception types
 355      *     thrown by the underlying executable
 356      * @throws GenericSignatureFormatError
 357      *     if the generic method signature does not conform to the format
 358      *     specified in
 359      *     <cite>The Java&trade; Virtual Machine Specification</cite>
 360      * @throws TypeNotPresentException if the underlying executable's
 361      *     {@code throws} clause refers to a non-existent type declaration
 362      * @throws MalformedParameterizedTypeException if
 363      *     the underlying executable's {@code throws} clause refers to a
 364      *     parameterized type that cannot be instantiated for any reason
 365      */
 366     public Type[] getGenericExceptionTypes() {
 367         Type[] result;
 368         if (hasGenericInformation() &&
 369             ((result = getGenericInfo().getExceptionTypes()).length > 0))
 370             return result;
 371         else
 372             return getExceptionTypes();
 373     }
 374 
 375     /**
 376      * Returns a string describing this {@code Executable}, including
 377      * any type parameters.
 378      */
 379     public abstract String toGenericString();
 380 
 381     /**
 382      * Returns {@code true} if this executable was declared to take a
 383      * variable number of arguments; returns {@code false} otherwise.
 384      *
 385      * @return {@code true} if an only if this executable was declared
 386      * to take a variable number of arguments.
 387      */
 388     public boolean isVarArgs()  {
 389         return (getModifiers() & Modifier.VARARGS) != 0;
 390     }
 391 
 392     /**
 393      * Returns {@code true} if this executable is a synthetic
 394      * construct; returns {@code false} otherwise.
 395      *
 396      * @return true if and only if this executable is a synthetic
 397      * construct as defined by
 398      * <cite>The Java&trade; Language Specification</cite>.
 399      * @jls 13.1 The Form of a Binary
 400      */
 401     public boolean isSynthetic() {
 402         return Modifier.isSynthetic(getModifiers());
 403     }
 404 
 405     /**
 406      * Returns an array of arrays that represent the annotations on
 407      * the formal parameters, in declaration order, of the executable
 408      * represented by this object. (Returns an array of length zero if
 409      * the underlying executable is parameterless.  If the executable has
 410      * one or more parameters, a nested array of length zero is
 411      * returned for each parameter with no annotations.) The
 412      * annotation objects contained in the returned arrays are
 413      * serializable.  The caller of this method is free to modify the
 414      * returned arrays; it will have no effect on the arrays returned
 415      * to other callers.
 416      *
 417      * @return an array of arrays that represent the annotations on the formal
 418      *    parameters, in declaration order, of the executable represented by this
 419      *    object
 420      */
 421     public abstract Annotation[][] getParameterAnnotations();
 422 
 423     Annotation[][] sharedGetParameterAnnotations(Class<?>[] parameterTypes,
 424                                                  byte[] parameterAnnotations) {
 425         int numParameters = parameterTypes.length;
 426         if (parameterAnnotations == null)
 427             return new Annotation[numParameters][0];
 428 
 429         Annotation[][] result = parseParameterAnnotations(parameterAnnotations);
 430 
 431         if (result.length != numParameters)
 432             handleParameterNumberMismatch(result.length, numParameters);
 433         return result;
 434     }
 435 
 436     abstract void handleParameterNumberMismatch(int resultLength, int numParameters);
 437 
 438     /**
 439      * {@inheritDoc}
 440      * @throws NullPointerException  {@inheritDoc}
 441      */
 442     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 443         Objects.requireNonNull(annotationClass);
 444         return annotationClass.cast(declaredAnnotations().get(annotationClass));
 445     }
 446 
 447     /**
 448      * {@inheritDoc}
 449      * @throws NullPointerException {@inheritDoc}
 450      * @since 1.8
 451      */
 452     @Override
 453     public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
 454         Objects.requireNonNull(annotationClass);
 455 
 456         return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
 457     }
 458 
 459     /**
 460      * {@inheritDoc}
 461      */
 462     public Annotation[] getDeclaredAnnotations()  {
 463         return AnnotationParser.toArray(declaredAnnotations());
 464     }
 465 
 466     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
 467 
 468     private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
 469         if (declaredAnnotations == null) {
 470             declaredAnnotations = AnnotationParser.parseAnnotations(
 471                 getAnnotationBytes(),
 472                 sun.misc.SharedSecrets.getJavaLangAccess().
 473                 getConstantPool(getDeclaringClass()),
 474                 getDeclaringClass());
 475         }
 476         return declaredAnnotations;
 477     }
 478 
 479     /**
 480      * Returns an AnnotatedType object that represents the potentially
 481      * annotated return type of the method/constructor represented by this
 482      * Executable.
 483      *
 484      * If this Executable represents a constructor, the AnnotatedType object
 485      * represents the type of the constructed object.
 486      *
 487      * If this Executable represents a method, the AnnotatedType object
 488      * represents the use of a type to specify the return type of the method.
 489      *
 490      * @since 1.8
 491      */
 492     public abstract AnnotatedType getAnnotatedReturnType();
 493 
 494     /* Helper for subclasses of Executable.
 495      *
 496      * Returns an AnnotatedType object that represents the use of a type to
 497      * specify the return type of the method/constructor represented by this
 498      * Executable.
 499      *
 500      * @since 1.8
 501      */
 502     AnnotatedType getAnnotatedReturnType0(Type returnType) {
 503         return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
 504                                                        sun.misc.SharedSecrets.getJavaLangAccess().
 505                                                            getConstantPool(getDeclaringClass()),
 506                                                        this,
 507                                                        getDeclaringClass(),
 508                                                        returnType,
 509                                                        TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE);
 510     }
 511 
 512     /**
 513      * Returns an AnnotatedType object that represents the use of a type to
 514      * specify the receiver type of the method/constructor represented by this
 515      * Executable. The receiver type of a method/constructor is available only
 516      * if the method/constructor declares a formal parameter called 'this'.
 517      *
 518      * Returns null if this Executable represents a constructor or instance
 519      * method that either declares no formal parameter called 'this', or
 520      * declares a formal parameter called 'this' with no annotations on its
 521      * type.
 522      *
 523      * Returns null if this Executable represents a static method.
 524      *
 525      * @since 1.8
 526      */
 527     public AnnotatedType getAnnotatedReceiverType() {
 528         return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
 529                                                        sun.misc.SharedSecrets.getJavaLangAccess().
 530                                                            getConstantPool(getDeclaringClass()),
 531                                                        this,
 532                                                        getDeclaringClass(),
 533                                                        getDeclaringClass(),
 534                                                        TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
 535     }
 536 
 537     /**
 538      * Returns an array of AnnotatedType objects that represent the use of
 539      * types to specify formal parameter types of the method/constructor
 540      * represented by this Executable. The order of the objects in the array
 541      * corresponds to the order of the formal parameter types in the
 542      * declaration of the method/constructor.
 543      *
 544      * Returns an array of length 0 if the method/constructor declares no
 545      * parameters.
 546      *
 547      * @since 1.8
 548      */
 549     public AnnotatedType[] getAnnotatedParameterTypes() {
 550         throw new UnsupportedOperationException("Not yet");
 551     }
 552 
 553     /**
 554      * Returns an array of AnnotatedType objects that represent the use of
 555      * types to specify the declared exceptions of the method/constructor
 556      * represented by this Executable. The order of the objects in the array
 557      * corresponds to the order of the exception types in the declaration of
 558      * the method/constructor.
 559      *
 560      * Returns an array of length 0 if the method/constructor declares no
 561      * exceptions.
 562      *
 563      * @since 1.8
 564      */
 565     public AnnotatedType[] getAnnotatedExceptionTypes() {
 566         return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
 567                                                         sun.misc.SharedSecrets.getJavaLangAccess().
 568                                                             getConstantPool(getDeclaringClass()),
 569                                                         this,
 570                                                         getDeclaringClass(),
 571                                                         getGenericExceptionTypes(),
 572                                                         TypeAnnotation.TypeAnnotationTarget.THROWS);
 573     }
 574 
 575 }