blob: c068d2369c7f7e10661f3e7cab4e074f5261f818 [file] [log] [blame]
jeffhao5d1ac922011-09-29 17:41:15 -07001/*
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
17import other.OtherPackage;
18
19import java.lang.reflect.Field;
20
21/*
22 * Test field access through reflection.
23 */
24public class Main {
25 public static void main(String[] args) {
26 SubOther.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
54 Object result = null;
55 try {
56 switch (type) {
57 case 'Z':
58 result = new Boolean(field.getBoolean(obj));
59 break;
60 case 'B':
61 result = new Byte(field.getByte(obj));
62 break;
63 case 'S':
64 result = new Short(field.getShort(obj));
65 break;
66 case 'C':
67 result = new Character(field.getChar(obj));
68 break;
69 case 'I':
70 result = new Integer(field.getInt(obj));
71 break;
72 case 'J':
73 result = new Long(field.getLong(obj));
74 break;
75 case 'F':
76 result = new Float(field.getFloat(obj));
77 break;
78 case 'D':
79 result = new Double(field.getDouble(obj));
80 break;
81 case 'L':
82 result = field.get(obj);
83 break;
84 default:
85 throw new RuntimeException("bad type '" + type + "'");
86 }
87
88 /* success; expected? */
89 if (expectedException != null) {
90 Throwable th = new Throwable();
91 System.err.println("ERROR: call succeeded, was expecting "
92 + expectedException);
93 th.printStackTrace();
94 }
95 } catch (Exception ex) {
96 if (expectedException == null) {
97 System.err.println("ERROR: call failed unexpectedly: "
98 + ex.getClass());
99 ex.printStackTrace();
100 } else {
101 if (!expectedException.equals(ex.getClass())) {
102 System.err.println("ERROR: incorrect exception: wanted "
103 + expectedException.getName() + ", got "
104 + ex.getClass());
105 ex.printStackTrace();
106 }
107 }
108 }
109
110 return result;
111 }
112}
113
114/*
115 * Local class with some fields.
116 */
117class SamePackage {
118 public byte pubByteField;
119
120 protected byte protByteField;
121 protected Object protObjectField;
122
123 private float privFloatField;
124}
125
126/*
127 * This is a sub-class of OtherPackage, which should be allowed to access
128 * the various protected fields.
129 */
130class SubOther extends OtherPackage {
131
132 protected long protLongField = 0x1122334455667788L;
133
134 /*
135 * Perform the various tests.
136 *
137 * localInst.getValue() is performed using an instance of Main as the
138 * source of the reflection call. otherInst.getValue() uses a subclass
139 * of OtherPackage as the source.
140 */
141 public static void main(String[] args) {
142 SubOther subOther = new SubOther();
143 subOther.doTests();
144 }
145
146 public void doTests() {
147 Class localClass = SamePackage.class;
148 Class otherClass = OtherPackage.class;
149 Field localPubByteField, localProtByteField, localProtObjectField,
150 localPrivFloatField;
151 Field otherPubCharField, otherProtShortField, otherProtObjectField,
152 otherPkgDoubleField;
153 Field subProtLongField;
154 Main localInst = new Main();
155 SamePackage samePkgInst = new SamePackage();
156 OtherPackage otherPkgInst = new OtherPackage();
157 Object plainObj = new Object();
158
159 /*
160 * Locate the various fields.
161 */
162 try {
163 localPubByteField = localClass.getDeclaredField("pubByteField");
164 localProtByteField = localClass.getDeclaredField("protByteField");
165 localProtObjectField = localClass.getDeclaredField("protObjectField");
166 localPrivFloatField = localClass.getDeclaredField("privFloatField");
167
168 otherPubCharField = otherClass.getDeclaredField("pubCharField");
169 otherProtShortField = otherClass.getDeclaredField("protShortField");
170 otherProtObjectField = otherClass.getDeclaredField("protObjectField");
171 otherPkgDoubleField = otherClass.getDeclaredField("pkgDoubleField");
172
173 subProtLongField = getClass().getDeclaredField("protLongField");
174 } catch (NoSuchFieldException nsfe) {
175 throw new RuntimeException(nsfe);
176 }
177
178 /*
179 * Get a public field from a class in the same package.
180 */
181 localInst.getValue(localPubByteField, samePkgInst, 'B', null);
182
183 /*
184 * Get a protected field from a class in the same package.
185 */
186 this.getValue(localProtByteField, samePkgInst, 'B', null);
187
188 /*
189 * Get a private field from a class in the same package.
190 */
191 this.getValue(localPrivFloatField, samePkgInst, 'F',
192 IllegalAccessException.class);
193
194 /*
195 * Get a protected field from otherInst's superclass.
196 *
197 * We can get at "this.protShortField" but not
198 * "otherPkgInst.protShortField" because we can only access
199 * protected fields in instances of our class -- being a subclass
200 * of OtherPackage does not allow us to modify protected fields in
201 * all other subclasses of OtherPackage.
202 */
203 this.getValue(otherProtShortField, this, 'S',
204 null);
205 this.getValue(otherProtShortField, otherPkgInst, 'S',
206 IllegalAccessException.class);
207 this.getValue(otherPkgDoubleField, otherPkgInst, 'D',
208 IllegalAccessException.class);
209
210 /*
211 * Null object. Different exceptions based on which package
212 * we would be trying to access and whether or not our object
213 * has the correct type.
214 */
215 localInst.getValue(localPubByteField, null, 'B',
216 NullPointerException.class);
217
218 this.getValue(subProtLongField, null, 'J',
219 NullPointerException.class);
220
221 this.getValue(localPrivFloatField, null, 'F',
222 IllegalAccessException.class);
223
224 localInst.getValue(otherProtShortField, null, 'S',
225 IllegalAccessException.class);
226 this.getValue(otherProtShortField, null, 'S',
227 IllegalAccessException.class);
228 this.getValue(otherPkgDoubleField, null, 'D',
229 IllegalAccessException.class);
230
231 localInst.getValue(otherProtShortField, null, 'Z',
232 IllegalAccessException.class);
233 /* -- Dalvik VM currently throws NPE
234 this.getValue(subProtLongField, null, 'Z',
235 IllegalArgumentException.class);
236 */
237
238 /*
239 * Valid object, wrong field type.
240 */
241 this.getValue(subProtLongField, this, 'J',
242 null);
243 this.getValue(localProtByteField, samePkgInst, 'Z',
244 IllegalArgumentException.class);
245 this.getValue(subProtLongField, this, 'Z',
246 IllegalArgumentException.class);
247 this.getValue(localPrivFloatField, this, 'Z',
248 IllegalAccessException.class);
249 this.getValue(localPrivFloatField, this, 'Z',
250 IllegalAccessException.class);
251 localInst.getValue(otherProtShortField, otherPkgInst, 'Z',
252 IllegalAccessException.class);
253 this.getValue(otherProtShortField, otherPkgInst, 'Z',
254 IllegalAccessException.class);
255
256 /*
257 * Wrong object.
258 */
259 this.getValue(subProtLongField, plainObj, 'J',
260 IllegalArgumentException.class);
261
262 /* wrong object + private field */
263 this.getValue(localPrivFloatField, plainObj, 'F',
264 IllegalAccessException.class);
265
266 /* wrong object + wrong field type */
267 this.getValue(subProtLongField, plainObj, 'Z',
268 IllegalArgumentException.class);
269
270 /* wrong object + invalid access */
271 localInst.getValue(otherProtShortField, plainObj, 'S',
272 IllegalAccessException.class);
273 this.getValue(otherProtShortField, plainObj, 'S',
274 IllegalAccessException.class);
275
276 System.out.println("good");
277 }
278
279 /*
280 * [this is a clone of Main.getValue() -- the class issuing the
281 * reflection call is significant]
282 */
283 public Object getValue(Field field, Object obj, char type,
284 Class expectedException) {
285
286 Object result = null;
287 try {
288 switch (type) {
289 case 'Z':
290 result = new Boolean(field.getBoolean(obj));
291 break;
292 case 'B':
293 result = new Byte(field.getByte(obj));
294 break;
295 case 'S':
296 result = new Short(field.getShort(obj));
297 break;
298 case 'C':
299 result = new Character(field.getChar(obj));
300 break;
301 case 'I':
302 result = new Integer(field.getInt(obj));
303 break;
304 case 'J':
305 result = new Long(field.getLong(obj));
306 break;
307 case 'F':
308 result = new Float(field.getFloat(obj));
309 break;
310 case 'D':
311 result = new Double(field.getDouble(obj));
312 break;
313 case 'L':
314 result = field.get(obj);
315 break;
316 default:
317 throw new RuntimeException("bad type '" + type + "'");
318 }
319
320 /* success; expected? */
321 if (expectedException != null) {
322 Throwable th = new Throwable();
323 System.err.println("ERROR: call succeeded, was expecting "
324 + expectedException);
325 th.printStackTrace();
326 }
327 } catch (Exception ex) {
328 if (expectedException == null) {
329 System.err.println("ERROR: call failed unexpectedly: "
330 + ex.getClass());
331 ex.printStackTrace();
332 } else {
333 if (!expectedException.equals(ex.getClass())) {
334 System.err.println("ERROR: incorrect exception: wanted "
335 + expectedException.getName() + ", got "
336 + ex.getClass());
337 ex.printStackTrace();
338 }
339 }
340 }
341
342 return result;
343 }
344
345}