Author: ehillenius
Date: Mon Feb 12 12:18:29 2007
New Revision: 506617

URL: http://svn.apache.org/viewvc?view=rev&rev=506617
Log:
use identity table rather than object hasCode based

Modified:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/SerializableChecker.java

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/SerializableChecker.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/SerializableChecker.java?view=diff&rev=506617&r1=506616&r2=506617
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/SerializableChecker.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/SerializableChecker.java
 Mon Feb 12 12:18:29 2007
@@ -29,9 +29,9 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
@@ -79,6 +79,134 @@
        }
 
        /**
+        * Lightweight identity hash table which maps objects to integer 
handles,
+        * assigned in ascending order (comes from [EMAIL PROTECTED] 
ObjectOutputStream}).
+        */
+       private static final class HandleTable
+       {
+               /* number of mappings in table/next available handle */
+               private int size;
+               /* size threshold determining when to expand hash spine */
+               private int threshold;
+               /* factor for computing size threshold */
+               private final float loadFactor;
+               /* maps hash value -> candidate handle value */
+               private int[] spine;
+               /* maps handle value -> next candidate handle value */
+               private int[] next;
+               /* maps handle value -> associated object */
+               private Object[] objs;
+
+               HandleTable(int initialCapacity, float loadFactor)
+               {
+                       this.loadFactor = loadFactor;
+                       spine = new int[initialCapacity];
+                       next = new int[initialCapacity];
+                       objs = new Object[initialCapacity];
+                       threshold = (int)(initialCapacity * loadFactor);
+                       clear();
+               }
+
+               private void growEntries()
+               {
+                       int newLength = (next.length << 1) + 1;
+                       int[] newNext = new int[newLength];
+                       System.arraycopy(next, 0, newNext, 0, size);
+                       next = newNext;
+
+                       Object[] newObjs = new Object[newLength];
+                       System.arraycopy(objs, 0, newObjs, 0, size);
+                       objs = newObjs;
+               }
+
+               private void growSpine()
+               {
+                       spine = new int[(spine.length << 1) + 1];
+                       threshold = (int)(spine.length * loadFactor);
+                       Arrays.fill(spine, -1);
+                       for (int i = 0; i < size; i++)
+                       {
+                               insert(objs[i], i);
+                       }
+               }
+
+               private int hash(Object obj)
+               {
+                       return System.identityHashCode(obj) & 0x7FFFFFFF;
+               }
+
+               private void insert(Object obj, int handle)
+               {
+                       int index = hash(obj) % spine.length;
+                       objs[handle] = obj;
+                       next[handle] = spine[index];
+                       spine[index] = handle;
+               }
+
+               /**
+                * Assigns next available handle to given object, and returns 
handle
+                * value. Handles are assigned in ascending order starting at 0.
+                * 
+                * @param obj
+                * @return
+                */
+               int assign(Object obj)
+               {
+                       if (size >= next.length)
+                       {
+                               growEntries();
+                       }
+                       if (size >= threshold)
+                       {
+                               growSpine();
+                       }
+                       insert(obj, size);
+                       return size++;
+               }
+
+               void clear()
+               {
+                       Arrays.fill(spine, -1);
+                       Arrays.fill(objs, 0, size, null);
+                       size = 0;
+               }
+
+               boolean contains(Object obj)
+               {
+                       return lookup(obj) != -1;
+               }
+
+               /**
+                * Looks up and returns handle associated with given object, or 
-1 if no
+                * mapping found.
+                * 
+                * @param obj
+                * @return
+                */
+               int lookup(Object obj)
+               {
+                       if (size == 0)
+                       {
+                               return -1;
+                       }
+                       int index = hash(obj) % spine.length;
+                       for (int i = spine[index]; i >= 0; i = next[i])
+                       {
+                               if (objs[i] == obj)
+                               {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               }
+
+               int size()
+               {
+                       return size;
+               }
+       }
+
+       /**
         * Does absolutely nothing.
         */
        private static class NoopOutputStream extends OutputStream
@@ -270,7 +398,7 @@
        private final LinkedList traceStack = new LinkedList();
 
        /** set for checking circular references. */
-       private final HashSet checked = new HashSet();
+       private final HandleTable checked = new HandleTable(10, (float)3.00);
 
        /** string stack with current names pushed. */
        private LinkedList nameStack = new LinkedList();
@@ -355,7 +483,7 @@
                }
                else if (cls.isArray())
                {
-                       checked.add(obj);
+                       checked.assign(obj);
                        Class ccl = cls.getComponentType();
                        if (!(ccl.isPrimitive()))
                        {
@@ -380,22 +508,13 @@
 
                                        public void writeObject(Object 
streamObj) throws IOException
                                        {
-                                               try
-                                               {
-                                                       // Check for circular 
reference.
-                                                       if 
(checked.contains(streamObj))
-                                                       {
-                                                               return;
-                                                       }
-                                               }
-                                               catch (Exception e)
+                                               // Check for circular reference.
+                                               if (checked.contains(streamObj))
                                                {
-                                                       log.warn("error 
invoking hashCode: " + e.getMessage() + ", path:"
-                                                                       + 
currentPath() + ": ");
                                                        return;
                                                }
 
-                                               checked.add(streamObj);
+                                               checked.assign(streamObj);
                                                String arrayPos = "[write:" + 
count++ + "]";
                                                simpleName = arrayPos;
                                                fieldDescription += arrayPos;
@@ -464,22 +583,13 @@
                                                }
 
                                                counter++;
-                                               try
-                                               {
-                                                       // Check for circular 
reference.
-                                                       if 
(checked.contains(streamObj))
-                                                       {
-                                                               return null;
-                                                       }
-                                               }
-                                               catch (Exception e)
+                                               // Check for circular reference.
+                                               if (checked.contains(streamObj))
                                                {
-                                                       log.warn("error 
invoking hashCode: " + e.getMessage() + ", path:"
-                                                                       + 
currentPath() + ": ");
                                                        return null;
                                                }
 
-                                               checked.add(obj);
+                                               checked.assign(obj);
                                                String arrayPos = "[write:" + 
counter + "]";
                                                simpleName = arrayPos;
                                                fieldDescription += arrayPos;
@@ -526,7 +636,7 @@
                                        {
                                                throw new RuntimeException(e);
                                        }
-                                       checked.add(obj);
+                                       checked.assign(obj);
                                        checkFields(obj, slotDesc);
                                }
                        }
@@ -580,18 +690,9 @@
                                        continue;
                                }
 
-                               try
-                               {
-                                       // Check for circular reference.
-                                       if (checked.contains(objVals[i]))
-                                       {
-                                               continue;
-                                       }
-                               }
-                               catch (Exception e)
+                               // Check for circular reference.
+                               if (checked.contains(objVals[i]))
                                {
-                                       log.warn("error invoking hashCode: " + 
e.getMessage() + ", path:"
-                                                       + currentPath() + ": ");
                                        continue;
                                }
 


Reply via email to