aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/sun/rmi/transport/LiveRef.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/classes/sun/rmi/transport/LiveRef.java')
-rw-r--r--src/share/classes/sun/rmi/transport/LiveRef.java317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/share/classes/sun/rmi/transport/LiveRef.java b/src/share/classes/sun/rmi/transport/LiveRef.java
new file mode 100644
index 000000000..f8810c0d2
--- /dev/null
+++ b/src/share/classes/sun/rmi/transport/LiveRef.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.rmi.transport;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.ObjID;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Arrays;
+import sun.rmi.transport.tcp.TCPEndpoint;
+
+/**
+ * NOTE: There is a JDK-internal dependency on the existence of this
+ * class and its getClientSocketFactory method in the implementation
+ * of javax.management.remote.rmi.RMIConnector.
+ **/
+public class LiveRef implements Cloneable {
+ /** wire representation for the object*/
+ private final Endpoint ep;
+ private final ObjID id;
+
+ /** cached connection service for the object */
+ private transient Channel ch;
+
+ /** flag to indicate whether this ref specifies a local server or
+ * is a ref for a remote object (surrogate)
+ */
+ private final boolean isLocal;
+
+ /**
+ * Construct a "well-known" live reference to a remote object
+ * @param isLocalServer If true, indicates this ref specifies a local
+ * server in this address space; if false, the ref is for a remote
+ * object (hence a surrogate or proxy) in another address space.
+ */
+ public LiveRef(ObjID objID, Endpoint endpoint, boolean isLocal) {
+ ep = endpoint;
+ id = objID;
+ this.isLocal = isLocal;
+ }
+
+ /**
+ * Construct a new live reference for a server object in the local
+ * address space.
+ */
+ public LiveRef(int port) {
+ this((new ObjID()), port);
+ }
+
+ /**
+ * Construct a new live reference for a server object in the local
+ * address space, to use sockets of the specified type.
+ */
+ public LiveRef(int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ {
+ this((new ObjID()), port, csf, ssf);
+ }
+
+ /**
+ * Construct a new live reference for a "well-known" server object
+ * in the local address space.
+ */
+ public LiveRef(ObjID objID, int port) {
+ this(objID, TCPEndpoint.getLocalEndpoint(port), true);
+ }
+
+ /**
+ * Construct a new live reference for a "well-known" server object
+ * in the local address space, to use sockets of the specified type.
+ */
+ public LiveRef(ObjID objID, int port, RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ {
+ this(objID, TCPEndpoint.getLocalEndpoint(port, csf, ssf), true);
+ }
+
+ /**
+ * Return a shallow copy of this ref.
+ */
+ public Object clone() {
+ try {
+ LiveRef newRef = (LiveRef) super.clone();
+ return newRef;
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Return the port number associated with this ref.
+ */
+ public int getPort() {
+ return ((TCPEndpoint) ep).getPort();
+ }
+
+ /**
+ * Return the client socket factory associated with this ref.
+ *
+ * NOTE: There is a JDK-internal dependency on the existence of
+ * this method in the implementation of
+ * javax.management.remote.rmi.RMIConnector.
+ **/
+ public RMIClientSocketFactory getClientSocketFactory() {
+ return ((TCPEndpoint) ep).getClientSocketFactory();
+ }
+
+ /**
+ * Return the server socket factory associated with this ref.
+ */
+ public RMIServerSocketFactory getServerSocketFactory() {
+ return ((TCPEndpoint) ep).getServerSocketFactory();
+ }
+
+ /**
+ * Export the object to accept incoming calls.
+ */
+ public void exportObject(Target target) throws RemoteException {
+ ep.exportObject(target);
+ }
+
+ public Channel getChannel() throws RemoteException {
+ if (ch == null) {
+ ch = ep.getChannel();
+ }
+ return ch;
+ }
+
+ public ObjID getObjID() {
+ return id;
+ }
+
+ Endpoint getEndpoint() {
+ return ep;
+ }
+
+ public String toString() {
+ String type;
+
+ if (isLocal)
+ type = "local";
+ else
+ type = "remote";
+ return "[endpoint:" + ep + "(" + type + ")," +
+ "objID:" + id + "]";
+ }
+
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof LiveRef) {
+ LiveRef ref = (LiveRef) obj;
+
+ return (ep.equals(ref.ep) && id.equals(ref.id) &&
+ isLocal == ref.isLocal);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean remoteEquals(Object obj) {
+ if (obj != null && obj instanceof LiveRef) {
+ LiveRef ref = (LiveRef) obj;
+
+ TCPEndpoint thisEp = ((TCPEndpoint) ep);
+ TCPEndpoint refEp = ((TCPEndpoint) ref.ep);
+
+ RMIClientSocketFactory thisClientFactory =
+ thisEp.getClientSocketFactory();
+ RMIClientSocketFactory refClientFactory =
+ refEp.getClientSocketFactory();
+
+ /**
+ * Fix for 4254103: LiveRef.remoteEquals should not fail
+ * if one of the objects in the comparison has a null
+ * server socket. Comparison should only consider the
+ * following criteria:
+ *
+ * hosts, ports, client socket factories and object IDs.
+ */
+ if (thisEp.getPort() != refEp.getPort() ||
+ !thisEp.getHost().equals(refEp.getHost()))
+ {
+ return false;
+ }
+ if ((thisClientFactory == null) ^ (refClientFactory == null)) {
+ return false;
+ }
+ if ((thisClientFactory != null) &&
+ !((thisClientFactory.getClass() ==
+ refClientFactory.getClass()) &&
+ (thisClientFactory.equals(refClientFactory))))
+ {
+ return false;
+ }
+ return (id.equals(ref.id));
+ } else {
+ return false;
+ }
+ }
+
+ public void write(ObjectOutput out, boolean useNewFormat)
+ throws IOException
+ {
+ boolean isResultStream = false;
+ if (out instanceof ConnectionOutputStream) {
+ ConnectionOutputStream stream = (ConnectionOutputStream) out;
+ isResultStream = stream.isResultStream();
+ /*
+ * Ensure that referential integrity is not broken while
+ * this LiveRef is in transit. If it is being marshalled
+ * as part of a result, it may not otherwise be strongly
+ * reachable after the remote call has completed; even if
+ * it is being marshalled as part of an argument, the VM
+ * may determine that the reference on the stack is no
+ * longer reachable after marshalling (see 6181943)--
+ * therefore, tell the stream to save a reference until a
+ * timeout expires or, for results, a DGCAck message has
+ * been received from the caller, or for arguments, the
+ * remote call has completed. For a "local" LiveRef, save
+ * a reference to the impl directly, because the impl is
+ * not reachable from the LiveRef (see 4114579);
+ * otherwise, save a reference to the LiveRef, for the
+ * client-side DGC to watch over. (Also see 4017232.)
+ */
+ if (isLocal) {
+ ObjectEndpoint oe =
+ new ObjectEndpoint(id, ep.getInboundTransport());
+ Target target = ObjectTable.getTarget(oe);
+
+ if (target != null) {
+ Remote impl = target.getImpl();
+ if (impl != null) {
+ stream.saveObject(impl);
+ }
+ }
+ } else {
+ stream.saveObject(this);
+ }
+ }
+ // All together now write out the endpoint, id, and flag
+
+ // (need to choose whether or not to use old JDK1.1 endpoint format)
+ if (useNewFormat) {
+ ((TCPEndpoint) ep).write(out);
+ } else {
+ ((TCPEndpoint) ep).writeHostPortFormat(out);
+ }
+ id.write(out);
+ out.writeBoolean(isResultStream);
+ }
+
+ public static LiveRef read(ObjectInput in, boolean useNewFormat)
+ throws IOException, ClassNotFoundException
+ {
+ Endpoint ep;
+ ObjID id;
+
+ // Now read in the endpoint, id, and result flag
+ // (need to choose whether or not to read old JDK1.1 endpoint format)
+ if (useNewFormat) {
+ ep = TCPEndpoint.read(in);
+ } else {
+ ep = TCPEndpoint.readHostPortFormat(in);
+ }
+ id = ObjID.read(in);
+ boolean isResultStream = in.readBoolean();
+
+ LiveRef ref = new LiveRef(id, ep, false);
+
+ if (in instanceof ConnectionInputStream) {
+ ConnectionInputStream stream = (ConnectionInputStream)in;
+ // save ref to send "dirty" call after all args/returns
+ // have been unmarshaled.
+ stream.saveRef(ref);
+ if (isResultStream) {
+ // set flag in stream indicating that remote objects were
+ // unmarshaled. A DGC ack should be sent by the transport.
+ stream.setAckNeeded();
+ }
+ } else {
+ DGCClient.registerRefs(ep, Arrays.asList(new LiveRef[] { ref }));
+ }
+
+ return ref;
+ }
+}