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