1. /*
  2. * @(#)PortableRemoteObject.java 1.8 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.internal.javax.rmi;
  16. import java.lang.reflect.Method ;
  17. import javax.rmi.CORBA.Tie;
  18. import javax.rmi.CORBA.Util;
  19. import javax.rmi.CORBA.Stub;
  20. import java.rmi.RemoteException;
  21. import java.rmi.NoSuchObjectException;
  22. import java.rmi.Remote;
  23. import java.util.Properties;
  24. import org.omg.CORBA.ORB;
  25. import org.omg.CORBA.portable.Delegate;
  26. import org.omg.CORBA.portable.ObjectImpl;
  27. import org.omg.CORBA.SystemException;
  28. import java.rmi.server.UnicastRemoteObject;
  29. import java.rmi.server.RemoteStub;
  30. import java.rmi.server.ExportException;
  31. import java.net.URL;
  32. import com.sun.corba.se.internal.util.JDKBridge;
  33. import com.sun.corba.se.internal.util.Utility;
  34. import com.sun.corba.se.internal.util.RepositoryId;
  35. import java.security.AccessController;
  36. import sun.security.action.GetPropertyAction;
  37. /**
  38. * Server implementation objects may either inherit from
  39. * javax.rmi.PortableRemoteObject or they may implement a remote interface
  40. * and then use the exportObject method to register themselves as a server object.
  41. * The toStub method takes a server implementation and returns a stub that
  42. * can be used to access that server object.
  43. * The connect method makes a Remote object ready for remote communication.
  44. * The unexportObject method is used to deregister a server object, allowing it to become
  45. * available for garbage collection.
  46. * The narrow method takes an object reference or abstract interface type and
  47. * attempts to narrow it to conform to
  48. * the given interface. If the operation is successful the result will be an
  49. * object of the specified type, otherwise an exception will be thrown.
  50. */
  51. public class PortableRemoteObject
  52. implements javax.rmi.CORBA.PortableRemoteObjectDelegate {
  53. /**
  54. * Makes a server object ready to receive remote calls. Note
  55. * that subclasses of PortableRemoteObject do not need to call this
  56. * method, as it is called by the constructor.
  57. * @param obj the server object to export.
  58. * @exception RemoteException if export fails.
  59. */
  60. public void exportObject(Remote obj)
  61. throws RemoteException {
  62. if (obj == null) {
  63. throw new NullPointerException("invalid argument");
  64. }
  65. // Has this object already been exported to IIOP?
  66. if (Util.getTie(obj) != null) {
  67. // Yes, so this is an error...
  68. throw new ExportException (obj.getClass().getName() + " already exported");
  69. }
  70. // Can we load a Tie?
  71. Tie theTie = Utility.loadTie(obj);
  72. if (theTie != null) {
  73. // Yes, so export it to IIOP...
  74. Util.registerTarget(theTie,obj);
  75. } else {
  76. // No, so export to JRMP. If this is called twice for the
  77. // same object, it will throw an ExportException...
  78. UnicastRemoteObject.exportObject(obj);
  79. }
  80. }
  81. /**
  82. * Returns a stub for the given server object.
  83. * @param obj the server object for which a stub is required. Must either be a subclass
  84. * of PortableRemoteObject or have been previously the target of a call to
  85. * {@link #exportObject}.
  86. * @return the most derived stub for the object.
  87. * @exception NoSuchObjectException if a stub cannot be located for the given server object.
  88. */
  89. public Remote toStub (Remote obj)
  90. throws NoSuchObjectException {
  91. Remote result = null;
  92. if (obj == null) {
  93. throw new NullPointerException("invalid argument");
  94. }
  95. // If the class is already an IIOP stub then return it.
  96. if (obj instanceof javax.rmi.CORBA.Stub) {
  97. return obj;
  98. }
  99. // If the class is already a JRMP stub then return it.
  100. if (obj instanceof java.rmi.server.RemoteStub) {
  101. return obj;
  102. }
  103. // Has it been exported to IIOP?
  104. Tie theTie = Util.getTie(obj);
  105. if (theTie != null) {
  106. // Yes, so load a stub for it...
  107. result = Utility.loadStub(theTie,null,null,true);
  108. } else {
  109. // No. Can we load a tie for it?
  110. if (Utility.loadTie(obj) == null) {
  111. // No, so ask JRMP to find the stub. The 1.1.6 and 1.2
  112. // implementations differ, and have been built into
  113. // the JDKBridge class...
  114. result = java.rmi.server.RemoteObject.toStub(obj);
  115. }
  116. }
  117. if (result == null) {
  118. throw new NoSuchObjectException("object not exported");
  119. }
  120. return result;
  121. }
  122. /**
  123. * Deregisters a server object from the runtime, allowing the object to become
  124. * available for garbage collection.
  125. * @param obj the object to unexport.
  126. * @exception NoSuchObjectException if the remote object is not
  127. * currently exported.
  128. */
  129. public void unexportObject(Remote obj)
  130. throws NoSuchObjectException {
  131. if (obj == null) {
  132. throw new NullPointerException("invalid argument");
  133. }
  134. // Was a stub passed?
  135. if (obj instanceof javax.rmi.CORBA.Stub ||
  136. obj instanceof java.rmi.server.RemoteStub) {
  137. throw new NoSuchObjectException("Can only unexport a server object.");
  138. }
  139. // Was this object exported to IIOP?
  140. Tie theTie = Util.getTie(obj);
  141. if (theTie != null) {
  142. // Yes, so unexport from IIOP...
  143. Util.unexportObject(obj);
  144. } else {
  145. // No, can we find a Tie for it?
  146. if (Utility.loadTie(obj) == null) {
  147. // No, so unexport from JRMP. This is only possible when running
  148. // on a 1.2 vm, because 1.1 had no unexport API method, so we
  149. // use a method on JDKBridge which is compiled on 1.2. If we're on
  150. // 1.1 it does nothing.
  151. UnicastRemoteObject.unexportObject(obj,true);
  152. } else {
  153. // Yes, so someone is trying to unexport an IIOP object that
  154. // was never exported...
  155. throw new NoSuchObjectException("Object not exported.");
  156. }
  157. }
  158. }
  159. /**
  160. * Checks to ensure that an object of a remote or abstract interface type
  161. * can be cast to a desired type.
  162. * @param narrowFrom the object to check.
  163. * @param narrowTo the desired type.
  164. * @return an object which can be cast to the desired type.
  165. * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
  166. */
  167. public java.lang.Object narrow ( java.lang.Object narrowFrom,
  168. java.lang.Class narrowTo)
  169. throws ClassCastException {
  170. java.lang.Object result = null;
  171. if (narrowFrom == null) {
  172. return null;
  173. }
  174. if (narrowTo == null) {
  175. throw new NullPointerException("invalid argument");
  176. }
  177. Class narrowFromClass = narrowFrom.getClass();
  178. try {
  179. // Will a cast work?
  180. if (narrowTo.isAssignableFrom(narrowFromClass)) {
  181. // Yep, so we're done...
  182. result = narrowFrom;
  183. } else {
  184. // No. Is narrowTo an interface that might be
  185. // implemented by a servant running on iiop?
  186. if (narrowTo.isInterface() &&
  187. // What was this test supposed to achieve?
  188. // narrowTo != java.rmi.Remote.class &&
  189. narrowTo != java.io.Serializable.class &&
  190. narrowTo != java.io.Externalizable.class) {
  191. // Yes. Ok, so assume the current stub (narrowFrom) is an
  192. // ObjectImpl (it should be a _"xxx"_Stub). If it is not,
  193. // we'll catch it below and end up failing with a
  194. // ClassCastException...
  195. org.omg.CORBA.portable.ObjectImpl narrowObj
  196. = (org.omg.CORBA.portable.ObjectImpl) narrowFrom;
  197. // Create an id from the narrowTo type...
  198. String id = RepositoryId.createForAnyType(narrowTo);
  199. // Can the server act as the narrowTo type?
  200. if (narrowObj._is_a(id)) {
  201. // Yes, so try to load a stub for it...
  202. result = Utility.loadStub(narrowObj,narrowTo);
  203. }
  204. }
  205. }
  206. } catch(Exception error) {
  207. result = null;
  208. }
  209. if (result == null) {
  210. throw new ClassCastException();
  211. }
  212. return result;
  213. }
  214. /**
  215. * Makes a Remote object ready for remote communication. This normally
  216. * happens implicitly when the object is sent or received as an argument
  217. * on a remote method call, but in some circumstances it is useful to
  218. * perform this action by making an explicit call. See the
  219. * {@link Stub#connect} method for more information.
  220. * @param target the object to connect.
  221. * @param source a previously connected object.
  222. * @throws RemoteException if <code>source</code> is not connected
  223. * or if <code>target</code> is already connected to a different ORB than
  224. * <code>source</code>.
  225. */
  226. public void connect (Remote target, Remote source)
  227. throws RemoteException {
  228. if (target == null || source == null) {
  229. throw new NullPointerException("invalid argument");
  230. }
  231. // See if we can get an ORB from the 'source'
  232. // object...
  233. ORB orb = null;
  234. try {
  235. if (source instanceof ObjectImpl) {
  236. orb = ((ObjectImpl)source)._orb();
  237. } else {
  238. // Is this a servant that was exported to iiop?
  239. Tie tie = Util.getTie(source);
  240. if (tie == null) {
  241. // No, can we get a tie for it? If not,
  242. // assume that source is a JRMP object...
  243. if (Utility.loadTie(source) != null) {
  244. // Yes, so it is an iiop object which
  245. // has not been exported...
  246. throw new RemoteException("'source' object not exported");
  247. }
  248. } else {
  249. orb = tie.orb();
  250. }
  251. }
  252. } catch (SystemException e) {
  253. // The object was not connected...
  254. throw new RemoteException("'source' object not connected");
  255. }
  256. // Decide what the target object is...
  257. boolean targetIsIIOP;
  258. Tie targetTie = null;
  259. if (target instanceof java.rmi.server.RemoteStub) {
  260. targetIsIIOP = false;
  261. } else if (target instanceof javax.rmi.CORBA.Stub) {
  262. targetIsIIOP = true;
  263. } else {
  264. // Is it a servant exported to iiop?
  265. targetTie = Util.getTie(target);
  266. if (targetTie != null) {
  267. targetIsIIOP = true;
  268. } else {
  269. // No. Can we get a tie for it?
  270. if (Utility.loadTie(target) != null) {
  271. // Yes, so it is an iiop servant that has not
  272. // been exported...
  273. throw new RemoteException("'target' servant not exported");
  274. } else {
  275. // No, so not iiop...
  276. targetIsIIOP = false;
  277. }
  278. }
  279. }
  280. // Ok, is the target object JRMP?
  281. if (!targetIsIIOP) {
  282. // Yes. Do we have an ORB from the source object?
  283. // If not, we're done - there is nothing to do to
  284. // connect a JRMP object. If so, it is an error because
  285. // the caller mixed JRMP and IIOP...
  286. if (orb != null) {
  287. throw new RemoteException("'source' object exported to IIOP, 'target' is JRMP");
  288. }
  289. } else {
  290. // The target object is IIOP. Make sure we have a
  291. // valid ORB from the source object...
  292. if (orb == null) {
  293. throw new RemoteException("'source' object is JRMP, 'target' is IIOP");
  294. }
  295. // And, finally, connect it up...
  296. try {
  297. if (targetTie != null) {
  298. // Is the tie already connected?
  299. try {
  300. ORB existingOrb = targetTie.orb();
  301. // Yes. Is it the same orb?
  302. if (existingOrb == orb) {
  303. // Yes, so nothing to do...
  304. return;
  305. } else {
  306. // No, so this is an error...
  307. throw new RemoteException("'target' object was already connected");
  308. }
  309. } catch (SystemException e) {}
  310. // No, so do it...
  311. targetTie.orb(orb);
  312. } else {
  313. ((javax.rmi.CORBA.Stub)target).connect(orb);
  314. }
  315. } catch (SystemException e) {
  316. // The stub or tie was already connected...
  317. throw new RemoteException("'target' object was already connected");
  318. }
  319. }
  320. }
  321. }