Home | History | Annotate | Download | only in src
      1 // Copyright 2006 The Android Open Source Project
      2 
      3 import java.lang.reflect.*;
      4 import java.io.IOException;
      5 import java.util.Collections;
      6 import java.util.ArrayList;
      7 import java.util.List;
      8 import java.util.Map;
      9 
     10 /**
     11  * Reflection test.
     12  */
     13 public class Main {
     14     private static boolean FULL_ACCESS_CHECKS = false;  // b/5861201
     15     public Main() {}
     16     public Main(ArrayList<Integer> stuff) {}
     17 
     18     void printMethodInfo(Method meth) {
     19         Class[] params, exceptions;
     20         int i;
     21 
     22         System.out.println("Method name is " + meth.getName());
     23         System.out.println(" Declaring class is "
     24             + meth.getDeclaringClass().getName());
     25         params = meth.getParameterTypes();
     26         for (i = 0; i < params.length; i++)
     27             System.out.println(" Arg " + i + ": " + params[i].getName());
     28         exceptions = meth.getExceptionTypes();
     29         for (i = 0; i < exceptions.length; i++)
     30             System.out.println(" Exc " + i + ": " + exceptions[i].getName());
     31         System.out.println(" Return type is " + meth.getReturnType().getName());
     32         System.out.println(" Access flags are 0x"
     33             + Integer.toHexString(meth.getModifiers()));
     34         //System.out.println(" GenericStr is " + meth.toGenericString());
     35     }
     36 
     37     void printFieldInfo(Field field) {
     38         System.out.println("Field name is " + field.getName());
     39         System.out.println(" Declaring class is "
     40             + field.getDeclaringClass().getName());
     41         System.out.println(" Field type is " + field.getType().getName());
     42         System.out.println(" Access flags are 0x"
     43             + Integer.toHexString(field.getModifiers()));
     44     }
     45 
     46     private void showStrings(Target instance)
     47         throws NoSuchFieldException, IllegalAccessException {
     48 
     49         Class target = Target.class;
     50         String one, two, three, four;
     51         Field field = null;
     52 
     53         field = target.getField("string1");
     54         one = (String) field.get(instance);
     55 
     56         field = target.getField("string2");
     57         two = (String) field.get(instance);
     58 
     59         field = target.getField("string3");
     60         three = (String) field.get(instance);
     61 
     62         System.out.println("  ::: " + one + ":" + two + ":" + three);
     63     }
     64 
     65     public static void checkAccess() {
     66         try {
     67             Class target = otherpackage.Other.class;
     68             Object instance = new otherpackage.Other();
     69             Method meth;
     70 
     71             meth = target.getMethod("publicMethod", (Class[]) null);
     72             meth.invoke(instance);
     73 
     74             try {
     75                 meth = target.getMethod("packageMethod", (Class[]) null);
     76                 System.err.println("succeeded on package-scope method");
     77             } catch (NoSuchMethodException nsme) {
     78                 // good
     79             }
     80 
     81 
     82             instance = otherpackage.Other.getInnerClassInstance();
     83             target = instance.getClass();
     84             meth = target.getMethod("innerMethod", (Class[]) null);
     85             try {
     86                 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); }
     87                 meth.invoke(instance);
     88                 System.err.println("inner-method invoke unexpectedly worked");
     89             } catch (IllegalAccessException iae) {
     90                 // good
     91             }
     92 
     93             Field field = target.getField("innerField");
     94             try {
     95                 int x = field.getInt(instance);
     96                 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); }
     97                 System.err.println("field get unexpectedly worked: " + x);
     98             } catch (IllegalAccessException iae) {
     99                 // good
    100             }
    101         } catch (Exception ex) {
    102             System.out.println("----- unexpected exception -----");
    103             ex.printStackTrace();
    104         }
    105     }
    106 
    107     public void run() {
    108         Class target = Target.class;
    109         Method meth = null;
    110         Field field = null;
    111         boolean excep;
    112 
    113         try {
    114             meth = target.getMethod("myMethod", new Class[] { int.class });
    115 
    116             if (meth.getDeclaringClass() != target)
    117                 throw new RuntimeException();
    118             printMethodInfo(meth);
    119 
    120             meth = target.getMethod("myMethod", new Class[] { float.class });
    121             printMethodInfo(meth);
    122 
    123             meth = target.getMethod("myNoargMethod", (Class[]) null);
    124             printMethodInfo(meth);
    125 
    126             meth = target.getMethod("myMethod",
    127                 new Class[] { String[].class, float.class, char.class });
    128             printMethodInfo(meth);
    129 
    130             Target instance = new Target();
    131             Object[] argList = new Object[] {
    132                 new String[] { "hi there" },
    133                 new Float(3.1415926f),
    134                 new Character('Q')
    135             };
    136             System.out.println("Before, float is "
    137                 + ((Float)argList[1]).floatValue());
    138 
    139             Integer boxval;
    140             boxval = (Integer) meth.invoke(instance, argList);
    141             System.out.println("Result of invoke: " + boxval.intValue());
    142 
    143             System.out.println("Calling no-arg void-return method");
    144             meth = target.getMethod("myNoargMethod", (Class[]) null);
    145             meth.invoke(instance, (Object[]) null);
    146 
    147             /* try invoking a method that throws an exception */
    148             meth = target.getMethod("throwingMethod", (Class[]) null);
    149             try {
    150                 meth.invoke(instance, (Object[]) null);
    151                 System.out.println("GLITCH: didn't throw");
    152             } catch (InvocationTargetException ite) {
    153                 System.out.println("Invoke got expected exception:");
    154                 System.out.println(ite.getClass().getName());
    155                 System.out.println(ite.getCause());
    156             }
    157             catch (Exception ex) {
    158                 System.out.println("GLITCH: invoke got wrong exception:");
    159                 ex.printStackTrace();
    160             }
    161             System.out.println("");
    162 
    163 
    164             field = target.getField("string1");
    165             if (field.getDeclaringClass() != target)
    166                 throw new RuntimeException();
    167             printFieldInfo(field);
    168             String strVal = (String) field.get(instance);
    169             System.out.println("  string1 value is '" + strVal + "'");
    170 
    171             showStrings(instance);
    172 
    173             field.set(instance, new String("a new string"));
    174             strVal = (String) field.get(instance);
    175             System.out.println("  string1 value is now '" + strVal + "'");
    176 
    177             showStrings(instance);
    178 
    179             try {
    180                 field.set(instance, new Object());
    181                 System.out.println("WARNING: able to store Object into String");
    182             }
    183             catch (IllegalArgumentException iae) {
    184                 System.out.println("  got expected illegal obj store exc");
    185             }
    186 
    187 
    188             try {
    189                 String four;
    190                 field = target.getField("string4");
    191                 four = (String) field.get(instance);
    192                 System.out.println("WARNING: able to access string4: "
    193                     + four);
    194             }
    195             catch (IllegalAccessException iae) {
    196                 System.out.println("  got expected access exc");
    197             }
    198             catch (NoSuchFieldException nsfe) {
    199                 System.out.println("  got the other expected access exc");
    200             }
    201             try {
    202                 String three;
    203                 field = target.getField("string3");
    204                 three = (String) field.get(this);
    205                 System.out.println("WARNING: able to get string3 in wrong obj: "
    206                     + three);
    207             }
    208             catch (IllegalArgumentException iae) {
    209                 System.out.println("  got expected arg exc");
    210             }
    211 
    212             /*
    213              * Try setting a field to null.
    214              */
    215             String four;
    216             field = target.getDeclaredField("string3");
    217             field.set(instance, null);
    218 
    219             /*
    220              * Do some stuff with long.
    221              */
    222             long longVal;
    223             field = target.getField("pubLong");
    224             longVal = field.getLong(instance);
    225             System.out.println("pubLong initial value is " +
    226                 Long.toHexString(longVal));
    227             field.setLong(instance, 0x9988776655443322L);
    228             longVal = field.getLong(instance);
    229             System.out.println("pubLong new value is " +
    230                 Long.toHexString(longVal));
    231 
    232 
    233             field = target.getField("superInt");
    234             if (field.getDeclaringClass() == target)
    235                 throw new RuntimeException();
    236             printFieldInfo(field);
    237             int intVal = field.getInt(instance);
    238             System.out.println("  superInt value is " + intVal);
    239             Integer boxedIntVal = (Integer) field.get(instance);
    240             System.out.println("  superInt boxed is " + boxedIntVal);
    241 
    242             field.set(instance, new Integer(20202));
    243             intVal = field.getInt(instance);
    244             System.out.println("  superInt value is now " + intVal);
    245             field.setShort(instance, (short)30303);
    246             intVal = field.getInt(instance);
    247             System.out.println("  superInt value (from short) is now " +intVal);
    248             field.setInt(instance, 40404);
    249             intVal = field.getInt(instance);
    250             System.out.println("  superInt value is now " + intVal);
    251             try {
    252                 field.set(instance, new Long(123));
    253                 System.out.println("FAIL: expected exception not thrown");
    254             }
    255             catch (IllegalArgumentException iae) {
    256                 System.out.println("  got expected long->int failure");
    257             }
    258             try {
    259                 field.setLong(instance, 123);
    260                 System.out.println("FAIL: expected exception not thrown");
    261             }
    262             catch (IllegalArgumentException iae) {
    263                 System.out.println("  got expected long->int failure");
    264             }
    265             try {
    266                 field.set(instance, new String("abc"));
    267                 System.out.println("FAIL: expected exception not thrown");
    268             }
    269             catch (IllegalArgumentException iae) {
    270                 System.out.println("  got expected string->int failure");
    271             }
    272 
    273             try {
    274                 field.getShort(instance);
    275                 System.out.println("FAIL: expected exception not thrown");
    276             }
    277             catch (IllegalArgumentException iae) {
    278                 System.out.println("  got expected int->short failure");
    279             }
    280 
    281             field = target.getField("superClassInt");
    282             printFieldInfo(field);
    283             int superClassIntVal = field.getInt(instance);
    284             System.out.println("  superClassInt value is " + superClassIntVal);
    285 
    286             field = target.getField("staticDouble");
    287             printFieldInfo(field);
    288             double staticDoubleVal = field.getDouble(null);
    289             System.out.println("  staticDoubleVal value is " + staticDoubleVal);
    290 
    291             try {
    292                 field.getLong(instance);
    293                 System.out.println("FAIL: expected exception not thrown");
    294             }
    295             catch (IllegalArgumentException iae) {
    296                 System.out.println("  got expected double->long failure");
    297             }
    298 
    299             excep = false;
    300             try {
    301                 field = target.getField("aPrivateInt");
    302                 printFieldInfo(field);
    303             }
    304             catch (NoSuchFieldException nsfe) {
    305                 System.out.println("as expected: aPrivateInt not found");
    306                 excep = true;
    307             }
    308             if (!excep)
    309                 System.out.println("BUG: got aPrivateInt");
    310 
    311 
    312             field = target.getField("constantString");
    313             printFieldInfo(field);
    314             String val = (String) field.get(instance);
    315             System.out.println("  Constant test value is " + val);
    316 
    317 
    318             field = target.getField("cantTouchThis");
    319             printFieldInfo(field);
    320             intVal = field.getInt(instance);
    321             System.out.println("  cantTouchThis is " + intVal);
    322             try {
    323                 field.setInt(instance, 99);
    324                 System.out.println("ERROR: set-final succeeded");
    325             } catch (IllegalAccessException iae) {
    326                 System.out.println("  got expected set-final failure");
    327             }
    328             intVal = field.getInt(instance);
    329             System.out.println("  cantTouchThis is now " + intVal);
    330 
    331             field.setAccessible(true);
    332             field.setInt(instance, 87);     // exercise int version
    333             field.set(instance, 88);        // exercise Object version
    334             intVal = field.getInt(instance);
    335             System.out.println("  cantTouchThis is now " + intVal);
    336 
    337             Constructor<Target> cons;
    338             Target targ;
    339             Object[] args;
    340 
    341             cons = target.getConstructor(new Class[] { int.class,float.class });
    342             args = new Object[] { new Integer(7), new Float(3.3333) };
    343             System.out.println("cons modifiers=" + cons.getModifiers());
    344             targ = cons.newInstance(args);
    345             targ.myMethod(17);
    346 
    347         } catch (Exception ex) {
    348             System.out.println("----- unexpected exception -----");
    349             ex.printStackTrace();
    350         }
    351 
    352         System.out.println("ReflectTest done!");
    353     }
    354 
    355     public static void checkType() {
    356         Method m;
    357 
    358         try {
    359             m = Collections.class.getDeclaredMethod("checkType",
    360                             Object.class, Class.class);
    361         } catch (NoSuchMethodException nsme) {
    362             nsme.printStackTrace();
    363             return;
    364         }
    365 
    366         m.setAccessible(true);
    367         try {
    368             m.invoke(null, new Object(), Object.class);
    369         } catch (IllegalAccessException iae) {
    370             iae.printStackTrace();
    371             return;
    372         } catch (InvocationTargetException ite) {
    373             ite.printStackTrace();
    374             return;
    375         }
    376 
    377         try {
    378             System.out.println("checkType invoking null");
    379             m.invoke(null, new Object(), int.class);
    380             System.out.println("ERROR: should throw InvocationTargetException");
    381         } catch (InvocationTargetException ite) {
    382             System.out.println("checkType got expected exception");
    383         } catch (IllegalAccessException iae) {
    384             iae.printStackTrace();
    385             return;
    386         }
    387     }
    388 
    389     public static void checkInit() {
    390         Class niuClass = NoisyInitUser.class;
    391         Method[] methods;
    392 
    393         methods = niuClass.getDeclaredMethods();
    394         System.out.println("got methods");
    395         /* neither NoisyInit nor NoisyInitUser should be initialized yet */
    396         NoisyInitUser niu = new NoisyInitUser();
    397         NoisyInit ni = new NoisyInit();
    398 
    399         System.out.println("");
    400     }
    401 
    402 
    403     /*
    404      * Test some generic type stuff.
    405      */
    406     public List<String> dummy;
    407     public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; }
    408     public static void checkGeneric() {
    409         Field field;
    410         try {
    411             field = Main.class.getField("dummy");
    412         } catch (NoSuchFieldException nsfe) {
    413             throw new RuntimeException(nsfe);
    414         }
    415         Type listType = field.getGenericType();
    416         System.out.println("generic field: " + listType);
    417 
    418         Method method;
    419         try {
    420             method = Main.class.getMethod("fancyMethod",
    421                 new Class[] { ArrayList.class });
    422         } catch (NoSuchMethodException nsme) {
    423             throw new RuntimeException(nsme);
    424         }
    425         Type[] parmTypes = method.getGenericParameterTypes();
    426         Type ret = method.getGenericReturnType();
    427         System.out.println("generic method " + method.getName() + " params='"
    428             + stringifyTypeArray(parmTypes) + "' ret='" + ret + "'");
    429 
    430         Constructor ctor;
    431         try {
    432             ctor = Main.class.getConstructor(new Class[] { ArrayList.class });
    433         } catch (NoSuchMethodException nsme) {
    434             throw new RuntimeException(nsme);
    435         }
    436         parmTypes = ctor.getGenericParameterTypes();
    437         System.out.println("generic ctor " + ctor.getName() + " params='"
    438             + stringifyTypeArray(parmTypes) + "'");
    439     }
    440 
    441     /*
    442      * Convert an array of Type into a string.  Start with an array count.
    443      */
    444     private static String stringifyTypeArray(Type[] types) {
    445         StringBuilder stb = new StringBuilder();
    446         boolean first = true;
    447 
    448         stb.append("[" + types.length + "]");
    449 
    450         for (Type t: types) {
    451             if (first) {
    452                 stb.append(" ");
    453                 first = false;
    454             } else {
    455                 stb.append(", ");
    456             }
    457             stb.append(t.toString());
    458         }
    459 
    460         return stb.toString();
    461     }
    462 
    463 
    464     public static void main(String[] args) {
    465         Main test = new Main();
    466         test.run();
    467 
    468         checkAccess();
    469         checkType();
    470         checkInit();
    471         checkGeneric();
    472     }
    473 }
    474 
    475 
    476 class SuperTarget {
    477     public SuperTarget() {
    478         System.out.println("SuperTarget constructor ()V");
    479         superInt = 1010101;
    480         superClassInt = 1010102;
    481     }
    482 
    483     public int myMethod(float floatArg) {
    484         System.out.println("myMethod (F)I " + floatArg);
    485         return 6;
    486     }
    487 
    488     public int superInt;
    489     public static int superClassInt;
    490 }
    491 
    492 class Target extends SuperTarget {
    493     public Target() {
    494         System.out.println("Target constructor ()V");
    495     }
    496 
    497     public Target(int ii, float ff) {
    498         System.out.println("Target constructor (IF)V : ii="
    499             + ii + " ff=" + ff);
    500         anInt = ii;
    501     }
    502 
    503     public int myMethod(int intarg) throws NullPointerException, IOException {
    504         System.out.println("myMethod (I)I");
    505         System.out.println(" arg=" + intarg + " anInt=" + anInt);
    506         return 5;
    507     }
    508 
    509     public int myMethod(String[] strarg, float f, char c) {
    510         System.out.println("myMethod: " + strarg[0] + " " + f + " " + c + " !");
    511         return 7;
    512     }
    513 
    514     public static void myNoargMethod() {
    515         System.out.println("myNoargMethod ()V");
    516     }
    517 
    518     public void throwingMethod() {
    519         System.out.println("throwingMethod");
    520         throw new NullPointerException("gratuitous throw!");
    521     }
    522 
    523     public void misc() {
    524         System.out.println("misc");
    525     }
    526 
    527     public int anInt;
    528     public String string1 = "hey";
    529     public String string2 = "yo";
    530     public String string3 = "there";
    531     private String string4 = "naughty";
    532     public static final String constantString = "a constant string";
    533     private int aPrivateInt;
    534 
    535     public final int cantTouchThis = 77;
    536 
    537     public long pubLong = 0x1122334455667788L;
    538 
    539     public static double staticDouble = 3.3;
    540 }
    541 
    542 class NoisyInit {
    543     static {
    544         System.out.println("NoisyInit is initializing");
    545         //Throwable th = new Throwable();
    546         //th.printStackTrace();
    547     }
    548 }
    549 
    550 class NoisyInitUser {
    551     static {
    552         System.out.println("NoisyInitUser is initializing");
    553     }
    554     public void createNoisyInit(NoisyInit ni) {}
    555 }
    556