Title: [2301] trunk: Private method readResolve() called on base classes (XSTR-762).

Diff

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (2300 => 2301)


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -53,7 +53,7 @@
     public AbstractReflectionConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
         this.mapper = mapper;
         this.reflectionProvider = reflectionProvider;
-        init();
+        serializationMethodInvoker = new SerializationMethodInvoker();
     }
 
     protected boolean canAccess(final Class<?> type) {
@@ -532,12 +532,8 @@
         serializationMethodInvoker.flushCache();
     }
 
-    protected void init() {
+    protected Object readResolve() {
         serializationMethodInvoker = new SerializationMethodInvoker();
-    }
-
-    private Object readResolve() {
-        init();
         return this;
     }
 

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (2300 => 2301)


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -435,8 +435,9 @@
         return typeHierarchy;
     }
 
-    private Object readResolve() {
-        init();
+    @Override
+    protected Object readResolve() {
+        super.readResolve();
         fieldCache = new HashMap<String, List<Field>>();
         return this;
     }

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java (2300 => 2301)


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -6,7 +6,7 @@
  * 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 23. August 2004 by Joe Walnes
  */
 package com.thoughtworks.xstream.converters.reflection;
@@ -15,10 +15,11 @@
 import java.io.ObjectOutputStream;
 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;
@@ -27,7 +28,7 @@
 
 /**
  * Convenience wrapper to invoke special serialization methods on objects (and perform reflection caching).
- * 
+ *
  * @author Joe Walnes
  * @author J&ouml;rg Schaible
  */
@@ -38,14 +39,20 @@
         private void noMethod() {
         }
     }.getClass().getDeclaredMethods()[0];
