/*
 * Copyright (C) 2008 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.
 */

/**
 * Class loader test.
 */
public class Main {
    /**
     * Main entry point.
     */
    public static void main(String[] args) throws Exception {
        FancyLoader loader;

        loader = new FancyLoader(ClassLoader.getSystemClassLoader());
        //System.out.println("SYSTEM: " + ClassLoader.getSystemClassLoader());
        //System.out.println("ALTERN: " + loader);

        /*
         * This statement has no effect on this program, but it can
         * change the point where a LinkageException is thrown in
         * testImplement().  When this is present the "reference
         * implementation" throws an exception from Class.newInstance(),
         * when it's absent the exception is deferred until the first time
         * we call a method that isn't actually implemented.
         *
         * This isn't the class that fails -- it's a class with the same
         * name in the "fancy" class loader --  but the VM thinks it has a
         * reference to one of these; presumably the difference is that
         * without this the VM finds itself holding a reference to an
         * instance of an uninitialized class.
         */
        System.out.println("base: " + DoubledImplement.class);
        System.out.println("base2: " + DoubledImplement2.class);

        /*
         * Run tests.
         */
        testAccess1(loader);
        testAccess2(loader);
        testAccess3(loader);

        testExtend(loader);
        testExtendOkay(loader);
        testInterface(loader);
        testAbstract(loader);
        testImplement(loader);
        testIfaceImplement(loader);

        testSeparation();

        testClassForName();
    }

