content: /*
   * 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.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  
  public class Main {
      public static void main(String[] args) {
          System.loadLibrary(args[0]);
  
          testGetFieldId(TestClass.class, "intField", "I");
          testGetFieldId(TestClass.class, "intField", "int");
          testGetFieldId(TestClass.class, "intField", "Lint;");
          testGetFieldId(TestClass.class, "stringField", "I");
          testGetFieldId(TestClass.class, "stringField", "Ljava/lang/String;");
          testGetFieldId(TestClass.class, "stringField", "java/lang/String");
          testGetFieldId(TestClass.class, "stringField", "Ljava.lang.String;");
          testGetFieldId(TestClass.class, "stringField", "java.lang.String");
  
          try {
              Method get = Main.class.getDeclaredMethod("getFieldId",
                                                        Class.class,
                                                        String.class,
                                                        String.class);
              MyClassLoader loader = new MyClassLoader(Main.class.getClassLoader());
              Class<?> otherMain = Class.forName("Main", true, loader);
              Method m = otherMain.getDeclaredMethod("testClassLoading", Method.class);
              m.invoke(null, get);
          } catch (Throwable t) {
              t.printStackTrace(System.out);
          }
      }
  
      public static void testClassLoading(Method get) throws Exception {
          System.out.println("Test that MyClassLoader.loadClass(\"Bad.Class\") shall not be called.");
          String[] bad_class_names = { "Bad/Class", "Bad.Class", "LBad.Class;" };
          for (String signature : bad_class_names) {
              try {
                  get.invoke(null, TestClass.class, "bogus", signature);
                  System.out.println("FAIL!");
              } catch (InvocationTargetException ite) {
                  if (!(ite.getCause() instanceof NoSuchFieldError) ||
                      !(ite.getCause().getCause() instanceof NoClassDefFoundError)) {
                    throw ite;
                  }
                  NoClassDefFoundError ncdfe = (NoClassDefFoundError) ite.getCause().getCause();
                  System.out.println("  Error message for " + signature + ": " + ncdfe.getMessage());
              }
          }
      }
  
      public static void testGetFieldId(Class<?> cls, String name, String signature) {
          System.out.println("getFieldId(" + cls + ", \"" + name + "\", \"" + signature + "\")");
          try {
              boolean result = getFieldId(cls, name, signature);
              System.out.println("Result: " + result);
          } catch (Throwable t) {
              System.out.println("Caught " + DescribeThrowable(t));
              for (Throwable cause = t.getCause(); cause != null; cause = cause.getCause()) {
                  System.out.println("  caused by " + DescribeThrowable(cause));
              }
          }
      }
  
      public static String DescribeThrowable(Throwable t) {
          return PRINT_MESSAGE ? t.getClass().getName() + ": " + t.getMessage()
                               : t.getClass().getName();
      }
  
      public static native boolean getFieldId(Class<?> cls, String name, String signature);
  
      // Set to true to see actual messages.
      public static final boolean PRINT_MESSAGE = false;
  }
  
  class TestClass {
      public int intField;
      public String stringField;
  }
  
  class MyClassLoader extends DefiningLoader {
    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }
  
    public Class<?> loadClass(String name) throws ClassNotFoundException
    {
        if (name.equals("Bad.Class")) {
            throw new Error("findClass(\"Bad.Class\")");
        }
        return super.loadClass(name);
    }
  }
  