// Copyright 2006 The Android Open Source Project

import java.lang.reflect.*;
import java.io.IOException;
import java.util.Collections;

/**
 * Reflection test.
 */
public class Main {
    void printMethodInfo(Method meth) {
        Class[] params, exceptions;
        int i;

        System.out.println("Method name is " + meth.getName());
        System.out.println(" Declaring class is "
            + meth.getDeclaringClass().getName());
        params = meth.getParameterTypes();
        for (i = 0; i < params.length; i++)
            System.out.println(" Arg " + i + ": " + params[i].getName());
        exceptions = meth.getExceptionTypes();
        for (i = 0; i < exceptions.length; i++)
            System.out.println(" Exc " + i + ": " + exceptions[i].getName());
        System.out.println(" Return type is " + meth.getReturnType().getName());
        System.out.println(" Access flags are 0x"
            + Integer.toHexString(meth.getModifiers()));
        //System.out.println(" GenericStr is " + meth.toGenericString());
    }

    void printFieldInfo(Field field) {
        System.out.println("Field name is " + field.getName());
        System.out.println(" Declaring class is "
            + field.getDeclaringClass().getName());
        System.out.println(" Field type is " + field.getType().getName());
        System.out.println(" Access flags are 0x"
            + Integer.toHexString(field.getModifiers()));
    }

    private void showStrings(Target instance)
        throws NoSuchFieldException, IllegalAccessException {

        Class target = Target.class;
        String one, two, three, four;
        Field field = null;

        field = target.getField("string1");
        one = (String) field.get(instance);

        field = target.getField("string2");
        two = (String) field.get(instance);

        field = target.getField("string3");
        three = (String) field.get(instance);

        System.out.println("  ::: " + one + ":" + two + ":" + three);
    }