-    private static final FastField[] OBJECT_TYPE_FIELDS = new FastField[]{
+    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 Map<FastField, Method> cache = Collections.synchronizedMap(new HashMap<FastField, Method>());
+    private final ConcurrentMap<FastField, Method> declaredCache = new ConcurrentHashMap<FastField, Method>(
+            new HashMap<FastField, Method>());
+    private final ConcurrentMap<FastField, Method> resRepCache = new ConcurrentHashMap<FastField, Method>(
+            new HashMap<FastField, Method>());
     {
         for (final FastField element : OBJECT_TYPE_FIELDS) {
-            cache.put(element, NO_METHOD);
+            declaredCache.put(element, NO_METHOD);
         }
+        for (final FastField element : Arrays.copyOf(OBJECT_TYPE_FIELDS, 2)) {
+            resRepCache.put(element, NO_METHOD);
+        }
     }
 
     /**
@@ -55,16 +62,16 @@
         if (result == null) {
             return null;
         } else {
-            final Method readResolveMethod = getMethod(result.getClass(), "readResolve", true);
+            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 " + result.getClass().getName() + ".readResolve()",
-                        e);
+                    throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e);
                 } catch (final InvocationTargetException e) {
-                    throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()",
-                        e.getTargetException());
+                    throw new ObjectAccessException("Could not call " + resultType.getName() + ".readResolve()", e
+                        .getTargetException());
                 }
             } else {
                 return result;
@@ -76,16 +83,16 @@
         if (object == null) {
             return null;
         } else {
-            final Method writeReplaceMethod = getMethod(object.getClass(), "writeReplace", true);
+            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 " + object.getClass().getName() + ".writeReplace()", e);
+                    throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e);
                 } catch (final InvocationTargetException e) {
-                    throw new ObjectAccessException(
-                        "Could not call " + object.getClass().getName() + ".writeReplace()", e.getTargetException());
+                    throw new ObjectAccessException("Could not call " + objectType.getName() + ".writeReplace()", e
+                        .getTargetException());
                 }
             } else {
                 return object;
@@ -136,7 +143,7 @@
             return null;
         }
         final FastField method = new FastField(type, name);
-        Method result = cache.get(method);
+        Method result = declaredCache.get(method);
 
         if (result == null) {
             try {
@@ -147,13 +154,34 @@
             } catch (final NoSuchMethodException e) {
                 result = getMethod(type.getSuperclass(), name, parameterTypes);
             }
-            cache.put(method, result);
+            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;
+    }
+
     @Override
     public void flushCache() {
-        cache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+        declaredCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+        resRepCache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
     }
 }

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/mapper/AbstractAttributeAliasingMapper.java (2300 => 2301)


--- trunk/xstream/src/java/com/thoughtworks/xstream/mapper/AbstractAttributeAliasingMapper.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/mapper/AbstractAttributeAliasingMapper.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -34,7 +34,7 @@
         nameToAlias.put(attributeName, alias);
     }
 
-    private Object readResolve() {
+    Object readResolve() {
         nameToAlias = new HashMap<String, String>();
         for (final Map.Entry<String, String> entry : aliasToName.entrySet()) {
             nameToAlias.put(entry.getValue(), entry.getKey());

Modified: trunk/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java (2300 => 2301)


--- trunk/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -397,7 +397,7 @@
             return true;
         }
 
-        private Object writeReplace() {
+        protected Object writeReplace() {
             if (getClass() == TreeData.class) {
                 return this;
             }

Modified: trunk/xstream/src/test/com/thoughtworks/acceptance/SerializationCallbackOrderTest.java (2300 => 2301)


--- trunk/xstream/src/test/com/thoughtworks/acceptance/SerializationCallbackOrderTest.java	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream/src/test/com/thoughtworks/acceptance/SerializationCallbackOrderTest.java	2014-10-30 12:58:59 UTC (rev 2301)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2014 XStream Committers.
  * All rights reserved.
  *
  * The software in this package is published under the terms of the BSD
@@ -26,64 +26,214 @@
     // static so it can be accessed by objects under test, without them needing a reference back to the testcase
     private static CallLog log = new CallLog();
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         log.reset();
     }
    
 
-    // --- Sample class hiearchy
+    // --- Sample class hierarchy
 
-    public static class Base implements Serializable{
+    public static class PrivateBase implements Serializable{
 
         private void writeObject(ObjectOutputStream out) throws IOException {
-            log.actual("Base.writeObject() start");
+            log.actual("PrivateBase.writeObject() start");
             out.defaultWriteObject();
-            log.actual("Base.writeObject() end");
+            log.actual("PrivateBase.writeObject() end");
         }
 
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            log.actual("Base.readObject() start");
+            log.actual("PrivateBase.readObject() start");
             in.defaultReadObject();
-            log.actual("Base.readObject() end");
+            log.actual("PrivateBase.readObject() end");
         }
 
         private Object writeReplace() {
-            log.actual("Base.writeReplace()");
+            log.actual("PrivateBase.writeReplace()");
             return this;
         }
 
         private Object readResolve() {
-            log.actual("Base.readResolve()");
+            log.actual("PrivateBase.readResolve()");
             return this;
         }
     }
 
-    public static class Child extends Base implements Serializable{
+    public static class PrivateChildOwnRR extends PrivateBase implements Serializable{
 
         private void writeObject(ObjectOutputStream out) throws IOException {
-            log.actual("Child.writeObject() start");
+            log.actual("PrivateChildOwnRR.writeObject() start");
             out.defaultWriteObject();
-            log.actual("Child.writeObject() end");
+            log.actual("PrivateChildOwnRR.writeObject() end");
         }
 
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            log.actual("Child.readObject() start");
+            log.actual("PrivateChildOwnRR.readObject() start");
             in.defaultReadObject();
-            log.actual("Child.readObject() end");
+            log.actual("PrivateChildOwnRR.readObject() end");
         }
 
         private Object writeReplace() {
-            log.actual("Child.writeReplace()");
+            log.actual("PrivateChildOwnRR.writeReplace()");
             return this;
         }
 
         private Object readResolve() {
-            log.actual("Child.readResolve()");
+            log.actual("PrivateChildOwnRR.readResolve()");
             return this;
         }
     }
 
+    public static class PrivateChildNoRR extends PrivateBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("PrivateChildNoRR.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("PrivateChildNoRR.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("PrivateChildNoRR.readObject() start");
+            in.defaultReadObject();
+            log.actual("PrivateChildNoRR.readObject() end");
+        }
+    }
+    
+    public static class ProtectedBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("ProtectedBase.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("ProtectedBase.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("ProtectedBase.readObject() start");
+            in.defaultReadObject();
+            log.actual("ProtectedBase.readObject() end");
+        }
+
+        protected Object writeReplace() {
+            log.actual("ProtectedBase.writeReplace()");
+            return this;
+        }
+
+        protected Object readResolve() {
+            log.actual("ProtectedBase.readResolve()");
+            return this;
+        }
+    }
+
+    public static class ProtectedChildOwnRR extends ProtectedBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("ProtectedChildOwnRR.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("ProtectedChildOwnRR.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("ProtectedChildOwnRR.readObject() start");
+            in.defaultReadObject();
+            log.actual("ProtectedChildOwnRR.readObject() end");
+        }
+
+        @Override
+        protected Object writeReplace() {
+            log.actual("ProtectedChildOwnRR.writeReplace()");
+            return this;
+        }
+
+        @Override
+        protected Object readResolve() {
+            log.actual("ProtectedChildOwnRR.readResolve()");
+            return this;
+        }
+    }
+
+    public static class ProtectedChildInheritedRR extends ProtectedBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("ProtectedChildInheritedRR.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("ProtectedChildInheritedRR.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("ProtectedChildInheritedRR.readObject() start");
+            in.defaultReadObject();
+            log.actual("ProtectedChildInheritedRR.readObject() end");
+        }
+    }
+    
+    public static class PackageBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("PackageBase.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("PackageBase.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("PackageBase.readObject() start");
+            in.defaultReadObject();
+            log.actual("PackageBase.readObject() end");
+        }
+
+        Object writeReplace() {
+            log.actual("PackageBase.writeReplace()");
+            return this;
+        }
+
+        Object readResolve() {
+            log.actual("PackageBase.readResolve()");
+            return this;
+        }
+    }
+
+    public static class PackageChildOwnRR extends PackageBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("PackageChildOwnRR.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("PackageChildOwnRR.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("PackageChildOwnRR.readObject() start");
+            in.defaultReadObject();
+            log.actual("PackageChildOwnRR.readObject() end");
+        }
+
+        @Override
+        Object writeReplace() {
+            log.actual("PackageChildOwnRR.writeReplace()");
+            return this;
+        }
+
+        @Override
+        Object readResolve() {
+            log.actual("PackageChildOwnRR.readResolve()");
+            return this;
+        }
+    }
+
+    public static class PackageChildInheritedRR extends PackageBase implements Serializable{
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            log.actual("PackageChildInheritedRR.writeObject() start");
+            out.defaultWriteObject();
+            log.actual("PackageChildInheritedRR.writeObject() end");
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            log.actual("PackageChildInheritedRR.readObject() start");
+            in.defaultReadObject();
+            log.actual("PackageChildInheritedRR.readObject() end");
+        }
+    }
+
     // --- Convenience wrappers around Java Object Serialization
 
     private byte[] javaSerialize(Object object) throws IOException {
@@ -101,47 +251,195 @@
 
     // --- Tests
 
-    public void testJavaSerialization() throws IOException {
+    public void testJavaSerializationOwnPrivateRR() throws IOException {
         // expectations
-        log.expect("Child.writeReplace()");
-        log.expect("Base.writeObject() start");
-        log.expect("Base.writeObject() end");
-        log.expect("Child.writeObject() start");
-        log.expect("Child.writeObject() end");
+        log.expect("PrivateChildOwnRR.writeReplace()");
+        log.expect("PrivateBase.writeObject() start");
+        log.expect("PrivateBase.writeObject() end");
+        log.expect("PrivateChildOwnRR.writeObject() start");
+        log.expect("PrivateChildOwnRR.writeObject() end");
 
         // execute
-        javaSerialize(new Child());
+        javaSerialize(new PrivateChildOwnRR());
 
         // verify
         log.verify();
     }
 
-    public void testXStreamSerialization() {
+    public void testJavaSerializationNoRR() throws IOException {
         // expectations
-        log.expect("Child.writeReplace()");
-        log.expect("Base.writeObject() start");
-        log.expect("Base.writeObject() end");
-        log.expect("Child.writeObject() start");
-        log.expect("Child.writeObject() end");
+        log.expect("PrivateBase.writeObject() start");
+        log.expect("PrivateBase.writeObject() end");
+        log.expect("PrivateChildNoRR.writeObject() start");
+        log.expect("PrivateChildNoRR.writeObject() end");
 
         // execute
-        xstream.toXML(new Child());
+        javaSerialize(new PrivateChildNoRR());
 
         // verify
         log.verify();
     }
 
-    public void testJavaDeserialization() throws IOException, ClassNotFoundException {
+    public void testJavaSerializationOwnProtectedRR() throws IOException {
+        // expectations
+        log.expect("ProtectedChildOwnRR.writeReplace()");
+        log.expect("ProtectedBase.writeObject() start");
+        log.expect("ProtectedBase.writeObject() end");
+        log.expect("ProtectedChildOwnRR.writeObject() start");
+        log.expect("ProtectedChildOwnRR.writeObject() end");
+
+        // execute
+        javaSerialize(new ProtectedChildOwnRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaSerializationInheritedRR() throws IOException {
+        // expectations
+        log.expect("ProtectedBase.writeReplace()");
+        log.expect("ProtectedBase.writeObject() start");
+        log.expect("ProtectedBase.writeObject() end");
+        log.expect("ProtectedChildInheritedRR.writeObject() start");
+        log.expect("ProtectedChildInheritedRR.writeObject() end");
+
+        // execute
+        javaSerialize(new ProtectedChildInheritedRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaSerializationOwnPackageRR() throws IOException {
+        // expectations
+        log.expect("PackageChildOwnRR.writeReplace()");
+        log.expect("PackageBase.writeObject() start");
+        log.expect("PackageBase.writeObject() end");
+        log.expect("PackageChildOwnRR.writeObject() start");
+        log.expect("PackageChildOwnRR.writeObject() end");
+
+        // execute
+        javaSerialize(new PackageChildOwnRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaSerializationInheritedPackageRR() throws IOException {
+        // expectations
+        log.expect("PackageBase.writeReplace()");
+        log.expect("PackageBase.writeObject() start");
+        log.expect("PackageBase.writeObject() end");
+        log.expect("PackageChildInheritedRR.writeObject() start");
+        log.expect("PackageChildInheritedRR.writeObject() end");
+
+        // execute
+        javaSerialize(new PackageChildInheritedRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationOwnPrivateRR() {
+        // expectations
+        log.expect("PrivateChildOwnRR.writeReplace()");
+        log.expect("PrivateBase.writeObject() start");
+        log.expect("PrivateBase.writeObject() end");
+        log.expect("PrivateChildOwnRR.writeObject() start");
+        log.expect("PrivateChildOwnRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new PrivateChildOwnRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationNoRR() {
+        // expectations
+        log.expect("PrivateBase.writeObject() start");
+        log.expect("PrivateBase.writeObject() end");
+        log.expect("PrivateChildNoRR.writeObject() start");
+        log.expect("PrivateChildNoRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new PrivateChildNoRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationOwnProtectedRR() {
+        // expectations
+        log.expect("ProtectedChildOwnRR.writeReplace()");
+        log.expect("ProtectedBase.writeObject() start");
+        log.expect("ProtectedBase.writeObject() end");
+        log.expect("ProtectedChildOwnRR.writeObject() start");
+        log.expect("ProtectedChildOwnRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new ProtectedChildOwnRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationOwnInheritedRR() {
+        // expectations
+        log.expect("ProtectedBase.writeReplace()");
+        log.expect("ProtectedBase.writeObject() start");
+        log.expect("ProtectedBase.writeObject() end");
+        log.expect("ProtectedChildInheritedRR.writeObject() start");
+        log.expect("ProtectedChildInheritedRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new ProtectedChildInheritedRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationOwnPackageRR() {
+        // expectations
+        log.expect("PackageChildOwnRR.writeReplace()");
+        log.expect("PackageBase.writeObject() start");
+        log.expect("PackageBase.writeObject() end");
+        log.expect("PackageChildOwnRR.writeObject() start");
+        log.expect("PackageChildOwnRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new PackageChildOwnRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamSerializationOwnInheritedPackageRR() {
+        // expectations
+        log.expect("PackageBase.writeReplace()");
+        log.expect("PackageBase.writeObject() start");
+        log.expect("PackageBase.writeObject() end");
+        log.expect("PackageChildInheritedRR.writeObject() start");
+        log.expect("PackageChildInheritedRR.writeObject() end");
+
+        // execute
+        xstream.toXML(new PackageChildInheritedRR());
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaDeserializationOwnPrivateRR() throws IOException, ClassNotFoundException {
         // setup
-        byte[] data = "" Child());
+        byte[] data = "" PrivateChildOwnRR());
         log.reset();
 
         // expectations
-        log.expect("Base.readObject() start");
-        log.expect("Base.readObject() end");
-        log.expect("Child.readObject() start");
-        log.expect("Child.readObject() end");
-        log.expect("Child.readResolve()");
+        log.expect("PrivateBase.readObject() start");
+        log.expect("PrivateBase.readObject() end");
+        log.expect("PrivateChildOwnRR.readObject() start");
+        log.expect("PrivateChildOwnRR.readObject() end");
+        log.expect("PrivateChildOwnRR.readResolve()");
 
         // execute
         javaDeserialize(data);
@@ -150,26 +448,213 @@
         log.verify();
     }
 
-    public void testXStreamDeserialization() {
+    public void testJavaDeserializationNoRR() throws IOException, ClassNotFoundException {
         // setup
-        String data = "" Child());
+        byte[] data = "" PrivateChildNoRR());
         log.reset();
 
         // expectations
-        log.expect("Base.readObject() start");
-        log.expect("Base.readObject() end");
-        log.expect("Child.readObject() start");
-        log.expect("Child.readObject() end");
-        log.expect("Child.readResolve()");
+        log.expect("PrivateBase.readObject() start");
+        log.expect("PrivateBase.readObject() end");
+        log.expect("PrivateChildNoRR.readObject() start");
+        log.expect("PrivateChildNoRR.readObject() end");
 
         // execute
+        javaDeserialize(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaDeserializationOwnProtectedRR() throws IOException, ClassNotFoundException {
+        // setup
+        byte[] data = "" ProtectedChildOwnRR());
+        log.reset();
+
+        // expectations
+        log.expect("ProtectedBase.readObject() start");
+        log.expect("ProtectedBase.readObject() end");
+        log.expect("ProtectedChildOwnRR.readObject() start");
+        log.expect("ProtectedChildOwnRR.readObject() end");
+        log.expect("ProtectedChildOwnRR.readResolve()");
+
+        // execute
+        javaDeserialize(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaDeserializationInheritedRR() throws IOException, ClassNotFoundException {
+        // setup
+        byte[] data = "" ProtectedChildInheritedRR());
+        log.reset();
+
+        // expectations
+        log.expect("ProtectedBase.readObject() start");
+        log.expect("ProtectedBase.readObject() end");
+        log.expect("ProtectedChildInheritedRR.readObject() start");
+        log.expect("ProtectedChildInheritedRR.readObject() end");
+        log.expect("ProtectedBase.readResolve()");
+
+        // execute
+        javaDeserialize(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaDeserializationOwnPackageRR() throws IOException, ClassNotFoundException {
+        // setup
+        byte[] data = "" PackageChildOwnRR());
+        log.reset();
+
+        // expectations
+        log.expect("PackageBase.readObject() start");
+        log.expect("PackageBase.readObject() end");
+        log.expect("PackageChildOwnRR.readObject() start");
+        log.expect("PackageChildOwnRR.readObject() end");
+        log.expect("PackageChildOwnRR.readResolve()");
+
+        // execute
+        javaDeserialize(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testJavaDeserializationInheritedPackageRR() throws IOException, ClassNotFoundException {
+        // setup
+        byte[] data = "" PackageChildInheritedRR());
+        log.reset();
+
+        // expectations
+        log.expect("PackageBase.readObject() start");
+        log.expect("PackageBase.readObject() end");
+        log.expect("PackageChildInheritedRR.readObject() start");
+        log.expect("PackageChildInheritedRR.readObject() end");
+        log.expect("PackageBase.readResolve()");
+
+        // execute
+        javaDeserialize(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamDeserializationOwnPrivateRR() {
+        // setup
+        String data = "" PrivateChildOwnRR());
+        log.reset();
+
+        // expectations
+        log.expect("PrivateBase.readObject() start");
+        log.expect("PrivateBase.readObject() end");
+        log.expect("PrivateChildOwnRR.readObject() start");
+        log.expect("PrivateChildOwnRR.readObject() end");
+        log.expect("PrivateChildOwnRR.readResolve()");
+
+        // execute
         xstream.fromXML(data);
 
         // verify
         log.verify();
     }
 
+    public void testXStreamDeserializationNoRR() {
+        // setup
+        String data = "" PrivateChildNoRR());
+        log.reset();
 
+        // expectations
+        log.expect("PrivateBase.readObject() start");
+        log.expect("PrivateBase.readObject() end");
+        log.expect("PrivateChildNoRR.readObject() start");
+        log.expect("PrivateChildNoRR.readObject() end");
+
+        // execute
+        xstream.fromXML(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamDeserializationOwnProtectedRR() {
+        // setup
+        String data = "" ProtectedChildOwnRR());
+        log.reset();
+
+        // expectations
+        log.expect("ProtectedBase.readObject() start");
+        log.expect("ProtectedBase.readObject() end");
+        log.expect("ProtectedChildOwnRR.readObject() start");
+        log.expect("ProtectedChildOwnRR.readObject() end");
+        log.expect("ProtectedChildOwnRR.readResolve()");
+
+        // execute
+        xstream.fromXML(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamDeserializationInheritedRR() {
+        // setup
+        String data = "" ProtectedChildInheritedRR());
+        log.reset();
+
+        // expectations
+        log.expect("ProtectedBase.readObject() start");
+        log.expect("ProtectedBase.readObject() end");
+        log.expect("ProtectedChildInheritedRR.readObject() start");
+        log.expect("ProtectedChildInheritedRR.readObject() end");
+        log.expect("ProtectedBase.readResolve()");
+
+        // execute
+        xstream.fromXML(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamDeserializationOwnPackageRR() {
+        // setup
+        String data = "" PackageChildOwnRR());
+        log.reset();
+
+        // expectations
+        log.expect("PackageBase.readObject() start");
+        log.expect("PackageBase.readObject() end");
+        log.expect("PackageChildOwnRR.readObject() start");
+        log.expect("PackageChildOwnRR.readObject() end");
+        log.expect("PackageChildOwnRR.readResolve()");
+
+        // execute
+        xstream.fromXML(data);
+
+        // verify
+        log.verify();
+    }
+
+    public void testXStreamDeserializationInheritedPackageRR() {
+        // setup
+        String data = "" PackageChildInheritedRR());
+        log.reset();
+
+        // expectations
+        log.expect("PackageBase.readObject() start");
+        log.expect("PackageBase.readObject() end");
+        log.expect("PackageChildInheritedRR.readObject() start");
+        log.expect("PackageChildInheritedRR.readObject() end");
+        log.expect("PackageBase.readResolve()");
+
+        // execute
+        xstream.fromXML(data);
+
+        // verify
+        log.verify();
+    }
+
     public static class ParentNotTransient implements Serializable {
 
         public int somethingNotTransient;

Modified: trunk/xstream-distribution/src/content/changes.html (2300 => 2301)


--- trunk/xstream-distribution/src/content/changes.html	2014-10-02 18:00:26 UTC (rev 2300)
+++ trunk/xstream-distribution/src/content/changes.html	2014-10-30 12:58:59 UTC (rev 2301)
@@ -60,6 +60,7 @@
     <h2>Minor changes</h2>
     
     <ul>
+    	<li>XSTR-762: Private method readResolve() called on base classes.</li>
     	<li>XSTR-755: ExternalizableConverter does not respect writeReplace and readResolve.</li>
     	<li>XSTR-757: Deserialized TreeSet does not honor remove(Object) return value contract.</li>
     	<li>Fix: DateConverter ignores provided locale.</li>
@@ -71,6 +72,8 @@
     <h2>API changes</h2>
     
     <ul>
+    	<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.io.AttributeNameIterator, it is an internal helper class.</li>
     	<li>Deprecated c.t.x.XStream.useXStream11XmlFriendlyMapper(), corresponding

To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to