001: /*
002: * Copyright (C) 2008 XStream Committers.
003: * All rights reserved.
004: *
005: * The software in this package is published under the terms of the BSD
006: * style license a copy of which has been included with this distribution in
007: * the LICENSE.txt file.
008: *
009: * Created on 09. January 2008 by Joerg Schaible
010: */
011: package com.thoughtworks.xstream.converters.reflection;
012:
013: import org.apache.harmony.awt.FieldsAccessor;
014: import org.apache.harmony.misc.accessors.ObjectAccessor;
015:
016: import java.lang.reflect.Field;
017:
018: /**
019: * Instantiates a new object on the Harmony JVM by bypassing the constructor (meaning code in
020: * the constructor will never be executed and parameters do not have to be known). This is the
021: * same method used by the internals of standard Java serialization, but relies on internal Harmony
022: * code.
023: *
024: * Note, this is work in progress. Harmony 5.0M4 crashes after running quite some test of the test
025: * suite. Additionally it fails with a NPE processing the annotations and has a wrong offset dealing
026: * with time zone.
027: *
028: * @author Jörg Schaible
029: * @author Joe Walnes
030: */
031: public class HarmonyReflectionProvider extends
032: PureJavaReflectionProvider {
033: private final static ObjectAccessor objectAccess;
034: private final static Exception exception;
035: static {
036: ObjectAccessor accessor = null;
037: Exception ex = null;
038: FieldsAccessor fieldsAccessor = new FieldsAccessor(
039: ReflectionProvider.class, null);
040: Field field;
041: try {
042: field = FieldsAccessor.class.getDeclaredField("accessor");
043: field.setAccessible(true);
044: accessor = (ObjectAccessor) field.get(fieldsAccessor);
045: } catch (NoSuchFieldException e) {
046: ex = e;
047: } catch (IllegalAccessException e) {
048: ex = e;
049: }
050: objectAccess = accessor;
051: exception = ex;
052: }
053:
054: public HarmonyReflectionProvider() {
055: super ();
056: }
057:
058: public HarmonyReflectionProvider(FieldDictionary dic) {
059: super (dic);
060: }
061:
062: public Object newInstance(Class type) {
063: if (exception != null) {
064: throw new ObjectAccessException("Cannot construct "
065: + type.getName(), exception);
066: }
067: try {
068: return objectAccess.newInstance(type);
069: } catch (SecurityException e) {
070: throw new ObjectAccessException("Cannot construct "
071: + type.getName(), e);
072: } catch (IllegalArgumentException e) {
073: throw new ObjectAccessException("Cannot construct "
074: + type.getName(), e);
075: }
076: }
077:
078: public void writeField(Object object, String fieldName,
079: Object value, Class definedIn) {
080: write(fieldDictionary.field(object.getClass(), fieldName,
081: definedIn), object, value);
082: }
083:
084: private void write(Field field, Object object, Object value) {
085: if (exception != null) {
086: throw new ObjectAccessException("Could not set field "
087: + object.getClass() + "." + field.getName(),
088: exception);
089: }
090: try {
091: long offset = objectAccess.getFieldID(field);
092: Class type = field.getType();
093: if (type.isPrimitive()) {
094: if (type.equals(Integer.TYPE)) {
095: objectAccess.setInt(object, offset,
096: ((Integer) value).intValue());
097: } else if (type.equals(Long.TYPE)) {
098: objectAccess.setLong(object, offset, ((Long) value)
099: .longValue());
100: } else if (type.equals(Short.TYPE)) {
101: objectAccess.setShort(object, offset,
102: ((Short) value).shortValue());
103: } else if (type.equals(Character.TYPE)) {
104: objectAccess.setChar(object, offset,
105: ((Character) value).charValue());
106: } else if (type.equals(Byte.TYPE)) {
107: objectAccess.setByte(object, offset, ((Byte) value)
108: .byteValue());
109: } else if (type.equals(Float.TYPE)) {
110: objectAccess.setFloat(object, offset,
111: ((Float) value).floatValue());
112: } else if (type.equals(Double.TYPE)) {
113: objectAccess.setDouble(object, offset,
114: ((Double) value).doubleValue());
115: } else if (type.equals(Boolean.TYPE)) {
116: objectAccess.setBoolean(object, offset,
117: ((Boolean) value).booleanValue());
118: } else {
119: throw new ObjectAccessException(
120: "Could not set field " + object.getClass()
121: + "." + field.getName()
122: + ": Unknown type " + type);
123: }
124: } else {
125: objectAccess.setObject(object, offset, value);
126: }
127:
128: } catch (IllegalArgumentException e) {
129: throw new ObjectAccessException("Could not set field "
130: + object.getClass() + "." + field.getName(), e);
131: }
132: }
133:
134: protected void validateFieldAccess(Field field) {
135: // (overriden) don't mind final fields.
136: }
137: }
|