home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / rmi / MarshalledObject.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  8.3 KB  |  266 lines

  1. /*
  2.  * @(#)MarshalledObject.java    1.19 98/03/18
  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, classes are annotated with a codebase URL
  29.  * from where the class can be loaded (if available), and when copies of
  30.  * the object are retrieved, if the bytecodes for a class is not available
  31.  * locally, they will be loaded from the annotated URL.  Also, Remote
  32.  * objects are replaced with their proxy stubs during serialization.
  33.  *
  34.  * <code>MarshalledObject</code> facilitates passing objects in RMI calls that
  35.  * are not automatically deserialized immediately by the remote peer.
  36.  *
  37.  * @author Ann Wollrath
  38.  * @author Peter Jones
  39.  */
  40. public final class MarshalledObject implements Serializable
  41. {
  42.     /**
  43.      * Bytes of serialized representation.  If <code>objBytes</code> is
  44.      * <code>null</code> then the object marshalled was a <code>null</code>
  45.      * reference.
  46.      */
  47.     private byte[] objBytes = null;
  48.  
  49.     /**
  50.      * Bytes of location annotations, which are ignored by <code>equals</code>.
  51.      * If <code>locBytes</code> is null, there were no non-<code>null</code>
  52.      * annotations during marshalling.
  53.      */
  54.     private byte[] locBytes = null;
  55.  
  56.     /** Stored hash code of contained object. */
  57.     private int hash;
  58.  
  59.     /** Indicate compatibility with JDK 1.1.x version of class. */
  60.     private static final long serialVersionUID = 8988374069173025854L;
  61.  
  62.     /**
  63.      * Create a new <code>MarshalledObject</code> that contains the serialized
  64.      * representation of the current state of the supplied object.  The
  65.      * object is serialized with the semantics used for marshaling
  66.      * parameters for RMI calls.
  67.      *
  68.      * @param obj the object to be serialized (must be serializable)
  69.      */
  70.     public MarshalledObject(Object obj)
  71.     throws java.io.IOException
  72.     {
  73.     if (obj == null) {
  74.         hash = 13;
  75.         return;
  76.     }
  77.  
  78.     ByteArrayOutputStream bout = new ByteArrayOutputStream();
  79.     ByteArrayOutputStream lout = new ByteArrayOutputStream();
  80.     MarshalledObjectOutputStream out =
  81.         new MarshalledObjectOutputStream(bout, lout);
  82.     out.writeObject(obj);
  83.     out.flush();
  84.     objBytes = bout.toByteArray();
  85.     // locBytes is null if no annotations
  86.     locBytes = (out.hadAnnotations() ? lout.toByteArray() : null);
  87.  
  88.     /*
  89.      * Calculate hash from the marshalled representation of object
  90.      * so the hashcode will be comparable when sent between VMs.
  91.      */
  92.     int h = 0;
  93.     for (int i = 0; i < objBytes.length; i++) {
  94.         h = 31 * h + objBytes[i];
  95.     }
  96.     hash = h;
  97.     }
  98.  
  99.     /**
  100.      * Return a new copy of the contained object.  The internal
  101.      * representation is deserialized with the semantics used for
  102.      * unmarshaling paramters for RMI calls.
  103.      *
  104.      * @return a copy of the contained object
  105.      */
  106.     public Object get()
  107.     throws java.io.IOException, java.lang.ClassNotFoundException
  108.     {
  109.     if (objBytes == null)    // must have been a null object
  110.         return null;
  111.  
  112.     ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);
  113.     // locBytes is null if no annotations
  114.     ByteArrayInputStream lin =
  115.         (locBytes == null ? null : new ByteArrayInputStream(locBytes));
  116.     MarshalledObjectInputStream in =
  117.         new MarshalledObjectInputStream(bin, lin);
  118.     return in.readObject();
  119.     }
  120.  
  121.     /**
  122.      * Return a hash code for this <code>MarshalledObject</code>.
  123.      *
  124.      * @return a hash code
  125.      */
  126.     public int hashCode() {
  127.     return hash;
  128.     }
  129.  
  130.     /**
  131.      * Compare this <code>MarshalledObject</code> to another object.
  132.      * Return true if and only if the argument refers to a
  133.      * <code>MarshalledObject</code> that contains exactly the same
  134.      * serialized representation of an object as this one does.
  135.      *
  136.      *
  137.      * @param obj the object to compare this <code>MarshalledObject</code>
  138.      * against
  139.      * @return <code>true</code> if the argument contains an equaivalent
  140.      * serialized object
  141.      */
  142.     public boolean equals(Object obj) {
  143.     if (obj == this)
  144.         return true;
  145.  
  146.     if (obj != null && obj instanceof MarshalledObject) {
  147.         MarshalledObject other = (MarshalledObject) obj;
  148.  
  149.         // if either is a ref to null, both must be
  150.         if (objBytes == null || other.objBytes == null)
  151.         return objBytes == other.objBytes;
  152.  
  153.         // quick, easy test
  154.         if (objBytes.length != other.objBytes.length)
  155.         return false;
  156.  
  157.         //!! There is talk about adding an array comparision method
  158.         //!! at JDK1.2 -- if so, this should be rewritten.  -arnold
  159.         for (int i = 0; i < objBytes.length; ++i) {
  160.         if (objBytes[i] != other.objBytes[i])
  161.             return false;
  162.         }
  163.         return true;
  164.     } else {
  165.         return false;
  166.     }
  167.     }
  168.  
  169.     /**
  170.      * This class is used to marshall objects for
  171.      * <code>MarshalledObject</code>.  It places the location annotations
  172.      * to one side so that two <code>MarshalledObject</code>s will be
  173.      * considered <code>equal</code> if they differ only in location
  174.      * annotations.  Objects written using this stream should be read back
  175.      * from a <code>MarshalledObjectInputStream</code>.
  176.      *
  177.      * @see java.rmi.MarshalledObject
  178.      * @see MarshalledObjectInputStream
  179.      */
  180.     private class MarshalledObjectOutputStream extends MarshalOutputStream {
  181.     /** The stream on which location objects are written. */
  182.     private ObjectOutputStream locOut;
  183.  
  184.     /** <code>true</code> if non-<code>null</code> annotations are
  185.          *  written.
  186.      */
  187.     private boolean hadAnnotations;
  188.  
  189.     /**
  190.      * Create a new <code>MarshalledObjectOutputStream</code> whose
  191.      * non-location bytes will be written to <code>objOut</code> and whose
  192.      * location annotations (if any) will be written to <code>locOut</code>.
  193.      */
  194.     public MarshalledObjectOutputStream(OutputStream objOut,
  195.                         OutputStream locOut)
  196.         throws IOException
  197.     {
  198.         super(objOut);
  199.         this.useProtocolVersion(ObjectStreamConstants.PROTOCOL_VERSION_2);
  200.         this.locOut = new ObjectOutputStream(locOut);
  201.         hadAnnotations = false;
  202.     }
  203.  
  204.     /**
  205.      * Return <code>true</code> if any non-<code>null</code> location
  206.      * annotations have been written to this stream.
  207.      */
  208.     public boolean hadAnnotations() {
  209.         return hadAnnotations;
  210.     }
  211.  
  212.     /**
  213.      * Override implementation to write annotations to the location stream.
  214.      */
  215.     protected void writeLocation(String loc) throws IOException {
  216.         hadAnnotations |= (loc != null);
  217.         locOut.writeObject(loc);
  218.     }
  219.     
  220.     
  221.     public void flush() throws IOException {
  222.         super.flush();
  223.         locOut.flush();
  224.     }
  225.     }
  226.     
  227.     /**
  228.      * The counterpart to <code>MarshalledObjectOutputStream</code>.
  229.      *
  230.      * @see MarshalledObjectOutputStream
  231.      */
  232.     private static class MarshalledObjectInputStream
  233.     extends MarshalInputStream {
  234.     /**
  235.      * The stream from which annotations will be read.  If this is
  236.      * <code>null</code>, then all annotations were <code>null</code>.
  237.      */
  238.     private ObjectInputStream locIn;
  239.  
  240.     /**
  241.      * Create a new <code>MarshalledObjectInputStream</code> that
  242.      * reads its objects from <code>objIn</code> and annotations
  243.      * from <code>locIn</code>.  If <code>locIn</code> is
  244.      * <code>null</code>, then all annotations will be
  245.      * <code>null</code>.
  246.      */
  247.     MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
  248.         throws IOException
  249.     {
  250.         super(objIn);
  251.         this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
  252.     }
  253.  
  254.     /**
  255.      * Override to return locations from the stream we were given,
  256.      * or <code>null</code> if we were given a <code>null</code>
  257.      * location stream.  */
  258.     protected Object readLocation()
  259.         throws IOException, ClassNotFoundException
  260.     {
  261.         return (locIn == null ? null : locIn.readObject());
  262.     }
  263.     }
  264.  
  265. }
  266.