1. /*
  2. * @(#)StubDelegateImpl.java 1.12 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.CORBA;
  16. import org.omg.CORBA.ORB;
  17. import org.omg.CORBA.BAD_OPERATION;
  18. import org.omg.CORBA.BAD_INV_ORDER;
  19. import org.omg.CORBA.SystemException;
  20. import java.io.IOException;
  21. import java.rmi.RemoteException;
  22. import javax.rmi.CORBA.Tie;
  23. import org.omg.CORBA_2_3.portable.ObjectImpl;
  24. import com.sun.corba.se.internal.util.Utility;
  25. import org.omg.CORBA.portable.Delegate;
  26. import org.omg.CORBA.portable.OutputStream;
  27. import org.omg.CORBA.portable.InputStream;
  28. /**
  29. * Base class from which all RMI-IIOP stubs must inherit.
  30. */
  31. public class StubDelegateImpl
  32. implements javax.rmi.CORBA.StubDelegate {
  33. private int hashCode = 0;
  34. // IOR components
  35. private int typeLength;
  36. private byte[] typeData;
  37. private int numProfiles = 0;
  38. private int[] profileTags;
  39. private byte[][] profileData;
  40. public StubDelegateImpl() {
  41. }
  42. /**
  43. * Sets the IOR components if not already set.
  44. */
  45. private void init (javax.rmi.CORBA.Stub self) {
  46. // If the Stub is not connected to an ORB, BAD_OPERATION exception
  47. // will be raised by the code below.
  48. if (numProfiles == 0) {
  49. // write the IOR to an OutputStream
  50. OutputStream ostr = ((org.omg.CORBA.ORB)(self._orb())).create_output_stream();
  51. ostr.write_Object(self);
  52. // read the IOR components back from the stream
  53. InputStream istr = ostr.create_input_stream();
  54. typeLength = istr.read_long();
  55. typeData = new byte[typeLength];
  56. istr.read_octet_array(typeData, 0, typeLength);
  57. numProfiles = istr.read_long();
  58. profileTags = new int[numProfiles];
  59. profileData = new byte[numProfiles][];
  60. for (int i = 0; i < numProfiles; i++) {
  61. profileTags[i] = istr.read_long();
  62. profileData[i] = new byte[istr.read_long()];
  63. istr.read_octet_array(profileData[i], 0, profileData[i].length);
  64. }
  65. }
  66. }
  67. /**
  68. * Returns a hash code value for the object which is the same for all stubs
  69. * that represent the same remote object.
  70. * @return the hash code value.
  71. */
  72. public int hashCode(javax.rmi.CORBA.Stub self) {
  73. init(self);
  74. if (hashCode == 0) {
  75. // compute the hash code
  76. for (int i = 0; i < typeLength; i++) {
  77. hashCode = hashCode * 37 + typeData[i];
  78. }
  79. for (int i = 0; i < numProfiles; i++) {
  80. hashCode = hashCode * 37 + profileTags[i];
  81. for (int j = 0; j < profileData[i].length; j++) {
  82. hashCode = hashCode * 37 + profileData[i][j];
  83. }
  84. }
  85. }
  86. return hashCode;
  87. }
  88. /**
  89. * Compares two stubs for equality. Returns <code>true</code> when used to compare stubs
  90. * that represent the same remote object, and <code>false</code> otherwise.
  91. * @param obj the reference object with which to compare.
  92. * @return <code>true</code> if this object is the same as the <code>obj</code>
  93. * argument; <code>false</code> otherwise.
  94. */
  95. public boolean equals(javax.rmi.CORBA.Stub self, java.lang.Object obj) {
  96. if (self == obj) {
  97. return true;
  98. }
  99. if (!(obj instanceof javax.rmi.CORBA.Stub)) {
  100. return false;
  101. }
  102. // no need to call init() because of calls to hashCode() below
  103. javax.rmi.CORBA.Stub other = (javax.rmi.CORBA.Stub) obj;
  104. if (other.hashCode() != self.hashCode()) {
  105. return false;
  106. }
  107. // hashCodes being the same does not mean equality. The stubs still
  108. // could be pointing to different IORs. So, do a literal comparison.
  109. if (self.toString().equals(other.toString())) {
  110. return true;
  111. }
  112. return false;
  113. }
  114. /**
  115. * Returns a string representation of this stub. Returns the same string
  116. * for all stubs that represent the same remote object.
  117. * @return a string representation of this stub.
  118. */
  119. public String toString(javax.rmi.CORBA.Stub self) {
  120. try {
  121. // _REVISIT_ returning the full IOR seems a bit verbose...
  122. return ((org.omg.CORBA.ORB)(self._orb())).object_to_string(self);
  123. } catch (org.omg.CORBA.BAD_OPERATION e) {
  124. // No delegate, so unconnected...
  125. return null;
  126. }
  127. }
  128. /**
  129. * Connects this stub to an ORB. Required after the stub is deserialized
  130. * but not after it is demarshalled by an ORB stream. If an unconnected
  131. * stub is passed to an ORB stream for marshalling, it is implicitly
  132. * connected to that ORB. Application code should not call this method
  133. * directly, but should call the portable wrapper method
  134. * {@link javax.rmi.PortableRemoteObject#connect}.
  135. * @param orb the ORB to connect to.
  136. * @exception RemoteException if the stub is already connected to a different
  137. * ORB, or if the stub does not represent an exported remote or local object.
  138. */
  139. public void connect(javax.rmi.CORBA.Stub self, ORB orb)
  140. throws RemoteException
  141. {
  142. // Do we already have a delegate set?
  143. boolean error = false;
  144. try {
  145. Delegate del = self._get_delegate();
  146. // Yes, is it the same orb? If so,
  147. // ignore it...
  148. if (del.orb(self) != orb) {
  149. // No, so error.
  150. error = true;
  151. }
  152. } catch (org.omg.CORBA.BAD_OPERATION err) {
  153. // No. Do we know what the IOR is?
  154. if (numProfiles == 0) {
  155. // No, can we get a Tie for this stub?
  156. Tie tie = (javax.rmi.CORBA.Tie) Utility.getAndForgetTie(self);
  157. if (tie == null) {
  158. // No, so there is no exported object
  159. // to use to connect this guy, so we
  160. // must fail...
  161. error = true;
  162. } else {
  163. // Yes. Is the tie already connected?
  164. try {
  165. ORB existingOrb = tie.orb();
  166. // Yes. Is it the same orb? If so,
  167. // ignore it...
  168. if (existingOrb != orb) {
  169. // No, so this is an error.
  170. error = true;
  171. }
  172. } catch (SystemException se) {
  173. // Should be BAD_OPERATION or BAD_INV_ORDER
  174. if (!(se instanceof BAD_OPERATION) &&
  175. !(se instanceof BAD_INV_ORDER))
  176. throw se;
  177. // Not connected, so connect it...
  178. if( tie instanceof ObjectImpl ) {
  179. tie.orb(orb);
  180. // Copy the delegate from the tie to
  181. // ourself...
  182. self._set_delegate(((ObjectImpl)tie)._get_delegate());
  183. } else {
  184. // Tie must be Servant
  185. tie.orb(orb);
  186. try {
  187. org.omg.CORBA.Object ref =
  188. ((org.omg.PortableServer.Servant)tie)._this_object( );
  189. self._set_delegate(((ObjectImpl)ref)._get_delegate());
  190. } catch( org.omg.CORBA.BAD_INV_ORDER bad) {
  191. error = true;
  192. }
  193. }
  194. }
  195. }
  196. } else {
  197. // Yes, so convert it to an object, extract
  198. // the delegate, and set it on ourself...
  199. try {
  200. // write the IOR components to an OutputStream
  201. OutputStream ostr = orb.create_output_stream();
  202. ostr.write_long(typeLength);
  203. ostr.write_octet_array(typeData, 0, typeLength);
  204. ostr.write_long(numProfiles);
  205. for (int i = 0; i < numProfiles; i++) {
  206. ostr.write_long(profileTags[i]);
  207. ostr.write_long(profileData[i].length);
  208. ostr.write_octet_array(profileData[i], 0, profileData[i].length);
  209. }
  210. // read the IOR back from the stream
  211. ObjectImpl obj = (ObjectImpl)((ostr.create_input_stream()).read_Object());
  212. // copy the delegate
  213. self._set_delegate(obj._get_delegate());
  214. } catch (Exception e) {
  215. error = true;
  216. }
  217. }
  218. }
  219. if (error) {
  220. throw new RemoteException("CORBA BAD_OPERATION 0");
  221. }
  222. }
  223. /**
  224. * Serialization method to restore the IOR state.
  225. */
  226. public void readObject(javax.rmi.CORBA.Stub self, java.io.ObjectInputStream stream)
  227. throws IOException, ClassNotFoundException {
  228. // read the IOR from the ObjectInputStream
  229. typeLength = stream.readInt();
  230. typeData = new byte[typeLength];
  231. stream.readFully(typeData);
  232. numProfiles = stream.readInt();
  233. profileTags = new int[numProfiles];
  234. profileData = new byte[numProfiles][];
  235. for (int i = 0; i < numProfiles; i++) {
  236. profileTags[i] = stream.readInt();
  237. profileData[i] = new byte[stream.readInt()];
  238. stream.readFully(profileData[i]);
  239. }
  240. }
  241. /**
  242. * Serialization method to save the IOR state.
  243. * @serialData The length of the IOR type ID (int), followed by the IOR type ID
  244. * (byte array encoded using ISO8859-1), followed by the number of IOR profiles
  245. * (int), followed by the IOR profiles. Each IOR profile is written as a
  246. * profile tag (int), followed by the length of the profile data (int), followed
  247. * by the profile data (byte array).
  248. */
  249. public void writeObject(javax.rmi.CORBA.Stub self, java.io.ObjectOutputStream stream) throws IOException {
  250. init(self);
  251. // write the IOR to the ObjectOutputStream
  252. stream.writeInt(typeLength);
  253. stream.write(typeData);
  254. stream.writeInt(numProfiles);
  255. for (int i = 0; i < numProfiles; i++) {
  256. stream.writeInt(profileTags[i]);
  257. stream.writeInt(profileData[i].length);
  258. stream.write(profileData[i]);
  259. }
  260. }
  261. }