History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/rmi/MarshalledObject.java (1 of 18352 files). Show all

Unified · Split

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