KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > persist > impl > ReflectionAccessor


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: ReflectionAccessor.java,v 1.18 2006/10/30 21:14:32 bostic Exp $
7  */

8
9 package com.sleepycat.persist.impl;
10
11 import java.lang.reflect.AccessibleObject JavaDoc;
12 import java.lang.reflect.Array JavaDoc;
13 import java.lang.reflect.Constructor JavaDoc;
14 import java.lang.reflect.Field JavaDoc;
15 import java.lang.reflect.InvocationTargetException JavaDoc;
16 import java.lang.reflect.Modifier JavaDoc;
17 import java.util.List JavaDoc;
18
19 /**
20  * Implements Accessor using reflection.
21  *
22  * @author Mark Hayes
23  */

24 class ReflectionAccessor implements Accessor {
25
26     private static final FieldAccess[] EMPTY_KEYS = {};
27
28     private Class JavaDoc type;
29     private Accessor superAccessor;
30     private Constructor JavaDoc constructor;
31     private FieldAccess priKey;
32     private FieldAccess[] secKeys;
33     private FieldAccess[] nonKeys;
34
35     private ReflectionAccessor(Class JavaDoc type, Accessor superAccessor) {
36         this.type = type;
37         this.superAccessor = superAccessor;
38         try {
39             constructor = type.getDeclaredConstructor();
40         } catch (NoSuchMethodException JavaDoc e) {
41             throw new IllegalStateException JavaDoc(type.getName());
42         }
43         if (!Modifier.isPublic(constructor.getModifiers())) {
44             setAccessible(constructor, type.getName() + "()");
45         }
46     }
47
48     ReflectionAccessor(Catalog catalog,
49                        Class JavaDoc type,
50                        Accessor superAccessor,
51                        FieldInfo priKeyField,
52                        List JavaDoc<FieldInfo> secKeyFields,
53                        List JavaDoc<FieldInfo> nonKeyFields) {
54         this(type, superAccessor);
55         if (priKeyField != null) {
56             priKey = getField(catalog, priKeyField, true, false);
57         } else {
58             priKey = null;
59         }
60         if (secKeyFields.size() > 0) {
61             secKeys = getFields(catalog, secKeyFields, false, false);
62         } else {
63             secKeys = EMPTY_KEYS;
64         }
65         if (nonKeyFields.size() > 0) {
66             nonKeys = getFields(catalog, nonKeyFields, false, false);
67         } else {
68             nonKeys = EMPTY_KEYS;
69         }
70     }
71
72     ReflectionAccessor(Catalog catalog,
73                        Class JavaDoc type,
74                        List JavaDoc<FieldInfo> fieldInfos) {
75         this(type, null);
76         priKey = null;
77         secKeys = EMPTY_KEYS;
78         nonKeys = getFields(catalog, fieldInfos, true, true);
79     }
80
81     private FieldAccess[] getFields(Catalog catalog,
82                                     List JavaDoc<FieldInfo> fieldInfos,
83                                     boolean isRequiredKeyField,
84                                     boolean isCompositeKey) {
85         int index = 0;
86         FieldAccess[] fields = new FieldAccess[fieldInfos.size()];
87         for (FieldInfo info : fieldInfos) {
88             fields[index] = getField
89                 (catalog, info, isRequiredKeyField, isCompositeKey);
90             index += 1;
91         }
92         return fields;
93     }
94
95     private FieldAccess getField(Catalog catalog,
96                                  FieldInfo fieldInfo,
97                                  boolean isRequiredKeyField,
98                                  boolean isCompositeKey) {
99         Field JavaDoc field;
100         try {
101             field = type.getDeclaredField(fieldInfo.getName());
102         } catch (NoSuchFieldException JavaDoc e) {
103             throw new IllegalStateException JavaDoc(e);
104         }
105         if (!Modifier.isPublic(field.getModifiers())) {
106             setAccessible(field, field.getName());
107         }
108         Class JavaDoc fieldCls = field.getType();
109         if (fieldCls.isPrimitive()) {
110             assert SimpleCatalog.isSimpleType(fieldCls);
111             return new PrimitiveAccess
112                 (field, SimpleCatalog.getSimpleFormat(fieldCls));
113         } else if (isRequiredKeyField) {
114             Format format = catalog.getFormat(fieldCls);
115             if (isCompositeKey && !SimpleCatalog.isSimpleType(fieldCls)) {
116                 throw new IllegalArgumentException JavaDoc
117                     ("Composite key class has non-simple type field: " +
118                      type.getName() + '.' + field.getName());
119             }
120             return new KeyObjectAccess(field, format);
121         } else {
122             return new ObjectAccess(field);
123         }
124     }
125
126     private void setAccessible(AccessibleObject JavaDoc object, String JavaDoc memberName) {
127         try {
128             object.setAccessible(true);
129         } catch (SecurityException JavaDoc e) {
130             throw new IllegalStateException JavaDoc
131                 ("Unable to access non-public member: " +
132                  type.getName() + '.' + memberName +
133                  ". Please configure the Java Security Manager setting: " +
134                  " ReflectPermission suppressAccessChecks", e);
135         }
136     }
137
138     public Object JavaDoc newInstance() {
139         try {
140             return constructor.newInstance();
141         } catch (IllegalAccessException JavaDoc e) {
142             throw new IllegalStateException JavaDoc(e);
143         } catch (InstantiationException JavaDoc e) {
144             throw new IllegalStateException JavaDoc(e);
145         } catch (InvocationTargetException JavaDoc e) {
146             throw new IllegalStateException JavaDoc(e);
147         }
148     }
149
150     public Object JavaDoc newArray(int len) {
151         return Array.newInstance(type, len);
152     }
153
154     public boolean isPriKeyFieldNullOrZero(Object JavaDoc o) {
155         try {
156             if (priKey != null) {
157                 return priKey.isNullOrZero(o);
158             } else if (superAccessor != null) {
159                 return superAccessor.isPriKeyFieldNullOrZero(o);
160             } else {
161                 throw new IllegalStateException JavaDoc("No primary key field");
162             }
163         } catch (IllegalAccessException JavaDoc e) {
164             throw new IllegalStateException JavaDoc(e);
165         }
166     }
167
168     public void writePriKeyField(Object JavaDoc o, EntityOutput output) {
169         try {
170             if (priKey != null) {
171                 priKey.write(o, output);
172             } else if (superAccessor != null) {
173                 superAccessor.writePriKeyField(o, output);
174             } else {
175                 throw new IllegalStateException JavaDoc("No primary key field");
176             }
177         } catch (IllegalAccessException JavaDoc e) {
178             throw new IllegalStateException JavaDoc(e);
179         }
180     }
181
182     public void readPriKeyField(Object JavaDoc o, EntityInput input) {
183         try {
184             if (priKey != null) {
185                 priKey.read(o, input);
186             } else if (superAccessor != null) {
187                 superAccessor.readPriKeyField(o, input);
188             } else {
189                 throw new IllegalStateException JavaDoc("No primary key field");
190             }
191         } catch (IllegalAccessException JavaDoc e) {
192             throw new IllegalStateException JavaDoc(e);
193         }
194     }
195
196     public void writeSecKeyFields(Object JavaDoc o, EntityOutput output) {
197         try {
198             if (priKey != null && !priKey.isPrimitive) {
199                 output.registerPriKeyObject(priKey.field.get(o));
200             }
201             if (superAccessor != null) {
202                 superAccessor.writeSecKeyFields(o, output);
203             }
204             for (int i = 0; i < secKeys.length; i += 1) {
205                 secKeys[i].write(o, output);
206             }
207         } catch (IllegalAccessException JavaDoc e) {
208             throw new IllegalStateException JavaDoc(e);
209         }
210     }
211     
212     public void readSecKeyFields(Object JavaDoc o,
213                                  EntityInput input,
214                                  int startField,
215                                  int endField,
216                                  int superLevel) {
217         try {
218             if (priKey != null && !priKey.isPrimitive) {
219                 input.registerPriKeyObject(priKey.field.get(o));
220             }
221             if (superLevel != 0 && superAccessor != null) {
222                 superAccessor.readSecKeyFields
223                     (o, input, startField, endField, superLevel - 1);
224             } else {
225                 if (superLevel > 0) {
226                     throw new IllegalStateException JavaDoc
227                         ("Superclass does not exist");
228                 }
229             }
230             if (superLevel <= 0) {
231                 for (int i = startField;
232                      i <= endField && i < secKeys.length;
233                      i += 1) {
234                     secKeys[i].read(o, input);
235                 }
236             }
237         } catch (IllegalAccessException JavaDoc e) {
238             throw new IllegalStateException JavaDoc(e);
239         }
240     }
241
242     public void writeNonKeyFields(Object JavaDoc o, EntityOutput output) {
243         try {
244             if (superAccessor != null) {
245                 superAccessor.writeNonKeyFields(o, output);
246             }
247             for (int i = 0; i < nonKeys.length; i += 1) {
248                 nonKeys[i].write(o, output);
249             }
250         } catch (IllegalAccessException JavaDoc e) {
251             throw new IllegalStateException JavaDoc(e);
252         }
253     }
254     
255     public void readNonKeyFields(Object JavaDoc o,
256                                  EntityInput input,
257                                  int startField,
258                                  int endField,
259                                  int superLevel) {
260         try {
261             if (superLevel != 0 && superAccessor != null) {
262                 superAccessor.readNonKeyFields
263                     (o, input, startField, endField, superLevel - 1);
264             } else {
265                 if (superLevel > 0) {
266                     throw new IllegalStateException JavaDoc
267                         ("Superclass does not exist");
268                 }
269             }
270             if (superLevel <= 0) {
271                 for (int i = startField;
272                      i <= endField && i < nonKeys.length;
273                      i += 1) {
274                     nonKeys[i].read(o, input);
275                 }
276             }
277         } catch (IllegalAccessException JavaDoc e) {
278             throw new IllegalStateException JavaDoc(e);
279         }
280     }
281
282     public Object JavaDoc getField(Object JavaDoc o,
283                            int field,
284                            int superLevel,
285                            boolean isSecField) {
286         if (superLevel > 0) {
287             return superAccessor.getField
288                 (o, field, superLevel - 1, isSecField);
289         }
290         try {
291             Field JavaDoc fld = isSecField ? secKeys[field].field
292                                    : nonKeys[field].field;
293             return fld.get(o);
294         } catch (IllegalAccessException JavaDoc e) {
295             throw new IllegalStateException JavaDoc(e);
296         }
297     }
298
299     public void setField(Object JavaDoc o,
300                          int field,
301                          int superLevel,
302                          boolean isSecField,
303                          Object JavaDoc value) {
304         if (superLevel > 0) {
305             superAccessor.setField
306                 (o, field, superLevel - 1, isSecField, value);
307         }
308         try {
309             Field JavaDoc fld = isSecField ? secKeys[field].field
310                                    : nonKeys[field].field;
311             fld.set(o, value);
312         } catch (IllegalAccessException JavaDoc e) {
313             throw new IllegalStateException JavaDoc(e);
314         }
315     }
316
317     /**
318      * Abstract base class for field access classes.
319      */

320     private static abstract class FieldAccess {
321
322         Field JavaDoc field;
323         boolean isPrimitive;
324
325         FieldAccess(Field JavaDoc field) {
326             this.field = field;
327             isPrimitive = field.getType().isPrimitive();
328         }
329
330         /**
331          * Writes a field.
332          */

333         abstract void write(Object JavaDoc o, EntityOutput out)
334             throws IllegalAccessException JavaDoc;
335
336         /**
337          * Reads a field.
338          */

339         abstract void read(Object JavaDoc o, EntityInput in)
340             throws IllegalAccessException JavaDoc;
341
342         /**
343          * Returns whether a field is null (for reference types) or zero (for
344          * primitive integer types). This implementation handles the reference
345          * types.
346          */

347         boolean isNullOrZero(Object JavaDoc o)
348             throws IllegalAccessException JavaDoc {
349
350             return field.get(o) == null;
351         }
352     }
353
354     /**
355      * Access for fields with object types.
356      */

357     private static class ObjectAccess extends FieldAccess {
358
359         ObjectAccess(Field JavaDoc field) {
360             super(field);
361         }
362
363         @Override JavaDoc
364         void write(Object JavaDoc o, EntityOutput out)
365             throws IllegalAccessException JavaDoc {
366
367             out.writeObject(field.get(o), null);
368         }
369
370         @Override JavaDoc
371         void read(Object JavaDoc o, EntityInput in)
372             throws IllegalAccessException JavaDoc {
373
374             field.set(o, in.readObject());
375         }
376     }
377
378     /**
379      * Access for primary key fields and composite key fields with object
380      * types.
381      */

382     private static class KeyObjectAccess extends FieldAccess {
383
384         private Format format;
385
386         KeyObjectAccess(Field JavaDoc field, Format format) {
387             super(field);
388             this.format = format;
389         }
390
391         @Override JavaDoc
392         void write(Object JavaDoc o, EntityOutput out)
393             throws IllegalAccessException JavaDoc {
394
395             out.writeKeyObject(field.get(o), format);
396         }
397
398         @Override JavaDoc
399         void read(Object JavaDoc o, EntityInput in)
400             throws IllegalAccessException JavaDoc {
401
402             field.set(o, in.readKeyObject(format));
403         }
404     }
405
406     /**
407      * Access for fields with primitive types.
408      */

409     private static class PrimitiveAccess extends FieldAccess {
410
411         private SimpleFormat format;
412
413         PrimitiveAccess(Field JavaDoc field, SimpleFormat format) {
414             super(field);
415             this.format = format;
416         }
417
418         @Override JavaDoc
419         void write(Object JavaDoc o, EntityOutput out)
420             throws IllegalAccessException JavaDoc {
421
422             format.writePrimitiveField(o, out, field);
423         }
424
425         @Override JavaDoc
426         void read(Object JavaDoc o, EntityInput in)
427             throws IllegalAccessException JavaDoc {
428
429             format.readPrimitiveField(o, in, field);
430         }
431
432         @Override JavaDoc
433         boolean isNullOrZero(Object JavaDoc o)
434             throws IllegalAccessException JavaDoc {
435
436             return field.getLong(o) == 0;
437         }
438     }
439 }
440
Popular Tags