• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/db-4.8.30/java/src/com/sleepycat/persist/impl/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002-2009 Oracle.  All rights reserved.
5 *
6 * $Id$
7 */
8
9package com.sleepycat.persist.impl;
10
11import java.lang.reflect.AccessibleObject;
12import java.lang.reflect.Array;
13import java.lang.reflect.Constructor;
14import java.lang.reflect.Field;
15import java.lang.reflect.InvocationTargetException;
16import java.lang.reflect.Modifier;
17import java.util.List;
18
19/**
20 * Implements Accessor using reflection.
21 *
22 * @author Mark Hayes
23 */
24class ReflectionAccessor implements Accessor {
25
26    private static final FieldAccess[] EMPTY_KEYS = {};
27
28    private Class type;
29    private Accessor superAccessor;
30    private Constructor constructor;
31    private FieldAccess priKey;
32    private FieldAccess[] secKeys;
33    private FieldAccess[] nonKeys;
34
35    private ReflectionAccessor(Class type, Accessor superAccessor) {
36        this.type = type;
37        this.superAccessor = superAccessor;
38        try {
39            constructor = type.getDeclaredConstructor();
40        } catch (NoSuchMethodException e) {
41            throw new IllegalStateException(type.getName());
42        }
43        if (!Modifier.isPublic(constructor.getModifiers())) {
44            setAccessible(constructor, type.getName() + "()");
45        }
46    }
47
48    /**
49     * Creates an accessor for a complex type.
50     */
51    ReflectionAccessor(Catalog catalog,
52                       Class type,
53                       Accessor superAccessor,
54                       FieldInfo priKeyField,
55                       List<FieldInfo> secKeyFields,
56                       List<FieldInfo> nonKeyFields) {
57        this(type, superAccessor);
58        if (priKeyField != null) {
59            priKey = getField(catalog, priKeyField,
60                              true /*isRequiredKeyField*/,
61                              false /*isCompositeKey*/);
62        } else {
63            priKey = null;
64        }
65        if (secKeyFields.size() > 0) {
66            secKeys = getFields(catalog, secKeyFields,
67                                false /*isRequiredKeyField*/,
68                                false /*isCompositeKey*/);
69        } else {
70            secKeys = EMPTY_KEYS;
71        }
72        if (nonKeyFields.size() > 0) {
73            nonKeys = getFields(catalog, nonKeyFields,
74                                false /*isRequiredKeyField*/,
75                                false /*isCompositeKey*/);
76        } else {
77            nonKeys = EMPTY_KEYS;
78        }
79    }
80
81    /**
82     * Creates an accessor for a composite key type.
83     */
84    ReflectionAccessor(Catalog catalog,
85                       Class type,
86                       List<FieldInfo> fieldInfos) {
87        this(type, null);
88        priKey = null;
89        secKeys = EMPTY_KEYS;
90        nonKeys = getFields(catalog, fieldInfos,
91                            true /*isRequiredKeyField*/,
92                            true /*isCompositeKey*/);
93    }
94
95    private FieldAccess[] getFields(Catalog catalog,
96                                    List<FieldInfo> fieldInfos,
97                                    boolean isRequiredKeyField,
98                                    boolean isCompositeKey) {
99        int index = 0;
100        FieldAccess[] fields = new FieldAccess[fieldInfos.size()];
101        for (FieldInfo info : fieldInfos) {
102            fields[index] = getField
103                (catalog, info, isRequiredKeyField, isCompositeKey);
104            index += 1;
105        }
106        return fields;
107    }
108
109    private FieldAccess getField(Catalog catalog,
110                                 FieldInfo fieldInfo,
111                                 boolean isRequiredKeyField,
112                                 boolean isCompositeKey) {
113        Field field;
114        try {
115            field = type.getDeclaredField(fieldInfo.getName());
116        } catch (NoSuchFieldException e) {
117            throw new IllegalStateException(e);
118        }
119        if (!Modifier.isPublic(field.getModifiers())) {
120            setAccessible(field, field.getName());
121        }
122        Class fieldCls = field.getType();
123        if (fieldCls.isPrimitive()) {
124            assert SimpleCatalog.isSimpleType(fieldCls);
125            return new PrimitiveAccess
126                (field, SimpleCatalog.getSimpleFormat(fieldCls));
127        } else if (isRequiredKeyField) {
128            Format format = catalog.getFormat(fieldInfo.getClassName());
129            assert format != null;
130            return new KeyObjectAccess(field, format);
131        } else {
132            return new ObjectAccess(field);
133        }
134    }
135
136    private void setAccessible(AccessibleObject object, String memberName) {
137        try {
138            object.setAccessible(true);
139        } catch (SecurityException e) {
140            throw new IllegalStateException
141                ("Unable to access non-public member: " +
142                 type.getName() + '.' + memberName +
143                 ". Please configure the Java Security Manager setting: " +
144                 " ReflectPermission suppressAccessChecks", e);
145        }
146    }
147
148    public Object newInstance() {
149        try {
150            return constructor.newInstance();
151        } catch (IllegalAccessException e) {
152            throw new IllegalStateException(e);
153        } catch (InstantiationException e) {
154            throw new IllegalStateException(e);
155        } catch (InvocationTargetException e) {
156            throw new IllegalStateException(e);
157        }
158    }
159
160    public Object newArray(int len) {
161        return Array.newInstance(type, len);
162    }
163
164    public boolean isPriKeyFieldNullOrZero(Object o) {
165        try {
166            if (priKey != null) {
167                return priKey.isNullOrZero(o);
168            } else if (superAccessor != null) {
169                return superAccessor.isPriKeyFieldNullOrZero(o);
170            } else {
171                throw new IllegalStateException("No primary key field");
172            }
173        } catch (IllegalAccessException e) {
174            throw new IllegalStateException(e);
175        }
176    }
177
178    public void writePriKeyField(Object o, EntityOutput output) {
179        try {
180            if (priKey != null) {
181                priKey.write(o, output);
182            } else if (superAccessor != null) {
183                superAccessor.writePriKeyField(o, output);
184            } else {
185                throw new IllegalStateException("No primary key field");
186            }
187        } catch (IllegalAccessException e) {
188            throw new IllegalStateException(e);
189        }
190    }
191
192    public void readPriKeyField(Object o, EntityInput input) {
193        try {
194            if (priKey != null) {
195                priKey.read(o, input);
196            } else if (superAccessor != null) {
197                superAccessor.readPriKeyField(o, input);
198            } else {
199                throw new IllegalStateException("No primary key field");
200            }
201        } catch (IllegalAccessException e) {
202            throw new IllegalStateException(e);
203        }
204    }
205
206    public void writeSecKeyFields(Object o, EntityOutput output) {
207        try {
208            if (priKey != null && !priKey.isPrimitive) {
209                output.registerPriKeyObject(priKey.field.get(o));
210            }
211            if (superAccessor != null) {
212                superAccessor.writeSecKeyFields(o, output);
213            }
214            for (int i = 0; i < secKeys.length; i += 1) {
215                secKeys[i].write(o, output);
216            }
217        } catch (IllegalAccessException e) {
218            throw new IllegalStateException(e);
219        }
220    }
221
222    public void readSecKeyFields(Object o,
223                                 EntityInput input,
224                                 int startField,
225                                 int endField,
226                                 int superLevel) {
227        try {
228            if (priKey != null && !priKey.isPrimitive) {
229                input.registerPriKeyObject(priKey.field.get(o));
230            }
231            if (superLevel != 0 && superAccessor != null) {
232                superAccessor.readSecKeyFields
233                    (o, input, startField, endField, superLevel - 1);
234            } else {
235                if (superLevel > 0) {
236                    throw new IllegalStateException
237                        ("Superclass does not exist");
238                }
239            }
240            if (superLevel <= 0) {
241                for (int i = startField;
242                     i <= endField && i < secKeys.length;
243                     i += 1) {
244                    secKeys[i].read(o, input);
245                }
246            }
247        } catch (IllegalAccessException e) {
248            throw new IllegalStateException(e);
249        }
250    }
251
252    public void writeNonKeyFields(Object o, EntityOutput output) {
253        try {
254            if (superAccessor != null) {
255                superAccessor.writeNonKeyFields(o, output);
256            }
257            for (int i = 0; i < nonKeys.length; i += 1) {
258                nonKeys[i].write(o, output);
259            }
260        } catch (IllegalAccessException e) {
261            throw new IllegalStateException(e);
262        }
263    }
264
265    public void readNonKeyFields(Object o,
266                                 EntityInput input,
267                                 int startField,
268                                 int endField,
269                                 int superLevel) {
270        try {
271            if (superLevel != 0 && superAccessor != null) {
272                superAccessor.readNonKeyFields
273                    (o, input, startField, endField, superLevel - 1);
274            } else {
275                if (superLevel > 0) {
276                    throw new IllegalStateException
277                        ("Superclass does not exist");
278                }
279            }
280            if (superLevel <= 0) {
281                for (int i = startField;
282                     i <= endField && i < nonKeys.length;
283                     i += 1) {
284                    nonKeys[i].read(o, input);
285                }
286            }
287        } catch (IllegalAccessException e) {
288            throw new IllegalStateException(e);
289        }
290    }
291
292    public void writeCompositeKeyFields(Object o, EntityOutput output) {
293        try {
294            for (int i = 0; i < nonKeys.length; i += 1) {
295                nonKeys[i].write(o, output);
296            }
297        } catch (IllegalAccessException e) {
298            throw new IllegalStateException(e);
299        }
300    }
301
302    public void readCompositeKeyFields(Object o, EntityInput input) {
303        try {
304            for (int i = 0; i < nonKeys.length; i += 1) {
305                nonKeys[i].read(o, input);
306            }
307        } catch (IllegalAccessException e) {
308            throw new IllegalStateException(e);
309        }
310    }
311
312    public Object getField(Object o,
313                           int field,
314                           int superLevel,
315                           boolean isSecField) {
316        if (superLevel > 0) {
317            return superAccessor.getField
318                (o, field, superLevel - 1, isSecField);
319        }
320        try {
321            Field fld =
322		isSecField ? secKeys[field].field : nonKeys[field].field;
323            return fld.get(o);
324        } catch (IllegalAccessException e) {
325            throw new IllegalStateException(e);
326        }
327    }
328
329    public void setField(Object o,
330                         int field,
331                         int superLevel,
332                         boolean isSecField,
333                         Object value) {
334        if (superLevel > 0) {
335            superAccessor.setField
336                (o, field, superLevel - 1, isSecField, value);
337	    return;
338        }
339        try {
340            Field fld =
341		isSecField ? secKeys[field].field : nonKeys[field].field;
342            fld.set(o, value);
343        } catch (IllegalAccessException e) {
344            throw new IllegalStateException(e);
345        }
346    }
347
348    /**
349     * Abstract base class for field access classes.
350     */
351    private static abstract class FieldAccess {
352
353        Field field;
354        boolean isPrimitive;
355
356        FieldAccess(Field field) {
357            this.field = field;
358            isPrimitive = field.getType().isPrimitive();
359        }
360
361        /**
362         * Writes a field.
363         */
364        abstract void write(Object o, EntityOutput out)
365            throws IllegalAccessException;
366
367        /**
368         * Reads a field.
369         */
370        abstract void read(Object o, EntityInput in)
371            throws IllegalAccessException;
372
373        /**
374         * Returns whether a field is null (for reference types) or zero (for
375         * primitive integer types).  This implementation handles the reference
376         * types.
377         */
378        boolean isNullOrZero(Object o)
379            throws IllegalAccessException {
380
381            return field.get(o) == null;
382        }
383    }
384
385    /**
386     * Access for fields with object types.
387     */
388    private static class ObjectAccess extends FieldAccess {
389
390        ObjectAccess(Field field) {
391            super(field);
392        }
393
394        @Override
395        void write(Object o, EntityOutput out)
396            throws IllegalAccessException {
397
398            out.writeObject(field.get(o), null);
399        }
400
401        @Override
402        void read(Object o, EntityInput in)
403            throws IllegalAccessException {
404
405            field.set(o, in.readObject());
406        }
407    }
408
409    /**
410     * Access for primary key fields and composite key fields with object
411     * types.
412     */
413    private static class KeyObjectAccess extends FieldAccess {
414
415        private Format format;
416
417        KeyObjectAccess(Field field, Format format) {
418            super(field);
419            this.format = format;
420        }
421
422        @Override
423        void write(Object o, EntityOutput out)
424            throws IllegalAccessException {
425
426            out.writeKeyObject(field.get(o), format);
427        }
428
429        @Override
430        void read(Object o, EntityInput in)
431            throws IllegalAccessException {
432
433            field.set(o, in.readKeyObject(format));
434        }
435    }
436
437    /**
438     * Access for fields with primitive types.
439     */
440    private static class PrimitiveAccess extends FieldAccess {
441
442        private SimpleFormat format;
443
444        PrimitiveAccess(Field field, SimpleFormat format) {
445            super(field);
446            this.format = format;
447        }
448
449        @Override
450        void write(Object o, EntityOutput out)
451            throws IllegalAccessException {
452
453            format.writePrimitiveField(o, out, field);
454        }
455
456        @Override
457        void read(Object o, EntityInput in)
458            throws IllegalAccessException {
459
460            format.readPrimitiveField(o, in, field);
461        }
462
463        @Override
464        boolean isNullOrZero(Object o)
465            throws IllegalAccessException {
466
467            return field.getLong(o) == 0;
468        }
469    }
470}
471