/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed 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.
 */

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVisitor;

public class ChildClass {
  enum PrimitiveType {
    TInteger('I', Integer.TYPE, Integer.valueOf(0)),
    TLong('J', Long.TYPE, Long.valueOf(0)),
    TFloat('F', Float.TYPE, Float.valueOf(0)),
    TDouble('D', Double.TYPE, Double.valueOf(0)),
    TBoolean('Z', Boolean.TYPE, Boolean.valueOf(false)),
    TByte('B', Byte.TYPE, Byte.valueOf((byte) 0)),
    TShort('S', Short.TYPE, Short.valueOf((short) 0)),
    TCharacter('C', Character.TYPE, Character.valueOf('0'));

    PrimitiveType(char shorty, Class klass, Object value) {
      mShorty = shorty;
      mClass = klass;
      mDefaultValue = value;
    }

    public char mShorty;
    public Class mClass;
    public Object mDefaultValue;
  }

  enum Hiddenness {
    Whitelist(PrimitiveType.TShort),
    LightGreylist(PrimitiveType.TBoolean),
    DarkGreylist(PrimitiveType.TByte),
    Blacklist(PrimitiveType.TCharacter);

    Hiddenness(PrimitiveType type) { mAssociatedType = type; }
    public PrimitiveType mAssociatedType;
  }

  enum Visibility {
    Public(PrimitiveType.TInteger),
    Package(PrimitiveType.TFloat),
    Protected(PrimitiveType.TLong),
    Private(PrimitiveType.TDouble);

    Visibility(PrimitiveType type) { mAssociatedType = type; }
    public PrimitiveType mAssociatedType;
  }

  enum Behaviour {
    Granted,
    Warning,
    Denied,
  }

  private static final boolean booleanValues[] = new boolean[] { false, true };

  public static void runTest(String libFileName, boolean expectedParentInBoot,
      boolean expectedChildInBoot) throws Exception {
    System.load(libFileName);

    // Check expectations about loading into boot class path.
    isParentInBoot = (ParentClass.class.getClassLoader().getParent() == null);
    if (isParentInBoot != expectedParentInBoot) {
      throw new RuntimeException("Expected ParentClass " +
                                 (expectedParentInBoot ? "" : "not ") + "in boot class path");
    }
    isChildInBoot = (ChildClass.class.getClassLoader().getParent() == null);
    if (isChildInBoot != expectedChildInBoot) {
      throw new RuntimeException("Expected ChildClass " + (expectedChildInBoot ? "" : "not ") +
                                 "in boot class path");
    }

    boolean isSameBoot = (isParentInBoot == isChildInBoot);

    // Run meaningful combinations of access flags.
    for (Hiddenness hiddenness : Hiddenness.values()) {
      final Behaviour expected;
      if (isSameBoot || hiddenness == Hiddenness.Whitelist) {
        expected = Behaviour.Granted;
      } else if (hiddenness == Hiddenness.Blacklist) {
        expected = Behaviour.Denied;
      } else {
        expected = Behaviour.Warning;
      }

      for (boolean isStatic : booleanValues) {
        String suffix = (isStatic ? "Static" : "") + hiddenness.name();

        for (Visibility visibility : Visibility.values()) {
          // Test reflection and JNI on methods and fields
          for (Class klass : new Class<?>[] { ParentClass.class, ParentInterface.class }) {
            String baseName = visibility.name() + suffix;
            checkField(klass, "field" + baseName, isStatic, visibility, expected);
            checkMethod(klass, "method" + baseName, isStatic, visibility, expected);
          }

          // Check whether one can use a class constructor.
          checkConstructor(ParentClass.class, visibility, hiddenness, expected);

          // Check whether one can use an interface default method.
          String name = "method" + visibility.name() + "Default" + hiddenness.name();
          checkMethod(ParentInterface.class, name, /*isStatic*/ false, visibility, expected);

          // Check whether one can override this method.
          checkOverriding(suffix, isStatic, visibility, expected);
        }

        // Test whether static linking succeeds.
        checkLinking("LinkFieldGet" + suffix, /*takesParameter*/ false, expected);
        checkLinking("LinkFieldSet" + suffix, /*takesParameter*/ true, expected);
        checkLinking("LinkMethod" + suffix, /*takesParameter*/ false, expected);
      }

      // Check whether Class.newInstance succeeds.
      checkNullaryConstructor(Class.forName("NullaryConstructor" + hiddenness.name()), expected);
    }
  }

