PortableRemoteObject.java revision 608:7e06bf1dcb09
1202375Srdivacky/* 2202375Srdivacky * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. 3202375Srdivacky * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4202375Srdivacky * 5202375Srdivacky * This code is free software; you can redistribute it and/or modify it 6202375Srdivacky * under the terms of the GNU General Public License version 2 only, as 7202375Srdivacky * published by the Free Software Foundation. Oracle designates this 8202375Srdivacky * particular file as subject to the "Classpath" exception as provided 9202375Srdivacky * by Oracle in the LICENSE file that accompanied this code. 10202375Srdivacky * 11202375Srdivacky * This code is distributed in the hope that it will be useful, but WITHOUT 12202375Srdivacky * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13202375Srdivacky * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14202375Srdivacky * version 2 for more details (a copy is included in the LICENSE file that 15226633Sdim * accompanied this code). 16218893Sdim * 17249423Sdim * You should have received a copy of the GNU General Public License version 18202375Srdivacky * 2 along with this work; if not, write to the Free Software Foundation, 19202375Srdivacky * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20202375Srdivacky * 21202375Srdivacky * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22202375Srdivacky * or visit www.oracle.com if you need additional information or have any 23202375Srdivacky * questions. 24202375Srdivacky */ 25202375Srdivacky/* 26202375Srdivacky * Licensed Materials - Property of IBM 27202375Srdivacky * RMI-IIOP v1.0 28202375Srdivacky * Copyright IBM Corp. 1998 1999 All Rights Reserved 29202375Srdivacky * 30202375Srdivacky */ 31202375Srdivacky 32202375Srdivackypackage com.sun.corba.se.impl.javax.rmi; 33202375Srdivacky 34202375Srdivackyimport java.lang.reflect.Method ; 35202375Srdivacky 36202375Srdivackyimport javax.rmi.CORBA.Tie; 37202375Srdivackyimport javax.rmi.CORBA.Util; 38202375Srdivacky 39218893Sdimimport java.rmi.RemoteException; 40218893Sdimimport java.rmi.NoSuchObjectException; 41218893Sdimimport java.rmi.Remote; 42218893Sdim 43218893Sdimimport java.util.Properties; 44218893Sdim 45218893Sdimimport org.omg.CORBA.ORB; 46218893Sdimimport org.omg.CORBA.portable.Delegate; 47218893Sdimimport org.omg.CORBA.SystemException; 48218893Sdim 49218893Sdimimport java.rmi.server.UnicastRemoteObject; 50218893Sdimimport java.rmi.server.RemoteStub; 51218893Sdimimport java.rmi.server.ExportException; 52249423Sdim 53202375Srdivackyimport java.net.URL; 54202375Srdivacky 55202375Srdivackyimport com.sun.corba.se.impl.util.JDKBridge; 56212904Sdimimport com.sun.corba.se.impl.util.Utility; 57212904Sdimimport com.sun.corba.se.impl.util.RepositoryId; 58212904Sdim 59212904Sdimimport com.sun.corba.se.spi.presentation.rmi.StubAdapter; 60212904Sdim 61212904Sdimimport java.security.AccessController; 62212904Sdimimport com.sun.corba.se.impl.orbutil.GetPropertyAction; 63212904Sdim 64212904Sdim/** 65212904Sdim * Server implementation objects may either inherit from 66212904Sdim * javax.rmi.PortableRemoteObject or they may implement a remote interface 67212904Sdim * and then use the exportObject method to register themselves as a server object. 68212904Sdim * The toStub method takes a server implementation and returns a stub that 69212904Sdim * can be used to access that server object. 70212904Sdim * The connect method makes a Remote object ready for remote communication. 71212904Sdim * The unexportObject method is used to deregister a server object, allowing it to become 72212904Sdim * available for garbage collection. 73249423Sdim * The narrow method takes an object reference or abstract interface type and 74212904Sdim * attempts to narrow it to conform to 75212904Sdim * the given interface. If the operation is successful the result will be an 76249423Sdim * object of the specified type, otherwise an exception will be thrown. 77212904Sdim */ 78212904Sdimpublic class PortableRemoteObject 79212904Sdim implements javax.rmi.CORBA.PortableRemoteObjectDelegate { 80212904Sdim 81218893Sdim /** 82212904Sdim * Makes a server object ready to receive remote calls. Note 83212904Sdim * that subclasses of PortableRemoteObject do not need to call this 84212904Sdim * method, as it is called by the constructor. 85212904Sdim * @param obj the server object to export. 86212904Sdim * @exception RemoteException if export fails. 87212904Sdim */ 88212904Sdim public void exportObject(Remote obj) 89212904Sdim throws RemoteException { 90212904Sdim 91212904Sdim if (obj == null) { 92212904Sdim throw new NullPointerException("invalid argument"); 93212904Sdim } 94212904Sdim 95212904Sdim // Has this object already been exported to IIOP? 96212904Sdim 97212904Sdim if (Util.getTie(obj) != null) { 98249423Sdim 99212904Sdim // Yes, so this is an error... 100212904Sdim 101249423Sdim throw new ExportException (obj.getClass().getName() + " already exported"); 102212904Sdim } 103212904Sdim 104212904Sdim // Can we load a Tie? 105249423Sdim 106212904Sdim Tie theTie = Utility.loadTie(obj); 107212904Sdim 108212904Sdim if (theTie != null) { 109212904Sdim 110212904Sdim // Yes, so export it to IIOP... 111212904Sdim 112212904Sdim Util.registerTarget(theTie,obj); 113212904Sdim 114249423Sdim } else { 115212904Sdim 116212904Sdim // No, so export to JRMP. If this is called twice for the 117212904Sdim // same object, it will throw an ExportException... 118212904Sdim 119212904Sdim UnicastRemoteObject.exportObject(obj); 120212904Sdim } 121212904Sdim } 122249423Sdim 123212904Sdim /** 124212904Sdim * Returns a stub for the given server object. 125249423Sdim * @param obj the server object for which a stub is required. Must either be a subclass 126212904Sdim * of PortableRemoteObject or have been previously the target of a call to 127212904Sdim * {@link #exportObject}. 128212904Sdim * @return the most derived stub for the object. 129212904Sdim * @exception NoSuchObjectException if a stub cannot be located for the given server object. 130212904Sdim */ 131218893Sdim public Remote toStub (Remote obj) 132212904Sdim throws NoSuchObjectException 133218893Sdim { 134212904Sdim Remote result = null; 135212904Sdim if (obj == null) { 136249423Sdim throw new NullPointerException("invalid argument"); 137212904Sdim } 138212904Sdim 139212904Sdim // If the class is already an IIOP stub then return it. 140212904Sdim if (StubAdapter.isStub( obj )) { 141212904Sdim return obj; 142212904Sdim } 143249423Sdim 144212904Sdim // If the class is already a JRMP stub then return it. 145212904Sdim if (obj instanceof java.rmi.server.RemoteStub) { 146249423Sdim return obj; 147212904Sdim } 148212904Sdim 149249423Sdim // Has it been exported to IIOP? 150212904Sdim Tie theTie = Util.getTie(obj); 151212904Sdim 152212904Sdim if (theTie != null) { 153212904Sdim result = Utility.loadStub(theTie,null,null,true); 154239462Sdim } else { 155212904Sdim if (Utility.loadTie(obj) == null) { 156212904Sdim result = java.rmi.server.RemoteObject.toStub(obj); 157218893Sdim } 158212904Sdim } 159212904Sdim 160249423Sdim if (result == null) { 161212904Sdim throw new NoSuchObjectException("object not exported"); 162212904Sdim } 163212904Sdim 164212904Sdim return result; 165212904Sdim } 166212904Sdim 167212904Sdim /** 168212904Sdim * Deregisters a server object from the runtime, allowing the object to become 169212904Sdim * available for garbage collection. 170212904Sdim * @param obj the object to unexport. 171212904Sdim * @exception NoSuchObjectException if the remote object is not 172212904Sdim * currently exported. 173212904Sdim */ 174212904Sdim public void unexportObject(Remote obj) 175212904Sdim throws NoSuchObjectException { 176212904Sdim 177212904Sdim if (obj == null) { 178249423Sdim throw new NullPointerException("invalid argument"); 179212904Sdim } 180212904Sdim 181212904Sdim if (StubAdapter.isStub(obj) || 182212904Sdim obj instanceof java.rmi.server.RemoteStub) { 183212904Sdim throw new NoSuchObjectException( 184212904Sdim "Can only unexport a server object."); 185212904Sdim } 186212904Sdim 187212904Sdim Tie theTie = Util.getTie(obj); 188212904Sdim if (theTie != null) { 189212904Sdim Util.unexportObject(obj); 190212904Sdim } else { 191212904Sdim if (Utility.loadTie(obj) == null) { 192212904Sdim UnicastRemoteObject.unexportObject(obj,true); 193243830Sdim } else { 194234353Sdim throw new NoSuchObjectException("Object not exported."); 195212904Sdim } 196212904Sdim } 197249423Sdim } 198212904Sdim 199212904Sdim /** 200212904Sdim * Checks to ensure that an object of a remote or abstract interface type 201212904Sdim * can be cast to a desired type. 202234353Sdim * @param narrowFrom the object to check. 203212904Sdim * @param narrowTo the desired type. 204212904Sdim * @return an object which can be cast to the desired type. 205212904Sdim * @throws ClassCastException if narrowFrom cannot be cast to narrowTo. 206212904Sdim */ 207212904Sdim public java.lang.Object narrow ( java.lang.Object narrowFrom, 208212904Sdim java.lang.Class narrowTo) throws ClassCastException 209212904Sdim { 210249423Sdim java.lang.Object result = null; 211212904Sdim 212226633Sdim if (narrowFrom == null) 213226633Sdim return null; 214212904Sdim 215212904Sdim if (narrowTo == null) 216226633Sdim throw new NullPointerException("invalid argument"); 217226633Sdim 218212904Sdim try { 219212904Sdim if (narrowTo.isAssignableFrom(narrowFrom.getClass())) 220212904Sdim return narrowFrom; 221212904Sdim 222212904Sdim // Is narrowTo an interface that might be 223212904Sdim // implemented by a servant running on iiop? 224212904Sdim if (narrowTo.isInterface() && 225226633Sdim narrowTo != java.io.Serializable.class && 226226633Sdim narrowTo != java.io.Externalizable.class) { 227226633Sdim 228212904Sdim org.omg.CORBA.Object narrowObj 229212904Sdim = (org.omg.CORBA.Object) narrowFrom; 230249423Sdim 231212904Sdim // Create an id from the narrowTo type... 232212904Sdim String id = RepositoryId.createForAnyType(narrowTo); 233212904Sdim 234212904Sdim if (narrowObj._is_a(id)) { 235226633Sdim return Utility.loadStub(narrowObj,narrowTo); 236226633Sdim } else { 237212904Sdim throw new ClassCastException( "Object is not of remote type " + 238226633Sdim narrowTo.getName() ) ; 239226633Sdim } 240212904Sdim } else { 241212904Sdim throw new ClassCastException( "Class " + narrowTo.getName() + 242212904Sdim " is not a valid remote interface" ) ; 243249423Sdim } 244212904Sdim } catch(Exception error) { 245212904Sdim ClassCastException cce = new ClassCastException() ; 246212904Sdim cce.initCause( error ) ; 247226633Sdim throw cce ; 248226633Sdim } 249226633Sdim } 250226633Sdim 251226633Sdim /** 252212904Sdim * Makes a Remote object ready for remote communication. This normally 253212904Sdim * happens implicitly when the object is sent or received as an argument 254226633Sdim * on a remote method call, but in some circumstances it is useful to 255226633Sdim * perform this action by making an explicit call. See the 256212904Sdim * {@link Stub#connect} method for more information. 257226633Sdim * @param target the object to connect. 258249423Sdim * @param source a previously connected object. 259212904Sdim * @throws RemoteException if <code>source</code> is not connected 260212904Sdim * or if <code>target</code> is already connected to a different ORB than 261212904Sdim * <code>source</code>. 262212904Sdim */ 263212904Sdim public void connect (Remote target, Remote source) 264226633Sdim throws RemoteException 265249423Sdim { 266226633Sdim if (target == null || source == null) { 267226633Sdim throw new NullPointerException("invalid argument"); 268212904Sdim } 269212904Sdim 270249423Sdim ORB orb = null; 271212904Sdim try { 272212904Sdim if (StubAdapter.isStub( source )) { 273212904Sdim orb = StubAdapter.getORB( source ) ; 274212904Sdim } else { 275212904Sdim // Is this a servant that was exported to iiop? 276226633Sdim Tie tie = Util.getTie(source); 277212904Sdim if (tie == null) { 278212904Sdim /* loadTie always succeeds for dynamic RMI-IIOP 279212904Sdim // No, can we get a tie for it? If not, 280212904Sdim // assume that source is a JRMP object... 281212904Sdim if (Utility.loadTie(source) != null) { 282212904Sdim // Yes, so it is an iiop object which 283249423Sdim // has not been exported... 284212904Sdim throw new RemoteException( 285212904Sdim "'source' object not exported"); 286212904Sdim } 287226633Sdim */ 288226633Sdim } else { 289226633Sdim orb = tie.orb(); 290226633Sdim } 291212904Sdim } 292249423Sdim } catch (SystemException e) { 293212904Sdim throw new RemoteException("'source' object not connected", e ); 294212904Sdim } 295212904Sdim 296212904Sdim boolean targetIsIIOP = false ; 297212904Sdim Tie targetTie = null; 298212904Sdim if (StubAdapter.isStub(target)) { 299212904Sdim targetIsIIOP = true; 300212904Sdim } else { 301212904Sdim targetTie = Util.getTie(target); 302212904Sdim if (targetTie != null) { 303212904Sdim targetIsIIOP = true; 304212904Sdim } else { 305212904Sdim /* loadTie always succeeds for dynamic RMI-IIOP 306212904Sdim if (Utility.loadTie(target) != null) { 307249423Sdim throw new RemoteException("'target' servant not exported"); 308212904Sdim } 309212904Sdim */ 310212904Sdim } 311212904Sdim } 312202375Srdivacky 313202375Srdivacky if (!targetIsIIOP) { 314202375Srdivacky // Yes. Do we have an ORB from the source object? 315249423Sdim // If not, we're done - there is nothing to do to 316249423Sdim // connect a JRMP object. If so, it is an error because 317212904Sdim // the caller mixed JRMP and IIOP... 318212904Sdim if (orb != null) { 319212904Sdim throw new RemoteException( 320212904Sdim "'source' object exported to IIOP, 'target' is JRMP"); 321212904Sdim } 322212904Sdim } else { 323249423Sdim // The target object is IIOP. Make sure we have a 324249423Sdim // valid ORB from the source object... 325212904Sdim if (orb == null) { 326212904Sdim throw new RemoteException( 327249423Sdim "'source' object is JRMP, 'target' is IIOP"); 328249423Sdim } 329249423Sdim 330202375Srdivacky // And, finally, connect it up... 331202375Srdivacky try { 332249423Sdim if (targetTie != null) { 333202375Srdivacky // Is the tie already connected? 334202375Srdivacky try { 335202375Srdivacky ORB existingOrb = targetTie.orb(); 336202375Srdivacky 337202375Srdivacky // Yes. Is it the same orb? 338202375Srdivacky if (existingOrb == orb) { 339203954Srdivacky 340203954Srdivacky // Yes, so nothing to do... 341203954Srdivacky return; 342202375Srdivacky } else { 343249423Sdim // No, so this is an error... 344202375Srdivacky throw new RemoteException( 345202375Srdivacky "'target' object was already connected"); 346202375Srdivacky } 347202375Srdivacky } catch (SystemException e) {} 348202375Srdivacky 349202375Srdivacky // No, so do it... 350249423Sdim targetTie.orb(orb); 351202375Srdivacky } else { 352202375Srdivacky StubAdapter.connect( target, orb ) ; 353202375Srdivacky } 354202375Srdivacky } catch (SystemException e) { 355202375Srdivacky 356202375Srdivacky // The stub or tie was already connected... 357202375Srdivacky throw new RemoteException( 358249423Sdim "'target' object was already connected", e ); 359202375Srdivacky } 360202375Srdivacky } 361202375Srdivacky } 362202375Srdivacky} 363202375Srdivacky