You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2011/10/09 06:07:07 UTC

svn commit: r1180542 - /river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/

Author: peter_firmstone
Date: Sun Oct  9 04:07:07 2011
New Revision: 1180542

URL: http://svn.apache.org/viewvc?rev=1180542&view=rev
Log:
Adding support for Serialization in ReferenceCollections

Added:
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java   (with props)
Modified:
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractSerializationOfRC.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceSerializedForm.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerialDataReferenceCollection.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerializationOfReferenceCollection.java

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractSerializationOfRC.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractSerializationOfRC.java?rev=1180542&r1=1180541&r2=1180542&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractSerializationOfRC.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractSerializationOfRC.java Sun Oct  9 04:07:07 2011
@@ -39,7 +39,11 @@ import java.util.concurrent.BlockingQueu
 import java.util.concurrent.TimeUnit;
 
 /**
- *
+ * The purpose of this class is to implement all the possible interfaces
+ * that subclasses of ReferenceCollection may implement.  This is designed
+ * to fix the readResolve issue that occurs in object graphs containing
+ * circular references.
+ * 
  * @author Peter Firmstone.
  */
 abstract class AbstractSerializationOfRC<T> extends SerializationOfReferenceCollection<T>
@@ -47,15 +51,15 @@ implements Serializable, List<T>, Set<T>
 Queue<T>, Deque<T>, BlockingQueue<T>, BlockingDeque<T>{
     private static final long serialVersionUID = 1L;
    
-   // This abstract class must not hold any serial data.
+    // This abstract class must not hold any serial data.
     
-   // Builder created List on deserialization
-   private volatile transient Collection<T> serialBuilt = null;
-   private volatile transient boolean built = false;
-   
+    // Builder created List on deserialization
+    private volatile transient Collection<T> serialBuilt = null;
+    private volatile transient boolean built = false;
    
     @Override
-    Collection<T> build() throws InstantiationException, IllegalAccessException {
+    Collection<T> build() throws InstantiationException, IllegalAccessException,
+    ObjectStreamException {
         if (isBuilt()) return getSerialBuilt();
         setBuilt();
         /* Traverse Inheritance heirarchy in reverse order */

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java?rev=1180542&r1=1180541&r2=1180542&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java Sun Oct  9 04:07:07 2011
@@ -40,11 +40,15 @@ class ReferenceFactory<T> {
     
     static <T> Referrer<T> create(T t, ReferenceQueue<? super T> queue, Ref type ){
         switch (type){
-            case WEAK_IDENTITY: return new WeakIdentityReferenceKey<T>(t, queue);
-            case SOFT_IDENTITY: return new SoftIdentityReferenceKey<T>(t, queue);
-            case WEAK: return new WeakReferenceKey<T>(t, queue);
-            case SOFT: return new SoftReferenceKey<T>(t, queue);
-            default: return new StrongReferenceKey<T>(t, queue);
+            case WEAK_IDENTITY: 
+                return new ReferrerWrapper<T>(new WeakIdentityReferenceKey<T>(t, queue));
+            case SOFT_IDENTITY: 
+                return new ReferrerWrapper<T>(new SoftIdentityReferenceKey<T>(t, queue));
+            case WEAK: 
+                return new ReferrerWrapper<T>(new WeakReferenceKey<T>(t, queue));
+            case SOFT: 
+                return new ReferrerWrapper<T>(new SoftReferenceKey<T>(t, queue));
+            default: return new ReferrerWrapper<T>(new StrongReferenceKey<T>(t, queue));
         }
     }
     

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceSerializedForm.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceSerializedForm.java?rev=1180542&r1=1180541&r2=1180542&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceSerializedForm.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceSerializedForm.java Sun Oct  9 04:07:07 2011
@@ -64,10 +64,7 @@ class ReferenceSerializedForm<T> extends
         return false;
     }
     
-    /* ReferenceQueue is not compared, because a lookup key is used to locate
-     * an existing key and ReferenceQueue is null in lookup key's.
-     *
-     * ReferenceQueue is not part of hashCode or equals.
+    /* In this case we're using Identity 
      */
     @Override
     public boolean equals(Object o) {
@@ -75,7 +72,7 @@ class ReferenceSerializedForm<T> extends
         if (!(o instanceof Referrer))  return false;
         Object k1 = get();
         Object k2 = ((Referrer) o).get();
-        if ( k1 != null && k1.equals(k2)) return true;
+        if ( k1 != null && k1 == k2) return true;
         return ( k1 == null && k2 == null && hashCode() == o.hashCode()); // Both objects were collected.
     }
 

Added: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java?rev=1180542&view=auto
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java (added)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java Sun Oct  9 04:07:07 2011
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.river.impl.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ *
+ * @author peter
+ */
+final class ReferrerWrapper<T> implements Referrer<T>, Serializable{
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * @serialField 
+     */
+    private volatile Referrer<T> reference;
+    
+    ReferrerWrapper(Referrer<T> ref){
+        if (ref == null) throw new NullPointerException("Referrer cannot be null");
+        reference = ref;
+    }
+    
+    void refresh(ReferenceQueuingFactory<T, Referrer<T>> rqf){
+        T object = get();
+        if (object != null){
+            Referrer<T> newRef = rqf.referenced(object, true);
+            synchronized (this){
+                reference = newRef;
+            }
+        }
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)  return true; // Same reference.
+        if (!(o instanceof Referrer))  return false;
+        return reference.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return reference.hashCode();
+    }
+
+    @Override
+    public T get() {
+        return reference.get();
+    }
+
+    @Override
+    public void clear() {
+        reference.clear();
+    }
+
+    @Override
+    public boolean isEnqueued() {
+        return reference.isEnqueued();
+    }
+
+    @Override
+    public boolean enqueue() {
+        return reference.enqueue();
+    }
+    
+    private void readObject(ObjectInputStream in)
+        throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        if (reference == null) throw new IOException("Attempt to write null Referrer");
+    }
+    
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+    }
+    
+}