  private static void checkField(Class<?> klass, String name, boolean isStatic,
      Visibility visibility, Behaviour behaviour) throws Exception {

    boolean isPublic = (visibility == Visibility.Public);
    boolean canDiscover = (behaviour != Behaviour.Denied);
    boolean setsWarning = (behaviour == Behaviour.Warning);

    if (klass.isInterface() && (!isStatic || !isPublic)) {
      // Interfaces only have public static fields.
      return;
    }

    // Test discovery with reflection.

    if (Reflection.canDiscoverWithGetDeclaredField(klass, name) != canDiscover) {
      throwDiscoveryException(klass, name, true, "getDeclaredField()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetDeclaredFields(klass, name) != canDiscover) {
      throwDiscoveryException(klass, name, true, "getDeclaredFields()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetField(klass, name) != (canDiscover && isPublic)) {
      throwDiscoveryException(klass, name, true, "getField()", (canDiscover && isPublic));
    }

    if (Reflection.canDiscoverWithGetFields(klass, name) != (canDiscover && isPublic)) {
      throwDiscoveryException(klass, name, true, "getFields()", (canDiscover && isPublic));
    }

    // Test discovery with JNI.

    if (JNI.canDiscoverField(klass, name, isStatic) != canDiscover) {
      throwDiscoveryException(klass, name, true, "JNI", canDiscover);
    }

    // Finish here if we could not discover the field.

    if (!canDiscover) {
      return;
    }

    // Test that modifiers are unaffected.

    if (Reflection.canObserveFieldHiddenAccessFlags(klass, name)) {
      throwModifiersException(klass, name, true);
    }

    // Test getters and setters when meaningful.

    clearWarning();
    if (!Reflection.canGetField(klass, name)) {
      throwAccessException(klass, name, true, "Field.getInt()");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, name, true, "Field.getInt()", setsWarning);
    }

    clearWarning();
    if (!Reflection.canSetField(klass, name)) {
      throwAccessException(klass, name, true, "Field.setInt()");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, name, true, "Field.setInt()", setsWarning);
    }

    clearWarning();
    if (!JNI.canGetField(klass, name, isStatic)) {
      throwAccessException(klass, name, true, "getIntField");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, name, true, "getIntField", setsWarning);
    }

