home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 8.3 KB | 266 lines |
- /*
- * @(#)MarshalledObject.java 1.19 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.rmi;
-
- import java.io.*;
- import sun.rmi.server.MarshalInputStream;
- import sun.rmi.server.MarshalOutputStream;
-
- /**
- * A <code>MarshalledObject</code> contains a byte stream with the serialized
- * representation of an object given to its constructor. The <code>get</code>
- * method returns a new copy of the original object, as deserialized from
- * the contained byte stream. The contained object is serialized and
- * deserialized with the same serialization semantics used for marshaling
- * and unmarshaling parameters and return values of RMI calls: When the
- * serialized form is created, classes are annotated with a codebase URL
- * from where the class can be loaded (if available), and when copies of
- * the object are retrieved, if the bytecodes for a class is not available
- * locally, they will be loaded from the annotated URL. Also, Remote
- * objects are replaced with their proxy stubs during serialization.
- *
- * <code>MarshalledObject</code> facilitates passing objects in RMI calls that
- * are not automatically deserialized immediately by the remote peer.
- *
- * @author Ann Wollrath
- * @author Peter Jones
- */
- public final class MarshalledObject implements Serializable
- {
- /**
- * Bytes of serialized representation. If <code>objBytes</code> is
- * <code>null</code> then the object marshalled was a <code>null</code>
- * reference.
- */
- private byte[] objBytes = null;
-
- /**
- * Bytes of location annotations, which are ignored by <code>equals</code>.
- * If <code>locBytes</code> is null, there were no non-<code>null</code>
- * annotations during marshalling.
- */
- private byte[] locBytes = null;
-
- /** Stored hash code of contained object. */
- private int hash;
-
- /** Indicate compatibility with JDK 1.1.x version of class. */
- private static final long serialVersionUID = 8988374069173025854L;
-
- /**
- * Create a new <code>MarshalledObject</code> that contains the serialized
- * representation of the current state of the supplied object. The
- * object is serialized with the semantics used for marshaling
- * parameters for RMI calls.
- *
- * @param obj the object to be serialized (must be serializable)
- */
- public MarshalledObject(Object obj)
- throws java.io.IOException
- {
- if (obj == null) {
- hash = 13;
- return;
- }
-
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ByteArrayOutputStream lout = new ByteArrayOutputStream();
- MarshalledObjectOutputStream out =
- new MarshalledObjectOutputStream(bout, lout);
- out.writeObject(obj);
- out.flush();
- objBytes = bout.toByteArray();
- // locBytes is null if no annotations
- locBytes = (out.hadAnnotations() ? lout.toByteArray() : null);
-
- /*
- * Calculate hash from the marshalled representation of object
- * so the hashcode will be comparable when sent between VMs.
- */
- int h = 0;
- for (int i = 0; i < objBytes.length; i++) {
- h = 31 * h + objBytes[i];
- }
- hash = h;
- }
-
- /**
- * Return a new copy of the contained object. The internal
- * representation is deserialized with the semantics used for
- * unmarshaling paramters for RMI calls.
- *
- * @return a copy of the contained object
- */
- public Object get()
- throws java.io.IOException, java.lang.ClassNotFoundException
- {
- if (objBytes == null) // must have been a null object
- return null;
-
- ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);
- // locBytes is null if no annotations
- ByteArrayInputStream lin =
- (locBytes == null ? null : new ByteArrayInputStream(locBytes));
- MarshalledObjectInputStream in =
- new MarshalledObjectInputStream(bin, lin);
- return in.readObject();
- }
-
- /**
- * Return a hash code for this <code>MarshalledObject</code>.
- *
- * @return a hash code
- */
- public int hashCode() {
- return hash;
- }
-
- /**
- * Compare this <code>MarshalledObject</code> to another object.
- * Return true if and only if the argument refers to a
- * <code>MarshalledObject</code> that contains exactly the same
- * serialized representation of an object as this one does.
- *
- *
- * @param obj the object to compare this <code>MarshalledObject</code>
- * against
- * @return <code>true</code> if the argument contains an equaivalent
- * serialized object
- */
- public boolean equals(Object obj) {
- if (obj == this)
- return true;
-
- if (obj != null && obj instanceof MarshalledObject) {
- MarshalledObject other = (MarshalledObject) obj;
-
- // if either is a ref to null, both must be
- if (objBytes == null || other.objBytes == null)
- return objBytes == other.objBytes;
-
- // quick, easy test
- if (objBytes.length != other.objBytes.length)
- return false;
-
- //!! There is talk about adding an array comparision method
- //!! at JDK1.2 -- if so, this should be rewritten. -arnold
- for (int i = 0; i < objBytes.length; ++i) {
- if (objBytes[i] != other.objBytes[i])
- return false;
- }
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * This class is used to marshall objects for
- * <code>MarshalledObject</code>. It places the location annotations
- * to one side so that two <code>MarshalledObject</code>s will be
- * considered <code>equal</code> if they differ only in location
- * annotations. Objects written using this stream should be read back
- * from a <code>MarshalledObjectInputStream</code>.
- *
- * @see java.rmi.MarshalledObject
- * @see MarshalledObjectInputStream
- */
- private class MarshalledObjectOutputStream extends MarshalOutputStream {
- /** The stream on which location objects are written. */
- private ObjectOutputStream locOut;
-
- /** <code>true</code> if non-<code>null</code> annotations are
- * written.
- */
- private boolean hadAnnotations;
-
- /**
- * Create a new <code>MarshalledObjectOutputStream</code> whose
- * non-location bytes will be written to <code>objOut</code> and whose
- * location annotations (if any) will be written to <code>locOut</code>.
- */
- public MarshalledObjectOutputStream(OutputStream objOut,
- OutputStream locOut)
- throws IOException
- {
- super(objOut);
- this.useProtocolVersion(ObjectStreamConstants.PROTOCOL_VERSION_2);
- this.locOut = new ObjectOutputStream(locOut);
- hadAnnotations = false;
- }
-
- /**
- * Return <code>true</code> if any non-<code>null</code> location
- * annotations have been written to this stream.
- */
- public boolean hadAnnotations() {
- return hadAnnotations;
- }
-
- /**
- * Override implementation to write annotations to the location stream.
- */
- protected void writeLocation(String loc) throws IOException {
- hadAnnotations |= (loc != null);
- locOut.writeObject(loc);
- }
-
-
- public void flush() throws IOException {
- super.flush();
- locOut.flush();
- }
- }
-
- /**
- * The counterpart to <code>MarshalledObjectOutputStream</code>.
- *
- * @see MarshalledObjectOutputStream
- */
- private static class MarshalledObjectInputStream
- extends MarshalInputStream {
- /**
- * The stream from which annotations will be read. If this is
- * <code>null</code>, then all annotations were <code>null</code>.
- */
- private ObjectInputStream locIn;
-
- /**
- * Create a new <code>MarshalledObjectInputStream</code> that
- * reads its objects from <code>objIn</code> and annotations
- * from <code>locIn</code>. If <code>locIn</code> is
- * <code>null</code>, then all annotations will be
- * <code>null</code>.
- */
- MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
- throws IOException
- {
- super(objIn);
- this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
- }
-
- /**
- * Override to return locations from the stream we were given,
- * or <code>null</code> if we were given a <code>null</code>
- * location stream. */
- protected Object readLocation()
- throws IOException, ClassNotFoundException
- {
- return (locIn == null ? null : locIn.readObject());
- }
- }
-
- }
-