home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / rmi / MarshalledObject.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  9.5 KB  |  299 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)MarshalledObject.java    1.24 98/07/08
  3.  * 
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.rmi;
  16.  
  17. import java.io.*;
  18. import sun.rmi.server.MarshalInputStream;
  19. import sun.rmi.server.MarshalOutputStream;
  20.  
  21. /**
  22.  * A <code>MarshalledObject</code> contains a byte stream with the serialized
  23.  * representation of an object given to its constructor.  The <code>get</code>
  24.  * method returns a new copy of the original object, as deserialized from
  25.  * the contained byte stream.  The contained object is serialized and
  26.  * deserialized with the same serialization semantics used for marshaling
  27.  * and unmarshaling parameters and return values of RMI calls:  When the
  28.  * serialized form is created:
  29.  *
  30.  * <ul>
  31.  * <li> classes are annotated with a codebase URL from where the class
  32.  *      can be loaded (if available), and
  33.  * <li> any remote object in the <code>MarshalledObject</code> is
  34.  *      represented by a serialized instance of its stub.
  35.  * </ul>
  36.  *
  37.  * <p>When copy of the object is retrieved (via the <code>get</code> method),
  38.  * if the class is not available locally, it will be loaded from the
  39.  * appropriate location (specified the URL annotated with the class descriptor
  40.  * when the class was serialized.
  41.  *
  42.  * <p><code>MarshalledObject</code> facilitates passing objects in RMI calls
  43.  * that are not automatically deserialized immediately by the remote peer.
  44.  *
  45.  * @version 1.24, 07/08/98
  46.  * @author  Ann Wollrath
  47.  * @author  Peter Jones
  48.  * @since   JDK1.2
  49.  */
  50. public final class MarshalledObject implements Serializable {
  51.     /**
  52.      * @serial Bytes of serialized representation.  If <code>objBytes</code> is
  53.      * <code>null</code> then the object marshalled was a <code>null</code>
  54.      * reference.
  55.      */
  56.     private byte[] objBytes = null;
  57.  
  58.     /**
  59.      * @serial Bytes of location annotations, which are ignored by
  60.      * <code>equals</code>.  If <code>locBytes</code> is null, there were no
  61.      * non-<code>null</code> annotations during marshalling.
  62.      */
  63.     private byte[] locBytes = null;
  64.  
  65.     /** 
  66.      * @serial Stored hash code of contained object. 
  67.      *
  68.      * @see #hashCode
  69.      */
  70.     private int hash;
  71.  
  72.     /** Indicate compatibility with JDK 1.2 version of class. */
  73.     private static final long serialVersionUID = 8988374069173025854L;
  74.  
  75.     /**
  76.      * Creates a new <code>MarshalledObject</code> that contains the
  77.      * serialized representation of the current state of the supplied object.
  78.      * The object is serialized with the semantics used for marshaling
  79.      * parameters for RMI calls.
  80.      *
  81.      * @param obj the object to be serialized (must be serializable)
  82.      * @exception IOException if an <code>IOException</code> occurs; an
  83.      * <code>IOException</code> may occur if <code>obj</code> is not
  84.      * serializable.
  85.      * @since JDK1.2
  86.      */
  87.     public MarshalledObject(Object obj)
  88.     throws java.io.IOException
  89.     {
  90.     if (obj == null) {
  91.         hash = 13;
  92.         return;
  93.     }
  94.  
  95.     ByteArrayOutputStream bout = new ByteArrayOutputStream();
  96.     ByteArrayOutputStream lout = new ByteArrayOutputStream();
  97.     MarshalledObjectOutputStream out =
  98.         new MarshalledObjectOutputStream(bout, lout);
  99.     out.writeObject(obj);
  100.     out.flush();
  101.     objBytes = bout.toByteArray();
  102.     // locBytes is null if no annotations
  103.     locBytes = (out.hadAnnotations() ? lout.toByteArray() : null);
  104.  
  105.     /*
  106.      * Calculate hash from the marshalled representation of object
  107.      * so the hashcode will be comparable when sent between VMs.
  108.      */
  109.     int h = 0;
  110.     for (int i = 0; i < objBytes.length; i++) {
  111.         h = 31 * h + objBytes[i];
  112.     }
  113.     hash = h;
  114.     }
  115.  
  116.     /**
  117.      * Returns a new copy of the contained marshalledobject.  The internal
  118.      * representation is deserialized with the semantics used for
  119.      * unmarshaling paramters for RMI calls.
  120.      *
  121.      * @return a copy of the contained object
  122.      * @exception IOException if an <code>IOException</code> occurs while
  123.      * deserializing the object from its internal representation.
  124.      * @exception ClassNotFoundException if a
  125.      * <code>ClassNotFoundException</code> occurs while deserializing the
  126.      * object from its internal representation.
  127.      * could not be found
  128.      * @since JDK1.2
  129.      */
  130.     public Object get()
  131.     throws java.io.IOException, java.lang.ClassNotFoundException
  132.     {
  133.     if (objBytes == null)    // must have been a null object
  134.         return null;
  135.  
  136.     ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);
  137.     // locBytes is null if no annotations
  138.     ByteArrayInputStream lin =
  139.         (locBytes == null ? null : new ByteArrayInputStream(locBytes));
  140.     MarshalledObjectInputStream in =
  141.         new MarshalledObjectInputStream(bin, lin);
  142.     return in.readObject();
  143.     }
  144.  
  145.     /**
  146.      * Return a hash code for this <code>MarshalledObject</code>.
  147.      *
  148.      * @return a hash code
  149.      */
  150.     public int hashCode() {
  151.     return hash;
  152.     }
  153.  
  154.     /**
  155.      * Compares this <code>MarshalledObject</code> to another object.
  156.      * Returns true if and only if the argument refers to a
  157.      * <code>MarshalledObject</code> that contains exactly the same
  158.      * serialized representation of an object as this one does. The
  159.      * comparison ignores any class codebase annotation, meaning that
  160.      * two objects are equivalent if they have the same serialized
  161.      * representation <i>except</i> for the codebase of each class
  162.      * in the serialized representation.
  163.      *
  164.      * @param obj the object to compare with this <code>MarshalledObject</code>
  165.      * @return <code>true</code> if the argument contains an equaivalent
  166.      * serialized object; <code>false</code> otherwise
  167.      * @since JDK1.2
  168.      */
  169.     public boolean equals(Object obj) {
  170.     if (obj == this)
  171.         return true;
  172.  
  173.     if (obj != null && obj instanceof MarshalledObject) {
  174.         MarshalledObject other = (MarshalledObject) obj;
  175.  
  176.         // if either is a ref to null, both must be
  177.         if (objBytes == null || other.objBytes == null)
  178.         return objBytes == other.objBytes;
  179.  
  180.         // quick, easy test
  181.         if (objBytes.length != other.objBytes.length)
  182.         return false;
  183.  
  184.         //!! There is talk about adding an array comparision method
  185.         //!! at JDK1.2 -- if so, this should be rewritten.  -arnold
  186.         for (int i = 0; i < objBytes.length; ++i) {
  187.         if (objBytes[i] != other.objBytes[i])
  188.             return false;
  189.         }
  190.         return true;
  191.     } else {
  192.         return false;
  193.     }
  194.     }
  195.  
  196.     /**
  197.      * This class is used to marshal objects for
  198.      * <code>MarshalledObject</code>.  It places the location annotations
  199.      * to one side so that two <code>MarshalledObject</code>s can be
  200.      * compared for equality if they differ only in location
  201.      * annotations.  Objects written using this stream should be read back
  202.      * from a <code>MarshalledObjectInputStream</code>.
  203.      *
  204.      * @see java.rmi.MarshalledObject
  205.      * @see MarshalledObjectInputStream
  206.      */
  207.     private static class MarshalledObjectOutputStream
  208.         extends MarshalOutputStream
  209.     {
  210.     /** The stream on which location objects are written. */
  211.     private ObjectOutputStream locOut;
  212.  
  213.     /** <code>true</code> if non-<code>null</code> annotations are
  214.          *  written.
  215.      */
  216.     private boolean hadAnnotations;
  217.  
  218.     /**
  219.      * Creates a new <code>MarshalledObjectOutputStream</code> whose
  220.      * non-location bytes will be written to <code>objOut</code> and whose
  221.      * location annotations (if any) will be written to
  222.      * <code>locOut</code>.
  223.      */
  224.     public MarshalledObjectOutputStream(OutputStream objOut,
  225.                         OutputStream locOut)
  226.         throws IOException
  227.     {
  228.         super(objOut);
  229.         this.useProtocolVersion(ObjectStreamConstants.PROTOCOL_VERSION_2);
  230.         this.locOut = new ObjectOutputStream(locOut);
  231.         hadAnnotations = false;
  232.     }
  233.  
  234.     /**
  235.      * Returns <code>true</code> if any non-<code>null</code> location
  236.      * annotations have been written to this stream.
  237.      */
  238.     public boolean hadAnnotations() {
  239.         return hadAnnotations;
  240.     }
  241.  
  242.     /**
  243.      * Overrides MarshalOutputStream.writeLocation implementation to write
  244.      * annotations to the location stream.
  245.      */
  246.     protected void writeLocation(String loc) throws IOException {
  247.         hadAnnotations |= (loc != null);
  248.         locOut.writeObject(loc);
  249.     }
  250.     
  251.     
  252.     public void flush() throws IOException {
  253.         super.flush();
  254.         locOut.flush();
  255.     }
  256.     }
  257.     
  258.     /**
  259.      * The counterpart to <code>MarshalledObjectOutputStream</code>.
  260.      *
  261.      * @see MarshalledObjectOutputStream
  262.      */
  263.     private static class MarshalledObjectInputStream
  264.         extends MarshalInputStream
  265.     {
  266.     /**
  267.      * The stream from which annotations will be read.  If this is
  268.      * <code>null</code>, then all annotations were <code>null</code>.
  269.      */
  270.     private ObjectInputStream locIn;
  271.  
  272.     /**
  273.      * Creates a new <code>MarshalledObjectInputStream</code> that
  274.      * reads its objects from <code>objIn</code> and annotations
  275.      * from <code>locIn</code>.  If <code>locIn</code> is
  276.      * <code>null</code>, then all annotations will be
  277.      * <code>null</code>.
  278.      */
  279.     MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
  280.         throws IOException
  281.     {
  282.         super(objIn);
  283.         this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
  284.     }
  285.  
  286.     /**
  287.      * Overrides MarshalInputStream.readLocation to return locations from
  288.      * the stream we were given, or <code>null</code> if we were given a
  289.      * <code>null</code> location stream.
  290.      */
  291.     protected Object readLocation()
  292.         throws IOException, ClassNotFoundException
  293.     {
  294.         return (locIn == null ? null : locIn.readObject());
  295.     }
  296.     }
  297.  
  298. }
  299.