    clearWarning();
    if (!JNI.canSetField(klass, name, isStatic)) {
      throwAccessException(klass, name, true, "setIntField");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, name, true, "setIntField", setsWarning);
    }
  }

  private static void checkMethod(Class<?> klass, String name, boolean isStatic,
      Visibility visibility, Behaviour behaviour) throws Exception {

    boolean isPublic = (visibility == Visibility.Public);
    if (klass.isInterface() && !isPublic) {
      // All interface members are public.
      return;
    }

    boolean canDiscover = (behaviour != Behaviour.Denied);
    boolean setsWarning = (behaviour == Behaviour.Warning);

    // Test discovery with reflection.

    if (Reflection.canDiscoverWithGetDeclaredMethod(klass, name) != canDiscover) {
      throwDiscoveryException(klass, name, false, "getDeclaredMethod()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetDeclaredMethods(klass, name) != canDiscover) {
      throwDiscoveryException(klass, name, false, "getDeclaredMethods()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetMethod(klass, name) != (canDiscover && isPublic)) {
      throwDiscoveryException(klass, name, false, "getMethod()", (canDiscover && isPublic));
    }

    if (Reflection.canDiscoverWithGetMethods(klass, name) != (canDiscover && isPublic)) {
      throwDiscoveryException(klass, name, false, "getMethods()", (canDiscover && isPublic));
    }

    // Test discovery with JNI.

    if (JNI.canDiscoverMethod(klass, name, isStatic) != canDiscover) {
      throwDiscoveryException(klass, name, false, "JNI", canDiscover);
    }

    // Finish here if we could not discover the field.

    if (!canDiscover) {
      return;
    }

    // Test that modifiers are unaffected.

    if (Reflection.canObserveMethodHiddenAccessFlags(klass, name)) {
      throwModifiersException(klass, name, false);
    }

    // Test whether we can invoke the method. This skips non-static interface methods.

    if (!klass.isInterface() || isStatic) {
      clearWarning();
      if (!Reflection.canInvokeMethod(klass, name)) {
        throwAccessException(klass, name, false, "invoke()");
      }
      if (hasPendingWarning() != setsWarning) {
        throwWarningException(klass, name, false, "invoke()", setsWarning);
      }

      clearWarning();
      if (!JNI.canInvokeMethodA(klass, name, isStatic)) {
        throwAccessException(klass, name, false, "CallMethodA");
      }
      if (hasPendingWarning() != setsWarning) {
        throwWarningException(klass, name, false, "CallMethodA()", setsWarning);
      }

      clearWarning();
      if (!JNI.canInvokeMethodV(klass, name, isStatic)) {
        throwAccessException(klass, name, false, "CallMethodV");
      }
      if (hasPendingWarning() != setsWarning) {
        throwWarningException(klass, name, false, "CallMethodV()", setsWarning);
      }
    }
  }

  private static void checkConstructor(Class<?> klass, Visibility visibility, Hiddenness hiddenness,
      Behaviour behaviour) throws Exception {

    boolean isPublic = (visibility == Visibility.Public);
    String signature = "(" + visibility.mAssociatedType.mShorty +
                             hiddenness.mAssociatedType.mShorty + ")V";
    String fullName = "<init>" + signature;
    Class<?> args[] = new Class[] { visibility.mAssociatedType.mClass,
                                    hiddenness.mAssociatedType.mClass };
    Object initargs[] = new Object[] { visibility.mAssociatedType.mDefaultValue,
                                       hiddenness.mAssociatedType.mDefaultValue };

    boolean canDiscover = (behaviour != Behaviour.Denied);
    boolean setsWarning = (behaviour == Behaviour.Warning);

    // Test discovery with reflection.

    if (Reflection.canDiscoverWithGetDeclaredConstructor(klass, args) != canDiscover) {
      throwDiscoveryException(klass, fullName, false, "getDeclaredConstructor()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetDeclaredConstructors(klass, args) != canDiscover) {
      throwDiscoveryException(klass, fullName, false, "getDeclaredConstructors()", canDiscover);
    }

    if (Reflection.canDiscoverWithGetConstructor(klass, args) != (canDiscover && isPublic)) {
      throwDiscoveryException(
          klass, fullName, false, "getConstructor()", (canDiscover && isPublic));
    }

    if (Reflection.canDiscoverWithGetConstructors(klass, args) != (canDiscover && isPublic)) {
      throwDiscoveryException(
          klass, fullName, false, "getConstructors()", (canDiscover && isPublic));
    }

    // Test discovery with JNI.

    if (JNI.canDiscoverConstructor(klass, signature) != canDiscover) {
      throwDiscoveryException(klass, fullName, false, "JNI", canDiscover);
    }

    // Finish here if we could not discover the field.

    if (!canDiscover) {
      return;
    }

    // Test whether we can invoke the constructor.

    clearWarning();
    if (!Reflection.canInvokeConstructor(klass, args, initargs)) {
      throwAccessException(klass, fullName, false, "invoke()");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, fullName, false, "invoke()", setsWarning);
    }

    clearWarning();
    if (!JNI.canInvokeConstructorA(klass, signature)) {
      throwAccessException(klass, fullName, false, "NewObjectA");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, fullName, false, "NewObjectA", setsWarning);
    }

    clearWarning();
    if (!JNI.canInvokeConstructorV(klass, signature)) {
      throwAccessException(klass, fullName, false, "NewObjectV");
    }
    if (hasPendingWarning() != setsWarning) {
      throwWarningException(klass, fullName, false, "NewObjectV", setsWarning);
    }
  }

  private static void checkNullaryConstructor(Class<?> klass, Behaviour behaviour)
      throws Exception {
    boolean canAccess = (behaviour != Behaviour.Denied);
    boolean setsWarning = (behaviour == Behaviour.Warning);

    clearWarning();
    if (Reflection.canUseNewInstance(klass) != canAccess) {
      throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") +
          "be able to construct " + klass.getName() + ". " +
          "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
    }
    if (canAccess && hasPendingWarning() != setsWarning) {
      throwWarningException(klass, "nullary constructor", false, "newInstance", setsWarning);
    }
  }

  private static void checkLinking(String className, boolean takesParameter, Behaviour behaviour)
      throws Exception {
    boolean canAccess = (behaviour != Behaviour.Denied);
    boolean setsWarning = (behaviour == Behaviour.Warning);

    clearWarning();
    if (Linking.canAccess(className, takesParameter) != canAccess) {
      throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") +
          "be able to verify " + className + "." +
          "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
    }
    if (canAccess && hasPendingWarning() != setsWarning) {
      throwWarningException(
          Class.forName(className), "access", false, "static linking", setsWarning);
    }
  }

  private static void checkOverriding(String suffix,
                                      boolean isStatic,
                                      Visibility visibility,
                                      Behaviour behaviour) throws Exception {
    if (isStatic || visibility == Visibility.Private) {
      // Does not make sense to override a static or private method.
      return;
    }

    // The classes are in the same package, but will be able to access each
    // other only if loaded with the same class loader, here the boot class loader.
    boolean canAccess = (visibility != Visibility.Package) || (isParentInBoot && isChildInBoot);
    boolean setsWarning = false;  // warnings may be set during vtable linking

    String methodName = "callMethod" + visibility.name() + suffix;

    // Force the test class to link its vtable, which may cause warnings, before
    // the actual test.
    new OverrideClass().methodPublicWhitelist();

    clearWarning();
    if (Linking.canOverride(methodName) != canAccess) {
      throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") +
          "be able to override " + methodName + "." +
          "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
    }
    if (canAccess && hasPendingWarning() != setsWarning) {
      throwWarningException(ParentClass.class, methodName, false, "static linking", setsWarning);
    }
  }

  private static void throwDiscoveryException(Class<?> klass, String name, boolean isField,
      String fn, boolean canAccess) {
    throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() +
        "." + name + " to " + (canAccess ? "" : "not ") + "be discoverable with " + fn + ". " +
        "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
  }

  private static void throwAccessException(Class<?> klass, String name, boolean isField,
      String fn) {
    throw new RuntimeException("Expected to be able to access " + (isField ? "field " : "method ") +
        klass.getName() + "." + name + " using " + fn + ". " +
        "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
  }

  private static void throwWarningException(Class<?> klass, String name, boolean isField,
      String fn, boolean setsWarning) {
    throw new RuntimeException("Expected access to " + (isField ? "field " : "method ") +
        klass.getName() + "." + name + " using " + fn + " to " + (setsWarning ? "" : "not ") +
        "set the warning flag. " +
        "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
  }

  private static void throwModifiersException(Class<?> klass, String name, boolean isField) {
    throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() +
        "." + name + " to not expose hidden modifiers");
  }

  private static boolean isParentInBoot;
  private static boolean isChildInBoot;

  private static native boolean hasPendingWarning();
  private static native void clearWarning();
}
