[e-cvs] cvs commit: e/src/jsrc/org/erights/e/elib/tables ConstMap.java ConstMapImpl.java EList.java Twine.java LoopyTwine.java

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Tue, 21 Aug 2001 09:36:19 -0400


markm       01/08/21 09:36:19

  Modified:    src/jsrc/org/erights/e/elib/deflect Deflector.java
                        EventualDeflector.java ImmediateDeflector.java
               src/jsrc/org/erights/e/elib/prim StaticMaker.java
               src/jsrc/org/erights/e/elib/ref DisconnectedRef.java
                        Ref.java UnconnectedRef.java
               src/jsrc/org/erights/e/elib/serial PersistenceResolver.java
                        RemoteDelivery.java
               src/jsrc/org/erights/e/elib/tables ConstMap.java
                        ConstMapImpl.java EList.java Twine.java
  Added:       src/jsrc/org/erights/e/elib/ref StemCell.java
  Removed:     src/jsrc/org/erights/e/elib/tables LoopyTwine.java
  Log:
  towards a working StemCell

Revision  Changes    Path
1.6       +2 -0      e/src/jsrc/org/erights/e/elib/deflect/Deflector.java

Index: Deflector.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/deflect/Deflector.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Deflector.java	2001/07/14 12:57:23	1.5
+++ Deflector.java	2001/08/21 13:36:18	1.6
@@ -70,6 +70,8 @@
 public abstract class Deflector
 implements InvocationHandler, PassByConstruction, Selfless, Persistent {
     
+    static private final long serialVersionUID = 8164442851196730818L;
+    
     /**
      * See the class comment about E-Interfaces
      */



1.6       +2 -0      e/src/jsrc/org/erights/e/elib/deflect/EventualDeflector.java

Index: EventualDeflector.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/deflect/EventualDeflector.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- EventualDeflector.java	2001/07/26 15:28:08	1.5
+++ EventualDeflector.java	2001/08/21 13:36:18	1.6
@@ -46,6 +46,8 @@
  */
 /*package*/ class EventualDeflector extends Deflector {
     
+    static private final long serialVersionUID = 7395156154486886043L;
+    
     /**
      * 
      */



1.4       +2 -0      e/src/jsrc/org/erights/e/elib/deflect/ImmediateDeflector.java

Index: ImmediateDeflector.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/deflect/ImmediateDeflector.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ImmediateDeflector.java	2001/07/14 12:57:23	1.3
+++ ImmediateDeflector.java	2001/08/21 13:36:18	1.4
@@ -31,6 +31,8 @@
  */
 /*package*/ class ImmediateDeflector extends Deflector {
     
+    static private final long serialVersionUID = 480382409162532751L;
+    
     /**
      * 
      */



1.15      +31 -2     e/src/jsrc/org/erights/e/elib/prim/StaticMaker.java

Index: StaticMaker.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/prim/StaticMaker.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- StaticMaker.java	2001/08/20 05:07:44	1.14
+++ StaticMaker.java	2001/08/21 13:36:19	1.15
@@ -18,11 +18,16 @@
 
 Contributor(s): ______________________________________.
 */
+
+import java.io.ObjectStreamException;
 import org.erights.e.develop.exception.ThrowableSugar;
 import org.erights.e.elib.base.Callable;
 import org.erights.e.elib.base.ClassDesc;
 import org.erights.e.elib.base.TypeDesc;
 import org.erights.e.elib.base.MessageDesc;
+import org.erights.e.elib.ref.Ref;
+import org.erights.e.elib.serial.PassByConstruction;
+import org.erights.e.elib.serial.Persistent;
 import org.erights.e.elib.tables.ConstList;
 import org.erights.e.elib.tables.ConstMap;
 import org.erights.e.elib.tables.EMap;
@@ -38,7 +43,8 @@
  *
  * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
  */
-public class StaticMaker implements Callable {
+public class StaticMaker
+implements Callable, PassByConstruction, Persistent {
 
     /**
      *
@@ -170,7 +176,7 @@
 
 
     private Class myClass;
-    private VTable myVTable;
+    private transient VTable myVTable;
     
     /**
      *
@@ -216,6 +222,29 @@
             }
         } catch (AlreadyDefinedException ade) {
             throw ThrowableSugar.backtrace(ade, "can't wrap class");
+        }
+    }
+    
+    /**
+     * @serialData The only StaticMakers that are serializable are those 
+     * wrapping importable (approved) classes.
+     * <p>
+     * While this restriction is necessary for CapTP's security, we should 
+     * probably find a way to relax it for persistence.
+     */
+    private Object readResolve() throws ObjectStreamException {
+        if (approve(myClass)) {
+            StaticMaker result = make(myClass);
+            //we become valid ourselves as well, just in case there are some 
+            //too early references to us. 
+            myVTable = result.myVTable;
+            return result;
+        } else {
+            Object result = Ref.broken("Not approved: " + myClass.getName());
+            //we become invalid ourselves as well, just in case there are 
+            //some too early references to us
+            myClass = null;
+            return result;
         }
     }
 



1.4       +2 -0      e/src/jsrc/org/erights/e/elib/ref/DisconnectedRef.java

Index: DisconnectedRef.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/ref/DisconnectedRef.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DisconnectedRef.java	2001/08/17 03:11:33	1.3
+++ DisconnectedRef.java	2001/08/21 13:36:19	1.4
@@ -42,6 +42,8 @@
 /*package*/ class DisconnectedRef 
 extends Ref implements PassByConstruction, Persistent {
     
+    static private final long serialVersionUID = 1307531130876647340L;
+    
     private final Throwable myProblem;
     /*package*/ final Object myIdentity;
     



1.24      +6 -5      e/src/jsrc/org/erights/e/elib/ref/Ref.java

Index: Ref.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/ref/Ref.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- Ref.java	2001/08/20 21:17:49	1.23
+++ Ref.java	2001/08/21 13:36:19	1.24
@@ -480,22 +480,23 @@
      * The cases are <ul>
      * <li>Broken references are persistent.
      * <li><code>null</code> is persistent.
-     * <li>Instances of {@link Persistent} are persistent.
+     * <li>Instances of {@link Persistent} (including {@link StemCell}s) are 
+     *     persistent. 
      * <li>Arrays are persistent.
      * <li>Instances of any {@link Persistent#HONORARY} classes are 
      *     persistent. 
      * <li>A Far reference (a Resolved Eventual reference) is not persistent, 
      *     but is saved as a DisconnectedRef (a kind of BrokenRef) that 
      *     maintains the far reference's sameness identity. 
-     * <li>All other non-persistent references, including all Promises 
-     *     (Unresolved references) are saved as UnconnectedRefs (Broken 
-     *     references without a sameness identity). 
+     * <li>All other non-persistent references, including all non-StemCell 
+     *     Promises (Unresolved references) are saved as UnconnectedRefs 
+     *     (Broken references without a sameness identity). 
      * <ul>
      */
     static public boolean isPersistent(Object ref) {
         ref = resolution(ref);
         if (isEventual(ref)) {
-            return false;
+            return ref instanceof StemCell;
         }
         if (null == ref) {
             //null is trivially Persistent



1.2       +2 -0      e/src/jsrc/org/erights/e/elib/ref/UnconnectedRef.java

Index: UnconnectedRef.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/ref/UnconnectedRef.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UnconnectedRef.java	2001/08/17 03:11:33	1.1
+++ UnconnectedRef.java	2001/08/21 13:36:19	1.2
@@ -46,6 +46,8 @@
 /*package*/ class UnconnectedRef 
 extends Ref implements PassByConstruction, Persistent {
     
+    static private final long serialVersionUID = -2749826475753817626L;
+    
     /** @serial The Throwable that caused or explains why I'm broken */
     private final Throwable myProblem;
     



1.1                  e/src/jsrc/org/erights/e/elib/ref/StemCell.java

Index: StemCell.java
===================================================================
package org.erights.e.elib.ref;

/*
The contents of this file are subject to the Improvements to the
Distributed E Language Implementation License Version 1.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.erights.org/mmlicense.html

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.

The Original Code is the Improvements to the Distributed E Language
Implementation, released May 27, 1999.

The Initial Developer of the Original Code is Mark S. Miller.
Copyright (C) 1999 Mark S. Miller. All Rights Reserved.

Contributor(s): ______________________________________. 
*/

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import org.erights.e.elib.base.TextWriter;
import org.erights.e.elib.prim.E;
import org.erights.e.elib.serial.PassByConstruction;
import org.erights.e.elib.serial.Persistent;
import org.erights.e.elib.tables.ConstList;

/**
 * An object can writeReplace itself with a StemCell when serialized in 
 * order to resolve to the StemCell's readResolveStem, but with circular 
 * references handled as correctly as possible.
 * <p>
 * A known problem with Java Unserialization is that a circular reference to 
 * an encoded object A may get bound to A itself rather than what A 
 * readResolves to.  For statically typed circular references, or circular 
 * references that are synchronously used before the cycle is closed, there's 
 * nothing we can do about this other than fail safely (which, unlike raw 
 * Java serialization, we do).  
 * <p>
 * For the sake of other circular references, an unserialized StemCell starts 
 * as a promise for what it will readResolveStem to.  Once it readResolves, 
 * the promise is also resolved, so further references encoded as references 
 * to the StemCell will be decoded as this resolution. 
 * <p>
 * On the encoding side, a made StemCell (as opposed to an unserialized 
 * StemCell) is a very weird creature.  It appears to be an eventual resolved 
 * reference (a far reference), but will not deliver any messages, since the 
 * object it designates doesn't exist until the StemCell is unserialized.  By 
 * the same token, we did not make it appear to be a broken reference, 
 * because it will become a live reference to the object it makes once it's 
 * unserialized.  In any case, a made Stem should only be used for an object 
 * to instruct its serializer on how to encode it.
 * 
 * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
 */
public abstract class StemCell extends Ref
implements PassByConstruction, Persistent {
    
    /**
     * null on the encoding side for a made StemCell.
     * Unresolved during the unserializing of the StemCell itself.
     * Resolved to the StemCell's resolution once the StemCell is fully 
     * unserialized.
     */
    private transient Ref myOptPromise;
    
    /**
     * Makes a made StemCell
     */
    protected StemCell() {
        myOptPromise = null;
    }
    
    /**
     * Initializes the promise, does the default thing, and then resolves to 
     * the result of readResolveStem(), to be provided by a subclass.
     */
    private void readObject(ObjectInputStream ois)
    throws ClassNotFoundException, IOException {
        Object[] pair = Ref.promise();
        myOptPromise = (Ref)pair[0];
        ois.defaultReadObject();
        ((Resolver)pair[1]).resolve(readResolveStem());
    }

    /**
     * Overridden by particular kinds of StemCells in order to provide the 
     * cycle-safe equivalent of readResolveStem
     */
    protected abstract Object readResolveStem();
    
    /**
     * Initializes the promise, does the default thing, and then resolves to 
     * the result of readResolveStem(), to be provided by a subclass.
     */
    private void readObject(ObjectInputStream ois)
    throws ClassNotFoundException, IOException {
        Object[] pair = Ref.promise();
        myOptPromise = (Ref)pair[0];
        ois.defaultReadObject();
        ((Resolver)pair[1]).resolve(readResolveStem());
    }

    /**
     * 
     */
    public Throwable optProblem() {
        if (null == myOptPromise) {
            return null;
        } else {
            return myOptPromise.optProblem();
        }
    }

    /**
     * A made StemCell's resolution is itself.  An unserialized one's is 
     * according to its promise.
     */
    /*package*/ Ref resolutionRef() {
        if (null == myOptPromise) {
            return this;
        } else {
            return myOptPromise.resolutionRef();
        }
    }

    /**
     * 
     */
    public String state() {
        if (null == myOptPromise) {
            return EVENTUAL;
        } else {
            return myOptPromise.state();
        }
    }

    /**
     * 
     */
    public Object callAll(String verb, Object[] args) {
        if (null == myOptPromise) {
            throw new RuntimeException("not on a made StemCell");
        } else {
            return myOptPromise.callAll(verb, args);
        }
    }

    /**
     *
     */
    public Ref sendAll(String verb, Object[] args) {
        if (null == myOptPromise) {
            throw new RuntimeException("not on a made StemCell");
        } else {
            return myOptPromise.sendAll(verb, args);
        }
    }

    /**
     *
     */
    public void sendAllOnly(String verb, Object[] args) {
        if (null == myOptPromise) {
            throw new RuntimeException("not on a made StemCell");
        } else {
            myOptPromise.sendAllOnly(verb, args);
        }
    }
    
    /**
     * A made StemCell is resolved, and so appears to be a far ref.
     */
    public boolean isResolved() {
        if (null == myOptPromise) {
            return true;
        } else {
            return myOptPromise.isResolved();
        }
    }

    /**
     * 
     */
    /*package*/ void setTarget(Ref newTarget) {
        throw new RuntimeException("internal: shouldn't happen");
    }
    
    /**
     * 
     */
    /*package*/ void commit() {
        throw new RuntimeException("internal: should not happen");
    }        
}



1.3       +1 -5      e/src/jsrc/org/erights/e/elib/serial/PersistenceResolver.java

Index: PersistenceResolver.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/serial/PersistenceResolver.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- PersistenceResolver.java	2001/08/20 00:45:04	1.2
+++ PersistenceResolver.java	2001/08/21 13:36:19	1.3
@@ -21,7 +21,6 @@
 Contributor(s): ______________________________________.
 */
 
-import org.erights.e.elib.ref.Ref;
 import org.erights.e.elib.util.OneArgFunc;
 
 /**
@@ -40,12 +39,9 @@
     private PersistenceResolver() {}
     
     /**
-     * Just insists that ref {@link Ref#isPersistent(Object)}.
+     * Currently, just returns ref.
      */
     public Object run(Object ref) {
-        if (! Ref.isPersistent(ref)) {
-            throw new RuntimeException("not persistent: " + ref);
-        }
         return ref;
     }
 }



1.4       +10 -34    e/src/jsrc/org/erights/e/elib/serial/RemoteDelivery.java

Index: RemoteDelivery.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/serial/RemoteDelivery.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- RemoteDelivery.java	2000/11/14 11:15:34	1.3
+++ RemoteDelivery.java	2001/08/21 13:36:19	1.4
@@ -23,10 +23,11 @@
 import java.io.Serializable;
 import org.erights.e.elib.base.TextWriter;
 import org.erights.e.elib.prim.E;
+import org.erights.e.elib.ref.StemCell;
 import org.erights.e.elib.tables.ConstList;
 
 /**
- * A RemoteDelivery deserializes into the result of <p><pre>
+ * A RemoteDelivery unserializes into the result of <pre>
  *
  *     recipient <- verb(args...)
  * </pre>
@@ -34,14 +35,13 @@
  * capability constraints.  All pointers serialized as pointers to the 
  * RemoteDelivery will be deserialized as pointing to the promise for the 
  * result of the send.  This may violate static types or other constraints, 
- * and cause deserialization to fail. <p>
- * 
- * Note that a RemoteDelivery is Serializable, but isn't PassBy-anything.  
- * It's a separate category.
- * 
+ * and cause deserialization to fail.
+ *
  * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
  */
-public class RemoteDelivery implements Serializable {
+public class RemoteDelivery extends StemCell {
+    
+    static private final long serialVersionUID = -1066078761914348565L;
     
     /** @serial receives the message */
     private Object myRecipient;
@@ -54,15 +54,7 @@
     
     /**
      * Descibe an invocation to be run on the other side of a serialization 
-     * barrier of some sort. <p>
-     * 
-     * DANGER DANGER WARNING WARNING, recipient and 
-     * args must not refer to the object getting serialized as this apply 
-     * capsule, or they may be deserialized to point at this capsule directly 
-     * rather than the result of readResolve().  This is a known *bad* 
-     * problem with Java Serialization.  XXX Perhaps we should make a
-     * RemoteDelivery a kind of Ref so it can E-transparently forward its 
-     * clients to its resolution.
+     * barrier of some sort.
      * 
      * @param recipient receives the message
      * @param verb the message name (selector, method name)
@@ -77,27 +69,11 @@
         myArgs = args;
     }
     
-    /**
-     *
-     */
-    public Object getRecipient() { return myRecipient; }
-    public String getVerb()      { return myVerb; }
-    public Object[] getArgs()    { return myArgs; }
-    
-    /**
-     * Returns a 3-tuple of recipient, verb, and args.  A convenience for 
-     * those (like equality) that just want to iterate through all the data.
-     */
-    public Object[] getState() {
-        Object[] state = { myRecipient, myVerb, myArgs };
-        return state;
-    }
-    
     /**
-     * Invoked directly by the ObjectInputStream following desrialization of 
+     * Invoked directly by the ObjectInputStream following desrialization of
      * the entire RemoteDelivery to get the object to use instead.
      */
-    private Object readResolve() {
+    protected Object readResolveStem() {
         return E.sendAll(myRecipient, myVerb, myArgs);
     }
     



1.21      +0 -9      e/src/jsrc/org/erights/e/elib/tables/ConstMap.java

Index: ConstMap.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/ConstMap.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- ConstMap.java	2001/08/20 05:07:44	1.20
+++ ConstMap.java	2001/08/21 13:36:19	1.21
@@ -28,7 +28,6 @@
 import org.erights.e.elib.prim.StaticMaker;
 import org.erights.e.elib.serial.PassByConstruction;
 import org.erights.e.elib.serial.Persistent;
-import org.erights.e.elib.serial.RemoteDelivery;
 import org.erights.e.elib.tables.Selfless;
 import org.erights.e.elib.util.ArityMismatchException;
 
@@ -82,14 +81,6 @@
     public Object[] getCanonicalState() {
         Object[] result = { GetMaker(), "fromColumns", getKeys(), getValues() };
         return result;
-    }
-    
-    /**
-     * Unserialzes to a promise for 'ConstMapMaker <- fromColumns(key, values)'
-     */
-    private Object writeReplace() {
-        Object[] args = { getKeys(), getValues() };
-        return new RemoteDelivery(GetMaker(), "fromColumns", args);
     }
     
     /**



1.15      +15 -2     e/src/jsrc/org/erights/e/elib/tables/ConstMapImpl.java

Index: ConstMapImpl.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/ConstMapImpl.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- ConstMapImpl.java	2000/11/14 11:15:34	1.14
+++ ConstMapImpl.java	2001/08/21 13:36:19	1.15
@@ -19,8 +19,9 @@
 Contributor(s): ______________________________________.
 */
 
+import java.io.ObjectStreamException;
+import org.erights.e.elib.serial.RemoteDelivery;
 
-
 /**
  *
  *
@@ -28,7 +29,11 @@
  */
 /*package*/ class ConstMapImpl extends ConstMap {
 
-    private FlexMap myTable;
+    /**
+     * This class should never be directly unserialized, so this instance 
+     * variable need not be declared serial.
+     */
+    private transient FlexMap myTable;
 
     /**
      * Callers *MUST* be sure to hand in the only reference to this map.
@@ -37,6 +42,14 @@
         myTable = map;
     }
 
+    /**
+     * Unserialzes to a promise for 'ConstMapMaker <- fromColumns(key, values)'
+     */
+    private Object writeReplace() throws ObjectStreamException {
+        Object[] args = { getKeys(), getValues() };
+        return new RemoteDelivery(GetMaker(), "fromColumns", args);
+    }
+    
     /**
      *
      */



1.26      +3 -0      e/src/jsrc/org/erights/e/elib/tables/EList.java

Index: EList.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/EList.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- EList.java	2001/07/29 02:16:50	1.25
+++ EList.java	2001/08/21 13:36:19	1.26
@@ -31,6 +31,7 @@
 
 /**
  * A EList is a sequence of values.
+ * <p>
  * 'EList' is a query-only interface that's agnostic about whether 
  * the data can change and whether a EList can be cast to an object by which 
  * to change it.  'EList' is also agnostic about the basis for equality 
@@ -46,6 +47,8 @@
  * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
  */
 public abstract class EList implements Printable, Persistent {
+    
+    static private final long serialVersionUID = 4755060696966322025L;
     
     /**
      *



1.16      +2 -18     e/src/jsrc/org/erights/e/elib/tables/Twine.java

Index: Twine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/Twine.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- Twine.java	2001/08/20 21:17:50	1.15
+++ Twine.java	2001/08/21 13:36:19	1.16
@@ -25,10 +25,8 @@
 import org.erights.e.elib.prim.StaticMaker;
 
 /**
- * Like a String, except that it keeps track of original source positions, 
- * and can contain objects that print on demand, in order to allow Twine to 
- * be used to print cyclic structures safely. <p>
- *
+ * Like a String, except that it keeps track of original source positions.
+ * <p>
  * Twine has exactly two immediate subclasses -- AtomicTwine and 
  * CompositeTwine.  Both will give their contents as a list of AtomicTwine.  
  * Only AtomicTwine gives accurate source positions, so to be accurate you 
@@ -106,20 +104,6 @@
         } else {
             return new LocatedTwine(str, optSourceSpan);
         }
-    }
-    
-    /**
-     *
-     */
-    static public Twine loopy(Object identity) {
-        return new LoopyTwine(E.toString(identity), identity);
-    }
-    
-    /**
-     *
-     */
-    static public Twine loopy(Object identity, String str) {
-        return new LoopyTwine(str, identity);
     }
     
     /**