1. /*
  2. * @(#)TypeCodeOutputStream.java 1.12 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.encoding;
  8. import org.omg.CORBA.TypeCode ;
  9. import org.omg.CORBA.StructMember ;
  10. import org.omg.CORBA.UnionMember ;
  11. import org.omg.CORBA.ValueMember ;
  12. import org.omg.CORBA.TCKind ;
  13. import org.omg.CORBA.Any ;
  14. import org.omg.CORBA.Principal ;
  15. import org.omg.CORBA.CompletionStatus ;
  16. import org.omg.CORBA.TypeCodePackage.BadKind ;
  17. import org.omg.CORBA_2_3.portable.InputStream;
  18. import org.omg.CORBA_2_3.portable.OutputStream;
  19. import com.sun.corba.se.spi.orb.ORB;
  20. import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
  21. import com.sun.corba.se.impl.encoding.MarshalInputStream;
  22. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  23. import com.sun.corba.se.impl.encoding.CodeSetConversion;
  24. import com.sun.corba.se.impl.encoding.CDRInputStream;
  25. import com.sun.corba.se.impl.encoding.CDROutputStream;
  26. import java.util.HashMap;
  27. import java.util.Map;
  28. import java.util.Iterator;
  29. import java.util.List;
  30. import java.util.Collections;
  31. import java.util.ArrayList;
  32. import java.io.IOException;
  33. import java.io.PrintStream;
  34. import java.io.ByteArrayOutputStream;
  35. import java.math.BigDecimal;
  36. import java.math.BigInteger;
  37. import java.nio.ByteBuffer;
  38. public final class TypeCodeOutputStream extends EncapsOutputStream
  39. {
  40. private OutputStream enclosure = null;
  41. private Map typeMap = null;
  42. private boolean isEncapsulation = false;
  43. public TypeCodeOutputStream(ORB orb) {
  44. super(orb, false);
  45. }
  46. public TypeCodeOutputStream(ORB orb, boolean littleEndian) {
  47. super(orb, littleEndian);
  48. }
  49. public org.omg.CORBA.portable.InputStream create_input_stream()
  50. {
  51. //return new TypeCodeInputStream((ORB)orb(), getByteBuffer(), getIndex(), isLittleEndian());
  52. TypeCodeInputStream tcis
  53. = new TypeCodeInputStream((ORB)orb(), getByteBuffer(), getIndex(), isLittleEndian(), getGIOPVersion());
  54. //if (TypeCodeImpl.debug) {
  55. //System.out.println("Created TypeCodeInputStream " + tcis + " with no parent");
  56. //tcis.printBuffer();
  57. //}
  58. return tcis;
  59. }
  60. public void setEnclosingOutputStream(OutputStream enclosure) {
  61. this.enclosure = enclosure;
  62. }
  63. /*
  64. public boolean isEncapsulatedIn(TypeCodeOutputStream outerEnclosure) {
  65. if (outerEnclosure == this)
  66. return true;
  67. if (enclosure == null)
  68. return false;
  69. if (enclosure instanceof TypeCodeOutputStream)
  70. return ((TypeCodeOutputStream)enclosure).isEncapsulatedIn(outerEnclosure);
  71. // Last chance! Recursion ends with first non TypeCodeOutputStream.
  72. return (enclosure == outerEnclosure);
  73. }
  74. */
  75. public TypeCodeOutputStream getTopLevelStream() {
  76. if (enclosure == null)
  77. return this;
  78. if (enclosure instanceof TypeCodeOutputStream)
  79. return ((TypeCodeOutputStream)enclosure).getTopLevelStream();
  80. return this;
  81. }
  82. public int getTopLevelPosition() {
  83. if (enclosure != null && enclosure instanceof TypeCodeOutputStream) {
  84. int pos = ((TypeCodeOutputStream)enclosure).getTopLevelPosition() + getPosition();
  85. // Add four bytes for the encaps length, not another 4 for the byte order
  86. // which is included in getPosition().
  87. if (isEncapsulation) pos += 4;
  88. //if (TypeCodeImpl.debug) {
  89. //System.out.println("TypeCodeOutputStream.getTopLevelPosition using getTopLevelPosition " +
  90. //((TypeCodeOutputStream)enclosure).getTopLevelPosition() +
  91. //" + getPosition() " + getPosition() +
  92. //(isEncapsulation ? " + encaps length 4" : "") +
  93. //" = " + pos);
  94. //}
  95. return pos;
  96. }
  97. //if (TypeCodeImpl.debug) {
  98. //System.out.println("TypeCodeOutputStream.getTopLevelPosition returning getPosition() = " +
  99. //getPosition() + ", enclosure is " + enclosure);
  100. //}
  101. return getPosition();
  102. }
  103. public void addIDAtPosition(String id, int position) {
  104. if (typeMap == null)
  105. typeMap = new HashMap(16);
  106. //if (TypeCodeImpl.debug) System.out.println(this + " adding id " + id + " at position " + position);
  107. typeMap.put(id, new Integer(position));
  108. }
  109. public int getPositionForID(String id) {
  110. if (typeMap == null)
  111. throw wrapper.refTypeIndirType( CompletionStatus.COMPLETED_NO ) ;
  112. //if (TypeCodeImpl.debug) System.out.println("Getting position " + ((Integer)typeMap.get(id)).intValue() +
  113. //" for id " + id);
  114. return ((Integer)typeMap.get(id)).intValue();
  115. }
  116. public void writeRawBuffer(org.omg.CORBA.portable.OutputStream s, int firstLong) {
  117. // Writes this streams buffer to the given OutputStream
  118. // without byte order flag and length as is the case for encapsulations.
  119. // Make sure to align s to 4 byte boundaries.
  120. // Unfortunately we can't do just this:
  121. // s.alignAndReserve(4, 4);
  122. // So we have to take the first four bytes given in firstLong and write them
  123. // with a call to write_long which will trigger the alignment.
  124. // Then write the rest of the byte array.
  125. //if (TypeCodeImpl.debug) {
  126. //System.out.println(this + ".writeRawBuffer(" + s + ", " + firstLong + ")");
  127. //if (s instanceof CDROutputStream) {
  128. //System.out.println("Parent position before writing kind = " + ((CDROutputStream)s).getIndex());
  129. //}
  130. //}
  131. s.write_long(firstLong);
  132. //if (TypeCodeImpl.debug) {
  133. //if (s instanceof CDROutputStream) {
  134. //System.out.println("Parent position after writing kind = " + ((CDROutputStream)s).getIndex());
  135. //}
  136. //}
  137. ByteBuffer byteBuffer = getByteBuffer();
  138. if (byteBuffer.hasArray())
  139. {
  140. s.write_octet_array(byteBuffer.array(), 4, getIndex() - 4);
  141. }
  142. else
  143. {
  144. // get bytes from DirectByteBuffer
  145. // NOTE: Microbenchmarks are showing it is faster to do
  146. // a loop of ByteBuffer.get(int) than it is to do
  147. // a bulk ByteBuffer.get(byte[], offset, length)
  148. byte[] buf = new byte[byteBuffer.limit()];
  149. for (int i = 0; i < buf.length; i++)
  150. buf[i] = byteBuffer.get(i);
  151. s.write_octet_array(buf, 4, getIndex() - 4);
  152. }
  153. //if (TypeCodeImpl.debug) {
  154. //if (s instanceof CDROutputStream) {
  155. //System.out.println("Parent position after writing all " + getIndex() + " bytes = " + ((CDROutputStream)s).getIndex());
  156. //}
  157. //}
  158. }
  159. public TypeCodeOutputStream createEncapsulation(org.omg.CORBA.ORB _orb) {
  160. TypeCodeOutputStream encap = new TypeCodeOutputStream((ORB)_orb, isLittleEndian());
  161. encap.setEnclosingOutputStream(this);
  162. encap.makeEncapsulation();
  163. //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + encap + " with parent " + this);
  164. return encap;
  165. }
  166. protected void makeEncapsulation() {
  167. // first entry in an encapsulation is the endianess
  168. putEndian();
  169. isEncapsulation = true;
  170. }
  171. public static TypeCodeOutputStream wrapOutputStream(OutputStream os) {
  172. boolean littleEndian = ((os instanceof CDROutputStream) ? ((CDROutputStream)os).isLittleEndian() : false);
  173. TypeCodeOutputStream tos = new TypeCodeOutputStream((ORB)os.orb(), littleEndian);
  174. tos.setEnclosingOutputStream(os);
  175. //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + tos + " with parent " + os);
  176. return tos;
  177. }
  178. public int getPosition() {
  179. return getIndex();
  180. }
  181. public int getRealIndex(int index) {
  182. int topPos = getTopLevelPosition();
  183. //if (TypeCodeImpl.debug) System.out.println("TypeCodeOutputStream.getRealIndex using getTopLevelPosition " +
  184. //topPos + " instead of getPosition " + getPosition());
  185. return topPos;
  186. }
  187. /*
  188. protected void printBuffer() {
  189. super.printBuffer();
  190. }
  191. */
  192. public byte[] getTypeCodeBuffer() {
  193. // Returns the buffer trimmed of the trailing zeros and without the
  194. // known _kind value at the beginning.
  195. ByteBuffer theBuffer = getByteBuffer();
  196. //System.out.println("outBuffer length = " + (getIndex() - 4));
  197. byte[] tcBuffer = new byte[getIndex() - 4];
  198. // Micro-benchmarks show that DirectByteBuffer.get(int) is faster
  199. // than DirectByteBuffer.get(byte[], offset, length).
  200. // REVISIT - May want to check if buffer is direct or non-direct
  201. // and use array copy if ByteBuffer is non-direct.
  202. for (int i = 0; i < tcBuffer.length; i++)
  203. tcBuffer[i] = theBuffer.get(i+4);
  204. return tcBuffer;
  205. }
  206. public void printTypeMap() {
  207. System.out.println("typeMap = {");
  208. Iterator i = typeMap.keySet().iterator();
  209. while (i.hasNext()) {
  210. String id = (String)i.next();
  211. Integer pos = (Integer)typeMap.get(id);
  212. System.out.println(" key = " + id + ", value = " + pos);
  213. }
  214. System.out.println("}");
  215. }
  216. }