1. /*
  2. * @(#)IIOPOutputStream.java 1.69 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. package com.sun.corba.se.internal.iiop;
  8. import java.io.IOException;
  9. import java.util.Iterator;
  10. import org.omg.CORBA.SystemException;
  11. import org.omg.CORBA.CompletionStatus;
  12. import org.omg.CORBA.INTERNAL;
  13. import org.omg.CORBA.MARSHAL;
  14. import org.omg.CORBA.DATA_CONVERSION;
  15. import org.omg.CORBA.BAD_PARAM;
  16. import org.omg.CORBA.INV_OBJREF;
  17. import org.omg.CORBA.COMM_FAILURE;
  18. import org.omg.CORBA.TRANSIENT;
  19. import org.omg.CORBA.NO_RESOURCES;
  20. import org.omg.CORBA.Principal;
  21. import org.omg.CORBA.TypeCode;
  22. import org.omg.CORBA.Any;
  23. import org.omg.CORBA.portable.*;
  24. import com.sun.corba.se.internal.util.Utility; //d11638
  25. import com.sun.corba.se.internal.orbutil.MinorCodes; //d11638
  26. import com.sun.corba.se.internal.core.ClientResponse;
  27. import com.sun.corba.se.internal.core.IOR;
  28. import com.sun.corba.se.internal.core.GIOPVersion;
  29. import com.sun.corba.se.internal.iiop.messages.Message;
  30. import com.sun.corba.se.internal.iiop.messages.MessageBase;
  31. import com.sun.corba.se.internal.core.CodeSetConversion;
  32. import com.sun.corba.se.internal.core.OSFCodeSetRegistry;
  33. import com.sun.corba.se.internal.core.CodeSetComponentInfo;
  34. import com.sun.corba.se.internal.orbutil.ORBUtility;
  35. public class IIOPOutputStream extends CDROutputStream
  36. {
  37. protected Connection conn;
  38. protected Message msg;
  39. /*
  40. Extraneous constructor
  41. Marked for removing
  42. public IIOPOutputStream(ORB orb, Connection c) {
  43. this(orb,
  44. orb.getGIOPVersion(),
  45. c);
  46. }
  47. */
  48. public IIOPOutputStream(GIOPVersion version, ORB orb, Connection c)
  49. {
  50. super(orb, version);
  51. getBufferManager().setIIOPOutputStream(this);
  52. this.conn = c;
  53. }
  54. // this is called during locate msg creation to force no fragmentation
  55. // for LocateRequest & LocateReply msgs for GIOP version 1.0 & 1.1.
  56. public IIOPOutputStream(GIOPVersion version, ORB orb, Connection c,
  57. boolean allowFragmentation) {
  58. super(orb, version, allowFragmentation);
  59. getBufferManager().setIIOPOutputStream(this);
  60. this.conn = c;
  61. }
  62. public IIOPOutputStream(IIOPInputStream s) {
  63. this(s.getGIOPVersion(),
  64. (com.sun.corba.se.internal.iiop.ORB)s.orb(),
  65. s.getConnection());
  66. }
  67. public final Connection getConnection() {
  68. return conn;
  69. }
  70. // once request stream is created, its connection should not be altered.
  71. /*
  72. public final void setConnection(Connection c) {
  73. this.conn = c;
  74. }
  75. */
  76. public final Message getMessage() {
  77. return msg;
  78. }
  79. public final void setMessage(Message msg) {
  80. this.msg = msg;
  81. }
  82. // Removes the connection from the cache
  83. private void deleteCurrentConnection()
  84. {
  85. GIOPImpl clientGIOP = (GIOPImpl)(((com.sun.corba.se.internal.core.ORB)orb()).getClientGIOP());
  86. if (clientGIOP != null)
  87. clientGIOP.deleteConnection(((IIOPConnection)conn).getEndpoint());
  88. }
  89. public IIOPInputStream invoke(boolean isOneway)
  90. {
  91. ClientResponse response = null;
  92. SystemException systemEx = null;
  93. try {
  94. // Sends either the entire message or the last fragment
  95. finishSendingMessage();
  96. // Call getResponse here even if it's a oneway call in order
  97. // to remove the out call descriptor
  98. response = (ClientResponse)((IIOPConnection)conn).getResponse(isOneway,
  99. MessageBase.getRequestId(getMessage()));
  100. if (isOneway)
  101. return null;
  102. if (response.isSystemException()) {
  103. systemEx = response.getSystemException();
  104. if (systemEx == null)
  105. throw new INTERNAL("getSystemException returned null in IIOPOutputStream",
  106. MinorCodes.GET_SYSTEM_EX_RETURNED_NULL,
  107. CompletionStatus.COMPLETED_MAYBE);
  108. } else
  109. return (IIOPInputStream)response;
  110. } catch (SystemException ex) {
  111. systemEx = ex;
  112. }
  113. if (systemEx.completed == CompletionStatus.COMPLETED_NO &&
  114. systemEx.getClass() == COMM_FAILURE.class ) {
  115. deleteCurrentConnection();
  116. }
  117. // Always return null even if we got a SystemException
  118. // for oneways.
  119. if (isOneway)
  120. return null;
  121. // A response from the server may have service contexts
  122. if (response != null)
  123. return (IIOPInputStream)response;
  124. else
  125. return new ClientResponseImpl(systemEx);
  126. }
  127. public final void finishSendingMessage() {
  128. getBufferManager().sendMessage();
  129. }
  130. /**
  131. * Write the contents of the CDROutputStream to the specified
  132. * output stream. Has the side-effect of pushing any current
  133. * Message onto the Message list.
  134. * @param s The output stream to write to.
  135. */
  136. public void writeTo(java.io.OutputStream s) throws java.io.IOException {
  137. //
  138. // Update the GIOP MessageHeader size field.
  139. //
  140. ByteBufferWithInfo bbwi = getByteBufferWithInfo();
  141. msg.setSize(bbwi.buf, bbwi.getSize());
  142. com.sun.corba.se.internal.corba.ORB ourORB =
  143. (com.sun.corba.se.internal.corba.ORB)orb();
  144. if (ourORB != null && ourORB.giopDebugFlag) {
  145. ORBUtility.dprint(this, "Sending message:");
  146. CDROutputStream_1_0.printBuffer(bbwi);
  147. }
  148. s.write(bbwi.buf, 0, bbwi.getSize());
  149. // TimeStamp connection to indicate it has been used
  150. // Note granularity of connection usage is assumed for
  151. // now to be that of a IIOP packet.
  152. conn.stampTime();
  153. }
  154. /** overrides create_input_stream from CDROutputStream */
  155. public org.omg.CORBA.portable.InputStream create_input_stream()
  156. {
  157. return new IIOPInputStream((com.sun.corba.se.internal.iiop.ORB)orb(), getByteBuffer(), getIndex(), isLittleEndian(), msg, conn);
  158. }
  159. // static methods
  160. /*
  161. * This chooses the right buffering strategy for the locate msg.
  162. * locate msgs 1.0 & 1.1 :=> grow, 1.2 :=> stream
  163. */
  164. public static IIOPOutputStream createIIOPOutputStreamForLocateMsg(
  165. GIOPVersion giopVersion, ORB orb, Connection c) {
  166. if (giopVersion.lessThan(GIOPVersion.V1_2)) { // no fragmentation
  167. return new IIOPOutputStream(giopVersion, orb, c, false);
  168. } else {
  169. return new IIOPOutputStream(giopVersion, orb, c);
  170. }
  171. }
  172. /**
  173. * Override the default CDR factory behavior to get the
  174. * negotiated code sets from the connection.
  175. *
  176. * These are only called once per message, the first time needed.
  177. *
  178. * In the local case, there is no Connection, so use the
  179. * local code sets.
  180. */
  181. protected CodeSetConversion.CTBConverter createCharCTBConverter() {
  182. CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
  183. // If the connection doesn't have its negotiated
  184. // code sets by now, fall back on the defaults defined
  185. // in CDRInputStream.
  186. if (codesets == null)
  187. return super.createCharCTBConverter();
  188. OSFCodeSetRegistry.Entry charSet
  189. = OSFCodeSetRegistry.lookupEntry(codesets.getCharCodeSet());
  190. if (charSet == null)
  191. throw new MARSHAL("Unknown char set: " + charSet,
  192. MinorCodes.UNKNOWN_CODESET,
  193. CompletionStatus.COMPLETED_NO);
  194. return CodeSetConversion.impl().getCTBConverter(charSet,
  195. isLittleEndian(),
  196. false);
  197. }
  198. protected CodeSetConversion.CTBConverter createWCharCTBConverter() {
  199. CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
  200. // If the connection doesn't have its negotiated
  201. // code sets by now, we have to throw an exception.
  202. // See CORBA formal 00-11-03 13.9.2.6.
  203. if (codesets == null) {
  204. if (conn.isServer())
  205. throw new BAD_PARAM(MinorCodes.NO_CLIENT_WCHAR_CODESET_CTX,
  206. CompletionStatus.COMPLETED_MAYBE);
  207. else
  208. throw new INV_OBJREF(MinorCodes.NO_SERVER_WCHAR_CODESET_CMP,
  209. CompletionStatus.COMPLETED_NO);
  210. }
  211. OSFCodeSetRegistry.Entry wcharSet
  212. = OSFCodeSetRegistry.lookupEntry(codesets.getWCharCodeSet());
  213. if (wcharSet == null)
  214. throw new MARSHAL("Unknown wchar set: " + wcharSet,
  215. MinorCodes.UNKNOWN_CODESET,
  216. CompletionStatus.COMPLETED_NO);
  217. boolean useByteOrderMarkers
  218. = ((com.sun.corba.se.internal.corba.ORB)orb()).useByteOrderMarkers();
  219. // With UTF-16:
  220. //
  221. // For GIOP 1.2, we can put byte order markers if we want to, and
  222. // use the default of big endian otherwise. (See issue 3405b)
  223. //
  224. // For GIOP 1.1, we don't use BOMs and use the endianness of
  225. // the stream.
  226. if (wcharSet == OSFCodeSetRegistry.UTF_16) {
  227. if (getGIOPVersion().equals(GIOPVersion.V1_2)) {
  228. return CodeSetConversion.impl().getCTBConverter(wcharSet,
  229. false,
  230. useByteOrderMarkers);
  231. }
  232. if (getGIOPVersion().equals(GIOPVersion.V1_1)) {
  233. return CodeSetConversion.impl().getCTBConverter(wcharSet,
  234. isLittleEndian(),
  235. false);
  236. }
  237. }
  238. // In the normal case, let the converter system handle it
  239. return CodeSetConversion.impl().getCTBConverter(wcharSet,
  240. isLittleEndian(),
  241. useByteOrderMarkers);
  242. }
  243. // If we're local and don't have a Connection, use the
  244. // local code sets, otherwise get them from the connection.
  245. // If the connection doesn't have negotiated code sets
  246. // yet, then we use ISO8859-1 for char/string and wchar/wstring
  247. // are illegal.
  248. private CodeSetComponentInfo.CodeSetContext getCodeSets() {
  249. if (conn == null)
  250. return CodeSetComponentInfo.LOCAL_CODE_SETS;
  251. else
  252. return conn.getCodeSetContext();
  253. }
  254. }