Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/rmi/MarshalledObject.java
38829 views
/*1* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.rmi;2627import java.io.ByteArrayInputStream;28import java.io.ByteArrayOutputStream;29import java.io.IOException;30import java.io.InputStream;31import java.io.ObjectInputStream;32import java.io.ObjectOutputStream;33import java.io.ObjectStreamConstants;34import java.io.OutputStream;35import java.io.Serializable;36import java.security.AccessController;37import java.security.PrivilegedAction;3839import sun.rmi.server.MarshalInputStream;40import sun.rmi.server.MarshalOutputStream;4142import sun.misc.ObjectInputFilter;4344/**45* A <code>MarshalledObject</code> contains a byte stream with the serialized46* representation of an object given to its constructor. The <code>get</code>47* method returns a new copy of the original object, as deserialized from48* the contained byte stream. The contained object is serialized and49* deserialized with the same serialization semantics used for marshaling50* and unmarshaling parameters and return values of RMI calls: When the51* serialized form is created:52*53* <ul>54* <li> classes are annotated with a codebase URL from where the class55* can be loaded (if available), and56* <li> any remote object in the <code>MarshalledObject</code> is57* represented by a serialized instance of its stub.58* </ul>59*60* <p>When copy of the object is retrieved (via the <code>get</code> method),61* if the class is not available locally, it will be loaded from the62* appropriate location (specified the URL annotated with the class descriptor63* when the class was serialized.64*65* <p><code>MarshalledObject</code> facilitates passing objects in RMI calls66* that are not automatically deserialized immediately by the remote peer.67*68* @param <T> the type of the object contained in this69* <code>MarshalledObject</code>70*71* @author Ann Wollrath72* @author Peter Jones73* @since 1.274*/75public final class MarshalledObject<T> implements Serializable {76/**77* @serial Bytes of serialized representation. If <code>objBytes</code> is78* <code>null</code> then the object marshalled was a <code>null</code>79* reference.80*/81private byte[] objBytes = null;8283/**84* @serial Bytes of location annotations, which are ignored by85* <code>equals</code>. If <code>locBytes</code> is null, there were no86* non-<code>null</code> annotations during marshalling.87*/88private byte[] locBytes = null;8990/**91* @serial Stored hash code of contained object.92*93* @see #hashCode94*/95private int hash;9697/** Filter used when creating the instance from a stream; may be null. */98private transient ObjectInputFilter objectInputFilter = null;99100/** Indicate compatibility with 1.2 version of class. */101private static final long serialVersionUID = 8988374069173025854L;102103/**104* Creates a new <code>MarshalledObject</code> that contains the105* serialized representation of the current state of the supplied object.106* The object is serialized with the semantics used for marshaling107* parameters for RMI calls.108*109* @param obj the object to be serialized (must be serializable)110* @exception IOException if an <code>IOException</code> occurs; an111* <code>IOException</code> may occur if <code>obj</code> is not112* serializable.113* @since 1.2114*/115public MarshalledObject(T obj) throws IOException {116if (obj == null) {117hash = 13;118return;119}120121ByteArrayOutputStream bout = new ByteArrayOutputStream();122ByteArrayOutputStream lout = new ByteArrayOutputStream();123MarshalledObjectOutputStream out =124new MarshalledObjectOutputStream(bout, lout);125out.writeObject(obj);126out.flush();127objBytes = bout.toByteArray();128// locBytes is null if no annotations129locBytes = (out.hadAnnotations() ? lout.toByteArray() : null);130131/*132* Calculate hash from the marshalled representation of object133* so the hashcode will be comparable when sent between VMs.134*/135int h = 0;136for (int i = 0; i < objBytes.length; i++) {137h = 31 * h + objBytes[i];138}139hash = h;140}141142/**143* Reads in the state of the object and saves the stream's144* serialization filter to be used when the object is deserialized.145*146* @param stream the stream147* @throws IOException if an I/O error occurs148* @throws ClassNotFoundException if a class cannot be found149*/150private void readObject(ObjectInputStream stream)151throws IOException, ClassNotFoundException {152stream.defaultReadObject(); // read in all fields153objectInputFilter = ObjectInputFilter.Config.getObjectInputFilter(stream);154}155156/**157* Returns a new copy of the contained marshalledobject. The internal158* representation is deserialized with the semantics used for159* unmarshaling parameters for RMI calls.160*161* @return a copy of the contained object162* @exception IOException if an <code>IOException</code> occurs while163* deserializing the object from its internal representation.164* @exception ClassNotFoundException if a165* <code>ClassNotFoundException</code> occurs while deserializing the166* object from its internal representation.167* could not be found168* @since 1.2169*/170public T get() throws IOException, ClassNotFoundException {171if (objBytes == null) // must have been a null object172return null;173174ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);175// locBytes is null if no annotations176ByteArrayInputStream lin =177(locBytes == null ? null : new ByteArrayInputStream(locBytes));178MarshalledObjectInputStream in =179new MarshalledObjectInputStream(bin, lin, objectInputFilter);180@SuppressWarnings("unchecked")181T obj = (T) in.readObject();182in.close();183return obj;184}185186/**187* Return a hash code for this <code>MarshalledObject</code>.188*189* @return a hash code190*/191public int hashCode() {192return hash;193}194195/**196* Compares this <code>MarshalledObject</code> to another object.197* Returns true if and only if the argument refers to a198* <code>MarshalledObject</code> that contains exactly the same199* serialized representation of an object as this one does. The200* comparison ignores any class codebase annotation, meaning that201* two objects are equivalent if they have the same serialized202* representation <i>except</i> for the codebase of each class203* in the serialized representation.204*205* @param obj the object to compare with this <code>MarshalledObject</code>206* @return <code>true</code> if the argument contains an equivalent207* serialized object; <code>false</code> otherwise208* @since 1.2209*/210public boolean equals(Object obj) {211if (obj == this)212return true;213214if (obj != null && obj instanceof MarshalledObject) {215MarshalledObject<?> other = (MarshalledObject<?>) obj;216217// if either is a ref to null, both must be218if (objBytes == null || other.objBytes == null)219return objBytes == other.objBytes;220221// quick, easy test222if (objBytes.length != other.objBytes.length)223return false;224225//!! There is talk about adding an array comparision method226//!! at 1.2 -- if so, this should be rewritten. -arnold227for (int i = 0; i < objBytes.length; ++i) {228if (objBytes[i] != other.objBytes[i])229return false;230}231return true;232} else {233return false;234}235}236237/**238* This class is used to marshal objects for239* <code>MarshalledObject</code>. It places the location annotations240* to one side so that two <code>MarshalledObject</code>s can be241* compared for equality if they differ only in location242* annotations. Objects written using this stream should be read back243* from a <code>MarshalledObjectInputStream</code>.244*245* @see java.rmi.MarshalledObject246* @see MarshalledObjectInputStream247*/248private static class MarshalledObjectOutputStream249extends MarshalOutputStream250{251/** The stream on which location objects are written. */252private ObjectOutputStream locOut;253254/** <code>true</code> if non-<code>null</code> annotations are255* written.256*/257private boolean hadAnnotations;258259/**260* Creates a new <code>MarshalledObjectOutputStream</code> whose261* non-location bytes will be written to <code>objOut</code> and whose262* location annotations (if any) will be written to263* <code>locOut</code>.264*/265MarshalledObjectOutputStream(OutputStream objOut, OutputStream locOut)266throws IOException267{268super(objOut);269this.useProtocolVersion(ObjectStreamConstants.PROTOCOL_VERSION_2);270this.locOut = new ObjectOutputStream(locOut);271hadAnnotations = false;272}273274/**275* Returns <code>true</code> if any non-<code>null</code> location276* annotations have been written to this stream.277*/278boolean hadAnnotations() {279return hadAnnotations;280}281282/**283* Overrides MarshalOutputStream.writeLocation implementation to write284* annotations to the location stream.285*/286protected void writeLocation(String loc) throws IOException {287hadAnnotations |= (loc != null);288locOut.writeObject(loc);289}290291292public void flush() throws IOException {293super.flush();294locOut.flush();295}296}297298/**299* The counterpart to <code>MarshalledObjectOutputStream</code>.300*301* @see MarshalledObjectOutputStream302*/303private static class MarshalledObjectInputStream304extends MarshalInputStream305{306/**307* The stream from which annotations will be read. If this is308* <code>null</code>, then all annotations were <code>null</code>.309*/310private ObjectInputStream locIn;311312/**313* Creates a new <code>MarshalledObjectInputStream</code> that314* reads its objects from <code>objIn</code> and annotations315* from <code>locIn</code>. If <code>locIn</code> is316* <code>null</code>, then all annotations will be317* <code>null</code>.318*/319MarshalledObjectInputStream(InputStream objIn, InputStream locIn,320ObjectInputFilter filter)321throws IOException322{323super(objIn);324this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));325if (filter != null) {326AccessController.doPrivileged(new PrivilegedAction<Void>() {327@Override328public Void run() {329ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this, filter);330if (MarshalledObjectInputStream.this.locIn != null) {331ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this.locIn, filter);332}333return null;334}335});336}337}338339/**340* Overrides MarshalInputStream.readLocation to return locations from341* the stream we were given, or <code>null</code> if we were given a342* <code>null</code> location stream.343*/344protected Object readLocation()345throws IOException, ClassNotFoundException346{347return (locIn == null ? null : locIn.readObject());348}349}350351}352353354