1. /*
  2. * @(#)TypeCodeImpl.java 1.91 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.corba;
  8. import org.omg.CORBA.*;
  9. import org.omg.CORBA.TypeCodePackage.*;
  10. import org.omg.CORBA_2_3.portable.InputStream;
  11. import org.omg.CORBA_2_3.portable.OutputStream;
  12. import com.sun.corba.se.internal.core.*;
  13. import com.sun.corba.se.internal.iiop.CDRInputStream;
  14. import com.sun.corba.se.internal.iiop.CDROutputStream;
  15. import java.util.HashMap;
  16. import java.util.Map;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Collections;
  20. import java.util.ArrayList;
  21. import java.io.IOException;
  22. import java.io.PrintStream;
  23. import java.io.ByteArrayOutputStream;
  24. import java.math.BigDecimal;
  25. import java.math.BigInteger;
  26. class WrapperInputStream extends org.omg.CORBA_2_3.portable.InputStream implements TypeCodeReader
  27. {
  28. private CDRInputStream stream;
  29. private Map typeMap = null;
  30. private int startPos = 0;
  31. public WrapperInputStream(CDRInputStream s) {
  32. super();
  33. stream = s;
  34. startPos = stream.getPosition();
  35. }
  36. public int read() throws IOException { return stream.read(); }
  37. public int read(byte b[]) throws IOException { return stream.read(b); }
  38. public int read(byte b[], int off, int len) throws IOException {
  39. return stream.read(b, off, len);
  40. }
  41. public long skip(long n) throws IOException { return stream.skip(n); }
  42. public int available() throws IOException { return stream.available(); }
  43. public void close() throws IOException { stream.close(); }
  44. public void mark(int readlimit) { stream.mark(readlimit); }
  45. public void reset() { stream.reset(); }
  46. public boolean markSupported() { return stream.markSupported(); }
  47. public int getPosition() { return stream.getPosition(); }
  48. public void consumeEndian() { stream.consumeEndian(); }
  49. public boolean read_boolean() { return stream.read_boolean(); }
  50. public char read_char() { return stream.read_char(); }
  51. public char read_wchar() { return stream.read_wchar(); }
  52. public byte read_octet() { return stream.read_octet(); }
  53. public short read_short() { return stream.read_short(); }
  54. public short read_ushort() { return stream.read_ushort(); }
  55. public int read_long() { return stream.read_long(); }
  56. public int read_ulong() { return stream.read_ulong(); }
  57. public long read_longlong() { return stream.read_longlong(); }
  58. public long read_ulonglong() { return stream.read_ulonglong(); }
  59. public float read_float() { return stream.read_float(); }
  60. public double read_double() { return stream.read_double(); }
  61. public String read_string() { return stream.read_string(); }
  62. public String read_wstring() { return stream.read_wstring(); }
  63. public void read_boolean_array(boolean[] value, int offset, int length) {
  64. stream.read_boolean_array(value, offset, length);
  65. }
  66. public void read_char_array(char[] value, int offset, int length) {
  67. stream.read_char_array(value, offset, length);
  68. }
  69. public void read_wchar_array(char[] value, int offset, int length) {
  70. stream.read_wchar_array(value, offset, length);
  71. }
  72. public void read_octet_array(byte[] value, int offset, int length) {
  73. stream.read_octet_array(value, offset, length);
  74. }
  75. public void read_short_array(short[] value, int offset, int length) {
  76. stream.read_short_array(value, offset, length);
  77. }
  78. public void read_ushort_array(short[] value, int offset, int length) {
  79. stream.read_ushort_array(value, offset, length);
  80. }
  81. public void read_long_array(int[] value, int offset, int length) {
  82. stream.read_long_array(value, offset, length);
  83. }
  84. public void read_ulong_array(int[] value, int offset, int length) {
  85. stream.read_ulong_array(value, offset, length);
  86. }
  87. public void read_longlong_array(long[] value, int offset, int length) {
  88. stream.read_longlong_array(value, offset, length);
  89. }
  90. public void read_ulonglong_array(long[] value, int offset, int length) {
  91. stream.read_ulonglong_array(value, offset, length);
  92. }
  93. public void read_float_array(float[] value, int offset, int length) {
  94. stream.read_float_array(value, offset, length);
  95. }
  96. public void read_double_array(double[] value, int offset, int length) {
  97. stream.read_double_array(value, offset, length);
  98. }
  99. public org.omg.CORBA.Object read_Object() { return stream.read_Object(); }
  100. public java.io.Serializable read_value() {return stream.read_value();}
  101. public TypeCode read_TypeCode() { return stream.read_TypeCode(); }
  102. public Any read_any() { return stream.read_any(); }
  103. public Principal read_Principal() { return stream.read_Principal(); }
  104. public java.math.BigDecimal read_fixed() { return stream.read_fixed(); }
  105. public org.omg.CORBA.Context read_Context() { return stream.read_Context(); }
  106. public org.omg.CORBA.ORB orb() { return stream.orb(); }
  107. public void addTypeCodeAtPosition(TypeCodeImpl tc, int position) {
  108. if (typeMap == null) {
  109. //if (TypeCodeImpl.debug) System.out.println("Creating typeMap");
  110. typeMap = new HashMap(16);
  111. }
  112. //if (TypeCodeImpl.debug) System.out.println(this + " adding tc " + tc + " at position " + position);
  113. typeMap.put(new Integer(position), tc);
  114. }
  115. public TypeCodeImpl getTypeCodeAtPosition(int position) {
  116. if (typeMap == null)
  117. return null;
  118. //if (TypeCodeImpl.debug) System.out.println("Getting tc " + (TypeCodeImpl)typeMap.get(new Integer(position)) +
  119. //" at position " + position);
  120. return (TypeCodeImpl)typeMap.get(new Integer(position));
  121. }
  122. public void setEnclosingInputStream(InputStream enclosure) {
  123. // WrapperInputStream has no enclosure
  124. }
  125. public TypeCodeReader getTopLevelStream() {
  126. // WrapperInputStream has no enclosure
  127. return this;
  128. }
  129. public int getTopLevelPosition() {
  130. //if (TypeCodeImpl.debug) System.out.println("WrapperInputStream.getTopLevelPosition " +
  131. //"returning getPosition " + getPosition() + " - startPos " + startPos +
  132. //" = " + (getPosition() - startPos));
  133. return getPosition() - startPos;
  134. }
  135. public void performORBVersionSpecificInit() {
  136. // This is never actually called on a WrapperInputStream, but
  137. // exists to satisfy the interface requirement.
  138. stream.performORBVersionSpecificInit();
  139. }
  140. public void resetCodeSetConverters() {
  141. stream.resetCodeSetConverters();
  142. }
  143. //public void printBuffer() { stream.printBuffer(); }
  144. public void printTypeMap() {
  145. System.out.println("typeMap = {");
  146. List sortedKeys = new ArrayList(typeMap.keySet());
  147. Collections.sort(sortedKeys);
  148. Iterator i = sortedKeys.iterator();
  149. while (i.hasNext()) {
  150. Integer pos = (Integer)i.next();
  151. TypeCodeImpl tci = (TypeCodeImpl)typeMap.get(pos);
  152. System.out.println(" key = " + pos.intValue() + ", value = " + tci.description());
  153. }
  154. System.out.println("}");
  155. }
  156. }
  157. interface TypeCodeReader extends MarshalInputStream {
  158. public void addTypeCodeAtPosition(TypeCodeImpl tc, int position);
  159. public TypeCodeImpl getTypeCodeAtPosition(int position);
  160. public void setEnclosingInputStream(InputStream enclosure);
  161. public TypeCodeReader getTopLevelStream();
  162. public int getTopLevelPosition();
  163. // for debugging
  164. //public void printBuffer();
  165. public int getPosition();
  166. public void printTypeMap();
  167. }
  168. class TypeCodeInputStream extends EncapsInputStream implements TypeCodeReader
  169. {
  170. private Map typeMap = null;
  171. private InputStream enclosure = null;
  172. private boolean isEncapsulation = false;
  173. public TypeCodeInputStream(org.omg.CORBA.ORB orb, byte[] data, int size) {
  174. super(orb, data, size);
  175. }
  176. public TypeCodeInputStream(org.omg.CORBA.ORB orb, byte[] data, int size,
  177. boolean littleEndian) {
  178. super(orb, data, size, littleEndian);
  179. }
  180. public void addTypeCodeAtPosition(TypeCodeImpl tc, int position) {
  181. if (typeMap == null) {
  182. //if (TypeCodeImpl.debug) System.out.println("Creating typeMap");
  183. typeMap = new HashMap(16);
  184. }
  185. //if (TypeCodeImpl.debug) System.out.println(this + " adding tc " + tc + " at position " + position);
  186. typeMap.put(new Integer(position), tc);
  187. }
  188. public TypeCodeImpl getTypeCodeAtPosition(int position) {
  189. if (typeMap == null)
  190. return null;
  191. //if (TypeCodeImpl.debug) {
  192. //System.out.println("Getting tc " + (TypeCode)typeMap.get(new Integer(position)) +
  193. //" at position " + position);
  194. //}
  195. return (TypeCodeImpl)typeMap.get(new Integer(position));
  196. }
  197. public void setEnclosingInputStream(InputStream enclosure) {
  198. this.enclosure = enclosure;
  199. }
  200. public TypeCodeReader getTopLevelStream() {
  201. if (enclosure == null)
  202. return this;
  203. if (enclosure instanceof TypeCodeReader)
  204. return ((TypeCodeReader)enclosure).getTopLevelStream();
  205. return this;
  206. }
  207. public int getTopLevelPosition() {
  208. if (enclosure != null && enclosure instanceof TypeCodeReader) {
  209. // The enclosed stream has to consider if the enclosing stream
  210. // had to read the enclosed stream completely when creating it.
  211. // This is why the size of the enclosed stream needs to be substracted.
  212. int topPos = ((TypeCodeReader)enclosure).getTopLevelPosition();
  213. // Substract getBufferLength from the parents pos because it read this stream
  214. // from its own when creating it
  215. int pos = topPos - getBufferLength() + getPosition();
  216. //if (TypeCodeImpl.debug) {
  217. //System.out.println("TypeCodeInputStream.getTopLevelPosition using getTopLevelPosition " + topPos +
  218. //(isEncapsulation ? " - encaps length 4" : "") +
  219. //" - getBufferLength() " + getBufferLength() +
  220. //" + getPosition() " + getPosition() + " = " + pos);
  221. //}
  222. return pos;
  223. }
  224. //if (TypeCodeImpl.debug) {
  225. //System.out.println("TypeCodeInputStream.getTopLevelPosition returning getPosition() = " +
  226. //getPosition() + " because enclosure is " + enclosure);
  227. //}
  228. return getPosition();
  229. }
  230. public static TypeCodeInputStream readEncapsulation(InputStream is, org.omg.CORBA.ORB _orb) {
  231. // _REVISIT_ Would be nice if we didn't have to copy the buffer!
  232. TypeCodeInputStream encap;
  233. int encapLength = is.read_long();
  234. // read off part of the buffer corresponding to the encapsulation
  235. byte[] encapBuffer = new byte[encapLength];
  236. is.read_octet_array(encapBuffer, 0, encapBuffer.length);
  237. // create an encapsulation using the marshal buffer
  238. if (is instanceof CDRInputStream) {
  239. encap = new TypeCodeInputStream(_orb, encapBuffer, encapBuffer.length,
  240. ((CDRInputStream)is).isLittleEndian());
  241. } else {
  242. encap = new TypeCodeInputStream(_orb, encapBuffer, encapBuffer.length);
  243. }
  244. encap.setEnclosingInputStream(is);
  245. encap.makeEncapsulation();
  246. //if (TypeCodeImpl.debug) {
  247. //System.out.println("Created TypeCodeInputStream " + encap + " with parent " + is);
  248. //encap.printBuffer();
  249. //}
  250. return encap;
  251. }
  252. protected void makeEncapsulation() {
  253. // first entry in an encapsulation is the endianess
  254. consumeEndian();
  255. isEncapsulation = true;
  256. }
  257. public void printTypeMap() {
  258. System.out.println("typeMap = {");
  259. Iterator i = typeMap.keySet().iterator();
  260. while (i.hasNext()) {
  261. Integer pos = (Integer)i.next();
  262. TypeCodeImpl tci = (TypeCodeImpl)typeMap.get(pos);
  263. System.out.println(" key = " + pos.intValue() + ", value = " + tci.description());
  264. }
  265. System.out.println("}");
  266. }
  267. }
  268. final class TypeCodeOutputStream extends EncapsOutputStream {
  269. private OutputStream enclosure = null;
  270. private Map typeMap = null;
  271. private boolean isEncapsulation = false;
  272. public TypeCodeOutputStream(org.omg.CORBA.ORB orb) {
  273. super(orb, false);
  274. }
  275. public TypeCodeOutputStream(org.omg.CORBA.ORB orb, boolean littleEndian) {
  276. super(orb, littleEndian);
  277. }
  278. public org.omg.CORBA.portable.InputStream create_input_stream()
  279. {
  280. //return new TypeCodeInputStream(orb(), getByteBuffer(), getIndex(), isLittleEndian());
  281. TypeCodeInputStream tcis = new TypeCodeInputStream(orb(), getByteBuffer(), getIndex(), isLittleEndian());
  282. //if (TypeCodeImpl.debug) {
  283. //System.out.println("Created TypeCodeInputStream " + tcis + " with no parent");
  284. //tcis.printBuffer();
  285. //}
  286. return tcis;
  287. }
  288. public void setEnclosingOutputStream(OutputStream enclosure) {
  289. this.enclosure = enclosure;
  290. }
  291. /*
  292. public boolean isEncapsulatedIn(TypeCodeOutputStream outerEnclosure) {
  293. if (outerEnclosure == this)
  294. return true;
  295. if (enclosure == null)
  296. return false;
  297. if (enclosure instanceof TypeCodeOutputStream)
  298. return ((TypeCodeOutputStream)enclosure).isEncapsulatedIn(outerEnclosure);
  299. // Last chance! Recursion ends with first non TypeCodeOutputStream.
  300. return (enclosure == outerEnclosure);
  301. }
  302. */
  303. public TypeCodeOutputStream getTopLevelStream() {
  304. if (enclosure == null)
  305. return this;
  306. if (enclosure instanceof TypeCodeOutputStream)
  307. return ((TypeCodeOutputStream)enclosure).getTopLevelStream();
  308. return this;
  309. }
  310. public int getTopLevelPosition() {
  311. if (enclosure != null && enclosure instanceof TypeCodeOutputStream) {
  312. int pos = ((TypeCodeOutputStream)enclosure).getTopLevelPosition() + getPosition();
  313. // Add four bytes for the encaps length, not another 4 for the byte order
  314. // which is included in getPosition().
  315. if (isEncapsulation) pos += 4;
  316. //if (TypeCodeImpl.debug) {
  317. //System.out.println("TypeCodeOutputStream.getTopLevelPosition using getTopLevelPosition " +
  318. //((TypeCodeOutputStream)enclosure).getTopLevelPosition() +
  319. //" + getPosition() " + getPosition() +
  320. //(isEncapsulation ? " + encaps length 4" : "") +
  321. //" = " + pos);
  322. //}
  323. return pos;
  324. }
  325. //if (TypeCodeImpl.debug) {
  326. //System.out.println("TypeCodeOutputStream.getTopLevelPosition returning getPosition() = " +
  327. //getPosition() + ", enclosure is " + enclosure);
  328. //}
  329. return getPosition();
  330. }
  331. public void addIDAtPosition(String id, int position) {
  332. if (typeMap == null)
  333. typeMap = new HashMap(16);
  334. //if (TypeCodeImpl.debug) System.out.println(this + " adding id " + id + " at position " + position);
  335. typeMap.put(id, new Integer(position));
  336. }
  337. public int getPositionForID(String id) {
  338. if (typeMap == null)
  339. throw new MARSHAL("Referenced type of indirect type not marshaled!");
  340. //if (TypeCodeImpl.debug) System.out.println("Getting position " + ((Integer)typeMap.get(id)).intValue() +
  341. //" for id " + id);
  342. return ((Integer)typeMap.get(id)).intValue();
  343. }
  344. public void writeRawBuffer(org.omg.CORBA.portable.OutputStream s, int firstLong) {
  345. // Writes this streams buffer to the given OutputStream
  346. // without byte order flag and length as is the case for encapsulations.
  347. // Make sure to align s to 4 byte boundaries.
  348. // Unfortunately we can't do just this:
  349. // s.alignAndReserve(4, 4);
  350. // So we have to take the first four bytes given in firstLong and write them
  351. // with a call to write_long which will trigger the alignment.
  352. // Then write the rest of the byte array.
  353. //if (TypeCodeImpl.debug) {
  354. //System.out.println(this + ".writeRawBuffer(" + s + ", " + firstLong + ")");
  355. //if (s instanceof CDROutputStream) {
  356. //System.out.println("Parent position before writing kind = " + ((CDROutputStream)s).getIndex());
  357. //}
  358. //}
  359. s.write_long(firstLong);
  360. //if (TypeCodeImpl.debug) {
  361. //if (s instanceof CDROutputStream) {
  362. //System.out.println("Parent position after writing kind = " + ((CDROutputStream)s).getIndex());
  363. //}
  364. //}
  365. s.write_octet_array(getByteBuffer(), 4, getIndex() - 4);
  366. //if (TypeCodeImpl.debug) {
  367. //if (s instanceof CDROutputStream) {
  368. //System.out.println("Parent position after writing all " + getIndex() + " bytes = " + ((CDROutputStream)s).getIndex());
  369. //}
  370. //}
  371. }
  372. public TypeCodeOutputStream createEncapsulation(org.omg.CORBA.ORB _orb) {
  373. TypeCodeOutputStream encap = new TypeCodeOutputStream(_orb, isLittleEndian());
  374. encap.setEnclosingOutputStream(this);
  375. encap.makeEncapsulation();
  376. //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + encap + " with parent " + this);
  377. return encap;
  378. }
  379. protected void makeEncapsulation() {
  380. // first entry in an encapsulation is the endianess
  381. putEndian();
  382. isEncapsulation = true;
  383. }
  384. public static TypeCodeOutputStream wrapOutputStream(OutputStream os) {
  385. boolean littleEndian = ((os instanceof CDROutputStream) ? ((CDROutputStream)os).isLittleEndian() : false);
  386. TypeCodeOutputStream wrapper = new TypeCodeOutputStream(os.orb(), littleEndian);
  387. wrapper.setEnclosingOutputStream(os);
  388. //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + wrapper + " with parent " + os);
  389. return wrapper;
  390. }
  391. public int getPosition() {
  392. return getIndex();
  393. }
  394. public int getRealIndex(int index) {
  395. int topPos = getTopLevelPosition();
  396. //if (TypeCodeImpl.debug) System.out.println("TypeCodeOutputStream.getRealIndex using getTopLevelPosition " +
  397. //topPos + " instead of getPosition " + getPosition());
  398. return topPos;
  399. }
  400. /*
  401. protected void printBuffer() {
  402. super.printBuffer();
  403. }
  404. */
  405. byte[] getTypeCodeBuffer() {
  406. // Returns the buffer trimmed of the trailing zeros and without the
  407. // known _kind value at the beginning.
  408. byte[] theBuffer = getByteBuffer();
  409. //System.out.println("outBuffer length = " + (getIndex() - 4));
  410. byte[] tcBuffer = new byte[getIndex() - 4];
  411. System.arraycopy(theBuffer, 4, tcBuffer, 0, getIndex() - 4);
  412. return tcBuffer;
  413. }
  414. public void printTypeMap() {
  415. System.out.println("typeMap = {");
  416. Iterator i = typeMap.keySet().iterator();
  417. while (i.hasNext()) {
  418. String id = (String)i.next();
  419. Integer pos = (Integer)typeMap.get(id);
  420. System.out.println(" key = " + id + ", value = " + pos);
  421. }
  422. System.out.println("}");
  423. }
  424. }
  425. // no chance of subclasses, so no problems with runtime helper lookup
  426. public final class TypeCodeImpl extends TypeCode
  427. {
  428. //static final boolean debug = false;
  429. // the predefined typecode constants
  430. private static final TypeCodeImpl primitiveConstants[] = {
  431. new TypeCodeImpl(TCKind._tk_null), // tk_null
  432. new TypeCodeImpl(TCKind._tk_void), // tk_void
  433. new TypeCodeImpl(TCKind._tk_short), // tk_short
  434. new TypeCodeImpl(TCKind._tk_long), // tk_long
  435. new TypeCodeImpl(TCKind._tk_ushort), // tk_ushort
  436. new TypeCodeImpl(TCKind._tk_ulong), // tk_ulong
  437. new TypeCodeImpl(TCKind._tk_float), // tk_float
  438. new TypeCodeImpl(TCKind._tk_double), // tk_double
  439. new TypeCodeImpl(TCKind._tk_boolean), // tk_boolean
  440. new TypeCodeImpl(TCKind._tk_char), // tk_char
  441. new TypeCodeImpl(TCKind._tk_octet), // tk_octet
  442. new TypeCodeImpl(TCKind._tk_any), // tk_any
  443. new TypeCodeImpl(TCKind._tk_TypeCode), // tk_typecode
  444. new TypeCodeImpl(TCKind._tk_Principal), // tk_principal
  445. new TypeCodeImpl(TCKind._tk_objref), // tk_objref
  446. null, // tk_struct
  447. null, // tk_union
  448. null, // tk_enum
  449. new TypeCodeImpl(TCKind._tk_string), // tk_string
  450. null, // tk_sequence
  451. null, // tk_array
  452. null, // tk_alias
  453. null, // tk_except
  454. new TypeCodeImpl(TCKind._tk_longlong), // tk_longlong
  455. new TypeCodeImpl(TCKind._tk_ulonglong), // tk_ulonglong
  456. new TypeCodeImpl(TCKind._tk_longdouble), // tk_longdouble
  457. new TypeCodeImpl(TCKind._tk_wchar), // tk_wchar
  458. new TypeCodeImpl(TCKind._tk_wstring), // tk_wstring
  459. new TypeCodeImpl(TCKind._tk_fixed), // tk_fixed
  460. new TypeCodeImpl(TCKind._tk_value), // tk_value
  461. new TypeCodeImpl(TCKind._tk_value_box), // tk_value_box
  462. new TypeCodeImpl(TCKind._tk_native), // tk_native
  463. new TypeCodeImpl(TCKind._tk_abstract_interface) // tk_abstract_interface
  464. };
  465. // the indirection TCKind, needed for recursive typecodes.
  466. protected static final int tk_indirect = 0xFFFFFFFF;
  467. // typecode encodings have three different categories that determine
  468. // how the encoding should be done.
  469. private static final int EMPTY = 0; // no parameters
  470. private static final int SIMPLE = 1; // simple parameters.
  471. private static final int COMPLEX = 2; // complex parameters. need to
  472. // use CDR encapsulation for
  473. // parameters
  474. // a table storing the encoding category for the various typecodes.
  475. private static final int typeTable[] = {
  476. EMPTY, // tk_null
  477. EMPTY, // tk_void
  478. EMPTY, // tk_short
  479. EMPTY, // tk_long
  480. EMPTY, // tk_ushort
  481. EMPTY, // tk_ulong
  482. EMPTY, // tk_float
  483. EMPTY, // tk_double
  484. EMPTY, // tk_boolean
  485. EMPTY, // tk_char
  486. EMPTY, // tk_octet
  487. EMPTY, // tk_any
  488. EMPTY, // tk_typecode
  489. EMPTY, // tk_principal
  490. COMPLEX, // tk_objref
  491. COMPLEX, // tk_struct
  492. COMPLEX, // tk_union
  493. COMPLEX, // tk_enum
  494. SIMPLE, // tk_string
  495. COMPLEX, // tk_sequence
  496. COMPLEX, // tk_array
  497. COMPLEX, // tk_alias
  498. COMPLEX, // tk_except
  499. EMPTY, // tk_longlong
  500. EMPTY, // tk_ulonglong
  501. EMPTY, // tk_longdouble
  502. EMPTY, // tk_wchar
  503. SIMPLE, // tk_wstring
  504. SIMPLE, // tk_fixed
  505. COMPLEX, // tk_value
  506. COMPLEX, // tk_value_box
  507. COMPLEX, // tk_native
  508. COMPLEX // tk_abstract_interface
  509. };
  510. // Maps TCKind values to names
  511. private static final String[] kindNames = {
  512. "null",
  513. "void",
  514. "short",
  515. "long",
  516. "ushort",
  517. "ulong",
  518. "float",
  519. "double",
  520. "boolean",
  521. "char",
  522. "octet",
  523. "any",
  524. "typecode",
  525. "principal",
  526. "objref",
  527. "struct",
  528. "union",
  529. "enum",
  530. "string",
  531. "sequence",
  532. "array",
  533. "alias",
  534. "exception",
  535. "longlong",
  536. "ulonglong",
  537. "longdouble",
  538. "wchar",
  539. "wstring",
  540. "fixed",
  541. "value",
  542. "valueBox",
  543. "native",
  544. "abstractInterface"
  545. };
  546. private int _kind = 0; // the typecode kind
  547. // data members for representing the various kinds of typecodes.
  548. private String _id = ""; // the typecode repository id
  549. private String _name = ""; // the typecode name
  550. private int _memberCount = 0; // member count
  551. private String _memberNames[] = null; // names of members
  552. private TypeCodeImpl _memberTypes[] = null; // types of members
  553. private AnyImpl _unionLabels[] = null; // values of union labels
  554. private TypeCodeImpl _discriminator = null; // union discriminator type
  555. private int _defaultIndex = -1; // union default index
  556. private int _length = 0; // string/seq/array length
  557. private TypeCodeImpl _contentType = null; // seq/array/alias type
  558. // fixed
  559. private short _digits = 0;
  560. private short _scale = 0;
  561. // value type
  562. // _REVISIT_ We might want to keep references to the ValueMember classes
  563. // passed in at initialization instead of copying the relevant data.
  564. // Is the data immutable? What about StructMember, UnionMember etc.?
  565. private short _type_modifier = -1; // VM_NONE, VM_CUSTOM,
  566. // VM_ABSTRACT, VM_TRUNCATABLE
  567. private TypeCodeImpl _concrete_base = null; // concrete base type
  568. private short _memberAccess[] = null; // visibility of ValueMember
  569. // recursive sequence support
  570. private TypeCodeImpl _parent = null; // the enclosing type code
  571. private int _parentOffset = 0; // the level of enclosure
  572. // recursive type code support
  573. private TypeCodeImpl _indirectType = null;
  574. // caches the byte buffer written in write_value for quick remarshaling...
  575. private byte[] outBuffer = null;
  576. // ... but only if caching is enabled
  577. private boolean cachingEnabled = false;
  578. // the ORB instance: may be instanceof ORBSingleton or ORB
  579. private org.omg.CORBA.ORB _orb;
  580. ///////////////////////////////////////////////////////////////////////////
  581. // Constructors...
  582. public TypeCodeImpl(org.omg.CORBA.ORB orb)
  583. {
  584. // initialized to tk_null
  585. _orb = orb;
  586. }
  587. public TypeCodeImpl(org.omg.CORBA.ORB orb, TypeCode tc)
  588. // to handle conversion of "remote" typecodes into "native" style.
  589. // also see the 'convertToNative(ORB orb, TypeCode tc)' function
  590. {
  591. // the orb object
  592. _orb = orb;
  593. // This is a protection against misuse of this constructor.
  594. // Should only be used if tc is not an instance of this class!
  595. // Otherwise we run into problems with recursive/indirect type codes.
  596. // _REVISIT_ We should make this constructor private
  597. if (tc instanceof TypeCodeImpl) {
  598. TypeCodeImpl tci = (TypeCodeImpl)tc;
  599. if (tci._kind == tk_indirect)
  600. throw new BAD_TYPECODE();
  601. if (tci._kind == TCKind._tk_sequence && tci._contentType == null)
  602. throw new BAD_TYPECODE();
  603. }
  604. // set up kind
  605. _kind = tc.kind().value();
  606. try {
  607. // set up parameters
  608. switch (_kind) {
  609. case TCKind._tk_value:
  610. _type_modifier = tc.type_modifier();
  611. // concrete base may be null
  612. TypeCode tccb = tc.concrete_base_type();
  613. if (tccb != null) {
  614. _concrete_base = convertToNative(_orb, tccb);
  615. } else {
  616. _concrete_base = null;
  617. }
  618. //_memberAccess = tc._memberAccess;
  619. // Need to reconstruct _memberAccess using member_count() and member_visibility()
  620. _memberAccess = new short[tc.member_count()];
  621. for (int i=0; i < tc.member_count(); i++) {
  622. _memberAccess[i] = tc.member_visibility(i);
  623. }
  624. case TCKind._tk_except:
  625. case TCKind._tk_struct:
  626. case TCKind._tk_union:
  627. // set up member types
  628. _memberTypes = new TypeCodeImpl[tc.member_count()];
  629. for (int i=0; i < tc.member_count(); i++) {
  630. _memberTypes[i] = convertToNative(_orb, tc.member_type(i));
  631. _memberTypes[i].setParent(this);
  632. }
  633. case TCKind._tk_enum:
  634. // set up member names
  635. _memberNames = new String[tc.member_count()];
  636. for (int i=0; i < tc.member_count(); i++) {
  637. _memberNames[i] = tc.member_name(i);
  638. }
  639. // set up member count
  640. _memberCount = tc.member_count();
  641. case TCKind._tk_objref:
  642. case TCKind._tk_alias:
  643. case TCKind._tk_value_box:
  644. case TCKind._tk_native:
  645. case TCKind._tk_abstract_interface:
  646. setId(tc.id());
  647. _name = tc.name();
  648. break;
  649. }
  650. // set up stuff for unions
  651. switch (_kind) {
  652. case TCKind._tk_union:
  653. _discriminator = convertToNative(_orb, tc.discriminator_type());
  654. _defaultIndex = tc.default_index();
  655. _unionLabels = new AnyImpl[_memberCount];
  656. for (int i=0; i < _memberCount; i++)
  657. _unionLabels[i] = new AnyImpl(_orb, tc.member_label(i));
  658. break;
  659. }
  660. // set up length
  661. switch (_kind) {
  662. case TCKind._tk_string:
  663. case TCKind._tk_wstring:
  664. case TCKind._tk_sequence:
  665. case TCKind._tk_array:
  666. _length = tc.length();
  667. }
  668. // set up content type
  669. switch (_kind) {
  670. case TCKind._tk_sequence:
  671. case TCKind._tk_array:
  672. case TCKind._tk_alias:
  673. case TCKind._tk_value_box:
  674. _contentType = convertToNative(_orb, tc.content_type());
  675. }
  676. } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
  677. // dont have to worry about these since code ensures we dont step
  678. // out of bounds.
  679. }
  680. public TypeCodeImpl(int creationKind)
  681. // for primitive types
  682. {
  683. // the orb object
  684. _orb = null;
  685. // private API. dont bother checking that
  686. // (creationKind < 0 || creationKind > typeTable.length)
  687. _kind = creationKind;
  688. // do initialization for special cases
  689. switch (_kind) {
  690. case TCKind._tk_objref:
  691. {
  692. // this is being used to create typecode for CORBA::Object
  693. setId("IDL:omg.org/CORBA/Object:1.0");
  694. _name = "Object";
  695. break;
  696. }
  697. case TCKind._tk_string:
  698. case TCKind._tk_wstring:
  699. {
  700. _length =0;
  701. break;
  702. }
  703. case TCKind._tk_value:
  704. {
  705. _concrete_base = null;
  706. break;
  707. }
  708. }
  709. }
  710. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  711. int creationKind,
  712. String id,
  713. String name,
  714. StructMember[] members)
  715. // for structs and exceptions
  716. {
  717. // the orb object
  718. _orb = orb;
  719. if ((creationKind == TCKind._tk_struct) || (creationKind == TCKind._tk_except))
  720. {
  721. _kind = creationKind;
  722. setId(id);
  723. _name = name;
  724. _memberCount = members.length;
  725. _memberNames = new String[_memberCount];
  726. _memberTypes = new TypeCodeImpl[_memberCount];
  727. for (int i = 0 ; i < _memberCount ; i++) {
  728. _memberNames[i] = members[i].name;
  729. _memberTypes[i] = convertToNative(_orb, members[i].type);
  730. _memberTypes[i].setParent(this);
  731. }
  732. } // else initializes to null
  733. }
  734. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  735. int creationKind,
  736. String id,
  737. String name,
  738. TypeCode discriminator_type,
  739. UnionMember[] members)
  740. // for unions
  741. {
  742. // the orb object
  743. _orb = orb;
  744. if (creationKind == TCKind._tk_union) {
  745. _kind = creationKind;
  746. setId(id);
  747. _name = name;
  748. _memberCount = members.length;
  749. _discriminator = convertToNative(_orb, discriminator_type);
  750. _memberNames = new String[_memberCount];
  751. _memberTypes = new TypeCodeImpl[_memberCount];
  752. _unionLabels = new AnyImpl[_memberCount];
  753. for (int i = 0 ; i < _memberCount ; i++) {
  754. _memberNames[i] = members[i].name;
  755. _memberTypes[i] = convertToNative(_orb, members[i].type);
  756. _memberTypes[i].setParent(this);
  757. _unionLabels[i] = new AnyImpl(_orb, members[i].label);
  758. // check whether this is the default branch.
  759. if (_unionLabels[i].type().kind() == TCKind.tk_octet) {
  760. if (_unionLabels[i].extract_octet() == (byte)0) {
  761. _defaultIndex = i;
  762. }
  763. }
  764. }
  765. } // else initializes to null
  766. }
  767. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  768. int creationKind,
  769. String id,
  770. String name,
  771. short type_modifier,
  772. TypeCode concrete_base,
  773. ValueMember[] members)
  774. // for value types
  775. {
  776. // the orb object
  777. _orb = orb;
  778. if (creationKind == TCKind._tk_value) {
  779. _kind = creationKind;
  780. setId(id);
  781. _name = name;
  782. _type_modifier = type_modifier;
  783. if (_concrete_base != null) {
  784. _concrete_base = convertToNative(_orb, concrete_base);
  785. }
  786. _memberCount = members.length;
  787. _memberNames = new String[_memberCount];
  788. _memberTypes = new TypeCodeImpl[_memberCount];
  789. _memberAccess = new short[_memberCount];
  790. for (int i = 0 ; i < _memberCount ; i++) {
  791. _memberNames[i] = members[i].name;
  792. _memberTypes[i] = convertToNative(_orb, members[i].type);
  793. _memberTypes[i].setParent(this);
  794. _memberAccess[i] = members[i].access;
  795. }
  796. } // else initializes to null
  797. }
  798. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  799. int creationKind,
  800. String id,
  801. String name,
  802. String[] members)
  803. // for enums
  804. {
  805. // the orb object
  806. _orb = orb;
  807. if (creationKind == TCKind._tk_enum)
  808. {
  809. _kind = creationKind;
  810. setId(id);
  811. _name = name;
  812. _memberCount = members.length;
  813. _memberNames = new String[_memberCount];
  814. for (int i = 0 ; i < _memberCount ; i++)
  815. _memberNames[i] = members[i];
  816. } // else initializes to null
  817. }
  818. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  819. int creationKind,
  820. String id,
  821. String name,
  822. TypeCode original_type)
  823. // for aliases and value boxes
  824. {
  825. // the orb object
  826. _orb = orb;
  827. if ( creationKind == TCKind._tk_alias || creationKind == TCKind._tk_value_box )
  828. {
  829. _kind = creationKind;
  830. setId(id);
  831. _name = name;
  832. _contentType = convertToNative(_orb, original_type);
  833. }
  834. // else initializes to null
  835. }
  836. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  837. int creationKind,
  838. String id,
  839. String name)
  840. {
  841. // the orb object
  842. _orb = orb;
  843. if (creationKind == TCKind._tk_objref ||
  844. creationKind == TCKind._tk_native ||
  845. creationKind == TCKind._tk_abstract_interface)
  846. {
  847. _kind = creationKind;
  848. setId(id);
  849. _name = name;
  850. } // else initializes to null
  851. }
  852. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  853. int creationKind,
  854. int bound)
  855. // for strings
  856. {
  857. if (bound < 0)
  858. throw new BAD_PARAM("bound can not be negative!");
  859. // the orb object
  860. _orb = orb;
  861. if ((creationKind == TCKind._tk_string) || (creationKind == TCKind._tk_wstring))
  862. {
  863. _kind = creationKind;
  864. _length = bound;
  865. } // else initializes to null
  866. }
  867. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  868. int creationKind,
  869. int bound,
  870. TypeCode element_type)
  871. // for sequences and arrays
  872. {
  873. // the orb object
  874. _orb = orb;
  875. if ( creationKind == TCKind._tk_sequence || creationKind == TCKind._tk_array )
  876. {
  877. _kind = creationKind;
  878. _length = bound;
  879. _contentType = convertToNative(_orb, element_type);
  880. } // else initializes to null
  881. }
  882. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  883. int creationKind,
  884. int bound,
  885. int offset)
  886. // for recursive sequences
  887. {
  888. // the orb object
  889. _orb = orb;
  890. if (creationKind == TCKind._tk_sequence) {
  891. _kind = creationKind;
  892. _length = bound;
  893. _parentOffset = offset;
  894. } // else initializes to null
  895. }
  896. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  897. String id)
  898. // for recursive type codes
  899. {
  900. // the orb object
  901. _orb = orb;
  902. _kind = tk_indirect;
  903. // This is the type code of the type we stand in for, not our own.
  904. _id = id;
  905. // Try to resolve it now. May return null in which case
  906. // we try again later (see indirectType()).
  907. tryIndirectType();
  908. }
  909. public TypeCodeImpl(org.omg.CORBA.ORB orb,
  910. int creationKind,
  911. short digits,
  912. short scale)
  913. // for fixed
  914. {
  915. // the orb object
  916. _orb = orb;
  917. //if (digits < 1 || digits > 31)
  918. //throw new BAD_TYPECODE();
  919. if (creationKind == TCKind._tk_fixed) {
  920. _kind = creationKind;
  921. _digits = digits;
  922. _scale = scale;
  923. } // else initializes to null
  924. }
  925. ///////////////////////////////////////////////////////////////////////////
  926. // Other creation functions...
  927. public static TypeCodeImpl get_primitive_tc(TCKind tcKind)
  928. {
  929. try {
  930. return primitiveConstants[tcKind.value()];
  931. } catch (Throwable t) {
  932. throw new BAD_OPERATION("Invalid or unavailable typecode for kind = "+tcKind.value());
  933. }
  934. }
  935. public static TypeCodeImpl get_primitive_tc(int val)
  936. {
  937. try {
  938. return primitiveConstants[val];
  939. } catch (Throwable t) {
  940. throw new BAD_OPERATION("Invalid or unavailable typecode for kind = "+val);
  941. }
  942. }
  943. // Optimization:
  944. // If we checked for and returned constant primitive typecodes
  945. // here we could reduce object creation and also enable more
  946. // efficient typecode comparisons for primitive typecodes.
  947. //
  948. protected static TypeCodeImpl convertToNative(org.omg.CORBA.ORB orb,
  949. TypeCode tc)
  950. {
  951. if (tc instanceof TypeCodeImpl)
  952. return (TypeCodeImpl) tc;
  953. else
  954. return new TypeCodeImpl(orb, tc);
  955. }
  956. public static CDROutputStream newOutputStream(org.omg.CORBA.ORB orb) {
  957. TypeCodeOutputStream tcos = new TypeCodeOutputStream(orb);
  958. //if (debug) System.out.println("Created TypeCodeOutputStream " + tcos + " with no parent");
  959. return tcos;
  960. }
  961. // Support for indirect/recursive type codes
  962. private TypeCodeImpl indirectType() {
  963. _indirectType = tryIndirectType();
  964. if (_indirectType == null) {
  965. // Nothing we can do about that.
  966. throw new BAD_TYPECODE("Invoked operation on unresolved recursive type code!");
  967. }
  968. return _indirectType;
  969. }
  970. private TypeCodeImpl tryIndirectType() {
  971. // Assert that _kind == tk_indirect
  972. if (_indirectType != null)
  973. return _indirectType;
  974. if (_orb instanceof TypeCodeFactory) {
  975. setIndirectType(((TypeCodeFactory)_orb).getTypeCode(_id));
  976. } else {
  977. throw new BAD_TYPECODE("ORB not supporting recursive type codes!");
  978. }
  979. return _indirectType;
  980. }
  981. private void setIndirectType(TypeCodeImpl newType) {
  982. _indirectType = newType;
  983. if (_indirectType != null) {
  984. try {
  985. _id = _indirectType.id();
  986. } catch (BadKind e) {} // can't happen
  987. }
  988. }
  989. private void setId(String newID) {
  990. _id = newID;
  991. if (_orb instanceof TypeCodeFactory) {
  992. ((TypeCodeFactory)_orb).setTypeCode(_id, this);
  993. }
  994. // check whether return value != this which would indicate that the
  995. // repository id isn't unique.
  996. }
  997. private void setParent(TypeCodeImpl parent) {
  998. _parent = parent;
  999. }
  1000. private TypeCodeImpl getParentAtLevel(int level) {
  1001. if (level == 0)
  1002. return this;
  1003. if (_parent == null)
  1004. throw new BAD_TYPECODE("Invoked operation on unresolved recursive type code!");
  1005. return _parent.getParentAtLevel(level - 1);
  1006. }
  1007. private TypeCodeImpl lazy_content_type() {
  1008. if (_contentType == null) {
  1009. if (_kind == TCKind._tk_sequence && _parentOffset > 0 && _parent != null) {
  1010. // This is an unresolved recursive sequence tc.
  1011. // Try to resolve it now if the hierarchy is complete.
  1012. TypeCodeImpl realParent = getParentAtLevel(_parentOffset);
  1013. if (realParent != null && realParent._id != null) {
  1014. // Create a recursive type code object as the content type.
  1015. // This is when the recursive sequence typecode morphes
  1016. // into a sequence typecode containing a recursive typecode.
  1017. _contentType = new TypeCodeImpl(_orb, realParent._id);
  1018. }
  1019. }
  1020. }
  1021. return _contentType;
  1022. }
  1023. // Other private functions
  1024. private TypeCode realType(TypeCode aType) {
  1025. TypeCode realType = aType;
  1026. try {
  1027. // Note: Indirect types are handled in kind() method
  1028. while (realType.kind().value() == TCKind._tk_alias) {
  1029. realType = realType.content_type();
  1030. }
  1031. } catch (BadKind bad) { // impossible
  1032. }
  1033. return realType;
  1034. }
  1035. ///////////////////////////////////////////////////////////////////////////
  1036. // TypeCode operations
  1037. public final boolean equal(TypeCode tc)
  1038. // _REVISIT_ for all optional names/ids, we might want to check that
  1039. // they are equal in case both are non-nil.
  1040. {
  1041. if (tc == this)
  1042. return true;
  1043. try {
  1044. if (_kind == tk_indirect) {
  1045. //return indirectType().equal(tc);
  1046. if (_id != null && tc.id() != null)
  1047. return _id.equals(tc.id());
  1048. return (_id == null && tc.id() == null);
  1049. }
  1050. // make sure kinds are identical.
  1051. if (_kind != tc.kind().value()) {
  1052. return false;
  1053. }
  1054. switch (typeTable[_kind]) {
  1055. case EMPTY:
  1056. // no parameters to check.
  1057. return true;
  1058. case SIMPLE:
  1059. switch (_kind) {
  1060. case TCKind._tk_string:
  1061. case TCKind._tk_wstring:
  1062. // check for bound.
  1063. return (_length == tc.length());
  1064. case TCKind._tk_fixed:
  1065. return (_digits == tc.fixed_digits() && _scale == tc.fixed_scale());
  1066. default:
  1067. return false;
  1068. }
  1069. case COMPLEX:
  1070. switch(_kind) {
  1071. case TCKind._tk_objref:
  1072. {
  1073. // check for logical id.
  1074. if (_id.compareTo(tc.id()) == 0) {
  1075. return true;
  1076. }
  1077. if (_id.compareTo(get_primitive_tc(_kind).id()) == 0) {
  1078. return true;
  1079. }
  1080. if (tc.id().compareTo(get_primitive_tc(_kind).id()) == 0) {
  1081. return true;
  1082. }
  1083. return false;
  1084. }
  1085. case TCKind._tk_native:
  1086. case TCKind._tk_abstract_interface:
  1087. {
  1088. // check for logical id.
  1089. if (_id.compareTo(tc.id()) != 0) {
  1090. return false;
  1091. }
  1092. // ignore name since its optional.
  1093. return true;
  1094. }
  1095. case TCKind._tk_struct:
  1096. case TCKind._tk_except:
  1097. {
  1098. // check for member count
  1099. if (_memberCount != tc.member_count())
  1100. return false;
  1101. // check for repository id
  1102. if (_id.compareTo(tc.id()) != 0)
  1103. return false;
  1104. // check for member types.
  1105. for (int i = 0 ; i < _memberCount ; i++)
  1106. if (! _memberTypes[i].equal(tc.member_type(i)))
  1107. return false;
  1108. // ignore id and names since those are optional.
  1109. return true;
  1110. }
  1111. case TCKind._tk_union:
  1112. {
  1113. // check for member count
  1114. if (_memberCount != tc.member_count())
  1115. return false;
  1116. // check for repository id
  1117. if (_id.compareTo(tc.id()) != 0)
  1118. return false;
  1119. // check for default index
  1120. if (_defaultIndex != tc.default_index())
  1121. return false;
  1122. // check for discriminator type
  1123. if (!_discriminator.equal(tc.discriminator_type()))
  1124. return false;
  1125. // check for label types and values
  1126. for (int i = 0 ; i < _memberCount ; i++)
  1127. if (! _unionLabels[i].equal(tc.member_label(i)))
  1128. return false;
  1129. // check for branch types
  1130. for (int i = 0 ; i < _memberCount ; i++)
  1131. if (! _memberTypes[i].equal(tc.member_type(i)))
  1132. return false;
  1133. // ignore id and names since those are optional.
  1134. return true;
  1135. }
  1136. case TCKind._tk_enum:
  1137. {
  1138. // check for repository id
  1139. if (_id.compareTo(tc.id()) != 0)
  1140. return false;
  1141. // check member count