Author: peter_firmstone
Date: Wed May 29 21:59:16 2013
New Revision: 1487652

URL: http://svn.apache.org/r1487652
Log:
Update for Distributed Objects.

Added:
    
river/jtsk/skunk/qa_refactor/trunk/test/src/org/apache/river/api/io/SerialReflectionFactoryTest.java
Modified:
    
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
    
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java
    
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialReflectionFactory.java
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/Uri.java

Modified: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java?rev=1487652&r1=1487651&r2=1487652&view=diff
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
 (original)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
 Wed May 29 21:59:16 2013
@@ -24,7 +24,7 @@ import java.security.BasicPermission;
  * ObjectOutput
  * 
  * @author peter
- * @see SerialFactory
+ * @see SerialReflectionFactory
  * @see ObjectOutput
  */
 public class DistributePermission  extends BasicPermission{

Modified: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java?rev=1487652&r1=1487651&r2=1487652&view=diff
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java 
(original)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java 
Wed May 29 21:59:16 2013
@@ -17,45 +17,82 @@
 package org.apache.river.api.io;
 
 /**
- * Distributed objects are immutable value objects with final fields that may
- * be freely replicated.
- * Distributed objects are not serialized, instead they are only created using 
a 
- * public constructor, public static factory method or builder object making 
them
- * more suitable for security, validating class invariants and concurrent code
- * that relies on immutability.
- * <p>
- * Distributed objects are free to evolve and may have completely different 
- * classes or be completely unequal after distribution to separate nodes, 
- * but must always share a common public interface or superclass for 
referential
- * purposes.
+ * Distributed objects are suitable for use as immutable value objects with 
+ * final fields that may be freely replicated, alternatively they are also 
+ * suited as safely published thread safe mutable objects used 
+ * to store service snapshots in a {@link net.jini.io.MarshalledInstance} for 
+ * fail over replication to other nodes, or to upgrade a service.
+ * <p>
+ * Distributed objects are not serialized, instead they are only created using 
an 
+ * accessible constructor, public static factory method or builder object 
making them
+ * more suitable for security; validating class invariants and concurrent code
+ * that relies on immutability and safe publication of fields using final or
+ * volatile.
+ * <p>
+ * Distributed Objects are created remotely with an AccessControlContext
+ * containing one ProtectionDomain with a CodeSource that has a null location 
+ * and null Certificates.  
+ * Only minimal permissions granted to any location by the administrator will 
apply.  
+ * Minimal privilege is required to prevent remote instantiation 
+ * of ClassLoader, Policy, SecurityManager, or any other type of object with 
+ * security checks performed during construction.  The developer is free to
+ * use privileged access, including login context from within constructors and
+ * methods.
+ * <p>
+ * The serial form of a Distributed object is managed by 
SerialReflectionFactory
+ * and is solely dependant on the classes, parameters and signatures of methods
+ * or constructors.  
+ * <p>
+ * Distributed Objects with equal SerialReflectionFactory's shall be identical 
+ * in Object form after un-marshaling within an identical jvm and one 
+ * may be substituted for the other to reduce network traffic.
+ * <p>
+ * Distributed Objects that are equal in Object form are not guaranteed to be 
equal
+ * in serial form.  The implementor may enforce serial form equality by 
ensuring
+ * identical methods of creation are used for equal objects and document it in 
+ * javadoc. Distributed objects equal in Object form at one node should also be
+ * equal after un-marshaling to a second remote node even when serial form 
differs. 
+ * <p>
+ * Distributed Objects (boomerangs) that are duplicated across 
+ * nodes may not be equal when returning to a local node after construction 
and 
+ * redistribution on different nodes.  Later versions of code may elect to 
+ * use different classes, constructors or method signatures that result in
+ * inequality.
+ * <p>
+ * Distributed objects while free to evolve and possibly having completely 
different 
+ * classes or being completely unequal after distribution to separate nodes, 
+ * must always share a common public interface or superclass for referential
+ * purposes, this may of course be Object, however if it is, it should be 
stated
+ * clearly in Javadoc to avoid ClassCastException's upon un-marshaling.
  * <p>
  * Distributed objects have no version, instead SerialReflectionFactory 
contains all 
  * information required to distribute and recreate any Distributed Object using
  * reflection.  For this reason, Distributed objects cannot be used as Entry
- * objects, which is dependant on published serial form.  It may be possible
+ * objects, as they are dependant on published serial form.  It may be possible
  * in a later release to use Distributed objects as fields in Entry objects, 
this
  * is not supported presently.
  * <p>
- * Distributed objects are value objects from a domain driven design 
perspective.
+ * Distributed objects are recommended for use as value objects in domain 
+ * driven design.
  * <p>
- * Although final is not enforced, all fields must be final, safe
- * construction must be honored  the this reference must not be allowed to 
+ * Although final is not enforced, all fields should be final or volatile, safe
+ * construction must be honored 'this' must not be allowed to 
  * escape during construction, distributed objects will be exposed to multiple
- * threads on multiple nodes, without synchronization or transactions.
+ * threads on multiple nodes, without external synchronization.
  * <p>
- * Distributed objects are thread safe and immutable.
+ * Distributed objects are thread safe.
  * <p>
  * Do not use Distributed if you don't intend to honor this contract, use
  * Serializable instead.
  * <p>
- * Distributed Objects are created remotely using an AccessControlContext with 
one
- * ProtectionDomain containing a CodeSource with a null location and null 
- * Certificates.  Only permissions granted to  any location will apply.  
- * Minimal privilege is required to prevent remote instantiation 
- * of ClassLoader, Policy, SecurityManager, or any other type of object with 
- * security checks performed during construction.
+ * Caveat:<br>
+ * Distributed Objects cannot be stored directly in a 
+ * {@link java.rmi.MarshalledObject}, a {@link net.jini.io.MarshalledInstance}
+ * must first be created and converted, also a Distributed Object will
+ * returned as a {@link SerialReflectionFactory} when {@link 
java.rmi.MarshalledObject}
+ * is un-marshaled, the {@link java.rmi.MarshalledObject} must first be
+ * converted to {@link net.jini.io.MarshalledInstance} before un-marshaling.
  * <p>
- * 
  * @author Peter Firmstone.
  */
 public interface Distributed {

Modified: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialReflectionFactory.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialReflectionFactory.java?rev=1487652&r1=1487651&r2=1487652&view=diff
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialReflectionFactory.java
 (original)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialReflectionFactory.java
 Wed May 29 21:59:16 2013
@@ -23,7 +23,6 @@ import java.io.ObjectOutput;
 import java.io.Serializable;
 import java.io.StreamCorruptedException;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.AccessControlContext;
 import java.security.AccessController;
@@ -33,6 +32,7 @@ import java.security.PrivilegedActionExc
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
+import java.util.Arrays;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -40,9 +40,12 @@ import java.util.logging.Logger;
  * Distributed form, required for reflective calls to instantiate objects 
remotely, 
  * using a constructor, static method or an Object method.
  * 
- * This object must be Thread confined, it is not thread safe.
+ * This object must be Thread confined, it is not thread safe.  It should be
+ * created on demand, it is primarily for use by {@link 
DistributedObjectInputStream}
+ * and {@link DistributedObjectOutputStream}, it is created by {@link 
Distributed}
+ * Object implementations and {@link DistributedObjectInputStream}
  * 
- * Internal state is guarded, arrays are not defensively coped.
+ * Internal state is guarded, arrays are not defensively copied.
  * 
  * This is compatible with Version 2 of the Java Serialization Protocol.
  * 
@@ -80,11 +83,15 @@ public final class SerialReflectionFacto
     private static final byte OBJECT = 8;
     private static final byte NULL = 9;
     
+    // Serial Form
     private Object classOrObject;
     private String method;
     private Class [] parameterTypes;
     private Object [] parameters;
-    private final boolean constructed; // default value is false.
+    
+    // Private local object state.
+    private int hash;
+    private boolean constructed; // default value is false.
     
     /**
      * Public method provided for java serialization framework.
@@ -147,6 +154,12 @@ public final class SerialReflectionFacto
             throw new IllegalArgumentException("Array lengths don't match, or 
arrays are too long,"
                     + " parameter array limit 127, "
                     + "you need to see a shrink if you need this many 
parameters");
+        int hash = 7;
+        hash = 89 * hash + (this.classOrObject != null ? 
this.classOrObject.hashCode() : 0);
+        hash = 89 * hash + (this.method != null ? this.method.hashCode() : 0);
+        hash = 89 * hash + Arrays.hashCode(this.parameterTypes);
+        hash = 89 * hash + Arrays.deepHashCode(this.parameters);
+        this.hash = hash;
     }
     
     Object create() throws IOException {
@@ -196,6 +209,7 @@ public final class SerialReflectionFacto
     // Inherit documentation
     public void writeExternal(ObjectOutput out) throws IOException {
         distributable.checkGuard(null);
+        if (! constructed) throw new IOException("Attempt to write blank 
SerialReflectionFactory");
         out.writeObject(classOrObject);
         out.writeObject(method);
         /* don't clone arrays for defensive copies, it's up to constructing 
@@ -309,6 +323,7 @@ public final class SerialReflectionFacto
          * will never be shared with other threads and will be replaced by
          * a fully constructed thread safe immutable object. */
         if (constructed) throw new IllegalStateException("Object already 
constructed");
+        constructed = true;
         /* Don't defensively copy arrays, the object is used immediately after
          * deserialization to construct the Distributed Object, the fields are
          * not accessed again, it is up to creator methods themselves to 
@@ -322,5 +337,33 @@ public final class SerialReflectionFacto
         for (int i = 0; i < len; i++){
             parameters[i] = readObject(in);
         }
+        int hash = 7;
+        hash = 89 * hash + (this.classOrObject != null ? 
this.classOrObject.hashCode() : 0);
+        hash = 89 * hash + (this.method != null ? this.method.hashCode() : 0);
+        hash = 89 * hash + Arrays.deepHashCode(this.parameterTypes);
+        hash = 89 * hash + Arrays.deepHashCode(this.parameters);
+        this.hash = hash;
+    }
+    
+    // equals and hashcode are implemented to avoid sending duplicates in 
+    // object streams.
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+    
+    @Override
+    public boolean equals(Object o){
+        if (!(o instanceof SerialReflectionFactory)) return false;
+        if ( hash != o.hashCode()) return false;
+        SerialReflectionFactory other = (SerialReflectionFactory) o;
+        if ( classOrObject == null && other.classOrObject != null) return 
false;
+        if ( classOrObject != null && ! 
classOrObject.equals(other.classOrObject)) return false;
+        if ( method == null && other.method != null) return false;
+        if ( method != null && ! method.equals(other.method)) return false;
+        if (!Arrays.equals(parameterTypes, other.parameterTypes)) return false;
+        if (!Arrays.deepEquals(parameters, other.parameters)) return false;
+        return true;
+        // A locally constructed instance may be equal to a deserialized one.
     }
 }

Modified: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/Uri.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/Uri.java?rev=1487652&r1=1487651&r2=1487652&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/Uri.java 
(original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/Uri.java 
Wed May 29 21:59:16 2013
@@ -1921,7 +1921,7 @@ public final class Uri implements Compar
     private String getHashString() {
         StringBuilder result = new StringBuilder();
         if (scheme != null) {
-            result.append(scheme.toLowerCase());
+            result.append(toAsciiLowerCase(scheme));
             result.append(':');
         }
         if (opaque) {
@@ -1935,7 +1935,7 @@ public final class Uri implements Compar
                     if (userinfo != null) {
                         result.append(userinfo + "@"); //$NON-NLS-1$
                     }
-                    result.append(host.toLowerCase());
+                    result.append(toAsciiLowerCase(host));
                     if (port != -1) {
                         result.append(":" + port); //$NON-NLS-1$
                     }
@@ -1944,7 +1944,7 @@ public final class Uri implements Compar
 
             if (path != null) {
                 if (fileSchemeCaseInsensitiveOS){
-                    result.append(toAsciiUpperCase(path.toCharArray()));
+                    result.append(toAsciiUpperCase(path));
                 } else {
                     result.append(path);
                 }

Added: 
river/jtsk/skunk/qa_refactor/trunk/test/src/org/apache/river/api/io/SerialReflectionFactoryTest.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/test/src/org/apache/river/api/io/SerialReflectionFactoryTest.java?rev=1487652&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/test/src/org/apache/river/api/io/SerialReflectionFactoryTest.java
 (added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/test/src/org/apache/river/api/io/SerialReflectionFactoryTest.java
 Wed May 29 21:59:16 2013
@@ -0,0 +1,107 @@
+/*
+ *  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.api.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import junit.framework.Assert;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ *
+ * @author peter
+ */
+public class SerialReflectionFactoryTest {
+    
+    private final SerialReflectionFactory stringInstance;
+    private final String str;
+    
+    public SerialReflectionFactoryTest() {
+        str = "Fat Bear";
+        Class[] cl = {(new char [0]).getClass()};
+        Object [] chars = {str.toCharArray()};
+        stringInstance = new SerialReflectionFactory(str.getClass(), null, cl 
, chars);
+    }
+
+    /**
+     * Test of hashCode method, of class SerialReflectionFactory.
+     */
+    @Test
+    public void testHashCode() throws IOException {
+        System.out.println("hashCode");
+        int result = stringInstance.create().hashCode();
+        int expResult = str.hashCode();
+        assertEquals(expResult, result);
+        
+    }
+
+    /**
+     * Test of equals method, of class SerialReflectionFactory.
+     */
+    @Test
+    public void testEquals() throws IOException {
+        System.out.println("equals");
+        String expResult = str;
+        Class[] cl = {(new char [0]).getClass()};
+        Object [] chars = {str.toCharArray()};
+        // More than one way to create a string.
+        Object secondInstance = new SerialReflectionFactory(str.getClass(), 
null, cl, chars );
+        SerialReflectionFactory thirdInstance = 
+                new SerialReflectionFactory(new StringBuilder(str), 
"toString", null, null );
+        Object result = stringInstance.create();
+        Assert.assertEquals(stringInstance, secondInstance);
+        // Demonstrate that equal objects can have different serial form.
+        Assert.assertNotSame(stringInstance, thirdInstance);
+        Assert.assertEquals(expResult, result);
+        result = thirdInstance.create();
+        Assert.assertEquals(expResult, result);
+       
+    }
+
+    /**
+     * Test of writeExternal method, of class SerialReflectionFactory.
+     */
+    @Test
+    public void testWriteExternal() throws Exception {
+        System.out.println("writeExternal");
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ObjectOutputStream outst = new ObjectOutputStream(out);
+        outst.writeObject(stringInstance);
+        ObjectInputStream in = new ObjectInputStream(new 
ByteArrayInputStream(out.toByteArray()));
+        Object result = in.readObject();
+        assertEquals(stringInstance, result);
+    }
+
+    /**
+     * Test of readExternal method, of class SerialReflectionFactory.
+     */
+    @Test
+    public void testReadExternal() throws Exception {
+        System.out.println("readExternal");
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ObjectOutputStream outst = new ObjectOutputStream(out);
+        outst.writeObject(stringInstance);
+        ObjectInputStream in = new ObjectInputStream(new 
ByteArrayInputStream(out.toByteArray()));
+        Object result = in.readObject();
+        assertEquals(result, stringInstance);
+    }
+}


Reply via email to