Path: blob/master/src/java.rmi/share/classes/sun/rmi/transport/LiveRef.java
41154 views
/*1* Copyright (c) 1996, 2011, 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 sun.rmi.transport;2627import java.io.IOException;28import java.io.ObjectInput;29import java.io.ObjectOutput;30import java.rmi.Remote;31import java.rmi.RemoteException;32import java.rmi.server.ObjID;33import java.rmi.server.RMIClientSocketFactory;34import java.rmi.server.RMIServerSocketFactory;35import java.util.Arrays;36import sun.rmi.transport.tcp.TCPEndpoint;3738/**39* NOTE: There is a JDK-internal dependency on the existence of this40* class and its getClientSocketFactory method in the implementation41* of javax.management.remote.rmi.RMIConnector.42**/43public class LiveRef implements Cloneable {44/** wire representation for the object*/45private final Endpoint ep;46private final ObjID id;4748/** cached connection service for the object */49private transient Channel ch;5051/** flag to indicate whether this ref specifies a local server or52* is a ref for a remote object (surrogate)53*/54private final boolean isLocal;5556/**57* Construct a "well-known" live reference to a remote object58* @param isLocal If true, indicates this ref specifies a local59* server in this address space; if false, the ref is for a remote60* object (hence a surrogate or proxy) in another address space.61*/62public LiveRef(ObjID objID, Endpoint endpoint, boolean isLocal) {63ep = endpoint;64id = objID;65this.isLocal = isLocal;66}6768/**69* Construct a new live reference for a server object in the local70* address space.71*/72public LiveRef(int port) {73this((new ObjID()), port);74}7576/**77* Construct a new live reference for a server object in the local78* address space, to use sockets of the specified type.79*/80public LiveRef(int port,81RMIClientSocketFactory csf,82RMIServerSocketFactory ssf)83{84this((new ObjID()), port, csf, ssf);85}8687/**88* Construct a new live reference for a "well-known" server object89* in the local address space.90*/91public LiveRef(ObjID objID, int port) {92this(objID, TCPEndpoint.getLocalEndpoint(port), true);93}9495/**96* Construct a new live reference for a "well-known" server object97* in the local address space, to use sockets of the specified type.98*/99public LiveRef(ObjID objID, int port, RMIClientSocketFactory csf,100RMIServerSocketFactory ssf)101{102this(objID, TCPEndpoint.getLocalEndpoint(port, csf, ssf), true);103}104105/**106* Return a shallow copy of this ref.107*/108public Object clone() {109try {110LiveRef newRef = (LiveRef) super.clone();111return newRef;112} catch (CloneNotSupportedException e) {113throw new InternalError(e.toString(), e);114}115}116117/**118* Return the port number associated with this ref.119*/120public int getPort() {121return ((TCPEndpoint) ep).getPort();122}123124/**125* Return the client socket factory associated with this ref.126*127* NOTE: There is a JDK-internal dependency on the existence of128* this method in the implementation of129* javax.management.remote.rmi.RMIConnector.130**/131public RMIClientSocketFactory getClientSocketFactory() {132return ((TCPEndpoint) ep).getClientSocketFactory();133}134135/**136* Return the server socket factory associated with this ref.137*/138public RMIServerSocketFactory getServerSocketFactory() {139return ((TCPEndpoint) ep).getServerSocketFactory();140}141142/**143* Export the object to accept incoming calls.144*/145public void exportObject(Target target) throws RemoteException {146ep.exportObject(target);147}148149public Channel getChannel() throws RemoteException {150if (ch == null) {151ch = ep.getChannel();152}153return ch;154}155156public ObjID getObjID() {157return id;158}159160Endpoint getEndpoint() {161return ep;162}163164public String toString() {165String type;166167if (isLocal)168type = "local";169else170type = "remote";171return "[endpoint:" + ep + "(" + type + ")," +172"objID:" + id + "]";173}174175public int hashCode() {176return id.hashCode();177}178179public boolean equals(Object obj) {180if (obj != null && obj instanceof LiveRef) {181LiveRef ref = (LiveRef) obj;182183return (ep.equals(ref.ep) && id.equals(ref.id) &&184isLocal == ref.isLocal);185} else {186return false;187}188}189190public boolean remoteEquals(Object obj) {191if (obj != null && obj instanceof LiveRef) {192LiveRef ref = (LiveRef) obj;193194TCPEndpoint thisEp = ((TCPEndpoint) ep);195TCPEndpoint refEp = ((TCPEndpoint) ref.ep);196197RMIClientSocketFactory thisClientFactory =198thisEp.getClientSocketFactory();199RMIClientSocketFactory refClientFactory =200refEp.getClientSocketFactory();201202/**203* Fix for 4254103: LiveRef.remoteEquals should not fail204* if one of the objects in the comparison has a null205* server socket. Comparison should only consider the206* following criteria:207*208* hosts, ports, client socket factories and object IDs.209*/210if (thisEp.getPort() != refEp.getPort() ||211!thisEp.getHost().equals(refEp.getHost()))212{213return false;214}215if ((thisClientFactory == null) ^ (refClientFactory == null)) {216return false;217}218if ((thisClientFactory != null) &&219!((thisClientFactory.getClass() ==220refClientFactory.getClass()) &&221(thisClientFactory.equals(refClientFactory))))222{223return false;224}225return (id.equals(ref.id));226} else {227return false;228}229}230231public void write(ObjectOutput out, boolean useNewFormat)232throws IOException233{234boolean isResultStream = false;235if (out instanceof ConnectionOutputStream) {236ConnectionOutputStream stream = (ConnectionOutputStream) out;237isResultStream = stream.isResultStream();238/*239* Ensure that referential integrity is not broken while240* this LiveRef is in transit. If it is being marshalled241* as part of a result, it may not otherwise be strongly242* reachable after the remote call has completed; even if243* it is being marshalled as part of an argument, the VM244* may determine that the reference on the stack is no245* longer reachable after marshalling (see 6181943)--246* therefore, tell the stream to save a reference until a247* timeout expires or, for results, a DGCAck message has248* been received from the caller, or for arguments, the249* remote call has completed. For a "local" LiveRef, save250* a reference to the impl directly, because the impl is251* not reachable from the LiveRef (see 4114579);252* otherwise, save a reference to the LiveRef, for the253* client-side DGC to watch over. (Also see 4017232.)254*/255if (isLocal) {256ObjectEndpoint oe =257new ObjectEndpoint(id, ep.getInboundTransport());258Target target = ObjectTable.getTarget(oe);259260if (target != null) {261Remote impl = target.getImpl();262if (impl != null) {263stream.saveObject(impl);264}265}266} else {267stream.saveObject(this);268}269}270// All together now write out the endpoint, id, and flag271272// (need to choose whether or not to use old JDK1.1 endpoint format)273if (useNewFormat) {274((TCPEndpoint) ep).write(out);275} else {276((TCPEndpoint) ep).writeHostPortFormat(out);277}278id.write(out);279out.writeBoolean(isResultStream);280}281282public static LiveRef read(ObjectInput in, boolean useNewFormat)283throws IOException, ClassNotFoundException284{285Endpoint ep;286ObjID id;287288// Now read in the endpoint, id, and result flag289// (need to choose whether or not to read old JDK1.1 endpoint format)290if (useNewFormat) {291ep = TCPEndpoint.read(in);292} else {293ep = TCPEndpoint.readHostPortFormat(in);294}295id = ObjID.read(in);296boolean isResultStream = in.readBoolean();297298LiveRef ref = new LiveRef(id, ep, false);299300if (in instanceof ConnectionInputStream) {301ConnectionInputStream stream = (ConnectionInputStream)in;302// save ref to send "dirty" call after all args/returns303// have been unmarshaled.304stream.saveRef(ref);305if (isResultStream) {306// set flag in stream indicating that remote objects were307// unmarshaled. A DGC ack should be sent by the transport.308stream.setAckNeeded();309}310} else {311DGCClient.registerRefs(ep, Arrays.asList(new LiveRef[] { ref }));312}313314return ref;315}316}317318319