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