001/*
002 * Copyright (C) 2012 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.reflect;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import com.google.common.annotations.Beta;
020import com.google.common.collect.ImmutableList;
021import com.google.errorprone.annotations.CanIgnoreReturnValue;
022import com.google.errorprone.annotations.DoNotCall;
023import java.lang.annotation.Annotation;
024import java.lang.reflect.AccessibleObject;
025import java.lang.reflect.AnnotatedElement;
026import java.lang.reflect.AnnotatedType;
027import java.lang.reflect.Constructor;
028import java.lang.reflect.InvocationTargetException;
029import java.lang.reflect.Member;
030import java.lang.reflect.Method;
031import java.lang.reflect.Modifier;
032import java.lang.reflect.Type;
033import java.lang.reflect.TypeVariable;
034import java.util.Arrays;
035import javax.annotation.CheckForNull;
036import org.checkerframework.checker.nullness.qual.Nullable;
037
038/**
039 * Wrapper around either a {@link Method} or a {@link Constructor}. Convenience API is provided to
040 * make common reflective operation easier to deal with, such as {@link #isPublic}, {@link
041 * #getParameters} etc.
042 *
043 * <p>In addition to convenience methods, {@link TypeToken#method} and {@link TypeToken#constructor}
044 * will resolve the type parameters of the method or constructor in the context of the owner type,
045 * which may be a subtype of the declaring class. For example:
046 *
047 * <pre>{@code
048 * Method getMethod = List.class.getMethod("get", int.class);
049 * Invokable<List<String>, ?> invokable = new TypeToken<List<String>>() {}.method(getMethod);
050 * assertEquals(TypeToken.of(String.class), invokable.getReturnType()); // Not Object.class!
051 * assertEquals(new TypeToken<List<String>>() {}, invokable.getOwnerType());
052 * }</pre>
053 *
054 * <p><b>Note:</b> earlier versions of this class inherited from {@link
055 * java.lang.reflect.AccessibleObject AccessibleObject} and {@link
056 * java.lang.reflect.GenericDeclaration GenericDeclaration}. Since version 31.0 that is no longer
057 * the case. However, most methods from those types are present with the same signature in this
058 * class.
059 *
060 * @param <T> the type that owns this method or constructor.
061 * @param <R> the return type of (or supertype thereof) the method or the declaring type of the
062 *     constructor.
063 * @author Ben Yu
064 * @since 14.0 (no longer implements {@link AccessibleObject} or {@code GenericDeclaration} since
065 *     31.0)
066 */
067@ElementTypesAreNonnullByDefault
068public abstract class Invokable<T, R> implements AnnotatedElement, Member {
069  private final AccessibleObject accessibleObject;
070  private final Member member;
071
072  <M extends AccessibleObject & Member> Invokable(M member) {
073    checkNotNull(member);
074    this.accessibleObject = member;
075    this.member = member;
076  }
077
078  /** Returns {@link Invokable} of {@code method}. */
079  public static Invokable<?, Object> from(Method method) {
080    return new MethodInvokable<>(method);
081  }
082
083  /** Returns {@link Invokable} of {@code constructor}. */
084  public static <T> Invokable<T, T> from(Constructor<T> constructor) {
085    return new ConstructorInvokable<T>(constructor);
086  }
087
088  @Override
089  public final boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
090    return accessibleObject.isAnnotationPresent(annotationClass);
091  }
092
093  @Override
094  @CheckForNull
095  public final <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
096    return accessibleObject.getAnnotation(annotationClass);
097  }
098
099  @Override
100  public final Annotation[] getAnnotations() {
101    return accessibleObject.getAnnotations();
102  }
103
104  @Override
105  public final Annotation[] getDeclaredAnnotations() {
106    return accessibleObject.getDeclaredAnnotations();
107  }
108
109  // We ought to be able to implement GenericDeclaration instead its parent AnnotatedElement.
110  // That would give us this method declaration. But for some reason, implementing
111  // GenericDeclaration leads to weird errors in Android tests:
112  // IncompatibleClassChangeError: interface not implemented
113  /** See {@link java.lang.reflect.GenericDeclaration#getTypeParameters()}. */
114  public abstract TypeVariable<?>[] getTypeParameters();
115
116  /** See {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)}. */
117  public final void setAccessible(boolean flag) {
118    accessibleObject.setAccessible(flag);
119  }
120
121  /** See {@link java.lang.reflect.AccessibleObject#trySetAccessible()}. */
122  public final boolean trySetAccessible() {
123    // We can't call accessibleObject.trySetAccessible since that was added in Java 9 and this code
124    // should work on Java 8. So we emulate it this way.
125    try {
126      accessibleObject.setAccessible(true);
127      return true;
128    } catch (RuntimeException e) {
129      return false;
130    }
131  }
132
133  /** See {@link java.lang.reflect.AccessibleObject#isAccessible()}. */
134  public final boolean isAccessible() {
135    return accessibleObject.isAccessible();
136  }
137
138  @Override
139  public final String getName() {
140    return member.getName();
141  }
142
143  @Override
144  public final int getModifiers() {
145    return member.getModifiers();
146  }
147
148  @Override
149  public final boolean isSynthetic() {
150    return member.isSynthetic();
151  }
152
153  /** Returns true if the element is public. */
154  public final boolean isPublic() {
155    return Modifier.isPublic(getModifiers());
156  }
157
158  /** Returns true if the element is protected. */
159  public final boolean isProtected() {
160    return Modifier.isProtected(getModifiers());
161  }
162
163  /** Returns true if the element is package-private. */
164  public final boolean isPackagePrivate() {
165    return !isPrivate() && !isPublic() && !isProtected();
166  }
167
168  /** Returns true if the element is private. */
169  public final boolean isPrivate() {
170    return Modifier.isPrivate(getModifiers());
171  }
172
173  /** Returns true if the element is static. */
174  public final boolean isStatic() {
175    return Modifier.isStatic(getModifiers());
176  }
177
178  /**
179   * Returns {@code true} if this method is final, per {@code Modifier.isFinal(getModifiers())}.
180   *
181   * <p>Note that a method may still be effectively "final", or non-overridable when it has no
182   * {@code final} keyword. For example, it could be private, or it could be declared by a final
183   * class. To tell whether a method is overridable, use {@link Invokable#isOverridable}.
184   */
185  public final boolean isFinal() {
186    return Modifier.isFinal(getModifiers());
187  }
188
189  /** Returns true if the method is abstract. */
190  public final boolean isAbstract() {
191    return Modifier.isAbstract(getModifiers());
192  }
193
194  /** Returns true if the element is native. */
195  public final boolean isNative() {
196    return Modifier.isNative(getModifiers());
197  }
198
199  /** Returns true if the method is synchronized. */
200  public final boolean isSynchronized() {
201    return Modifier.isSynchronized(getModifiers());
202  }
203
204  /** Returns true if the field is volatile. */
205  final boolean isVolatile() {
206    return Modifier.isVolatile(getModifiers());
207  }
208
209  /** Returns true if the field is transient. */
210  final boolean isTransient() {
211    return Modifier.isTransient(getModifiers());
212  }
213
214  @Override
215  public boolean equals(@CheckForNull Object obj) {
216    if (obj instanceof Invokable) {
217      Invokable<?, ?> that = (Invokable<?, ?>) obj;
218      return getOwnerType().equals(that.getOwnerType()) && member.equals(that.member);
219    }
220    return false;
221  }
222
223  @Override
224  public int hashCode() {
225    return member.hashCode();
226  }
227
228  @Override
229  public String toString() {
230    return member.toString();
231  }
232
233  /**
234   * Returns {@code true} if this is an overridable method. Constructors, private, static or final
235   * methods, or methods declared by final classes are not overridable.
236   */
237  public abstract boolean isOverridable();
238
239  /** Returns {@code true} if this was declared to take a variable number of arguments. */
240  public abstract boolean isVarArgs();
241
242  /**
243   * Invokes with {@code receiver} as 'this' and {@code args} passed to the underlying method and
244   * returns the return value; or calls the underlying constructor with {@code args} and returns the
245   * constructed instance.
246   *
247   * @throws IllegalAccessException if this {@code Constructor} object enforces Java language access
248   *     control and the underlying method or constructor is inaccessible.
249   * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an
250   *     unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a
251   *     parameter value cannot be converted to the corresponding formal parameter type by a method
252   *     invocation conversion.
253   * @throws InvocationTargetException if the underlying method or constructor throws an exception.
254   */
255  // All subclasses are owned by us and we'll make sure to get the R type right, including nullness.
256  @SuppressWarnings({"unchecked", "nullness"})
257  @CanIgnoreReturnValue
258  @CheckForNull
259  public final R invoke(@CheckForNull T receiver, @Nullable Object... args)
260      throws InvocationTargetException, IllegalAccessException {
261    return (R) invokeInternal(receiver, checkNotNull(args));
262  }
263
264  /** Returns the return type of this {@code Invokable}. */
265  // All subclasses are owned by us and we'll make sure to get the R type right.
266  @SuppressWarnings("unchecked")
267  public final TypeToken<? extends R> getReturnType() {
268    return (TypeToken<? extends R>) TypeToken.of(getGenericReturnType());
269  }
270
271  /**
272   * Returns all declared parameters of this {@code Invokable}. Note that if this is a constructor
273   * of a non-static inner class, unlike {@link Constructor#getParameterTypes}, the hidden {@code
274   * this} parameter of the enclosing class is excluded from the returned parameters.
275   */
276  @IgnoreJRERequirement
277  public final ImmutableList<Parameter> getParameters() {
278    Type[] parameterTypes = getGenericParameterTypes();
279    Annotation[][] annotations = getParameterAnnotations();
280    @Nullable Object[] annotatedTypes =
281        ANNOTATED_TYPE_EXISTS ? getAnnotatedParameterTypes() : new Object[parameterTypes.length];
282    ImmutableList.Builder<Parameter> builder = ImmutableList.builder();
283    for (int i = 0; i < parameterTypes.length; i++) {
284      builder.add(
285          new Parameter(
286              this, i, TypeToken.of(parameterTypes[i]), annotations[i], annotatedTypes[i]));
287    }
288    return builder.build();
289  }
290
291  /** Returns all declared exception types of this {@code Invokable}. */
292  public final ImmutableList<TypeToken<? extends Throwable>> getExceptionTypes() {
293    ImmutableList.Builder<TypeToken<? extends Throwable>> builder = ImmutableList.builder();
294    for (Type type : getGenericExceptionTypes()) {
295      // getGenericExceptionTypes() will never return a type that's not exception
296      @SuppressWarnings("unchecked")
297      TypeToken<? extends Throwable> exceptionType =
298          (TypeToken<? extends Throwable>) TypeToken.of(type);
299      builder.add(exceptionType);
300    }
301    return builder.build();
302  }
303
304  /**
305   * Explicitly specifies the return type of this {@code Invokable}. For example:
306   *
307   * <pre>{@code
308   * Method factoryMethod = Person.class.getMethod("create");
309   * Invokable<?, Person> factory = Invokable.of(getNameMethod).returning(Person.class);
310   * }</pre>
311   */
312  public final <R1 extends R> Invokable<T, R1> returning(Class<R1> returnType) {
313    return returning(TypeToken.of(returnType));
314  }
315
316  /** Explicitly specifies the return type of this {@code Invokable}. */
317  public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) {
318    if (!returnType.isSupertypeOf(getReturnType())) {
319      throw new IllegalArgumentException(
320          "Invokable is known to return " + getReturnType() + ", not " + returnType);
321    }
322    @SuppressWarnings("unchecked") // guarded by previous check
323    Invokable<T, R1> specialized = (Invokable<T, R1>) this;
324    return specialized;
325  }
326
327  @SuppressWarnings("unchecked") // The declaring class is T's raw class, or one of its supertypes.
328  @Override
329  public final Class<? super T> getDeclaringClass() {
330    return (Class<? super T>) member.getDeclaringClass();
331  }
332
333  /** Returns the type of {@code T}. */
334  // Overridden in TypeToken#method() and TypeToken#constructor()
335  @SuppressWarnings("unchecked") // The declaring class is T.
336  public TypeToken<T> getOwnerType() {
337    return (TypeToken<T>) TypeToken.of(getDeclaringClass());
338  }
339
340  @CheckForNull
341  abstract Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args)
342      throws InvocationTargetException, IllegalAccessException;
343
344  abstract Type[] getGenericParameterTypes();
345
346  @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
347  @IgnoreJRERequirement
348  abstract AnnotatedType[] getAnnotatedParameterTypes();
349
350  /** This should never return a type that's not a subtype of Throwable. */
351  abstract Type[] getGenericExceptionTypes();
352
353  abstract Annotation[][] getParameterAnnotations();
354
355  abstract Type getGenericReturnType();
356
357  /**
358   * Returns the {@link AnnotatedType} for the return type.
359   *
360   * <p>This method will fail if run under an Android VM.
361   *
362   * @since NEXT for guava-android (available since 14.0 in guava-jre)
363   * @deprecated This method does not work under Android VMs. It is safe to use from guava-jre, but
364   *     this copy in guava-android is not safe to use.
365   */
366  @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
367  @DoNotCall("fails under Android VMs; do not use from guava-android")
368  @Deprecated
369  @IgnoreJRERequirement
370  @Beta
371  public abstract AnnotatedType getAnnotatedReturnType();
372
373  static class MethodInvokable<T> extends Invokable<T, Object> {
374
375    final Method method;
376
377    MethodInvokable(Method method) {
378      super(method);
379      this.method = method;
380    }
381
382    @Override
383    @CheckForNull
384    final Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args)
385        throws InvocationTargetException, IllegalAccessException {
386      return method.invoke(receiver, args);
387    }
388
389    @Override
390    Type getGenericReturnType() {
391      return method.getGenericReturnType();
392    }
393
394    @Override
395    Type[] getGenericParameterTypes() {
396      return method.getGenericParameterTypes();
397    }
398
399    @Override
400    @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
401    @IgnoreJRERequirement
402    AnnotatedType[] getAnnotatedParameterTypes() {
403      return method.getAnnotatedParameterTypes();
404    }
405
406    @Override
407    @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
408    @DoNotCall
409    @IgnoreJRERequirement
410    public AnnotatedType getAnnotatedReturnType() {
411      return method.getAnnotatedReturnType();
412    }
413
414    @Override
415    Type[] getGenericExceptionTypes() {
416      return method.getGenericExceptionTypes();
417    }
418
419    @Override
420    final Annotation[][] getParameterAnnotations() {
421      return method.getParameterAnnotations();
422    }
423
424    @Override
425    public final TypeVariable<?>[] getTypeParameters() {
426      return method.getTypeParameters();
427    }
428
429    @Override
430    public final boolean isOverridable() {
431      return !(isFinal()
432          || isPrivate()
433          || isStatic()
434          || Modifier.isFinal(getDeclaringClass().getModifiers()));
435    }
436
437    @Override
438    public final boolean isVarArgs() {
439      return method.isVarArgs();
440    }
441  }
442
443  static class ConstructorInvokable<T> extends Invokable<T, T> {
444
445    final Constructor<?> constructor;
446
447    ConstructorInvokable(Constructor<?> constructor) {
448      super(constructor);
449      this.constructor = constructor;
450    }
451
452    @Override
453    final Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args)
454        throws InvocationTargetException, IllegalAccessException {
455      try {
456        return constructor.newInstance(args);
457      } catch (InstantiationException e) {
458        throw new RuntimeException(constructor + " failed.", e);
459      }
460    }
461
462    /**
463     * If the class is parameterized, such as {@link java.util.ArrayList ArrayList}, this returns
464     * {@code ArrayList<E>}.
465     */
466    @Override
467    Type getGenericReturnType() {
468      Class<?> declaringClass = getDeclaringClass();
469      TypeVariable<?>[] typeParams = declaringClass.getTypeParameters();
470      if (typeParams.length > 0) {
471        return Types.newParameterizedType(declaringClass, typeParams);
472      } else {
473        return declaringClass;
474      }
475    }
476
477    @Override
478    Type[] getGenericParameterTypes() {
479      Type[] types = constructor.getGenericParameterTypes();
480      if (types.length > 0 && mayNeedHiddenThis()) {
481        Class<?>[] rawParamTypes = constructor.getParameterTypes();
482        if (types.length == rawParamTypes.length
483            && rawParamTypes[0] == getDeclaringClass().getEnclosingClass()) {
484          // first parameter is the hidden 'this'
485          return Arrays.copyOfRange(types, 1, types.length);
486        }
487      }
488      return types;
489    }
490
491    @Override
492    @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
493    @IgnoreJRERequirement
494    AnnotatedType[] getAnnotatedParameterTypes() {
495      return constructor.getAnnotatedParameterTypes();
496    }
497
498    @Override
499    @SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
500    @DoNotCall
501    @IgnoreJRERequirement
502    public AnnotatedType getAnnotatedReturnType() {
503      return constructor.getAnnotatedReturnType();
504    }
505
506    @Override
507    Type[] getGenericExceptionTypes() {
508      return constructor.getGenericExceptionTypes();
509    }
510
511    @Override
512    final Annotation[][] getParameterAnnotations() {
513      return constructor.getParameterAnnotations();
514    }
515
516    /**
517     * {@inheritDoc}
518     *
519     * <p>{@code [<E>]} will be returned for ArrayList's constructor. When both the class and the
520     * constructor have type parameters, the class parameters are prepended before those of the
521     * constructor's. This is an arbitrary rule since no existing language spec mandates one way or
522     * the other. From the declaration syntax, the class type parameter appears first, but the call
523     * syntax may show up in opposite order such as {@code new <A>Foo<B>()}.
524     */
525    @Override
526    public final TypeVariable<?>[] getTypeParameters() {
527      TypeVariable<?>[] declaredByClass = getDeclaringClass().getTypeParameters();
528      TypeVariable<?>[] declaredByConstructor = constructor.getTypeParameters();
529      TypeVariable<?>[] result =
530          new TypeVariable<?>[declaredByClass.length + declaredByConstructor.length];
531      System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length);
532      System.arraycopy(
533          declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length);
534      return result;
535    }
536
537    @Override
538    public final boolean isOverridable() {
539      return false;
540    }
541
542    @Override
543    public final boolean isVarArgs() {
544      return constructor.isVarArgs();
545    }
546
547    private boolean mayNeedHiddenThis() {
548      Class<?> declaringClass = constructor.getDeclaringClass();
549      if (declaringClass.getEnclosingConstructor() != null) {
550        // Enclosed in a constructor, needs hidden this
551        return true;
552      }
553      Method enclosingMethod = declaringClass.getEnclosingMethod();
554      if (enclosingMethod != null) {
555        // Enclosed in a method, if it's not static, must need hidden this.
556        return !Modifier.isStatic(enclosingMethod.getModifiers());
557      } else {
558        // Strictly, this doesn't necessarily indicate a hidden 'this' in the case of
559        // static initializer. But there seems no way to tell in that case. :(
560        // This may cause issues when an anonymous class is created inside a static initializer,
561        // and the class's constructor's first parameter happens to be the enclosing class.
562        // In such case, we may mistakenly think that the class is within a non-static context
563        // and the first parameter is the hidden 'this'.
564        return declaringClass.getEnclosingClass() != null
565            && !Modifier.isStatic(declaringClass.getModifiers());
566      }
567    }
568  }
569
570  private static final boolean ANNOTATED_TYPE_EXISTS = initAnnotatedTypeExists();
571
572  private static boolean initAnnotatedTypeExists() {
573    try {
574      Class.forName("java.lang.reflect.AnnotatedType");
575    } catch (ClassNotFoundException e) {
576      return false;
577    }
578    return true;
579  }
580}