Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import other.PublicClass;
     18 import java.lang.reflect.Field;
     19 import java.lang.reflect.Method;
     20 
     21 /*
     22  * Test field access through reflection.
     23  */
     24 public class Main {
     25   public static void main(String[] args) {
     26     SubClass.main(null);
     27 
     28     try {
     29       GetNonexistent.main(null);
     30       System.err.println("Not expected to succeed");
     31     } catch (VerifyError fe) {
     32       // dalvik
     33       System.out.println("Got expected failure");
     34     } catch (NoSuchFieldError nsfe) {
     35       // reference
     36       System.out.println("Got expected failure");
     37     }
     38   }
     39 
     40   /*
     41    * Get the field specified by "field" from "obj".
     42    *
     43    * "type" determines which "get" call is made, e.g. 'B' turns into
     44    * field.getByte().
     45    *
     46    * The "expectedException" must match the class of the exception thrown,
     47    * or be null if no exception was expected.
     48    *
     49    * On success, the boxed value retrieved is returned.
     50    */
     51   public Object getValue(Field field, Object obj, char type,
     52       Class expectedException) {
     53     Object result = null;
     54     try {
     55       switch (type) {
     56         case 'Z':
     57           result = field.getBoolean(obj);
     58           break;
     59         case 'B':
     60           result = field.getByte(obj);
     61           break;
     62         case 'S':
     63           result = field.getShort(obj);
     64           break;
     65         case 'C':
     66           result = field.getChar(obj);
     67           break;
     68         case 'I':
     69           result = field.getInt(obj);
     70           break;
     71         case 'J':
     72           result = field.getLong(obj);
     73           break;
     74         case 'F':
     75           result = field.getFloat(obj);
     76           break;
     77         case 'D':
     78           result = field.getDouble(obj);
     79           break;
     80         case 'L':
     81           result = field.get(obj);
     82           break;
     83         default:
     84           throw new RuntimeException("bad type '" + type + "'");
     85       }
     86 
     87       /* success; expected? */
     88       if (expectedException != null) {
     89         System.err.println("ERROR: call succeeded for field " + field +
     90             " with a read of type '" + type +
     91             "', was expecting " + expectedException);
     92         Thread.dumpStack();
     93       }
     94     } catch (Exception ex) {
     95       if (expectedException == null) {
     96         System.err.println("ERROR: call failed unexpectedly: "
     97             + ex.getClass());
     98         ex.printStackTrace();
     99       } else {
    100         if (!expectedException.equals(ex.getClass())) {
    101           System.err.println("ERROR: incorrect exception: wanted "
    102               + expectedException.getName() + ", got "
    103               + ex.getClass());
    104           ex.printStackTrace();
    105         }
    106       }
    107     }
    108 
    109     return result;
    110   }
    111 }
    112 
    113 /*
    114  * Local class with some fields.
    115  */
    116 class SamePackage {
    117   public boolean samePackagePublicBooleanInstanceField = true;
    118   public byte samePackagePublicByteInstanceField = 2;
    119   public char samePackagePublicCharInstanceField = 3;
    120   public short samePackagePublicShortInstanceField = 4;
    121   public int samePackagePublicIntInstanceField = 5;
    122   public long samePackagePublicLongInstanceField = 6;
    123   public float samePackagePublicFloatInstanceField = 7.0f;
    124   public double samePackagePublicDoubleInstanceField = 8.0;
    125   public Object samePackagePublicObjectInstanceField = "9";
    126 
    127   protected boolean samePackageProtectedBooleanInstanceField = true;
    128   protected byte samePackageProtectedByteInstanceField = 10;
    129   protected char samePackageProtectedCharInstanceField = 11;
    130   protected short samePackageProtectedShortInstanceField = 12;
    131   protected int samePackageProtectedIntInstanceField = 13;
    132   protected long samePackageProtectedLongInstanceField = 14;
    133   protected float samePackageProtectedFloatInstanceField = 15.0f;
    134   protected double samePackageProtectedDoubleInstanceField = 16.0;
    135   protected Object samePackageProtectedObjectInstanceField = "17";
    136 
    137   private boolean samePackagePrivateBooleanInstanceField = true;
    138   private byte samePackagePrivateByteInstanceField = 18;
    139   private char samePackagePrivateCharInstanceField = 19;
    140   private short samePackagePrivateShortInstanceField = 20;
    141   private int samePackagePrivateIntInstanceField = 21;
    142   private long samePackagePrivateLongInstanceField = 22;
    143   private float samePackagePrivateFloatInstanceField = 23.0f;
    144   private double samePackagePrivateDoubleInstanceField = 24.0;
    145   private Object samePackagePrivateObjectInstanceField = "25";
    146 
    147   /* package */ boolean samePackagePackageBooleanInstanceField = true;
    148   /* package */ byte samePackagePackageByteInstanceField = 26;
    149   /* package */ char samePackagePackageCharInstanceField = 27;
    150   /* package */ short samePackagePackageShortInstanceField = 28;
    151   /* package */ int samePackagePackageIntInstanceField = 29;
    152   /* package */ long samePackagePackageLongInstanceField = 30;
    153   /* package */ float samePackagePackageFloatInstanceField = 31.0f;
    154   /* package */ double samePackagePackageDoubleInstanceField = 32.0;
    155   /* package */ Object samePackagePackageObjectInstanceField = "33";
    156 
    157   public static boolean samePackagePublicBooleanStaticField = true;
    158   public static byte samePackagePublicByteStaticField = 34;
    159   public static char samePackagePublicCharStaticField = 35;
    160   public static short samePackagePublicShortStaticField = 36;
    161   public static int samePackagePublicIntStaticField = 37;
    162   public static long samePackagePublicLongStaticField = 38;
    163   public static float samePackagePublicFloatStaticField = 39.0f;
    164   public static double samePackagePublicDoubleStaticField = 40.0;
    165   public static Object samePackagePublicObjectStaticField = "41";
    166 
    167   protected static boolean samePackageProtectedBooleanStaticField = true;
    168   protected static byte samePackageProtectedByteStaticField = 42;
    169   protected static char samePackageProtectedCharStaticField = 43;
    170   protected static short samePackageProtectedShortStaticField = 44;
    171   protected static int samePackageProtectedIntStaticField = 45;
    172   protected static long samePackageProtectedLongStaticField = 46;
    173   protected static float samePackageProtectedFloatStaticField = 47.0f;
    174   protected static double samePackageProtectedDoubleStaticField = 48.0;
    175   protected static Object samePackageProtectedObjectStaticField = "49";
    176 
    177   private static boolean samePackagePrivateBooleanStaticField = true;
    178   private static byte samePackagePrivateByteStaticField = 50;
    179   private static char samePackagePrivateCharStaticField = 51;
    180   private static short samePackagePrivateShortStaticField = 52;
    181   private static int samePackagePrivateIntStaticField = 53;
    182   private static long samePackagePrivateLongStaticField = 54;
    183   private static float samePackagePrivateFloatStaticField = 55.0f;
    184   private static double samePackagePrivateDoubleStaticField = 56.0;
    185   private static Object samePackagePrivateObjectStaticField = "57";
    186 
    187   /* package */ static boolean samePackagePackageBooleanStaticField = true;
    188   /* package */ static byte samePackagePackageByteStaticField = 58;
    189   /* package */ static char samePackagePackageCharStaticField = 59;
    190   /* package */ static short samePackagePackageShortStaticField = 60;
    191   /* package */ static int samePackagePackageIntStaticField = 61;
    192   /* package */ static long samePackagePackageLongStaticField = 62;
    193   /* package */ static float samePackagePackageFloatStaticField = 63.0f;
    194   /* package */ static double samePackagePackageDoubleStaticField = 64.0;
    195   /* package */ static Object samePackagePackageObjectStaticField = "65";
    196 
    197   public void samePublicMethod() { }
    198   protected void sameProtectedMethod() { }
    199   private void samePrivateMethod() { }
    200   /* package */ void samePackageMethod() { }
    201 }
    202 
    203 /*
    204  * This is a sub-class of other.PublicClass, which should be allowed to access
    205  * the various protected fields declared by other.PublicClass and its parent
    206  * other.ProtectedClass.
    207  */
    208 class SubClass extends PublicClass {
    209   /*
    210    * Perform the various tests.
    211    *
    212    * localInst.getValue() is performed using an instance of Main as the
    213    * source of the reflection call.  otherInst.getValue() uses a subclass
    214    * of OtherPackage as the source.
    215    */
    216   public static void main(String[] args) {
    217     SubClass subOther = new SubClass();
    218     subOther.doDirectTests();
    219     subOther.doReflectionTests();
    220   }
    221 
    222   private static void check(boolean b) {
    223     if (!b) {
    224       throw new Error("Test failed");
    225     }
    226   }
    227 
    228   public void doDirectTests() {
    229     check(otherProtectedClassPublicBooleanInstanceField == true);
    230     check(otherProtectedClassPublicByteInstanceField == 2);
    231     check(otherProtectedClassPublicCharInstanceField == 3);
    232     check(otherProtectedClassPublicShortInstanceField == 4);
    233     check(otherProtectedClassPublicIntInstanceField == 5);
    234     check(otherProtectedClassPublicLongInstanceField == 6);
    235     check(otherProtectedClassPublicFloatInstanceField == 7.0f);
    236     check(otherProtectedClassPublicDoubleInstanceField == 8.0);
    237     check(otherProtectedClassPublicObjectInstanceField == "9");
    238 
    239     check(otherProtectedClassProtectedBooleanInstanceField == true);
    240     check(otherProtectedClassProtectedByteInstanceField == 10);
    241     check(otherProtectedClassProtectedCharInstanceField == 11);
    242     check(otherProtectedClassProtectedShortInstanceField == 12);
    243     check(otherProtectedClassProtectedIntInstanceField == 13);
    244     check(otherProtectedClassProtectedLongInstanceField == 14);
    245     check(otherProtectedClassProtectedFloatInstanceField == 15.0f);
    246     check(otherProtectedClassProtectedDoubleInstanceField == 16.0);
    247     check(otherProtectedClassProtectedObjectInstanceField == "17");
    248 
    249     // check(otherProtectedClassPrivateBooleanInstanceField == true);
    250     // check(otherProtectedClassPrivateByteInstanceField == 18);
    251     // check(otherProtectedClassPrivateCharInstanceField == 19);
    252     // check(otherProtectedClassPrivateShortInstanceField == 20);
    253     // check(otherProtectedClassPrivateIntInstanceField == 21);
    254     // check(otherProtectedClassPrivateLongInstanceField == 22);
    255     // check(otherProtectedClassPrivateFloatInstanceField == 23.0f);
    256     // check(otherProtectedClassPrivateDoubleInstanceField == 24.0);
    257     // check(otherProtectedClassPrivateObjectInstanceField == "25");
    258 
    259     // check(otherProtectedClassPackageBooleanInstanceField == true);
    260     // check(otherProtectedClassPackageByteInstanceField == 26);
    261     // check(otherProtectedClassPackageCharInstanceField == 27);
    262     // check(otherProtectedClassPackageShortInstanceField == 28);
    263     // check(otherProtectedClassPackageIntInstanceField == 29);
    264     // check(otherProtectedClassPackageLongInstanceField == 30);
    265     // check(otherProtectedClassPackageFloatInstanceField == 31.0f);
    266     // check(otherProtectedClassPackageDoubleInstanceField == 32.0);
    267     // check(otherProtectedClassPackageObjectInstanceField == "33");
    268 
    269     check(otherProtectedClassPublicBooleanStaticField == true);
    270     check(otherProtectedClassPublicByteStaticField == 34);
    271     check(otherProtectedClassPublicCharStaticField == 35);
    272     check(otherProtectedClassPublicShortStaticField == 36);
    273     check(otherProtectedClassPublicIntStaticField == 37);
    274     check(otherProtectedClassPublicLongStaticField == 38);
    275     check(otherProtectedClassPublicFloatStaticField == 39.0f);
    276     check(otherProtectedClassPublicDoubleStaticField == 40.0);
    277     check(otherProtectedClassPublicObjectStaticField == "41");
    278 
    279     check(otherProtectedClassProtectedBooleanStaticField == true);
    280     check(otherProtectedClassProtectedByteStaticField == 42);
    281     check(otherProtectedClassProtectedCharStaticField == 43);
    282     check(otherProtectedClassProtectedShortStaticField == 44);
    283     check(otherProtectedClassProtectedIntStaticField == 45);
    284     check(otherProtectedClassProtectedLongStaticField == 46);
    285     check(otherProtectedClassProtectedFloatStaticField == 47.0f);
    286     check(otherProtectedClassProtectedDoubleStaticField == 48.0);
    287     check(otherProtectedClassProtectedObjectStaticField == "49");
    288 
    289     // check(otherProtectedClassPrivateBooleanStaticField == true);
    290     // check(otherProtectedClassPrivateByteStaticField == 50);
    291     // check(otherProtectedClassPrivateCharStaticField == 51);
    292     // check(otherProtectedClassPrivateShortStaticField == 52);
    293     // check(otherProtectedClassPrivateIntStaticField == 53);
    294     // check(otherProtectedClassPrivateLongStaticField == 54);
    295     // check(otherProtectedClassPrivateFloatStaticField == 55.0f);
    296     // check(otherProtectedClassPrivateDoubleStaticField == 56.0);
    297     // check(otherProtectedClassPrivateObjectStaticField == "57");
    298 
    299     // check(otherProtectedClassPackageBooleanStaticField == true);
    300     // check(otherProtectedClassPackageByteStaticField == 58);
    301     // check(otherProtectedClassPackageCharStaticField == 59);
    302     // check(otherProtectedClassPackageShortStaticField == 60);
    303     // check(otherProtectedClassPackageIntStaticField == 61);
    304     // check(otherProtectedClassPackageLongStaticField == 62);
    305     // check(otherProtectedClassPackageFloatStaticField == 63.0f);
    306     // check(otherProtectedClassPackageDoubleStaticField == 64.0);
    307     // check(otherProtectedClassPackageObjectStaticField == "65");
    308 
    309     check(otherPublicClassPublicBooleanInstanceField == true);
    310     check(otherPublicClassPublicByteInstanceField == -2);
    311     check(otherPublicClassPublicCharInstanceField == (char)-3);
    312     check(otherPublicClassPublicShortInstanceField == -4);
    313     check(otherPublicClassPublicIntInstanceField == -5);
    314     check(otherPublicClassPublicLongInstanceField == -6);
    315     check(otherPublicClassPublicFloatInstanceField == -7.0f);
    316     check(otherPublicClassPublicDoubleInstanceField == -8.0);
    317     check(otherPublicClassPublicObjectInstanceField == "-9");
    318 
    319     check(otherPublicClassProtectedBooleanInstanceField == true);
    320     check(otherPublicClassProtectedByteInstanceField == -10);
    321     check(otherPublicClassProtectedCharInstanceField == (char)-11);
    322     check(otherPublicClassProtectedShortInstanceField == -12);
    323     check(otherPublicClassProtectedIntInstanceField == -13);
    324     check(otherPublicClassProtectedLongInstanceField == -14);
    325     check(otherPublicClassProtectedFloatInstanceField == -15.0f);
    326     check(otherPublicClassProtectedDoubleInstanceField == -16.0);
    327     check(otherPublicClassProtectedObjectInstanceField == "-17");
    328 
    329     // check(otherPublicClassPrivateBooleanInstanceField == true);
    330     // check(otherPublicClassPrivateByteInstanceField == -18);
    331     // check(otherPublicClassPrivateCharInstanceField == (char)-19);
    332     // check(otherPublicClassPrivateShortInstanceField == -20);
    333     // check(otherPublicClassPrivateIntInstanceField == -21);
    334     // check(otherPublicClassPrivateLongInstanceField == -22);
    335     // check(otherPublicClassPrivateFloatInstanceField == -23.0f);
    336     // check(otherPublicClassPrivateDoubleInstanceField == -24.0);
    337     // check(otherPublicClassPrivateObjectInstanceField == "-25");
    338 
    339     // check(otherPublicClassPackageBooleanInstanceField == true);
    340     // check(otherPublicClassPackageByteInstanceField == -26);
    341     // check(otherPublicClassPackageCharInstanceField == (char)-27);
    342     // check(otherPublicClassPackageShortInstanceField == -28);
    343     // check(otherPublicClassPackageIntInstanceField == -29);
    344     // check(otherPublicClassPackageLongInstanceField == -30);
    345     // check(otherPublicClassPackageFloatInstanceField == -31.0f);
    346     // check(otherPublicClassPackageDoubleInstanceField == -32.0);
    347     // check(otherPublicClassPackageObjectInstanceField == "-33");
    348 
    349     check(otherPublicClassPublicBooleanStaticField == true);
    350     check(otherPublicClassPublicByteStaticField == -34);
    351     check(otherPublicClassPublicCharStaticField == (char)-35);
    352     check(otherPublicClassPublicShortStaticField == -36);
    353     check(otherPublicClassPublicIntStaticField == -37);
    354     check(otherPublicClassPublicLongStaticField == -38);
    355     check(otherPublicClassPublicFloatStaticField == -39.0f);
    356     check(otherPublicClassPublicDoubleStaticField == -40.0);
    357     check(otherPublicClassPublicObjectStaticField == "-41");
    358 
    359     check(otherPublicClassProtectedBooleanStaticField == true);
    360     check(otherPublicClassProtectedByteStaticField == -42);
    361     check(otherPublicClassProtectedCharStaticField == (char)-43);
    362     check(otherPublicClassProtectedShortStaticField == -44);
    363     check(otherPublicClassProtectedIntStaticField == -45);
    364     check(otherPublicClassProtectedLongStaticField == -46);
    365     check(otherPublicClassProtectedFloatStaticField == -47.0f);
    366     check(otherPublicClassProtectedDoubleStaticField == -48.0);
    367     check(otherPublicClassProtectedObjectStaticField == "-49");
    368 
    369     // check(otherPublicClassPrivateBooleanStaticField == true);
    370     // check(otherPublicClassPrivateByteStaticField == -50);
    371     // check(otherPublicClassPrivateCharStaticField == (char)-51);
    372     // check(otherPublicClassPrivateShortStaticField == -52);
    373     // check(otherPublicClassPrivateIntStaticField == -53);
    374     // check(otherPublicClassPrivateLongStaticField == -54);
    375     // check(otherPublicClassPrivateFloatStaticField == -55.0f);
    376     // check(otherPublicClassPrivateDoubleStaticField == -56.0);
    377     // check(otherPublicClassPrivateObjectStaticField == "-57");
    378 
    379     // check(otherPublicClassPackageBooleanStaticField == true);
    380     // check(otherPublicClassPackageByteStaticField == -58);
    381     // check(otherPublicClassPackageCharStaticField == (char)-59);
    382     // check(otherPublicClassPackageShortStaticField == -60);
    383     // check(otherPublicClassPackageIntStaticField == -61);
    384     // check(otherPublicClassPackageLongStaticField == -62);
    385     // check(otherPublicClassPackageFloatStaticField == -63.0f);
    386     // check(otherPublicClassPackageDoubleStaticField == -64.0);
    387     // check(otherPublicClassPackageObjectStaticField == "-65");
    388 
    389     SamePackage s = new SamePackage();
    390     check(s.samePackagePublicBooleanInstanceField == true);
    391     check(s.samePackagePublicByteInstanceField == 2);
    392     check(s.samePackagePublicCharInstanceField == 3);
    393     check(s.samePackagePublicShortInstanceField == 4);
    394     check(s.samePackagePublicIntInstanceField == 5);
    395     check(s.samePackagePublicLongInstanceField == 6);
    396     check(s.samePackagePublicFloatInstanceField == 7.0f);
    397     check(s.samePackagePublicDoubleInstanceField == 8.0);
    398     check(s.samePackagePublicObjectInstanceField == "9");
    399 
    400     check(s.samePackageProtectedBooleanInstanceField == true);
    401     check(s.samePackageProtectedByteInstanceField == 10);
    402     check(s.samePackageProtectedCharInstanceField == 11);
    403     check(s.samePackageProtectedShortInstanceField == 12);
    404     check(s.samePackageProtectedIntInstanceField == 13);
    405     check(s.samePackageProtectedLongInstanceField == 14);
    406     check(s.samePackageProtectedFloatInstanceField == 15.0f);
    407     check(s.samePackageProtectedDoubleInstanceField == 16.0);
    408     check(s.samePackageProtectedObjectInstanceField == "17");
    409 
    410     // check(s.samePackagePrivateBooleanInstanceField == true);
    411     // check(s.samePackagePrivateByteInstanceField == 18);
    412     // check(s.samePackagePrivateCharInstanceField == 19);
    413     // check(s.samePackagePrivateShortInstanceField == 20);
    414     // check(s.samePackagePrivateIntInstanceField == 21);
    415     // check(s.samePackagePrivateLongInstanceField == 22);
    416     // check(s.samePackagePrivateFloatInstanceField == 23.0f);
    417     // check(s.samePackagePrivateDoubleInstanceField == 24.0);
    418     // check(s.samePackagePrivateObjectInstanceField == "25");
    419 
    420     check(s.samePackagePackageBooleanInstanceField == true);
    421     check(s.samePackagePackageByteInstanceField == 26);
    422     check(s.samePackagePackageCharInstanceField == 27);
    423     check(s.samePackagePackageShortInstanceField == 28);
    424     check(s.samePackagePackageIntInstanceField == 29);
    425     check(s.samePackagePackageLongInstanceField == 30);
    426     check(s.samePackagePackageFloatInstanceField == 31.0f);
    427     check(s.samePackagePackageDoubleInstanceField == 32.0);
    428     check(s.samePackagePackageObjectInstanceField == "33");
    429 
    430     check(SamePackage.samePackagePublicBooleanStaticField == true);
    431     check(SamePackage.samePackagePublicByteStaticField == 34);
    432     check(SamePackage.samePackagePublicCharStaticField == 35);
    433     check(SamePackage.samePackagePublicShortStaticField == 36);
    434     check(SamePackage.samePackagePublicIntStaticField == 37);
    435     check(SamePackage.samePackagePublicLongStaticField == 38);
    436     check(SamePackage.samePackagePublicFloatStaticField == 39.0f);
    437     check(SamePackage.samePackagePublicDoubleStaticField == 40.0);
    438     check(SamePackage.samePackagePublicObjectStaticField == "41");
    439 
    440     check(SamePackage.samePackageProtectedBooleanStaticField == true);
    441     check(SamePackage.samePackageProtectedByteStaticField == 42);
    442     check(SamePackage.samePackageProtectedCharStaticField == 43);
    443     check(SamePackage.samePackageProtectedShortStaticField == 44);
    444     check(SamePackage.samePackageProtectedIntStaticField == 45);
    445     check(SamePackage.samePackageProtectedLongStaticField == 46);
    446     check(SamePackage.samePackageProtectedFloatStaticField == 47.0f);
    447     check(SamePackage.samePackageProtectedDoubleStaticField == 48.0);
    448     check(SamePackage.samePackageProtectedObjectStaticField == "49");
    449 
    450     // check(SamePackage.samePackagePrivateBooleanStaticField == true);
    451     // check(SamePackage.samePackagePrivateByteStaticField == 50);
    452     // check(SamePackage.samePackagePrivateCharStaticField == 51);
    453     // check(SamePackage.samePackagePrivateShortStaticField == 52);
    454     // check(SamePackage.samePackagePrivateIntStaticField == 53);
    455     // check(SamePackage.samePackagePrivateLongStaticField == 54);
    456     // check(SamePackage.samePackagePrivateFloatStaticField == 55.0f);
    457     // check(SamePackage.samePackagePrivateDoubleStaticField == 56.0);
    458     // check(SamePackage.samePackagePrivateObjectStaticField == "57");
    459 
    460     check(SamePackage.samePackagePackageBooleanStaticField == true);
    461     check(SamePackage.samePackagePackageByteStaticField == 58);
    462     check(SamePackage.samePackagePackageCharStaticField == 59);
    463     check(SamePackage.samePackagePackageShortStaticField == 60);
    464     check(SamePackage.samePackagePackageIntStaticField == 61);
    465     check(SamePackage.samePackagePackageLongStaticField == 62);
    466     check(SamePackage.samePackagePackageFloatStaticField == 63.0f);
    467     check(SamePackage.samePackagePackageDoubleStaticField == 64.0);
    468     check(SamePackage.samePackagePackageObjectStaticField == "65");
    469   }
    470 
    471   private static boolean compatibleTypes(char srcType, char dstType) {
    472     switch (dstType) {
    473       case 'Z':
    474       case 'C':
    475       case 'B':
    476         return srcType == dstType;
    477       case 'S':
    478         return srcType == 'B' || srcType == 'S';
    479       case 'I':
    480         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I';
    481       case 'J':
    482         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
    483         srcType == 'J';
    484       case 'F':
    485         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
    486         srcType == 'J' || srcType == 'F';
    487       case 'D':
    488         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
    489         srcType == 'J' || srcType == 'F' || srcType == 'D';
    490       case 'L':
    491         return true;
    492       default:
    493         throw new Error("Unexpected type char " + dstType);
    494     }
    495   }
    496 
    497   public void doReflectionTests() {
    498     String typeChars = "ZBCSIJFDL";
    499     String fieldNameForTypeChar[] = {
    500         "Boolean",
    501         "Byte",
    502         "Char",
    503         "Short",
    504         "Int",
    505         "Long",
    506         "Float",
    507         "Double",
    508         "Object"
    509     };
    510 
    511     Main localInst = new Main();
    512     SamePackage samePkgInst = new SamePackage();
    513     PublicClass otherPkgInst = new PublicClass();
    514     Object plainObj = new Object();
    515 
    516     for (int round = 0; round < 3; round++) {
    517       Object validInst;
    518       Field[] fields;
    519       Method[] methods;
    520       boolean same_package = false;
    521       boolean protected_class = false;
    522       switch (round) {
    523         case 0:
    524           validInst = new SamePackage();
    525           fields = SamePackage.class.getDeclaredFields();
    526           check(fields.length == 72);
    527           methods = SamePackage.class.getDeclaredMethods();
    528           check(methods.length == 4);
    529           same_package = true;
    530           break;
    531         case 1:
    532           validInst = new PublicClass();
    533           fields = PublicClass.class.getDeclaredFields();
    534           check(fields.length == 72);
    535           methods = PublicClass.class.getDeclaredMethods();
    536           check(methods.length == 4);
    537           break;
    538         default:
    539           validInst = new PublicClass();
    540           fields = PublicClass.class.getSuperclass().getDeclaredFields();
    541           check(fields.length == 72);
    542           methods = PublicClass.class.getSuperclass().getDeclaredMethods();
    543           check(methods.length == 4);
    544           protected_class = true;
    545           break;
    546       }
    547       for (Field f : fields) {
    548         char typeChar = '?';
    549         for (int i = 0; i < fieldNameForTypeChar.length; i++) {
    550           if (f.getName().contains(fieldNameForTypeChar[i])) {
    551             typeChar = typeChars.charAt(i);
    552             break;
    553           }
    554         }
    555         // Check access or lack of to field.
    556         Class<?> subClassAccessExceptionClass = null;
    557         if ((f.getName().contains("Private") ||
    558             (!same_package && f.getName().contains("Package")) ||
    559             (!same_package && f.getName().contains("Protected"))) &&
    560             !(protected_class && f.getName().contains("Public"))) {
    561           subClassAccessExceptionClass = IllegalAccessException.class;
    562         }
    563         Class<?> mainClassAccessExceptionClass = null;
    564         if ((f.getName().contains("Private") ||
    565             (!same_package && f.getName().contains("Package")) ||
    566             (!same_package && f.getName().contains("Protected"))) &&
    567             !(protected_class && f.getName().contains("Public"))) {
    568           mainClassAccessExceptionClass = IllegalAccessException.class;
    569         }
    570 
    571         this.getValue(f, validInst, typeChar, subClassAccessExceptionClass);
    572         localInst.getValue(f, validInst, typeChar, mainClassAccessExceptionClass);
    573 
    574         // Check things that can get beyond the IllegalAccessException.
    575         if (subClassAccessExceptionClass == null) {
    576           // Check NPE.
    577           Class<?> npeClass = null;
    578           if (!f.getName().contains("Static")) {
    579             npeClass = NullPointerException.class;
    580           }
    581 
    582           this.getValue(f, null, typeChar, npeClass);
    583           if (mainClassAccessExceptionClass == null) {
    584             localInst.getValue(f, null, typeChar, npeClass);
    585           }
    586 
    587           // Check access of wrong field type for valid instance.
    588           for (int i = 0; i < typeChars.length(); i++) {
    589             char otherChar = typeChars.charAt(i);
    590             Class<?> illArgClass = compatibleTypes(typeChar, otherChar) ?
    591                 null : IllegalArgumentException.class;
    592             this.getValue(f, validInst, otherChar, illArgClass);
    593             if (mainClassAccessExceptionClass == null) {
    594               localInst.getValue(f, validInst, otherChar, illArgClass);
    595             }
    596           }
    597 
    598           if (!f.getName().contains("Static")) {
    599             // Wrong object.
    600             this.getValue(f, plainObj, typeChar, IllegalArgumentException.class);
    601             if (mainClassAccessExceptionClass == null) {
    602               localInst.getValue(f, plainObj, typeChar, IllegalArgumentException.class);
    603             }
    604           }
    605         }
    606       }
    607 
    608       for (Method m : methods) {
    609         Class<?> subClassAccessExceptionClass = null;
    610         if (m.getName().contains("Private") ||
    611             (!same_package && m.getName().contains("Package")) ||
    612             (!same_package && m.getName().contains("Protected"))) {
    613           subClassAccessExceptionClass = IllegalAccessException.class;
    614         }
    615         this.invoke(m, validInst, subClassAccessExceptionClass);
    616       }
    617     }
    618     System.out.println("good");
    619   }
    620 
    621   /*
    622    * [this is a clone of Main.getValue() -- the class issuing the
    623    * reflection call is significant]
    624    */
    625   public Object getValue(Field field, Object obj, char type,
    626       Class expectedException) {
    627     Object result = null;
    628     try {
    629       switch (type) {
    630         case 'Z':
    631           result = field.getBoolean(obj);
    632           break;
    633         case 'B':
    634           result = field.getByte(obj);
    635           break;
    636         case 'S':
    637           result = field.getShort(obj);
    638           break;
    639         case 'C':
    640           result = field.getChar(obj);
    641           break;
    642         case 'I':
    643           result = field.getInt(obj);
    644           break;
    645         case 'J':
    646           result = field.getLong(obj);
    647           break;
    648         case 'F':
    649           result = field.getFloat(obj);
    650           break;
    651         case 'D':
    652           result = field.getDouble(obj);
    653           break;
    654         case 'L':
    655           result = field.get(obj);
    656           break;
    657         default:
    658           throw new RuntimeException("bad type '" + type + "'");
    659       }
    660 
    661       /* success; expected? */
    662       if (expectedException != null) {
    663         System.err.println("ERROR: call succeeded for field " + field +
    664             " with a read of type '" + type +
    665             "', was expecting " + expectedException);
    666         Thread.dumpStack();
    667       }
    668     } catch (Exception ex) {
    669       if (expectedException == null) {
    670         System.err.println("ERROR: call failed unexpectedly: "
    671             + ex.getClass());
    672         ex.printStackTrace();
    673       } else {
    674         if (!expectedException.equals(ex.getClass())) {
    675           System.err.println("ERROR: incorrect exception: wanted "
    676               + expectedException.getName() + ", got "
    677               + ex.getClass());
    678           ex.printStackTrace();
    679         }
    680       }
    681     }
    682 
    683     return result;
    684   }
    685 
    686   public Object invoke(Method method, Object obj, Class expectedException) {
    687     Object result = null;
    688     try {
    689       result = method.invoke(obj);
    690       /* success; expected? */
    691       if (expectedException != null) {
    692         System.err.println("ERROR: call succeeded for method " + method + "', was expecting " +
    693                            expectedException);
    694         Thread.dumpStack();
    695       }
    696     } catch (Exception ex) {
    697       if (expectedException == null) {
    698         System.err.println("ERROR: call failed unexpectedly: " + ex.getClass());
    699         ex.printStackTrace();
    700       } else {
    701         if (!expectedException.equals(ex.getClass())) {
    702           System.err.println("ERROR: incorrect exception: wanted " + expectedException.getName() +
    703                              ", got " + ex.getClass());
    704           ex.printStackTrace();
    705         }
    706       }
    707     }
    708     return result;
    709   }
    710 }
    711