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