You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2017/07/11 17:55:37 UTC

[07/50] commons-collections git commit: Backport COLLECTIONS-266 to 3.2.2.

Backport COLLECTIONS-266 to 3.2.2.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/branches/COLLECTIONS_3_2_X@1713176 13f79535-47bb-0310-9956-ffa450edef68


Project: http://git-wip-us.apache.org/repos/asf/commons-collections/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-collections/commit/fd179052
Tree: http://git-wip-us.apache.org/repos/asf/commons-collections/tree/fd179052
Diff: http://git-wip-us.apache.org/repos/asf/commons-collections/diff/fd179052

Branch: refs/heads/COLLECTIONS_3_2_X
Commit: fd1790522e7dbb407dc281eab2d79c088d43362e
Parents: 3afb3cb
Author: Thomas Neidhart <tn...@apache.org>
Authored: Sat Nov 7 20:53:57 2015 +0000
Committer: Thomas Neidhart <tn...@apache.org>
Committed: Sat Nov 7 20:53:57 2015 +0000

----------------------------------------------------------------------
 src/changes/changes.xml                         |  6 +--
 .../commons/collections/keyvalue/MultiKey.java  | 38 ++++++++++----
 .../collections/keyvalue/TestMultiKey.java      | 55 +++++++++++++++++++-
 3 files changed, 86 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-collections/blob/fd179052/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index e06564d..0612b0f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -26,6 +26,9 @@
     <action issue="COLLECTIONS-335" dev="jochen" type="fix" due-to="sebb">
       Fixed cache assignment for "TreeBidiMap#entrySet".
     </action>
+    <action issue="COLLECTIONS-266" dev="bayard" type="fix" due-to="Joerg Schaible">
+      "MultiKey" will now be correctly serialized/de-serialized.
+    </action>
     <action issue="COLLECTIONS-249" dev="bayard" type="fix" due-to="Joe Kelly">
       "SetUniqueList.addAll(int, Collection)" now correctly add the collection at the
       provided index.
@@ -75,9 +78,6 @@
       "CaseInsensitiveMap" will now convert input strings to lower-case in a
       locale-independant manner.
     </action>
-    <action issue="COLLECTIONS-266" dev="bayard" type="fix" due-to="Joerg Schaible">
-      "MultiKey" will now be correctly serialized/de-serialized.
-    </action>
     <action issue="COLLECTIONS-261" dev="bayard" type="fix" due-to="ori">
       "Flat3Map#remove(Object)" will now return the correct value mapped to the removed key
       if the size of the map is less or equal 3.

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/fd179052/src/java/org/apache/commons/collections/keyvalue/MultiKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/keyvalue/MultiKey.java b/src/java/org/apache/commons/collections/keyvalue/MultiKey.java
index 7368443..1d9ab35 100644
--- a/src/java/org/apache/commons/collections/keyvalue/MultiKey.java
+++ b/src/java/org/apache/commons/collections/keyvalue/MultiKey.java
@@ -54,7 +54,7 @@ public class MultiKey implements Serializable {
     /** The individual keys */
     private final Object[] keys;
     /** The cached hashCode */
-    private final int hashCode;
+    private transient int hashCode;
     
     /**
      * Constructor taking two keys.
@@ -163,14 +163,8 @@ public class MultiKey implements Serializable {
         } else {
             this.keys = keys;
         }
-        
-        int total = 0;
-        for (int i = 0; i < keys.length; i++) {
-            if (keys[i] != null) {
-                total ^= keys[i].hashCode();
-            }
-        }
-        hashCode = total;
+
+        calculateHashCode(keys);        
     }
     
     //-----------------------------------------------------------------------
@@ -255,4 +249,30 @@ public class MultiKey implements Serializable {
         return "MultiKey" + Arrays.asList(keys).toString();
     }
 
+    /**
+     * Calculate the hash code of the instance using the provided keys.
+     * 
+     * @param keys
+     */
+    private void calculateHashCode(Object[] keys) {
+        int total = 0;
+        for (int i = 0; i < keys.length; i++) {
+            if (keys[i] != null) {
+                total ^= keys[i].hashCode();
+            }
+        }
+        hashCode = total;
+    }
+
+    /**
+     * Recalculate the hash code after deserialization.
+     * The hash code of some keys might have change (hash codes based
+     * on the system hash code are only stable for the same process).
+     * 
+     * @return the instance with recalculated hash code
+     */
+    private Object readResolve() {
+        calculateHashCode(keys);
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/fd179052/src/test/org/apache/commons/collections/keyvalue/TestMultiKey.java
----------------------------------------------------------------------
diff --git a/src/test/org/apache/commons/collections/keyvalue/TestMultiKey.java b/src/test/org/apache/commons/collections/keyvalue/TestMultiKey.java
index 316a784..f4704d2 100644
--- a/src/test/org/apache/commons/collections/keyvalue/TestMultiKey.java
+++ b/src/test/org/apache/commons/collections/keyvalue/TestMultiKey.java
@@ -16,7 +16,15 @@
  */
 package org.apache.commons.collections.keyvalue;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 
 import junit.framework.Assert;
 import junit.framework.Test;
@@ -205,5 +213,50 @@ public class TestMultiKey extends TestCase {
         Assert.assertTrue(mk1.equals("") == false);
         Assert.assertTrue(mk1.equals(null) == false);
     }
-    
+
+    static class SystemHashCodeSimulatingKey implements Serializable {
+        private static final long serialVersionUID = 1L;
+        private final String name;
+        private int hashCode = 1;
+
+        public SystemHashCodeSimulatingKey(String name) {
+            this.name = name;
+        }
+
+        public boolean equals(Object obj) {
+            return obj instanceof SystemHashCodeSimulatingKey
+                && name.equals(((SystemHashCodeSimulatingKey) obj).name);
+        }
+
+        public int hashCode() {
+            return hashCode;
+        }
+
+        private Object readResolve() {
+            hashCode = 2; // simulate different hashCode after deserialization in another process
+            return this;
+        }
+    }
+
+    public void testEqualsAfterSerialization() throws IOException, ClassNotFoundException {
+        SystemHashCodeSimulatingKey sysKey = new SystemHashCodeSimulatingKey("test");
+        MultiKey mk = new MultiKey(ONE, sysKey);
+        Map map = new HashMap();
+        map.put(mk, TWO);
+        // serialize
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream(baos);
+        out.writeObject(sysKey);
+        out.writeObject(map);
+        out.close();
+        // deserialize
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        ObjectInputStream in = new ObjectInputStream(bais);
+        sysKey = (SystemHashCodeSimulatingKey) in.readObject(); // simulate deserialization in another process
+        Map map2 = (Map) in.readObject();
+        in.close();
+        assertEquals(2, sysKey.hashCode()); // different hashCode now
+        MultiKey mk2 = new MultiKey(ONE, sysKey);
+        assertEquals(TWO, map2.get(mk2));
+    }
 }