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