    static void testSeparation() {
        FancyLoader loader1 = new FancyLoader(ClassLoader.getSystemClassLoader());
        FancyLoader loader2 = new FancyLoader(ClassLoader.getSystemClassLoader());

        try {
            Class target1 = loader1.loadClass("MutationTarget");
            Class target2 = loader2.loadClass("MutationTarget");

            if (target1 == target2) {
                throw new RuntimeException("target1 should not be equal to target2");
            }

            Class mutator1 = loader1.loadClass("Mutator");
            Class mutator2 = loader2.loadClass("Mutator");

            if (mutator1 == mutator2) {
                throw new RuntimeException("mutator1 should not be equal to mutator2");
            }

            runMutator(mutator1, 1);

            int value = getMutationTargetValue(target1);
            if (value != 1) {
                throw new RuntimeException("target 1 has unexpected value " + value);
            }
            value = getMutationTargetValue(target2);
            if (value != 0) {
                throw new RuntimeException("target 2 has unexpected value " + value);
            }

            runMutator(mutator2, 2);

            value = getMutationTargetValue(target1);
            if (value != 1) {
                throw new RuntimeException("target 1 has unexpected value " + value);
            }
            value = getMutationTargetValue(target2);
            if (value != 2) {
                throw new RuntimeException("target 2 has unexpected value " + value);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void runMutator(Class c, int v) throws Exception {
        java.lang.reflect.Method m = c.getDeclaredMethod("mutate", int.class);
        m.invoke(null, v);
    }

    private static int getMutationTargetValue(Class c) throws Exception {
        java.lang.reflect.Field f = c.getDeclaredField("value");
        return f.getInt(null);
    }

    /**
     * See if we can load a class that isn't public to us.  We should be
     * able to load it but not instantiate it.
     */
    static void testAccess1(ClassLoader loader) {
        Class altClass;

        try {
            altClass = loader.loadClass("Inaccessible1");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed");
            cnfe.printStackTrace();
            return;
        }

        /* instantiate */
        Object obj;
        try {
            obj = altClass.newInstance();
            System.err.println("ERROR: Inaccessible1 was accessible");
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.out.println("Got expected access exception #1");
            //System.out.println("+++ " + iae);
            return;
        }
    }

    /**
     * See if we can load a class whose base class is not accessible to it
     * (though the base *is* accessible to us).
     */
    static void testAccess2(ClassLoader loader) {
        Class altClass;

        try {
            altClass = loader.loadClass("Inaccessible2");
            System.err.println("ERROR: Inaccessible2 was accessible: " + altClass);
        } catch (ClassNotFoundException cnfe) {
            Throwable cause = cnfe.getCause();
            if (cause instanceof IllegalAccessError) {
                System.out.println("Got expected CNFE/IAE #2");
            } else {
                System.err.println("Got unexpected CNFE/IAE #2");
                cnfe.printStackTrace();
            }
        }
    }

    /**
     * See if we can load a class with an inaccessible interface.
     */
    static void testAccess3(ClassLoader loader) {
        Class altClass;

        try {
            altClass = loader.loadClass("Inaccessible3");
            System.err.println("ERROR: Inaccessible3 was accessible: " + altClass);
        } catch (ClassNotFoundException cnfe) {
            Throwable cause = cnfe.getCause();
            if (cause instanceof IllegalAccessError) {
                System.out.println("Got expected CNFE/IAE #3");
            } else {
                System.err.println("Got unexpected CNFE/IAE #3");
                cnfe.printStackTrace();
            }
        }
    }

    /**
     * Test a doubled class that extends the base class.
     */
    static void testExtend(ClassLoader loader) {
        Class doubledExtendClass;
        Object obj;

        /* get the "alternate" version of DoubledExtend */
        try {
            doubledExtendClass = loader.loadClass("DoubledExtend");
            //System.out.println("+++ DoubledExtend is " + doubledExtendClass
            //    + " in " + doubledExtendClass.getClassLoader());
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = doubledExtendClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            System.out.println("Got expected LinkageError on DE");
            return;
        }

        /* use the base class reference to get a CL-specific instance */
        Base baseRef = (Base) obj;
        DoubledExtend de = baseRef.getExtended();

        /* try to call through it */
        try {
            String result;

            result = Base.doStuff(de);
            System.err.println("ERROR: did not get LinkageError on DE");
            System.err.println("(result=" + result + ")");
        } catch (LinkageError le) {
            System.out.println("Got expected LinkageError on DE");
            return;
        }
    }

    /**
     * Test a doubled class that extends the base class, but is okay since
     * it doesn't override the base class method.
     */
    static void testExtendOkay(ClassLoader loader) {
        Class doubledExtendOkayClass;
        Object obj;

        /* get the "alternate" version of DoubledExtendOkay */
        try {
            doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = doubledExtendOkayClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            System.err.println("Got unexpected LinkageError on DEO");
            le.printStackTrace();
            return;
        }

        /* use the base class reference to get a CL-specific instance */
        BaseOkay baseRef = (BaseOkay) obj;
        DoubledExtendOkay de = baseRef.getExtended();

        /* try to call through it */
        try {
            String result;

            result = BaseOkay.doStuff(de);
            System.out.println("Got DEO result " + result);
        } catch (LinkageError le) {
            System.err.println("Got unexpected LinkageError on DEO");
            le.printStackTrace();
            return;
        }
    }

    /**
     * Try to access a doubled class through a class that implements
     * an interface declared in a different class.
     */
    static void testInterface(ClassLoader loader) {
        Class getDoubledClass;
        Object obj;

        /* get GetDoubled from the "alternate" class loader */
        try {
            getDoubledClass = loader.loadClass("GetDoubled");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = getDoubledClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            // Dalvik bails here
            System.out.println("Got LinkageError on GD");
            return;
        }

        /*
         * Cast the object to the interface, and try to use it.
         */
        IGetDoubled iface = (IGetDoubled) obj;
        try {
            /* "de" will be the wrong variety of DoubledExtendOkay */
            DoubledExtendOkay de = iface.getDoubled();
            // reference impl bails here
            String str = de.getStr();
        } catch (LinkageError le) {
            System.out.println("Got LinkageError on GD");
            return;
        }
        System.err.println("Should have failed by now on GetDoubled");
    }

    /**
     * Throw an abstract class into the middle and see what happens.
     */
    static void testAbstract(ClassLoader loader) {
        Class abstractGetClass;
        Object obj;

        /* get AbstractGet from the "alternate" loader */
        try {
            abstractGetClass = loader.loadClass("AbstractGet");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass ta failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = abstractGetClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            System.out.println("Got LinkageError on TA");
            return;
        }

        /* use the base class reference to get a CL-specific instance */
        BaseOkay baseRef = (BaseOkay) obj;
        DoubledExtendOkay de = baseRef.getExtended();

        /* try to call through it */
        try {
            String result;

            result = BaseOkay.doStuff(de);
        } catch (LinkageError le) {
            System.out.println("Got LinkageError on TA");
            return;
        }
        System.err.println("Should have failed by now in testAbstract");
    }

    /**
     * Test a doubled class that implements a common interface.
     */
    static void testImplement(ClassLoader loader) {
        Class doubledImplementClass;
        Object obj;

        useImplement(new DoubledImplement(), true);

        /* get the "alternate" version of DoubledImplement */
        try {
            doubledImplementClass = loader.loadClass("DoubledImplement");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = doubledImplementClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            System.out.println("Got LinkageError on DI (early)");
            return;
        }

        /* if we lived this long, try to do something with it */
        ICommon icommon = (ICommon) obj;
        useImplement(icommon.getDoubledInstance(), false);
    }

    /**
     * Do something with a DoubledImplement instance.
     */
    static void useImplement(DoubledImplement di, boolean isOne) {
        //System.out.println("useObject: " + di.toString() + " -- "
        //    + di.getClass().getClassLoader());
        try {
            di.one();
            if (!isOne) {
                System.err.println("ERROR: did not get LinkageError on DI");
            }
        } catch (LinkageError le) {
            if (!isOne) {
                System.out.println("Got LinkageError on DI (late)");
            } else {
                throw le;
            }
        }
    }


    /**
     * Test a class that implements an interface with a super-interface
     * that refers to a doubled class.
     */
    static void testIfaceImplement(ClassLoader loader) {
        Class ifaceImplClass;
        Object obj;

        /*
         * Create an instance of IfaceImpl.  We also pull in
         * DoubledImplement2 from the other class loader; without this
         * we don't fail in some implementations.
         */
        try {
            ifaceImplClass = loader.loadClass("IfaceImpl");
            ifaceImplClass = loader.loadClass("DoubledImplement2");
        } catch (ClassNotFoundException cnfe) {
            System.err.println("loadClass failed: " + cnfe);
            return;
        }

        /* instantiate */
        try {
            obj = ifaceImplClass.newInstance();
        } catch (InstantiationException ie) {
            System.err.println("newInstance failed: " + ie);
            return;
        } catch (IllegalAccessException iae) {
            System.err.println("newInstance failed: " + iae);
            return;
        } catch (LinkageError le) {
            System.out.println("Got LinkageError on IDI (early)");
            //System.out.println(le);
            return;
        }

        /*
         * Without the pre-load of FancyLoader->DoubledImplement2, some
         * implementations will happily execute through this part.  "obj"
         * comes from FancyLoader, but the di2 returned from ifaceSuper
         * comes from the application class loader.
         */
        IfaceSuper ifaceSuper = (IfaceSuper) obj;
        DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2();
        di2.one();
    }

    static void testClassForName() throws Exception {
        System.out.println(Class.forName("Main").toString());
        try {
            System.out.println(Class.forName("Main", false, null).toString());
        } catch (ClassNotFoundException expected) {
            System.out.println("Got expected ClassNotFoundException");
        }
    }
}
