Title: [2329] trunk: Support ignored serialPersistentField at deserialization time (XSTR-761).

Diff

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (2328 => 2329)


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java	2015-02-11 23:57:37 UTC (rev 2328)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java	2015-02-12 22:40:06 UTC (rev 2329)
@@ -416,6 +416,10 @@
 
             @Override
             public void defaultReadObject() {
+                if (serializationMethodInvoker.getSerializablePersistentFields(currentType[0]) != null) {
+                    readFieldsFromStream();
+                    return;
+                }
                 if (!reader.hasMoreChildren()) {
                     return;
                 }

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


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java	2015-02-11 23:57:37 UTC (rev 2328)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java	2015-02-12 22:40:06 UTC (rev 2329)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2014 XStream Committers.
+ * 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
@@ -13,11 +13,15 @@
 
 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;
 
@@ -39,13 +43,14 @@
         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>(
-            new HashMap<FastField, Method>());
-    private final ConcurrentMap<FastField, Method> resRepCache = new ConcurrentHashMap<FastField, Method>(
-            new HashMap<FastField, Method>());
+    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);
@@ -179,6 +184,38 @@
         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));

Modified: trunk/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java (2328 => 2329)


--- trunk/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java	2015-02-11 23:57:37 UTC (rev 2328)
+++ trunk/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java	2015-02-12 22:40:06 UTC (rev 2329)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 XStream Committers.
+ * Copyright (C) 2012, 2015 XStream Committers.
  * All rights reserved.
  *
  * The software in this package is published under the terms of the BSD
@@ -10,16 +10,20 @@
  */
 package com.thoughtworks.acceptance;
 
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.thoughtworks.xstream.core.JVM;
+
+
 public class Concurrent15TypesTest extends AbstractAcceptanceTest {
-    
+
     public void testConcurrentHashMap() {
         ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
         map.put("walnes", "joe");
         String xml = xstream.toXML(map);
-        String expected = 
-               "<concurrent-hash-map>\n"
+        String expected = ""
+            + "<concurrent-hash-map>\n"
             + "  <entry>\n"
             + "    <string>walnes</string>\n"
             + "    <string>joe</string>\n"
@@ -27,7 +31,36 @@
             + "</concurrent-hash-map>";
         assertEquals(xml, expected);
         @SuppressWarnings("unchecked")
-        ConcurrentHashMap<String, String> out = (ConcurrentHashMap<String, String>) xstream.fromXML(xml);
+        ConcurrentHashMap<String, String> out = (ConcurrentHashMap<String, String>)xstream.fromXML(xml);
         assertEquals("{walnes=joe}", out.toString());
     }
+
+    public static class DerivedConcurrentHashMap extends ConcurrentHashMap<Object, Object> {
+        private static final long serialVersionUID = 1L;
+    }
+
+    public void testDerivedConcurrentHashMap() {
+        if (JVM.is18()) {
+            xstream.alias("derived-map", DerivedConcurrentHashMap.class);
+
+            Map<Object, Object> map = new DerivedConcurrentHashMap();
+            map.put("test", "JUnit");
+
+            String xml = ""
+                + "<derived-map serialization=\"custom\">\n"
+                + "  <unserializable-parents/>\n"
+                + "  <concurrent-hash-map>\n"
+                + "    <default>\n"
+                + "      <segmentMask>15</segmentMask>\n"
+                + "    </default>\n"
+                + "    <string>test</string>\n"
+                + "    <string>JUnit</string>\n"
+                + "    <null/>\n"
+                + "    <null/>\n"
+                + "  </concurrent-hash-map>\n"
+                + "</derived-map>";
+
+            assertBothWays(map, xml);
+        }
+    }
 }

Modified: trunk/xstream/src/test/com/thoughtworks/acceptance/CustomSerializationTest.java (2328 => 2329)


--- trunk/xstream/src/test/com/thoughtworks/acceptance/CustomSerializationTest.java	2015-02-11 23:57:37 UTC (rev 2328)
+++ trunk/xstream/src/test/com/thoughtworks/acceptance/CustomSerializationTest.java	2015-02-12 22:40:06 UTC (rev 2329)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
  * All rights reserved.
  *
  * The software in this package is published under the terms of the BSD
@@ -519,4 +519,42 @@
 
         assertBothWays(input, expectedXml);
     }
+    
+    public static class ObjectThatWritesCustomFieldsButDoesNotReadThem extends StandardObject implements Serializable {
+
+        private static final ObjectStreamField[] serialPersistentFields = {
+            new ObjectStreamField("number", int.class),
+            new ObjectStreamField("name", String.class),
+        };
+
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            ObjectOutputStream.PutField fields = out.putFields();
+            fields.put("name", "test");
+            fields.put("number", 42);
+            out.writeFields();
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+            in.defaultReadObject();
+        }
+
+    }
+
+    public void testSupportsPutFieldsWithoutGetFields() {
+        xstream.alias("an-object", ObjectThatWritesCustomFieldsButDoesNotReadThem.class);
+
+        ObjectThatWritesCustomFieldsButDoesNotReadThem input = new ObjectThatWritesCustomFieldsButDoesNotReadThem();
+
+        String expectedXml = ""
+                + "<an-object serialization=\"custom\">\n"
+                + "  <an-object>\n"
+                + "    <default>\n"
+                + "      <name>test</name>\n"
+                + "      <number>42</number>\n"
+                + "    </default>\n"
+                + "  </an-object>\n"
+                + "</an-object>";
+
+        assertBothWays(input, expectedXml);
+    }
 }

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


--- trunk/xstream-distribution/src/content/changes.html	2015-02-11 23:57:37 UTC (rev 2328)
+++ trunk/xstream-distribution/src/content/changes.html	2015-02-12 22:40:06 UTC (rev 2329)
@@ -67,6 +67,7 @@
     	<li>Detect Java 9 runtime.</li>
     	<li>XSTR-767: Deserialization of referenced lambda expressions fail.</li>
     	<li>XSTR-762: Private method readResolve() called on base classes.</li>
+    	<li>XSTR-761: Support ignored serialPersistentField at deserialization time.</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>

To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to