Author: peter_firmstone
Date: Wed Feb 27 08:50:56 2013
New Revision: 1450681

URL: http://svn.apache.org/r1450681
Log:
Clean and simple replacement for Serializable - Distributed objects.

Added:
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/
    
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/DistributedObjectInputStream.java
    
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectOutputStream.java
    
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialFactory.java

Added: 
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=1450681&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
 (added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributePermission.java
 Wed Feb 27 08:50:56 2013
@@ -0,0 +1,32 @@
+/*
+ *  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.security.BasicPermission;
+
+/**
+ *
+ * @author peter
+ */
+public class DistributePermission  extends BasicPermission{
+    private static final long serialVersionUID = 1L;
+
+    public DistributePermission(){
+        super("DISTRIBUTE");
+    }
+
+}
\ No newline at end of file

Added: 
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=1450681&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java 
(added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/Distributed.java 
Wed Feb 27 08:50:56 2013
@@ -0,0 +1,52 @@
+/*
+ *  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.Serializable;
+
+/**
+ * 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.
+ * <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.
+ * <p>
+ * Distributed objects have no version, instead SerialFactory contains all 
+ * information required to distribute and recreate any Distributed Object.
+ * <p>
+ * Distributed object all have a common serial form, defined by SerialFactory.
+ * <p>
+ * Distributed objects are value objects in domain driven design.
+ * <p>
+ * Remote objects are entity or service objects in domain driven design 
context.
+ * <p>
+ * Although final is not enforced, all fields must be final and safe
+ * construction must be honored, distributed objects will be exposed to 
multiple
+ * threads on multiple nodes, without synchronization or transactions.
+ * <p>
+ * Do not use Distributed if you don't intend to honor this contract, use
+ * Serializable instead.
+ * 
+ * @author Peter Firmstone.
+ */
+public interface Distributed {
+    SerialFactory substitute();
+}

Added: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectInputStream.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectInputStream.java?rev=1450681&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectInputStream.java
 (added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectInputStream.java
 Wed Feb 27 08:50:56 2013
@@ -0,0 +1,76 @@
+/*
+ *  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.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ *
+ * @author 
+ */
+public class DistributedObjectInputStream extends ObjectInputStream {
+    
+    public static ObjectInputStream create(InputStream in) throws IOException{
+        DistributedObjectInputStream result = new 
DistributedObjectInputStream(in);
+        AccessController.doPrivileged(new EnableResolveObject(result));
+        return result;
+    }
+    
+    /**
+     * Caller must have SerializablePermission("enableSubstitution") to call
+     * this method.
+     * 
+     * @param in
+     * @throws IOException 
+     */
+    protected DistributedObjectInputStream(InputStream in) throws IOException{
+        super(in);
+        try {
+            super.enableResolveObject(true);
+        } catch (SecurityException e){
+            // Ignore, will be called from privileged context if create method 
used.
+        }
+    }
+    
+    private void enableResolveObject(){
+        super.enableResolveObject(true);
+    }
+    
+    protected final Object resolveObject(Object o) throws IOException{
+        if (o instanceof SerialFactory) return ((SerialFactory)o).create();
+        return o;
+    }
+    
+    private static class EnableResolveObject implements PrivilegedAction{
+        private final DistributedObjectInputStream in;
+        
+        EnableResolveObject(DistributedObjectInputStream in){
+            this.in = in;
+        }
+        
+        @Override
+        public Object run() {
+            in.enableResolveObject();
+            return null;
+        }
+        
+    }
+}

Added: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectOutputStream.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectOutputStream.java?rev=1450681&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectOutputStream.java
 (added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/DistributedObjectOutputStream.java
 Wed Feb 27 08:50:56 2013
@@ -0,0 +1,65 @@
+/*
+ *  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.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ *
+ * @author peter
+ */
+public class DistributedObjectOutputStream extends ObjectOutputStream {
+    
+     public static ObjectOutputStream create(OutputStream out) throws 
IOException{
+        DistributedObjectOutputStream result = new 
DistributedObjectOutputStream(out);
+        AccessController.doPrivileged(new EnableReplaceObject(result));
+        return result;
+    }
+    
+    protected DistributedObjectOutputStream (OutputStream out) throws 
IOException{
+        super(out);
+        super.enableReplaceObject(true);
+    }
+    
+    protected final Object replaceObject(Object o){
+        if (o instanceof Distributed) return ((Distributed)o).substitute();
+        return o;
+    }
+    
+    private void enableReplaceObject(){
+        super.enableReplaceObject(true);
+    }
+    
+    private static class EnableReplaceObject implements PrivilegedAction{
+        private final DistributedObjectOutputStream out;
+        
+        EnableReplaceObject(DistributedObjectOutputStream out){
+            this.out = out;
+        }
+        
+        @Override
+        public Object run() {
+            out.enableReplaceObject();
+            return null;
+        }
+        
+    }
+}

Added: 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialFactory.java
URL: 
http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialFactory.java?rev=1450681&view=auto
==============================================================================
--- 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialFactory.java
 (added)
+++ 
river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/io/SerialFactory.java
 Wed Feb 27 08:50:56 2013
@@ -0,0 +1,217 @@
+/*
+ *  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.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.BasicPermission;
+import java.security.Guard;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Distributed form, required for Object reconstruction, using constructor, 
+ * static factory method instantiation or Object builder instantiation.
+ * 
+ * This object must be Thread confined, it is not thread safe.
+ * 
+ * Internal state is guarded.
+ * 
+ * @author Peter Firmstone.
+ * @see Distributed
+ * @see DistributePermission
+ */
+public final class SerialFactory implements Externalizable {
+    private static final long serialVersionUID = 1L;
+    /* Guard private state */
+    private static final Guard distributable = new DistributePermission();
+    
+    private Object classOrObject;
+    private String method;
+    private Class [] parameterTypes;
+    private Object [] parameters;
+    private final boolean constructed; // default value is false.
+    
+    public SerialFactory(){
+        constructed = false;
+    }
+    
+    /**
+     * 
+     * 
+     * 
+     * @param factoryClassOrObject will be used for constructor, factory 
static method,
+     * or builder Object.
+     * @param methodName name of static factory method, null if using a 
constructor.
+     * @param parameterTypes Type signature of method or constructor
+     * @param parameters Object to be passed to constructor.
+     */
+    public SerialFactory(Object factoryClassOrObject, String methodName, 
Class[] parameterTypes, Object [] parameters){
+        classOrObject = factoryClassOrObject;
+        method = methodName;
+        this.parameterTypes = parameterTypes;
+        this.parameters = parameters;
+        constructed = true;
+    }
+    
+    Object create() throws IOException {
+        Method m;
+        Constructor c;
+        Class clazz;
+        boolean object;
+        if (classOrObject instanceof Class) {
+            clazz = (Class) classOrObject;
+            object = false;
+        }
+        else {
+            clazz = classOrObject.getClass();
+            object = true;
+        }
+         try {
+            if (method != null){
+                m = clazz.getMethod(method, parameterTypes);
+                if (object) return m.invoke(classOrObject, parameters);
+                return m.invoke(null, parameters);
+            } else {
+                c = clazz.getConstructor(parameterTypes);
+                return c.newInstance(parameters);
+            }
+        } catch (InstantiationException ex) {
+            throw new IOException(ex);
+        } catch (IllegalAccessException ex) {
+            throw new SecurityException(ex);
+        } catch (IllegalArgumentException ex) {
+            throw new IOException(ex);
+        } catch (InvocationTargetException ex) {
+            throw new IOException(ex);
+        } catch (NoSuchMethodException ex) {
+            throw new IOException(ex);
+        } 
+    }
+    
+    @Override
+    public void writeExternal(ObjectOutput out) throws IOException {
+        distributable.checkGuard(null);
+        out.writeObject(classOrObject);
+        out.writeObject(method);
+        /* don't clone arrays for defensive copies, it's up to constructing 
+         * object to do so if needs to.
+         */
+        out.writeObject(parameterTypes);
+        out.writeObject(parameters);
+    }
+
+    @Override
+    public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        if (constructed) throw new IllegalStateException("Object already 
constructed");
+        /* Don't defensively copy arrays, the object is used immediately after
+         * deserialization to construct the Distributed Object, the fields are
+         * not accessed again.
+         * 
+         * DistributedObjectOutputStream.
+         */
+        classOrObject = in.readObject();
+        method = (String) in.readObject();
+        parameterTypes = (Class[]) in.readObject();
+        parameters = (Object[]) in.readObject();
+        
+        // All this hurts performance for little benefit.
+        // Read in before changing accessibility of fields.
+//        Object clas = in.readObject();
+//        Object methName = in.readObject();
+//        Object paramTypes = in.readObject();
+//        Object param = in.readObject();
+//        final String [] fieldNames = {"clazz", "method", "parameterTypes", 
"parameters"};
+//        Field [] fields = null;
+//        try {
+//            fields = AccessController.doPrivileged(new Action(fieldNames));
+//        } catch (PrivilegedActionException ex) {
+//            Exception e = ex.getException();
+//            if (e instanceof NoSuchFieldException) throw new 
ClassNotFoundException("No such field", e);
+//            if (e instanceof SecurityException ) throw (SecurityException)e;
+//            throw new IOException("Unable to instantiate fields", e);
+//        }
+//        // Don't worry about defensive copy arrays, the constructor or 
factory
+//        // method will be called soon.
+//        try {
+//             if (clas instanceof Class) fields[0].set(this, clas);
+//             if (methName instanceof String) fields[1].set(this, methName);
+//             if (paramTypes instanceof Class[]) 
fields[2].set(this,paramTypes);
+//             if (param instanceof Object[]) fields[3].set(this, param);
+//        } catch (IllegalArgumentException ex) {
+//            
Logger.getLogger(SerialFactory.class.getName()).log(Level.SEVERE, null, ex);
+//        } catch (IllegalAccessException ex) {
+//            
Logger.getLogger(SerialFactory.class.getName()).log(Level.SEVERE, null, ex);
+//        }
+//        try {
+//            AccessController.doPrivileged(new RestoreProtection(fields));
+//        } catch (PrivilegedActionException ex) {
+//            Exception e = ex.getException();
+//            if (e instanceof SecurityException ) throw (SecurityException)e;
+//            throw new IOException("Unable to restore access control on final 
fields", e);
+//        }
+    }
+    
+//    private class Action implements PrivilegedExceptionAction<Field[]>{
+//        private final String [] names;
+//        
+//        Action(String [] names){
+//            this.names = names;
+//        }
+//        
+//        @Override
+//        public Field[] run() throws Exception {
+//            int l = names.length;
+//            Field [] result = new Field[l];
+//            for (int i = 0; i < l; i++){
+//                result [i] = SerialFactory.class.getDeclaredField(names[i]);
+//                result [i].setAccessible(true);
+//            }
+//            return result;
+//        }
+//        
+//    }
+//    
+//    private class RestoreProtection implements 
PrivilegedExceptionAction<Boolean>{
+//        private final Field [] fields;
+//        
+//        RestoreProtection(Field [] f){
+//            fields = f;
+//        }
+//        @Override
+//        public Boolean run() throws Exception {
+//            int l = fields.length;
+//            for (int i = 0; i < l; i++){
+//                fields[i].setAccessible(false);
+//            }
+//            return Boolean.TRUE;
+//        }
+//        
+//    }
+    
+    
+    
+}


Reply via email to