Log Message
Move SerializationMethodInvoker into core.util and renamed it to SerializationMembers.
Modified Paths
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java
- trunk/xstream-distribution/src/content/changes.html
Added Paths
Diff
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (2332 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -36,6 +36,7 @@
import com.thoughtworks.xstream.core.util.FastField;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.core.util.Primitives;
+import com.thoughtworks.xstream.core.util.SerializationMembers;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -47,13 +48,19 @@
protected final ReflectionProvider reflectionProvider;
protected final Mapper mapper;
+ /**
+ * @deprecated As of upcoming, use {@link #serializationMembers}.
+ */
+ @Deprecated
protected transient SerializationMethodInvoker serializationMethodInvoker;
+ protected transient SerializationMembers serializationMembers;
private transient ReflectionProvider pureJavaReflectionProvider;
public AbstractReflectionConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
this.mapper = mapper;
this.reflectionProvider = reflectionProvider;
serializationMethodInvoker = new SerializationMethodInvoker();
+ serializationMembers = serializationMethodInvoker.serializationMembers;
}
protected boolean canAccess(final Class<?> type) {
@@ -68,7 +75,7 @@
@Override
public void marshal(final Object original, final HierarchicalStreamWriter writer, final MarshallingContext context) {
- final Object source = serializationMethodInvoker.callWriteReplace(original);
+ final Object source = serializationMembers.callWriteReplace(original);
if (source != original && context instanceof ReferencingMarshallingContext) {
((ReferencingMarshallingContext<?>)context).replace(original, source);
@@ -242,7 +249,7 @@
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
Object result = instantiateNewInstance(reader, context);
result = doUnmarshal(result, reader, context);
- return serializationMethodInvoker.callReadResolve(result);
+ return serializationMembers.callReadResolve(result);
}
public Object doUnmarshal(final Object result, final HierarchicalStreamReader reader,
@@ -534,6 +541,7 @@
protected Object readResolve() {
serializationMethodInvoker = new SerializationMethodInvoker();
+ serializationMembers = serializationMethodInvoker.serializationMembers;
return this;
}
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (2332 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -405,7 +405,7 @@
if (result == null) {
result = create(enhancer, callbacks, useFactory);
}
- return serializationMethodInvoker.callReadResolve(result);
+ return serializationMembers.callReadResolve(result);
}
private void readCallback(final HierarchicalStreamReader reader, final UnmarshallingContext context,
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java (2332 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -29,6 +29,7 @@
import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
+import com.thoughtworks.xstream.core.util.SerializationMembers;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -45,7 +46,7 @@
private final Mapper mapper;
private final ClassLoaderReference classLoaderReference;
- private transient SerializationMethodInvoker serializationMethodInvoker;
+ private transient SerializationMembers serializationMembers;
/**
* Construct an ExternalizableConverter.
@@ -57,7 +58,7 @@
public ExternalizableConverter(final Mapper mapper, final ClassLoaderReference classLoaderReference) {
this.mapper = mapper;
this.classLoaderReference = classLoaderReference;
- serializationMethodInvoker = new SerializationMethodInvoker();
+ serializationMembers = new SerializationMembers();
}
/**
@@ -83,7 +84,7 @@
@Override
public void marshal(final Object original, final HierarchicalStreamWriter writer, final MarshallingContext context) {
- final Object source = serializationMethodInvoker.callWriteReplace(original);
+ final Object source = serializationMembers.callWriteReplace(original);
if (source != original && context instanceof ReferencingMarshallingContext) {
((ReferencingMarshallingContext<?>)context).replace(original, source);
}
@@ -192,7 +193,7 @@
externalizable.readExternal(objectInput);
objectInput.popCallback();
}
- return serializationMethodInvoker.callReadResolve(externalizable);
+ return serializationMembers.callReadResolve(externalizable);
} catch (final NoSuchMethodException e) {
throw new ConversionException("Cannot construct " + type.getClass() + ", missing default constructor", e);
} catch (final InvocationTargetException e) {
@@ -209,7 +210,7 @@
}
private Object readResolve() {
- serializationMethodInvoker = new SerializationMethodInvoker();
+ serializationMembers = new SerializationMembers();
return this;
}
}
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (2332 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -111,7 +111,7 @@
if (type != null
&& Serializable.class.isAssignableFrom(type)
&& !type.isInterface()
- && (serializationMethodInvoker.supportsReadObject(type, true) || serializationMethodInvoker
+ && (serializationMembers.supportsReadObject(type, true) || serializationMembers
.supportsWriteObject(type, true))) {
for (final Class<?> clazz : hierarchyFor(type)) {
if (!Serializable.class.isAssignableFrom(clazz)) {
@@ -257,7 +257,7 @@
marshalUnserializableParent(writer, context, source);
mustHandleUnserializableParent = false;
}
- if (serializationMethodInvoker.supportsWriteObject(currentType, false)) {
+ if (serializationMembers.supportsWriteObject(currentType, false)) {
writtenClassWrapper[0] = true;
writer.startNode(mapper.serializedClass(currentType));
if (currentType != mapper.defaultImplementationOf(currentType)) {
@@ -269,10 +269,10 @@
@SuppressWarnings("resource")
final CustomObjectOutputStream objectOutputStream = CustomObjectOutputStream.getInstance(
context, callback);
- serializationMethodInvoker.callWriteObject(currentType, source, objectOutputStream);
+ serializationMembers.callWriteObject(currentType, source, objectOutputStream);
objectOutputStream.popCallback();
writer.endNode();
- } else if (serializationMethodInvoker.supportsReadObject(currentType, false)) {
+ } else if (serializationMembers.supportsReadObject(currentType, false)) {
// Special case for objects that have readObject(), but not writeObject().
// The class wrapper is always written, whether or not this class in the hierarchy has
// serializable fields. This guarantees that readObject() will be called upon deserialization.
@@ -416,7 +416,7 @@
@Override
public void defaultReadObject() {
- if (serializationMethodInvoker.getSerializablePersistentFields(currentType[0]) != null) {
+ if (serializationMembers.getSerializablePersistentFields(currentType[0]) != null) {
readFieldsFromStream();
return;
}
@@ -483,11 +483,11 @@
} else {
currentType[0] = mapper.realClass(classAttribute);
}
- if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
+ if (serializationMembers.supportsReadObject(currentType[0], false)) {
@SuppressWarnings("resource")
final CustomObjectInputStream objectInputStream = CustomObjectInputStream.getInstance(context,
callback, classLoaderReference);
- serializationMethodInvoker.callReadObject(currentType[0], result, objectInputStream);
+ serializationMembers.callReadObject(currentType[0], result, objectInputStream);
objectInputStream.popCallback();
} else {
try {
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java (2332 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -13,21 +13,9 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.core.Caching;
-import com.thoughtworks.xstream.core.util.FastField;
+import com.thoughtworks.xstream.core.util.SerializationMembers;
/**
@@ -35,190 +23,69 @@
*
* @author Joe Walnes
* @author Jörg Schaible
+ * @deprecated As of upcoming, moved into internal util package.
*/
+@Deprecated
public class SerializationMethodInvoker implements Caching {
- private static final Method NO_METHOD = new Object() {
- @SuppressWarnings("unused")
- private void noMethod() {
- }
- }.getClass().getDeclaredMethods()[0];
- private static final Map<String, ObjectStreamField> NO_FIELDS = Collections.emptyMap();
- private static final int PERSISTENT_FIELDS_MODIFIER = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
- private static final FastField[] OBJECT_TYPE_FIELDS = {
- new FastField(Object.class, "readResolve"), new FastField(Object.class, "writeReplace"),
- new FastField(Object.class, "readObject"), new FastField(Object.class, "writeObject")};
- private final ConcurrentMap<FastField, Method> declaredCache = new ConcurrentHashMap<FastField, Method>();
- private final ConcurrentMap<FastField, Method> resRepCache = new ConcurrentHashMap<FastField, Method>();
- private final ConcurrentMap<String, Map<String, ObjectStreamField>> fieldCache = new ConcurrentHashMap<String, Map<String, ObjectStreamField>>();
- {
- for (final FastField element : OBJECT_TYPE_FIELDS) {
- declaredCache.put(element, NO_METHOD);
- }
- for (final FastField element : Arrays.copyOf(OBJECT_TYPE_FIELDS, 2)) {
- resRepCache.put(element, NO_METHOD);
- }
- }
+ SerializationMembers serializationMembers = new SerializationMembers();
/**
* Resolves an object as native serialization does by calling readResolve(), if available.
+ *
+ * @deprecated As of upcoming, moved into internal util package.
*/
+ @Deprecated
public Object callReadResolve(final Object result) {
- if (result == null) {
- return null;
- } else {
- final Class<? extends Object> resultType = result.getClass();
- final Method readResolveMethod = getRRMethod(resultType, "readResolve");
- if (readResolveMethod != null) {
- try {
- return readResolveMethod.invoke(result);
- } catch (final IllegalAccessException e) {
- throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e);
- } catch (final InvocationTargetException e) {
- throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e
- .getTargetException());
- }
- } else {
- return result;
- }
- }
+ return serializationMembers.callReadResolve(result);
}
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
+ @Deprecated
public Object callWriteReplace(final Object object) {
- if (object == null) {
- return null;
- } else {
- final Class<? extends Object> objectType = object.getClass();
- final Method writeReplaceMethod = getRRMethod(objectType, "writeReplace");
- if (writeReplaceMethod != null) {
- try {
- return writeReplaceMethod.invoke(object);
- } catch (final IllegalAccessException e) {
- throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e);
- } catch (final InvocationTargetException e) {
- throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e
- .getTargetException());
- }
- } else {
- return object;
- }
- }
+ return serializationMembers.callWriteReplace(object);
}
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
+ @Deprecated
public boolean supportsReadObject(final Class<?> type, final boolean includeBaseClasses) {
- return getMethod(type, "readObject", includeBaseClasses, ObjectInputStream.class) != null;
+ return serializationMembers.supportsReadObject(type, includeBaseClasses);
}
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
+ @Deprecated
public void callReadObject(final Class<?> type, final Object object, final ObjectInputStream stream) {
- try {
- final Method readObjectMethod = getMethod(type, "readObject", false, ObjectInputStream.class);
- readObjectMethod.invoke(object, stream);
- } catch (final IllegalAccessException e) {
- throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e);
- } catch (final InvocationTargetException e) {
- throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e
- .getTargetException());
- }
+ serializationMembers.callReadObject(type, object, stream);
}
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
+ @Deprecated
public boolean supportsWriteObject(final Class<?> type, final boolean includeBaseClasses) {
- return getMethod(type, "writeObject", includeBaseClasses, ObjectOutputStream.class) != null;
+ return serializationMembers.supportsWriteObject(type, includeBaseClasses);
}
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
+ @Deprecated
public void callWriteObject(final Class<?> type, final Object instance, final ObjectOutputStream stream) {
- try {
- final Method readObjectMethod = getMethod(type, "writeObject", false, ObjectOutputStream.class);
- readObjectMethod.invoke(instance, stream);
- } catch (final IllegalAccessException e) {
- throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e);
- } catch (final InvocationTargetException e) {
- throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e
- .getTargetException());
- }
+ serializationMembers.callWriteObject(type, instance, stream);
}
- private Method getMethod(final Class<?> type, final String name, final boolean includeBaseclasses,
- final Class<?>... parameterTypes) {
- final Method method = getMethod(type, name, parameterTypes);
- return method == NO_METHOD || !includeBaseclasses && !method.getDeclaringClass().equals(type) ? null : method;
- }
-
- private Method getMethod(final Class<?> type, final String name, final Class<?>... parameterTypes) {
- if (type == null) {
- return null;
- }
- final FastField method = new FastField(type, name);
- Method result = declaredCache.get(method);
-
- if (result == null) {
- try {
- result = type.getDeclaredMethod(name, parameterTypes);
- if (!result.isAccessible()) {
- result.setAccessible(true);
- }
- } catch (final NoSuchMethodException e) {
- result = getMethod(type.getSuperclass(), name, parameterTypes);
- }
- declaredCache.put(method, result);
- }
- return result;
- }
-
- private Method getRRMethod(final Class<?> type, final String name) {
- final FastField method = new FastField(type, name);
- Method result = resRepCache.get(method);
- if (result == null) {
- result = getMethod(type, name, true);
- if (result != null && result.getDeclaringClass() != type) {
- if ((result.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0) {
- if ((result.getModifiers() & Modifier.PRIVATE) > 0
- || type.getPackage() != result.getDeclaringClass().getPackage()) {
- result = NO_METHOD;
- }
- }
- } else if (result == null) {
- result = NO_METHOD;
- }
- resRepCache.putIfAbsent(method, result);
- }
- return result == NO_METHOD ? null : result;
- }
-
- public Map<String, ObjectStreamField> getSerializablePersistentFields(final Class<?> type) {
- if (type == null) {
- return null;
- }
- Map<String, ObjectStreamField> result = fieldCache.get(type.getName());
- if (result == null) {
- try {
- final Field field = type.getDeclaredField("serialPersistentFields");
- if ((field.getModifiers() & PERSISTENT_FIELDS_MODIFIER) == PERSISTENT_FIELDS_MODIFIER) {
- field.setAccessible(true);
- final ObjectStreamField[] fields = (ObjectStreamField[])field.get(null);
- if (fields != null) {
- result = new HashMap<String, ObjectStreamField>();
- for (final ObjectStreamField f : fields) {
- result.put(f.getName(), f);
- }
- }
- }
- } catch (final NoSuchFieldException e) {
- } catch (final IllegalAccessException e) {
- throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
- } catch (final ClassCastException e) {
- throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
- }
- if (result == null) {
- result = NO_FIELDS;
- }
- fieldCache.putIfAbsent(type.getName(), result);
- }
- return result == NO_FIELDS ? null : result;
- }
-
+ /**
+ * @deprecated As of upcoming, moved into internal util package.
+ */
@Override
+ @Deprecated
public void flushCache() {
- declaredCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
- resRepCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+ serializationMembers.flushCache();
}
}
Copied: trunk/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java (from rev 2329, trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java) (0 => 2333)
--- trunk/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java (rev 0)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java 2015-02-14 16:44:43 UTC (rev 2333)
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2014, 2015 XStream Committers.
+ * All rights reserved.
+ *
+ * The software in this package is published under the terms of the BSD
+ * style license a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ *
+ * Created on 12. February 2015 by Joerg Schaible, copied from c.t.x.converters.reflection.SerializationMemberInvoker.
+ */
+package com.thoughtworks.xstream.core.util;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+import com.thoughtworks.xstream.core.Caching;
+
+
+/**
+ * Convenience wrapper to invoke special serialization methods on objects (and perform reflection caching).
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ */
+public class SerializationMembers implements Caching {
+
+ private static final Method NO_METHOD = new Object() {
+ @SuppressWarnings("unused")
+ private void noMethod() {
+ }
+ }.getClass().getDeclaredMethods()[0];
+ private static final Map<String, ObjectStreamField> NO_FIELDS = Collections.emptyMap();
+ private static final int PERSISTENT_FIELDS_MODIFIER = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
+ private static final FastField[] OBJECT_TYPE_FIELDS = {
+ new FastField(Object.class, "readResolve"), new FastField(Object.class, "writeReplace"),
+ new FastField(Object.class, "readObject"), new FastField(Object.class, "writeObject")};
+ private final ConcurrentMap<FastField, Method> declaredCache = new ConcurrentHashMap<FastField, Method>();
+ private final ConcurrentMap<FastField, Method> resRepCache = new ConcurrentHashMap<FastField, Method>();
+ private final ConcurrentMap<String, Map<String, ObjectStreamField>> fieldCache = new ConcurrentHashMap<String, Map<String, ObjectStreamField>>();
+ {
+ for (final FastField element : OBJECT_TYPE_FIELDS) {
+ declaredCache.put(element, NO_METHOD);
+ }
+ for (final FastField element : Arrays.copyOf(OBJECT_TYPE_FIELDS, 2)) {
+ resRepCache.put(element, NO_METHOD);
+ }
+ }
+
+ /**
+ * Resolves an object as native serialization does by calling readResolve(), if available.
+ */
+ public Object callReadResolve(final Object result) {
+ if (result == null) {
+ return null;
+ } else {
+ final Class<? extends Object> resultType = result.getClass();
+ final Method readResolveMethod = getRRMethod(resultType, "readResolve");
+ if (readResolveMethod != null) {
+ try {
+ return readResolveMethod.invoke(result);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e
+ .getTargetException());
+ }
+ } else {
+ return result;
+ }
+ }
+ }
+
+ public Object callWriteReplace(final Object object) {
+ if (object == null) {
+ return null;
+ } else {
+ final Class<? extends Object> objectType = object.getClass();
+ final Method writeReplaceMethod = getRRMethod(objectType, "writeReplace");
+ if (writeReplaceMethod != null) {
+ try {
+ return writeReplaceMethod.invoke(object);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e
+ .getTargetException());
+ }
+ } else {
+ return object;
+ }
+ }
+ }
+
+ public boolean supportsReadObject(final Class<?> type, final boolean includeBaseClasses) {
+ return getMethod(type, "readObject", includeBaseClasses, ObjectInputStream.class) != null;
+ }
+
+ public void callReadObject(final Class<?> type, final Object object, final ObjectInputStream stream) {
+ try {
+ final Method readObjectMethod = getMethod(type, "readObject", false, ObjectInputStream.class);
+ readObjectMethod.invoke(object, stream);
+ } catch (final IllegalAccessException e) {
+ throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e
+ .getTargetException());
+ }
+ }
+
+ public boolean supportsWriteObject(final Class<?> type, final boolean includeBaseClasses) {
+ return getMethod(type, "writeObject", includeBaseClasses, ObjectOutputStream.class) != null;
+ }
+
+ public void callWriteObject(final Class<?> type, final Object instance, final ObjectOutputStream stream) {
+ try {
+ final Method readObjectMethod = getMethod(type, "writeObject", false, ObjectOutputStream.class);
+ readObjectMethod.invoke(instance, stream);
+ } catch (final IllegalAccessException e) {
+ throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e
+ .getTargetException());
+ }
+ }
+
+ private Method getMethod(final Class<?> type, final String name, final boolean includeBaseclasses,
+ final Class<?>... parameterTypes) {
+ final Method method = getMethod(type, name, parameterTypes);
+ return method == NO_METHOD || !includeBaseclasses && !method.getDeclaringClass().equals(type) ? null : method;
+ }
+
+ private Method getMethod(final Class<?> type, final String name, final Class<?>... parameterTypes) {
+ if (type == null) {
+ return null;
+ }
+ final FastField method = new FastField(type, name);
+ Method result = declaredCache.get(method);
+
+ if (result == null) {
+ try {
+ result = type.getDeclaredMethod(name, parameterTypes);
+ if (!result.isAccessible()) {
+ result.setAccessible(true);
+ }
+ } catch (final NoSuchMethodException e) {
+ result = getMethod(type.getSuperclass(), name, parameterTypes);
+ }
+ declaredCache.put(method, result);
+ }
+ return result;
+ }
+
+ private Method getRRMethod(final Class<?> type, final String name) {
+ final FastField method = new FastField(type, name);
+ Method result = resRepCache.get(method);
+ if (result == null) {
+ result = getMethod(type, name, true);
+ if (result != null && result.getDeclaringClass() != type) {
+ if ((result.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0) {
+ if ((result.getModifiers() & Modifier.PRIVATE) > 0
+ || type.getPackage() != result.getDeclaringClass().getPackage()) {
+ result = NO_METHOD;
+ }
+ }
+ } else if (result == null) {
+ result = NO_METHOD;
+ }
+ resRepCache.putIfAbsent(method, result);
+ }
+ return result == NO_METHOD ? null : result;
+ }
+
+ public Map<String, ObjectStreamField> getSerializablePersistentFields(final Class<?> type) {
+ if (type == null) {
+ return null;
+ }
+ Map<String, ObjectStreamField> result = fieldCache.get(type.getName());
+ if (result == null) {
+ try {
+ final Field field = type.getDeclaredField("serialPersistentFields");
+ if ((field.getModifiers() & PERSISTENT_FIELDS_MODIFIER) == PERSISTENT_FIELDS_MODIFIER) {
+ field.setAccessible(true);
+ final ObjectStreamField[] fields = (ObjectStreamField[])field.get(null);
+ if (fields != null) {
+ result = new HashMap<String, ObjectStreamField>();
+ for (final ObjectStreamField f : fields) {
+ result.put(f.getName(), f);
+ }
+ }
+ }
+ } catch (final NoSuchFieldException e) {
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
+ } catch (final ClassCastException e) {
+ throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
+ }
+ if (result == null) {
+ result = NO_FIELDS;
+ }
+ fieldCache.putIfAbsent(type.getName(), result);
+ }
+ return result == NO_FIELDS ? null : result;
+ }
+
+ @Override
+ public void flushCache() {
+ declaredCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+ resRepCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+ }
+}
Modified: trunk/xstream-distribution/src/content/changes.html (2332 => 2333)
--- trunk/xstream-distribution/src/content/changes.html 2015-02-12 23:11:00 UTC (rev 2332)
+++ trunk/xstream-distribution/src/content/changes.html 2015-02-14 16:44:43 UTC (rev 2333)
@@ -86,6 +86,7 @@
<li>c.t.x.converters.reflection.AbstractReflectionConverter.readResolve() is protected now.</li>
<li>c.t.x.mapper.AbstractAttributeAliasingMapper.readResolve() is protected now.</li>
<li>Deprecated c.t.x.converters.extended.StackTraceElementFactory, it is an internal helper class.</li>
+ <li>Deprecated c.t.x.converters.reflection.SerializationMethodInvoker, it is an internal helper class.</li>
<li>Deprecated c.t.x.io.AttributeNameIterator, it is an internal helper class.</li>
<li>Deprecated c.t.x.XStream.useXStream11XmlFriendlyMapper(), corresponding
c.t.x.mapper.XStream11XmlFriendlyMapper has been deprecated long ago.</li>
To unsubscribe from this list please visit:
