/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.beam.sdk.util;

import static org.hamcrest.Matchers.anyOf;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Function;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Joiner;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Predicate;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.FluentIterable;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableList;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableMap;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableSet;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Lists;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Maps;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Multimap;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Multimaps;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Ordering;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Sets;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.reflect.Invokable;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.reflect.Parameter;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.reflect.TypeToken;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Represents the API surface of a package prefix. Used for accessing public classes, methods, and
 * the types they reference, to control what dependencies are re-exported.
 *
 * <p>For the purposes of calculating the public API surface, exposure includes any public or
 * protected occurrence of:
 *
 * <ul>
 *   <li>superclasses
 *   <li>interfaces implemented
 *   <li>actual type arguments to generic types
 *   <li>array component types
 *   <li>method return types
 *   <li>method parameter types
 *   <li>type variable bounds
 *   <li>wildcard bounds
 * </ul>
 *
 * <p>Exposure is a transitive property. The resulting map excludes primitives and array classes
 * themselves.
 *
 * <p>It is prudent (though not required) to prune prefixes like "java" via the builder method
 * {@link #pruningPrefix} to halt the traversal so it does not uselessly catalog references that are
 * not interesting.
 */
@SuppressWarnings("rawtypes")
public class ApiSurface {
  private static final Logger LOG = LoggerFactory.getLogger(ApiSurface.class);

  /** A factory method to create a {@link Class} matcher for classes residing in a given package. */
  public static Matcher<Class<?>> classesInPackage(final String packageName) {
    return new Matchers.ClassInPackage(packageName);
  }

  /**
   * A factory method to create an {@link ApiSurface} matcher, producing a positive match if the
   * queried api surface contains ONLY classes described by the provided matchers.
   */
  public static Matcher<ApiSurface> containsOnlyClassesMatching(
      final Set<Matcher<Class<?>>> classMatchers) {
    return new Matchers.ClassesInSurfaceMatcher(classMatchers);
  }

  /** See {@link ApiSurface#containsOnlyClassesMatching(Set)}. */
  @SafeVarargs
  public static Matcher<ApiSurface> containsOnlyClassesMatching(
      final Matcher<Class<?>>... classMatchers) {
    return new Matchers.ClassesInSurfaceMatcher(Sets.newHashSet(classMatchers));
  }

  /** See {@link ApiSurface#containsOnlyPackages(Set)}. */
  public static Matcher<ApiSurface> containsOnlyPackages(final String... packageNames) {
    return containsOnlyPackages(Sets.newHashSet(packageNames));
  }

  /**
   * A factory method to create an {@link ApiSurface} matcher, producing a positive match if the
   * queried api surface contains classes ONLY from specified package names.
   */
  public static Matcher<ApiSurface> containsOnlyPackages(final Set<String> packageNames) {

    final Function<String, Matcher<Class<?>>> packageNameToClassMatcher =
        ApiSurface::classesInPackage;

    final ImmutableSet<Matcher<Class<?>>> classesInPackages =
        FluentIterable.from(packageNames).transform(packageNameToClassMatcher).toSet();

    return containsOnlyClassesMatching(classesInPackages);
  }

  /**
   * {@link Matcher}s for use in {@link ApiSurface} related tests that aim to keep the public API
   * conformant to a hard-coded policy by controlling what classes are allowed to be exposed by an
   * API surface.
   */
  // based on previous code by @kennknowles and others.
  private static class Matchers {

    private static class ClassInPackage extends TypeSafeDiagnosingMatcher<Class<?>> {

      private final String packageName;

      private ClassInPackage(final String packageName) {
        this.packageName = packageName;
      }

      @Override
      public void describeTo(final Description description) {
        description.appendText("Classes in package \"");
        description.appendText(packageName);
        description.appendText("\"");
      }

      @Override
      protected boolean matchesSafely(final Class<?> clazz, final Description mismatchDescription) {
        return clazz.getName().startsWith(packageName + ".");
      }
    }

    private static class ClassesInSurfaceMatcher extends TypeSafeDiagnosingMatcher<ApiSurface> {

      private final Set<Matcher<Class<?>>> classMatchers;

      private ClassesInSurfaceMatcher(final Set<Matcher<Class<?>>> classMatchers) {
        this.classMatchers = classMatchers;
      }

      private boolean verifyNoAbandoned(
          final ApiSurface checkedApiSurface,
          final Set<Matcher<Class<?>>> allowedClasses,
          final Description mismatchDescription) {

        // <helper_lambdas>

        final Function<Matcher<Class<?>>, String> toMessage =
            abandonedClassMacther -> {
              final StringDescription description = new StringDescription();
              description.appendText("No ");
              abandonedClassMacther.describeTo(description);
              return description.toString();
            };

        final Predicate<Matcher<Class<?>>> matchedByExposedClasses =
            classMatcher ->
                FluentIterable.from(checkedApiSurface.getExposedClasses())
                    .anyMatch(classMatcher::matches);

        // </helper_lambdas>

        final ImmutableSet<Matcher<Class<?>>> matchedClassMatchers =
            FluentIterable.from(allowedClasses).filter(matchedByExposedClasses).toSet();

        final Sets.SetView<Matcher<Class<?>>> abandonedClassMatchers =
            Sets.difference(allowedClasses, matchedClassMatchers);

        final ImmutableList<String> messages =
            FluentIterable.from(abandonedClassMatchers)
                .transform(toMessage)
                .toSortedList(Ordering.natural());

        if (!messages.isEmpty()) {
          mismatchDescription.appendText(
              "The following white-listed scopes did not have matching classes on the API surface:"
                  + "\n\t"
                  + Joiner.on("\n\t").join(messages));
        }

        return messages.isEmpty();
      }

      private boolean verifyNoDisallowed(
          final ApiSurface checkedApiSurface,
          final Set<Matcher<Class<?>>> allowedClasses,
          final Description mismatchDescription) {

        /* <helper_lambdas> */

        final Function<Class<?>, List<Class<?>>> toExposure = checkedApiSurface::getAnyExposurePath;

        final Maps.EntryTransformer<Class<?>, List<Class<?>>, String> toMessage =
            (aClass, exposure) ->
                aClass + " exposed via:\n\t\t" + Joiner.on("\n\t\t").join(exposure);

        final Predicate<Class<?>> disallowed = aClass -> !classIsAllowed(aClass, allowedClasses);

        /* </helper_lambdas> */

        final FluentIterable<Class<?>> disallowedClasses =
            FluentIterable.from(checkedApiSurface.getExposedClasses()).filter(disallowed);

        final ImmutableMap<Class<?>, List<Class<?>>> exposures =
            Maps.toMap(disallowedClasses, toExposure);

        final ImmutableList<String> messages =
            FluentIterable.from(Maps.transformEntries(exposures, toMessage).values())
                .toSortedList(Ordering.natural());

        if (!messages.isEmpty()) {
          mismatchDescription.appendText(
              "The following disallowed classes appeared on the API surface:\n\t"
                  + Joiner.on("\n\t").join(messages));
        }

        return messages.isEmpty();
      }

      @SuppressWarnings({"rawtypes", "unchecked"})
      private boolean classIsAllowed(
          final Class<?> clazz, final Set<Matcher<Class<?>>> allowedClasses) {
        // Safe cast inexpressible in Java without rawtypes
        return anyOf((Iterable) allowedClasses).matches(clazz);
      }

      @Override
      protected boolean matchesSafely(
          final ApiSurface apiSurface, final Description mismatchDescription) {
        final boolean noDisallowed =
            verifyNoDisallowed(apiSurface, classMatchers, mismatchDescription);

        final boolean noAbandoned =
            verifyNoAbandoned(apiSurface, classMatchers, mismatchDescription);

        return noDisallowed && noAbandoned;
      }

      @Override
      public void describeTo(final Description description) {
        description.appendText("API surface to include only:" + "\n\t");
        for (final Matcher<Class<?>> classMatcher : classMatchers) {
          classMatcher.describeTo(description);
          description.appendText("\n\t");
        }
      }
    }
  }

  ///////////////

  /** Returns an empty {@link ApiSurface}. */
  public static ApiSurface empty() {
    LOG.debug("Returning an empty ApiSurface");
    return new ApiSurface(Collections.emptySet(), Collections.emptySet());
  }

  /** Returns an {@link ApiSurface} object representing the given package and all subpackages. */
  public static ApiSurface ofPackage(String packageName, ClassLoader classLoader)
      throws IOException {
    return ApiSurface.empty().includingPackage(packageName, classLoader);
  }

  /** Returns an {@link ApiSurface} object representing the given package and all subpackages. */
  public static ApiSurface ofPackage(Package aPackage, ClassLoader classLoader) throws IOException {
    return ofPackage(aPackage.getName(), classLoader);
  }

  /** Returns an {@link ApiSurface} object representing just the surface of the given class. */
  public static ApiSurface ofClass(Class<?> clazz) {
    return ApiSurface.empty().includingClass(clazz);
  }

  /**
   * Returns an {@link ApiSurface} like this one, but also including the named package and all of
   * its subpackages.
   */
  public ApiSurface includingPackage(String packageName, ClassLoader classLoader)
      throws IOException {
    ClassPath classPath = ClassPath.from(classLoader);

    Set<Class<?>> newRootClasses = Sets.newHashSet();
    for (ClassPath.ClassInfo classInfo : classPath.getTopLevelClassesRecursive(packageName)) {
      Class clazz = null;
      try {
        clazz = classInfo.load();
      } catch (NoClassDefFoundError e) {
        // TODO: Ignore any NoClassDefFoundError errors as a workaround. (BEAM-2231)
        LOG.warn("Failed to load class: {}", classInfo.toString(), e);
        continue;
      }

      if (exposed(clazz.getModifiers())) {
        newRootClasses.add(clazz);
      }
    }
    LOG.debug("Including package {} and subpackages: {}", packageName, newRootClasses);
    newRootClasses.addAll(rootClasses);

    return new ApiSurface(newRootClasses, patternsToPrune);
  }

  /** Returns an {@link ApiSurface} like this one, but also including the given class. */
  public ApiSurface includingClass(Class<?> clazz) {
    Set<Class<?>> newRootClasses = Sets.newHashSet();
    LOG.debug("Including class {}", clazz);
    newRootClasses.add(clazz);
    newRootClasses.addAll(rootClasses);
    return new ApiSurface(newRootClasses, patternsToPrune);
  }

  /**
   * Returns an {@link ApiSurface} like this one, but pruning transitive references from classes
   * whose full name (including package) begins with the provided prefix.
   */
  public ApiSurface pruningPrefix(String prefix) {
    return pruningPattern(Pattern.compile(Pattern.quote(prefix) + ".*"));
  }

  /** Returns an {@link ApiSurface} like this one, but pruning references from the named class. */
  public ApiSurface pruningClassName(String className) {
    return pruningPattern(Pattern.compile(Pattern.quote(className)));
  }

  /**
   * Returns an {@link ApiSurface} like this one, but pruning references from the provided class.
   */
  public ApiSurface pruningClass(Class<?> clazz) {
    return pruningClassName(clazz.getName());
  }

  /**
   * Returns an {@link ApiSurface} like this one, but pruning transitive references from classes
   * whose full name (including package) begins with the provided prefix.
   */
  public ApiSurface pruningPattern(Pattern pattern) {
    Set<Pattern> newPatterns = Sets.newHashSet();
    newPatterns.addAll(patternsToPrune);
    newPatterns.add(pattern);
    return new ApiSurface(rootClasses, newPatterns);
  }

  /** See {@link #pruningPattern(Pattern)}. */
  public ApiSurface pruningPattern(String patternString) {
    return pruningPattern(Pattern.compile(patternString));
  }

  /** Returns all public classes originally belonging to the package in the {@link ApiSurface}. */
  public Set<Class<?>> getRootClasses() {
    return rootClasses;
  }

  /** Returns exposed types in this set, including arrays and primitives as specified. */
  public Set<Class<?>> getExposedClasses() {
    return getExposedToExposers().keySet();
  }

  /**
   * Returns a path from an exposed class to a root class. There may be many, but this gives only
   * one.
   *
   * <p>If there are only cycles, with no path back to a root class, throws IllegalStateException.
   */
  public List<Class<?>> getAnyExposurePath(Class<?> exposedClass) {
    Set<Class<?>> excluded = Sets.newHashSet();
    excluded.add(exposedClass);
    List<Class<?>> path = getAnyExposurePath(exposedClass, excluded);
    if (path == null) {
      throw new IllegalArgumentException(
          "Class "
              + exposedClass
              + " has no path back to any root class."
              + " It should never have been considered exposed.");
    } else {
      return path;
    }
  }

  /**
   * Returns a path from an exposed class to a root class. There may be many, but this gives only
   * one. It will not return a path that crosses the excluded classes.
   *
   * <p>If there are only cycles or paths through the excluded classes, returns null.
   *
   * <p>If the class is not actually in the exposure map, throws IllegalArgumentException
   */
  private List<Class<?>> getAnyExposurePath(Class<?> exposedClass, Set<Class<?>> excluded) {
    List<Class<?>> exposurePath = Lists.newArrayList();
    exposurePath.add(exposedClass);

    Collection<Class<?>> exposers = getExposedToExposers().get(exposedClass);
    if (exposers.isEmpty()) {
      throw new IllegalArgumentException("Class " + exposedClass + " is not exposed.");
    }

    for (Class<?> exposer : exposers) {
      if (excluded.contains(exposer)) {
        continue;
      }

      // A null exposer means this is already a root class.
      if (exposer == null) {
        return exposurePath;
      }

      List<Class<?>> restOfPath =
          getAnyExposurePath(exposer, Sets.union(excluded, Sets.newHashSet(exposer)));

      if (restOfPath != null) {
        exposurePath.addAll(restOfPath);
        return exposurePath;
      }
    }
    return null;
  }

  ////////////////////////////////////////////////////////////////////

  // Fields initialized upon construction
  private final Set<Class<?>> rootClasses;
  private final Set<Pattern> patternsToPrune;

  // Fields computed on-demand
  private Multimap<Class<?>, Class<?>> exposedToExposers = null;
  private Pattern prunedPattern = null;
  private Set<Type> visited = null;

  private ApiSurface(Set<Class<?>> rootClasses, Set<Pattern> patternsToPrune) {
    this.rootClasses = rootClasses;
    this.patternsToPrune = patternsToPrune;
  }

  /**
   * A map from exposed types to place where they are exposed, in the sense of being a part of a
   * public-facing API surface.
   *
   * <p>This map is the adjencency list representation of a directed graph, where an edge from type
   * {@code T1} to type {@code T2} indicates that {@code T2} directly exposes {@code T1} in its API
   * surface.
   *
   * <p>The traversal methods in this class are designed to avoid repeatedly processing types, since
   * there will almost always be cyclic references.
   */
  private Multimap<Class<?>, Class<?>> getExposedToExposers() {
    if (exposedToExposers == null) {
      constructExposedToExposers();
    }
    return exposedToExposers;
  }

  /** See {@link #getExposedToExposers}. */
  private void constructExposedToExposers() {
    visited = Sets.newHashSet();
    exposedToExposers =
        Multimaps.newSetMultimap(
            Maps.<Class<?>, Collection<Class<?>>>newHashMap(), Sets::newHashSet);

    for (Class<?> clazz : rootClasses) {
      addExposedTypes(clazz, null);
    }
  }

  /** A combined {@code Pattern} that implements all the pruning specified. */
  private Pattern getPrunedPattern() {
    if (prunedPattern == null) {
      constructPrunedPattern();
    }
    return prunedPattern;
  }

  /** See {@link #getPrunedPattern}. */
  private void constructPrunedPattern() {
    Set<String> prunedPatternStrings = Sets.newHashSet();
    for (Pattern patternToPrune : patternsToPrune) {
      prunedPatternStrings.add(patternToPrune.pattern());
    }
    prunedPattern = Pattern.compile("(" + Joiner.on(")|(").join(prunedPatternStrings) + ")");
  }

  /** Whether a type and all that it references should be pruned from the graph. */
  private boolean pruned(Type type) {
    return pruned(TypeToken.of(type).getRawType());
  }

  /** Whether a class and all that it references should be pruned from the graph. */
  private boolean pruned(Class<?> clazz) {
    return clazz.isPrimitive()
        || clazz.isArray()
        || getPrunedPattern().matcher(clazz.getName()).matches();
  }

  /** Whether a type has already beens sufficiently processed. */
  private boolean done(Type type) {
    return visited.contains(type);
  }

  private void recordExposure(Class<?> exposed, Class<?> cause) {
    exposedToExposers.put(exposed, cause);
  }

  private void recordExposure(Type exposed, Class<?> cause) {
    exposedToExposers.put(TypeToken.of(exposed).getRawType(), cause);
  }

  private void visit(Type type) {
    visited.add(type);
  }

  /** See {@link #addExposedTypes(Type, Class)}. */
  private void addExposedTypes(TypeToken type, Class<?> cause) {
    LOG.debug(
        "Adding exposed types from {}, which is the type in type token {}", type.getType(), type);
    addExposedTypes(type.getType(), cause);
  }

  /**
   * Adds any references learned by following a link from {@code cause} to {@code type}. This will
   * dispatch according to the concrete {@code Type} implementation. See the other overloads of
   * {@code addExposedTypes} for their details.
   */
  private void addExposedTypes(Type type, Class<?> cause) {
    if (type instanceof TypeVariable) {
      LOG.debug("Adding exposed types from {}, which is a type variable", type);
      addExposedTypes((TypeVariable) type, cause);
    } else if (type instanceof WildcardType) {
      LOG.debug("Adding exposed types from {}, which is a wildcard type", type);
      addExposedTypes((WildcardType) type, cause);
    } else if (type instanceof GenericArrayType) {
      LOG.debug("Adding exposed types from {}, which is a generic array type", type);
      addExposedTypes((GenericArrayType) type, cause);
    } else if (type instanceof ParameterizedType) {
      LOG.debug("Adding exposed types from {}, which is a parameterized type", type);
      addExposedTypes((ParameterizedType) type, cause);
    } else if (type instanceof Class) {
      LOG.debug("Adding exposed types from {}, which is a class", type);
      addExposedTypes((Class) type, cause);
    } else {
      throw new IllegalArgumentException("Unknown implementation of Type");
    }
  }

  /**
   * Adds any types exposed to this set. These will come from the (possibly absent) bounds on the
   * type variable.
   */
  private void addExposedTypes(TypeVariable type, Class<?> cause) {
    if (done(type)) {
      return;
    }
    visit(type);
    for (Type bound : type.getBounds()) {
      LOG.debug("Adding exposed types from {}, which is a type bound on {}", bound, type);
      addExposedTypes(bound, cause);
    }
  }

  /**
   * Adds any types exposed to this set. These will come from the (possibly absent) bounds on the
   * wildcard.
   */
  private void addExposedTypes(WildcardType type, Class<?> cause) {
    visit(type);
    for (Type lowerBound : type.getLowerBounds()) {
      LOG.debug(
          "Adding exposed types from {}, which is a type lower bound on wildcard type {}",
          lowerBound,
          type);
      addExposedTypes(lowerBound, cause);
    }
    for (Type upperBound : type.getUpperBounds()) {
      LOG.debug(
          "Adding exposed types from {}, which is a type upper bound on wildcard type {}",
          upperBound,
          type);
      addExposedTypes(upperBound, cause);
    }
  }

  /**
   * Adds any types exposed from the given array type. The array type itself is not added. The cause
   * of the exposure of the underlying type is considered whatever type exposed the array type.
   */
  private void addExposedTypes(GenericArrayType type, Class<?> cause) {
    if (done(type)) {
      return;
    }
    visit(type);
    LOG.debug(
        "Adding exposed types from {}, which is the component type on generic array type {}",
        type.getGenericComponentType(),
        type);
    addExposedTypes(type.getGenericComponentType(), cause);
  }

  /**
   * Adds any types exposed to this set. Even if the root type is to be pruned, the actual type
   * arguments are processed.
   */
  private void addExposedTypes(ParameterizedType type, Class<?> cause) {
    // Even if the type is already done, this link to it may be new
    boolean alreadyDone = done(type);
    if (!pruned(type)) {
      visit(type);
      recordExposure(type, cause);
    }
    if (alreadyDone) {
      return;
    }

    // For a parameterized type, pruning does not take place
    // here, only for the raw class.
    // The type parameters themselves may not be pruned,
    // for example with List<MyApiType> probably the
    // standard List is pruned, but MyApiType is not.
    LOG.debug(
        "Adding exposed types from {}, which is the raw type on parameterized type {}",
        type.getRawType(),
        type);
    addExposedTypes(type.getRawType(), cause);
    for (Type typeArg : type.getActualTypeArguments()) {
      LOG.debug(
          "Adding exposed types from {}, which is a type argument on parameterized type {}",
          typeArg,
          type);
      addExposedTypes(typeArg, cause);
    }
  }

  /**
   * Adds a class and all of the types it exposes. The cause of the class being exposed is given,
   * and the cause of everything within the class is that class itself.
   */
  private void addExposedTypes(Class<?> clazz, Class<?> cause) {
    if (pruned(clazz)) {
      return;
    }
    // Even if `clazz` has been visited, the link from `cause` may be new
    boolean alreadyDone = done(clazz);
    visit(clazz);
    recordExposure(clazz, cause);
    if (alreadyDone || pruned(clazz)) {
      return;
    }

    TypeToken<?> token = TypeToken.of(clazz);
    for (TypeToken<?> superType : token.getTypes()) {
      if (!superType.equals(token)) {
        LOG.debug(
            "Adding exposed types from {}, which is a super type token on {}", superType, clazz);
        addExposedTypes(superType, clazz);
      }
    }
    for (Class innerClass : clazz.getDeclaredClasses()) {
      if (exposed(innerClass.getModifiers())) {
        LOG.debug(
            "Adding exposed types from {}, which is an exposed inner class of {}",
            innerClass,
            clazz);
        addExposedTypes(innerClass, clazz);
      }
    }
    for (Field field : clazz.getDeclaredFields()) {
      if (exposed(field.getModifiers())) {
        LOG.debug("Adding exposed types from {}, which is an exposed field on {}", field, clazz);
        addExposedTypes(field, clazz);
      }
    }
    for (Invokable invokable : getExposedInvokables(token)) {
      LOG.debug(
          "Adding exposed types from {}, which is an exposed invokable on {}", invokable, clazz);
      addExposedTypes(invokable, clazz);
    }
  }

  private void addExposedTypes(Invokable<?, ?> invokable, Class<?> cause) {
    addExposedTypes(invokable.getReturnType(), cause);
    for (Annotation annotation : invokable.getAnnotations()) {
      LOG.debug(
          "Adding exposed types from {}, which is an annotation on invokable {}",
          annotation,
          invokable);
      addExposedTypes(annotation.annotationType(), cause);
    }
    for (Parameter parameter : invokable.getParameters()) {
      LOG.debug(
          "Adding exposed types from {}, which is a parameter on invokable {}",
          parameter,
          invokable);
      addExposedTypes(parameter, cause);
    }
    for (TypeToken<?> exceptionType : invokable.getExceptionTypes()) {
      LOG.debug(
          "Adding exposed types from {}, which is an exception type on invokable {}",
          exceptionType,
          invokable);
      addExposedTypes(exceptionType, cause);
    }
  }

  private void addExposedTypes(Parameter parameter, Class<?> cause) {
    LOG.debug(
        "Adding exposed types from {}, which is the type of parameter {}",
        parameter.getType(),
        parameter);
    addExposedTypes(parameter.getType(), cause);
    for (Annotation annotation : parameter.getAnnotations()) {
      LOG.debug(
          "Adding exposed types from {}, which is an annotation on parameter {}",
          annotation,
          parameter);
      addExposedTypes(annotation.annotationType(), cause);
    }
  }

  private void addExposedTypes(Field field, Class<?> cause) {
    addExposedTypes(field.getGenericType(), cause);
    for (Annotation annotation : field.getDeclaredAnnotations()) {
      LOG.debug(
          "Adding exposed types from {}, which is an annotation on field {}", annotation, field);
      addExposedTypes(annotation.annotationType(), cause);
    }
  }

  /** Returns an {@link Invokable} for each public methods or constructors of a type. */
  private Set<Invokable> getExposedInvokables(TypeToken<?> type) {
    Set<Invokable> invokables = Sets.newHashSet();

    for (Constructor constructor : type.getRawType().getConstructors()) {
      if (0 != (constructor.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED))) {
        invokables.add(type.constructor(constructor));
      }
    }

    for (Method method : type.getRawType().getMethods()) {
      if (0 != (method.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED))) {
        invokables.add(type.method(method));
      }
    }

    return invokables;
  }

  /** Returns true of the given modifier bitmap indicates exposure (public or protected access). */
  private boolean exposed(int modifiers) {
    return 0 != (modifiers & (Modifier.PUBLIC | Modifier.PROTECTED));
  }

  ////////////////////////////////////////////////////////////////////////////

}
