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