    public void run() {
        Class target = Target.class;
        Method meth = null;
        Field field = null;
        boolean excep;

        try {
            meth = target.getMethod("myMethod", new Class[] { int.class });

            if (meth.getDeclaringClass() != target)
                throw new RuntimeException();
            printMethodInfo(meth);

            meth = target.getMethod("myMethod", new Class[] { float.class });
            printMethodInfo(meth);

            meth = target.getMethod("myNoargMethod", (Class[]) null);
            printMethodInfo(meth);

            meth = target.getMethod("myMethod",
                new Class[] { String[].class, float.class, char.class });
            printMethodInfo(meth);

            Target instance = new Target();
            Object[] argList = new Object[] {
                new String[] { "hi there" },
                new Float(3.1415926f),
                new Character('Q')
            };
            System.out.println("Before, float is "
                + ((Float)argList[1]).floatValue());

            Integer boxval;
            boxval = (Integer) meth.invoke(instance, argList);
            System.out.println("Result of invoke: " + boxval.intValue());

            System.out.println("Calling no-arg void-return method");
            meth = target.getMethod("myNoargMethod", (Class[]) null);
            meth.invoke(instance, (Object[]) null);

            /* try invoking a method that throws an exception */
            meth = target.getMethod("throwingMethod", (Class[]) null);
            try {
                meth.invoke(instance, (Object[]) null);
                System.out.println("GLITCH: didn't throw");
            } catch (InvocationTargetException ite) {
                System.out.println("Invoke got expected exception:");
                System.out.println(ite.getClass().getName());
                System.out.println(ite.getCause());
            }
            catch (Exception ex) {
                System.out.println("GLITCH: invoke got wrong exception:");
                ex.printStackTrace();
            }
            System.out.println("");


            field = target.getField("string1");
            if (field.getDeclaringClass() != target)
                throw new RuntimeException();
            printFieldInfo(field);
            String strVal = (String) field.get(instance);
            System.out.println("  string1 value is '" + strVal + "'");

            showStrings(instance);

            field.set(instance, new String("a new string"));
            strVal = (String) field.get(instance);
            System.out.println("  string1 value is now '" + strVal + "'");

            showStrings(instance);

            try {
                field.set(instance, new Object());
                System.out.println("WARNING: able to store Object into String");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected illegal obj store exc");
            }


            try {
                String four;
                field = target.getField("string4");
                four = (String) field.get(instance);
                System.out.println("WARNING: able to access string4: "
                    + four);
            }
            catch (IllegalAccessException iae) {
                System.out.println("  got expected access exc");
            }
            catch (NoSuchFieldException nsfe) {
                System.out.println("  got the other expected access exc");
            }
            try {
                String three;
                field = target.getField("string3");
                three = (String) field.get(this);
                System.out.println("WARNING: able to get string3 in wrong obj: "
                    + three);
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected arg exc");
            }

            /*
             * Try setting a field to null.
             */
            String four;
            field = target.getDeclaredField("string3");
            field.set(instance, null);

            /*
             * Do some stuff with long.
             */
            long longVal;
            field = target.getField("pubLong");
            longVal = field.getLong(instance);
            System.out.println("pubLong initial value is " +
                Long.toHexString(longVal));
            field.setLong(instance, 0x9988776655443322L);
            longVal = field.getLong(instance);
            System.out.println("pubLong new value is " +
                Long.toHexString(longVal));


            field = target.getField("superInt");
            if (field.getDeclaringClass() == target)
                throw new RuntimeException();
            printFieldInfo(field);
            int intVal = field.getInt(instance);
            System.out.println("  superInt value is " + intVal);
            Integer boxedIntVal = (Integer) field.get(instance);
            System.out.println("  superInt boxed is " + boxedIntVal);

            field.set(instance, new Integer(20202));
            intVal = field.getInt(instance);
            System.out.println("  superInt value is now " + intVal);
            field.setShort(instance, (short)30303);
            intVal = field.getInt(instance);
            System.out.println("  superInt value (from short) is now " +intVal);
            field.setInt(instance, 40404);
            intVal = field.getInt(instance);
            System.out.println("  superInt value is now " + intVal);
            try {
                field.set(instance, new Long(123));
                System.out.println("FAIL: expected exception not thrown");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected long->int failure");
            }
            try {
                field.setLong(instance, 123);
                System.out.println("FAIL: expected exception not thrown");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected long->int failure");
            }
            try {
                field.set(instance, new String("abc"));
                System.out.println("FAIL: expected exception not thrown");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected string->int failure");
            }

            try {
                field.getShort(instance);
                System.out.println("FAIL: expected exception not thrown");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected int->short failure");
            }

            field = target.getField("superClassInt");
            printFieldInfo(field);
            int superClassIntVal = field.getInt(instance);
            System.out.println("  superClassInt value is " + superClassIntVal);

            field = target.getField("staticDouble");
            printFieldInfo(field);
            double staticDoubleVal = field.getDouble(null);
            System.out.println("  staticDoubleVal value is " + staticDoubleVal);

            try {
                field.getLong(instance);
                System.out.println("FAIL: expected exception not thrown");
            }
            catch (IllegalArgumentException iae) {
                System.out.println("  got expected double->long failure");
            }

            excep = false;
            try {
                field = target.getField("aPrivateInt");
                printFieldInfo(field);
            }
            catch (NoSuchFieldException nsfe) {
                System.out.println("as expected: aPrivateInt not found");
                excep = true;
            }
            if (!excep)
                System.out.println("BUG: got aPrivateInt");


            field = target.getField("constantString");
            printFieldInfo(field);
            String val = (String) field.get(instance);
            System.out.println("  Constant test value is " + val);


            field = target.getField("cantTouchThis");
            printFieldInfo(field);
            intVal = field.getInt(instance);
            System.out.println("  cantTouchThis is " + intVal);
            try {
                field.setInt(instance, 99);
                System.out.println("  setAccessible is always true");
            } catch (IllegalAccessException iae) {
                System.out.println("ERROR: set-final failed");
            }
            intVal = field.getInt(instance);
            System.out.println("  cantTouchThis is now " + intVal);

            field.setAccessible(true);
            field.setInt(instance, 87);     // exercise int version
            intVal = field.getInt(instance);
            System.out.println("  cantTouchThis is now " + intVal);
            field.set(instance, 88);        // exercise Object version
            intVal = field.getInt(instance);
            System.out.println("  cantTouchThis is now " + intVal);

            Constructor<Target> cons;
            Target targ;
            Object[] args;

            cons = target.getConstructor(new Class[] { int.class,float.class });
            args = new Object[] { new Integer(7), new Float(3.3333) };
            System.out.println("cons modifiers=" + cons.getModifiers());
            targ = cons.newInstance(args);
            targ.myMethod(17);

        }
        catch (Exception ex) {
            System.out.println("----- unexpected exception -----");
            ex.printStackTrace();
        }

        System.out.println("ReflectTest done!");
    }