Propchange: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferrerWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerialDataReferenceCollection.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerialDataReferenceCollection.java?rev=1180542&r1=1180541&r2=1180542&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerialDataReferenceCollection.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerialDataReferenceCollection.java Sun Oct  9 04:07:07 2011
@@ -19,33 +19,46 @@
 package org.apache.river.impl.util;
 
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
 import java.util.Collection;
+import java.util.Iterator;
 
 /**
- *
+ * This class is the serial form of ReferenceCollection and all it's subclasses.
+ * 
+ * While the serial form of this class will remain compatible with itself,
+ * ReferenceCollection may replace this implementation with another
+ * at some point in the future.
+ * 
+ * This class will still be able to deserialize into a ReferenceCollection.
+ * 
  * @author peter
  */
 public class SerialDataReferenceCollection<T> extends AbstractSerializationOfRC<T> {
     private static final long serialVersionUID = 1L;
 
-   /** @serialData */
-   private Ref type = null;
-   /** @serialData */
+   /** @serialField  */
+   private Ref type;
+   /** @serialField */
    private Collection<Referrer<T>> collection;
-   /** @serialData */
+   /** @serialField */
    private Class clazz;
    
     @SuppressWarnings("unchecked")
    SerialDataReferenceCollection( Class clazz,
             Collection<Referrer<T>> underlyingCollection, Ref type) 
            throws InstantiationException, IllegalAccessException{
-       // Create a new instance of the underlying collection and
-       // add all objects.
-       this.collection = underlyingCollection;
-       this.type = type;
-       this.clazz = clazz;
+        // Create a new instance of the underlying collection and
+        // add all objects.
+        if ( clazz == null || underlyingCollection == null || type == null){
+            throw new NullPointerException("null parameters prohibited");
+        }
+        this.collection = underlyingCollection;
+        this.type = type;
+        this.clazz = clazz;
    }
     
     @Override
@@ -64,15 +77,36 @@ public class SerialDataReferenceCollecti
     }
     
     @Override
-    Collection<T> build() throws InstantiationException, IllegalAccessException{
+    final Collection<T> build() throws InstantiationException, IllegalAccessException, 
+    ObjectStreamException{
         Collection<T> result = super.build();
-        // What if the underlying collection is immutable?
+        /* What if the underlying collection is immutable?
+         * The ReferenceQueuingFactory is unknown until the ReferenceCollection
+         * has been built.
+         */
+        if ( result instanceof ReferenceCollection){
+            ReferenceCollection<T> refCol = (ReferenceCollection<T>) result;
+            ReferenceQueuingFactory<T, Referrer<T>> rqf = refCol.getRQF();
+            Iterator<Referrer<T>> colIt = collection.iterator();
+            while (colIt.hasNext()){
+                Referrer<T> ref = colIt.next();
+                if ( ref == null ) continue;
+                if (ref instanceof ReferrerWrapper){
+                    ((ReferrerWrapper<T>) ref).refresh(rqf);
+                } else {
+                    throw new InvalidObjectException("Referrer's must be a ReferrerWraper for ReferenceCollection");
+                }
+            }
+        }
         return result;
     }
 
      private void readObject(ObjectInputStream in)
         throws IOException, ClassNotFoundException {
         in.defaultReadObject();
+        if ( clazz == null || collection == null || type == null){
+            throw new InvalidObjectException("null fields found after deserialization");
+        }
     }
     
     private void writeObject(ObjectOutputStream out) throws IOException {

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerializationOfReferenceCollection.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerializationOfReferenceCollection.java?rev=1180542&r1=1180541&r2=1180542&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerializationOfReferenceCollection.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/SerializationOfReferenceCollection.java Sun Oct  9 04:07:07 2011
@@ -18,6 +18,7 @@
 
 package org.apache.river.impl.util;
 
+import java.io.ObjectStreamException;
 import java.util.AbstractCollection;
 import java.util.Collection;
 
@@ -34,6 +35,7 @@ abstract class SerializationOfReferenceC
         return new SerialDataReferenceCollection<T>(clazz, refCol, type);
     }
     
-    abstract Collection<T> build() throws InstantiationException, IllegalAccessException;
+    abstract Collection<T> build() throws InstantiationException, 
+            IllegalAccessException, ObjectStreamException;
     
 }