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