    public static void checkType() {
        Method m;

        try {
            m = Collections.class.getDeclaredMethod("checkType",
                            Object.class, Class.class);
        } catch (NoSuchMethodException nsme) {
            nsme.printStackTrace();
            return;
        }

        m.setAccessible(true);
        try {
            m.invoke(null, new Object(), Object.class);
        } catch (IllegalAccessException iae) {
            iae.printStackTrace();
            return;
        } catch (InvocationTargetException ite) {
            ite.printStackTrace();
            return;
        }

        try {
            System.out.println("checkType invoking null");
            m.invoke(null, new Object(), int.class);
            System.out.println("ERROR: should throw InvocationTargetException");
        } catch (InvocationTargetException ite) {
            System.out.println("checkType got expected exception");
        } catch (IllegalAccessException iae) {
            iae.printStackTrace();
            return;
        }
    }

    public static void checkInit() {
      System.out.println("calling const-class NoisyInitUser.class");
      Class niuClass = NoisyInitUser.class;
      System.out.println("called const-class NoisyInitUser.class");
      Method[] methods;

        methods = niuClass.getDeclaredMethods();
        System.out.println("got methods");
        /* neither NoisyInit nor NoisyInitUser should be initialized yet */
        NoisyInitUser niu = new NoisyInitUser();
        NoisyInit ni = new NoisyInit();
    }

    public static void main(String[] args) {
        Main test = new Main();
        test.run();

        checkType();
        checkInit();
    }
}


class SuperTarget {
    public SuperTarget() {
        System.out.println("SuperTarget constructor ()V");
        superInt = 1010101;
        superClassInt = 1010102;
    }

    public int myMethod(float floatArg) {
        System.out.println("myMethod (F)I " + floatArg);
        return 6;
    }

    public int superInt;
    public static int superClassInt;
}

class Target extends SuperTarget {
    public Target() {
        System.out.println("Target constructor ()V");
    }

    public Target(int ii, float ff) {
        System.out.println("Target constructor (IF)V : ii="
            + ii + " ff=" + ff);
        anInt = ii;
    }

    public int myMethod(int intarg) throws NullPointerException, IOException {
        System.out.println("myMethod (I)I");
        System.out.println(" arg=" + intarg + " anInt=" + anInt);
        return 5;
    }

    public int myMethod(String[] strarg, float f, char c) {
        System.out.println("myMethod: " + strarg[0] + " " + f + " " + c + " !");
        return 7;
    }

    public static void myNoargMethod() {
        System.out.println("myNoargMethod ()V");
    }

    public void throwingMethod() {
        System.out.println("throwingMethod");
        throw new NullPointerException("gratuitous throw!");
    }

    public void misc() {
        System.out.println("misc");
    }

    public int anInt;
    public String string1 = "hey";
    public String string2 = "yo";
    public String string3 = "there";
    private String string4 = "naughty";
    public static final String constantString = "a constant string";
    private int aPrivateInt;

    public final int cantTouchThis = 77;

    public long pubLong = 0x1122334455667788L;

    public static double staticDouble = 3.3;
}

class NoisyInit {
    static {
        System.out.println("NoisyInit is initializing");
        //Throwable th = new Throwable();
        //th.printStackTrace();
    }
}

class NoisyInitUser {
    static {
        System.out.println("NoisyInitUser is initializing");
    }
    public void createNoisyInit(NoisyInit ni) {}
}
