PortableRemoteObject.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 1999, 2004, 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 * Licensed Materials - Property of IBM 27 * RMI-IIOP v1.0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved 29 * 30 */ 31 32package com.sun.corba.se.impl.javax.rmi; 33 34import java.lang.reflect.Method ; 35 36import javax.rmi.CORBA.Tie; 37import javax.rmi.CORBA.Util; 38 39import java.rmi.RemoteException; 40import java.rmi.NoSuchObjectException; 41import java.rmi.Remote; 42 43import java.util.Properties; 44 45import org.omg.CORBA.ORB; 46import org.omg.CORBA.portable.Delegate; 47import org.omg.CORBA.SystemException; 48 49import java.rmi.server.UnicastRemoteObject; 50import java.rmi.server.RemoteStub; 51import java.rmi.server.ExportException; 52 53import java.net.URL; 54 55import com.sun.corba.se.impl.util.JDKBridge; 56import com.sun.corba.se.impl.util.Utility; 57import com.sun.corba.se.impl.util.RepositoryId; 58 59import com.sun.corba.se.spi.presentation.rmi.StubAdapter; 60 61import java.security.AccessController; 62import com.sun.corba.se.impl.orbutil.GetPropertyAction; 63 64/** 65 * Server implementation objects may either inherit from 66 * javax.rmi.PortableRemoteObject or they may implement a remote interface 67 * and then use the exportObject method to register themselves as a server object. 68 * The toStub method takes a server implementation and returns a stub that 69 * can be used to access that server object. 70 * The connect method makes a Remote object ready for remote communication. 71 * The unexportObject method is used to deregister a server object, allowing it to become 72 * available for garbage collection. 73 * The narrow method takes an object reference or abstract interface type and 74 * attempts to narrow it to conform to 75 * the given interface. If the operation is successful the result will be an 76 * object of the specified type, otherwise an exception will be thrown. 77 */ 78public class PortableRemoteObject 79 implements javax.rmi.CORBA.PortableRemoteObjectDelegate { 80 81 /** 82 * Makes a server object ready to receive remote calls. Note 83 * that subclasses of PortableRemoteObject do not need to call this 84 * method, as it is called by the constructor. 85 * @param obj the server object to export. 86 * @exception RemoteException if export fails. 87 */ 88 public void exportObject(Remote obj) 89 throws RemoteException { 90 91 if (obj == null) { 92 throw new NullPointerException("invalid argument"); 93 } 94 95 // Has this object already been exported to IIOP? 96 97 if (Util.getTie(obj) != null) { 98 99 // Yes, so this is an error... 100 101 throw new ExportException (obj.getClass().getName() + " already exported"); 102 } 103 104 // Can we load a Tie? 105 106 Tie theTie = Utility.loadTie(obj); 107 108 if (theTie != null) { 109 110 // Yes, so export it to IIOP... 111 112 Util.registerTarget(theTie,obj); 113 114 } else { 115 116 // No, so export to JRMP. If this is called twice for the 117 // same object, it will throw an ExportException... 118 119 UnicastRemoteObject.exportObject(obj); 120 } 121 } 122 123 /** 124 * Returns a stub for the given server object. 125 * @param obj the server object for which a stub is required. Must either be a subclass 126 * of PortableRemoteObject or have been previously the target of a call to 127 * {@link #exportObject}. 128 * @return the most derived stub for the object. 129 * @exception NoSuchObjectException if a stub cannot be located for the given server object. 130 */ 131 public Remote toStub (Remote obj) 132 throws NoSuchObjectException 133 { 134 Remote result = null; 135 if (obj == null) { 136 throw new NullPointerException("invalid argument"); 137 } 138 139 // If the class is already an IIOP stub then return it. 140 if (StubAdapter.isStub( obj )) { 141 return obj; 142 } 143 144 // If the class is already a JRMP stub then return it. 145 if (obj instanceof java.rmi.server.RemoteStub) { 146 return obj; 147 } 148 149 // Has it been exported to IIOP? 150 Tie theTie = Util.getTie(obj); 151 152 if (theTie != null) { 153 result = Utility.loadStub(theTie,null,null,true); 154 } else { 155 if (Utility.loadTie(obj) == null) { 156 result = java.rmi.server.RemoteObject.toStub(obj); 157 } 158 } 159 160 if (result == null) { 161 throw new NoSuchObjectException("object not exported"); 162 } 163 164 return result; 165 } 166 167 /** 168 * Deregisters a server object from the runtime, allowing the object to become 169 * available for garbage collection. 170 * @param obj the object to unexport. 171 * @exception NoSuchObjectException if the remote object is not 172 * currently exported. 173 */ 174 public void unexportObject(Remote obj) 175 throws NoSuchObjectException { 176 177 if (obj == null) { 178 throw new NullPointerException("invalid argument"); 179 } 180 181 if (StubAdapter.isStub(obj) || 182 obj instanceof java.rmi.server.RemoteStub) { 183 throw new NoSuchObjectException( 184 "Can only unexport a server object."); 185 } 186 187 Tie theTie = Util.getTie(obj); 188 if (theTie != null) { 189 Util.unexportObject(obj); 190 } else { 191 if (Utility.loadTie(obj) == null) { 192 UnicastRemoteObject.unexportObject(obj,true); 193 } else { 194 throw new NoSuchObjectException("Object not exported."); 195 } 196 } 197 } 198 199 /** 200 * Checks to ensure that an object of a remote or abstract interface type 201 * can be cast to a desired type. 202 * @param narrowFrom the object to check. 203 * @param narrowTo the desired type. 204 * @return an object which can be cast to the desired type. 205 * @throws ClassCastException if narrowFrom cannot be cast to narrowTo. 206 */ 207 public java.lang.Object narrow ( java.lang.Object narrowFrom, 208 java.lang.Class narrowTo) throws ClassCastException 209 { 210 java.lang.Object result = null; 211 212 if (narrowFrom == null) 213 return null; 214 215 if (narrowTo == null) 216 throw new NullPointerException("invalid argument"); 217 218 try { 219 if (narrowTo.isAssignableFrom(narrowFrom.getClass())) 220 return narrowFrom; 221 222 // Is narrowTo an interface that might be 223 // implemented by a servant running on iiop? 224 if (narrowTo.isInterface() && 225 narrowTo != java.io.Serializable.class && 226 narrowTo != java.io.Externalizable.class) { 227 228 org.omg.CORBA.Object narrowObj 229 = (org.omg.CORBA.Object) narrowFrom; 230 231 // Create an id from the narrowTo type... 232 String id = RepositoryId.createForAnyType(narrowTo); 233 234 if (narrowObj._is_a(id)) { 235 return Utility.loadStub(narrowObj,narrowTo); 236 } else { 237 throw new ClassCastException( "Object is not of remote type " + 238 narrowTo.getName() ) ; 239 } 240 } else { 241 throw new ClassCastException( "Class " + narrowTo.getName() + 242 " is not a valid remote interface" ) ; 243 } 244 } catch(Exception error) { 245 ClassCastException cce = new ClassCastException() ; 246 cce.initCause( error ) ; 247 throw cce ; 248 } 249 } 250 251 /** 252 * Makes a Remote object ready for remote communication. This normally 253 * happens implicitly when the object is sent or received as an argument 254 * on a remote method call, but in some circumstances it is useful to 255 * perform this action by making an explicit call. See the 256 * {@link Stub#connect} method for more information. 257 * @param target the object to connect. 258 * @param source a previously connected object. 259 * @throws RemoteException if <code>source</code> is not connected 260 * or if <code>target</code> is already connected to a different ORB than 261 * <code>source</code>. 262 */ 263 public void connect (Remote target, Remote source) 264 throws RemoteException 265 { 266 if (target == null || source == null) { 267 throw new NullPointerException("invalid argument"); 268 } 269 270 ORB orb = null; 271 try { 272 if (StubAdapter.isStub( source )) { 273 orb = StubAdapter.getORB( source ) ; 274 } else { 275 // Is this a servant that was exported to iiop? 276 Tie tie = Util.getTie(source); 277 if (tie == null) { 278 /* loadTie always succeeds for dynamic RMI-IIOP 279 // No, can we get a tie for it? If not, 280 // assume that source is a JRMP object... 281 if (Utility.loadTie(source) != null) { 282 // Yes, so it is an iiop object which 283 // has not been exported... 284 throw new RemoteException( 285 "'source' object not exported"); 286 } 287 */ 288 } else { 289 orb = tie.orb(); 290 } 291 } 292 } catch (SystemException e) { 293 throw new RemoteException("'source' object not connected", e ); 294 } 295 296 boolean targetIsIIOP = false ; 297 Tie targetTie = null; 298 if (StubAdapter.isStub(target)) { 299 targetIsIIOP = true; 300 } else { 301 targetTie = Util.getTie(target); 302 if (targetTie != null) { 303 targetIsIIOP = true; 304 } else { 305 /* loadTie always succeeds for dynamic RMI-IIOP 306 if (Utility.loadTie(target) != null) { 307 throw new RemoteException("'target' servant not exported"); 308 } 309 */ 310 } 311 } 312 313 if (!targetIsIIOP) { 314 // Yes. Do we have an ORB from the source object? 315 // If not, we're done - there is nothing to do to 316 // connect a JRMP object. If so, it is an error because 317 // the caller mixed JRMP and IIOP... 318 if (orb != null) { 319 throw new RemoteException( 320 "'source' object exported to IIOP, 'target' is JRMP"); 321 } 322 } else { 323 // The target object is IIOP. Make sure we have a 324 // valid ORB from the source object... 325 if (orb == null) { 326 throw new RemoteException( 327 "'source' object is JRMP, 'target' is IIOP"); 328 } 329 330 // And, finally, connect it up... 331 try { 332 if (targetTie != null) { 333 // Is the tie already connected? 334 try { 335 ORB existingOrb = targetTie.orb(); 336 337 // Yes. Is it the same orb? 338 if (existingOrb == orb) { 339 340 // Yes, so nothing to do... 341 return; 342 } else { 343 // No, so this is an error... 344 throw new RemoteException( 345 "'target' object was already connected"); 346 } 347 } catch (SystemException e) {} 348 349 // No, so do it... 350 targetTie.orb(orb); 351 } else { 352 StubAdapter.connect( target, orb ) ; 353 } 354 } catch (SystemException e) { 355 356 // The stub or tie was already connected... 357 throw new RemoteException( 358 "'target' object was already connected", e ); 359 } 360 } 361 } 362} 363