1. /*
  2. * @(#)TypeCodeImpl.java 1.94 04/06/21
  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.corba;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import java.util.Collections;
  13. import java.util.ArrayList;
  14. import java.io.IOException;
  15. import java.io.PrintStream;
  16. import java.io.ByteArrayOutputStream;
  17. import java.math.BigDecimal;
  18. import java.math.BigInteger;
  19. import org.omg.CORBA.TypeCode ;
  20. import org.omg.CORBA.StructMember ;
  21. import org.omg.CORBA.UnionMember ;
  22. import org.omg.CORBA.ValueMember ;
  23. import org.omg.CORBA.TCKind ;
  24. import org.omg.CORBA.Any ;
  25. import org.omg.CORBA.Principal ;
  26. import org.omg.CORBA.BAD_TYPECODE ;
  27. import org.omg.CORBA.BAD_PARAM ;
  28. import org.omg.CORBA.BAD_OPERATION ;
  29. import org.omg.CORBA.INTERNAL ;
  30. import org.omg.CORBA.MARSHAL ;
  31. import org.omg.CORBA.TypeCodePackage.BadKind ;
  32. import org.omg.CORBA_2_3.portable.InputStream;
  33. import org.omg.CORBA_2_3.portable.OutputStream;
  34. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  35. import com.sun.corba.se.spi.orb.ORB;
  36. import com.sun.corba.se.spi.logging.CORBALogDomains;
  37. import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
  38. import com.sun.corba.se.impl.encoding.MarshalInputStream;
  39. import com.sun.corba.se.impl.encoding.CodeSetConversion;
  40. import com.sun.corba.se.impl.encoding.CDRInputStream;
  41. import com.sun.corba.se.impl.encoding.CDROutputStream;
  42. import com.sun.corba.se.impl.encoding.TypeCodeInputStream;
  43. import com.sun.corba.se.impl.encoding.TypeCodeOutputStream;
  44. import com.sun.corba.se.impl.encoding.TypeCodeReader;
  45. import com.sun.corba.se.impl.encoding.WrapperInputStream;
  46. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  47. // no chance of subclasses, so no problems with runtime helper lookup
  48. public final class TypeCodeImpl extends TypeCode
  49. {
  50. //static final boolean debug = false;
  51. // the indirection TCKind, needed for recursive typecodes.
  52. protected static final int tk_indirect = 0xFFFFFFFF;
  53. // typecode encodings have three different categories that determine
  54. // how the encoding should be done.
  55. private static final int EMPTY = 0; // no parameters
  56. private static final int SIMPLE = 1; // simple parameters.
  57. private static final int COMPLEX = 2; // complex parameters. need to
  58. // use CDR encapsulation for
  59. // parameters
  60. // a table storing the encoding category for the various typecodes.
  61. private static final int typeTable[] = {
  62. EMPTY, // tk_null
  63. EMPTY, // tk_void
  64. EMPTY, // tk_short
  65. EMPTY, // tk_long
  66. EMPTY, // tk_ushort
  67. EMPTY, // tk_ulong
  68. EMPTY, // tk_float
  69. EMPTY, // tk_double
  70. EMPTY, // tk_boolean
  71. EMPTY, // tk_char
  72. EMPTY, // tk_octet
  73. EMPTY, // tk_any
  74. EMPTY, // tk_typecode
  75. EMPTY, // tk_principal
  76. COMPLEX, // tk_objref
  77. COMPLEX, // tk_struct
  78. COMPLEX, // tk_union
  79. COMPLEX, // tk_enum
  80. SIMPLE, // tk_string
  81. COMPLEX, // tk_sequence
  82. COMPLEX, // tk_array
  83. COMPLEX, // tk_alias
  84. COMPLEX, // tk_except
  85. EMPTY, // tk_longlong
  86. EMPTY, // tk_ulonglong
  87. EMPTY, // tk_longdouble
  88. EMPTY, // tk_wchar
  89. SIMPLE, // tk_wstring
  90. SIMPLE, // tk_fixed
  91. COMPLEX, // tk_value
  92. COMPLEX, // tk_value_box
  93. COMPLEX, // tk_native
  94. COMPLEX // tk_abstract_interface
  95. };
  96. // Maps TCKind values to names
  97. // This is also used in AnyImpl.
  98. static final String[] kindNames = {
  99. "null",
  100. "void",
  101. "short",
  102. "long",
  103. "ushort",
  104. "ulong",
  105. "float",
  106. "double",
  107. "boolean",
  108. "char",
  109. "octet",
  110. "any",
  111. "typecode",
  112. "principal",
  113. "objref",
  114. "struct",
  115. "union",
  116. "enum",
  117. "string",
  118. "sequence",
  119. "array",
  120. "alias",
  121. "exception",
  122. "longlong",
  123. "ulonglong",
  124. "longdouble",
  125. "wchar",
  126. "wstring",
  127. "fixed",
  128. "value",
  129. "valueBox",
  130. "native",
  131. "abstractInterface"
  132. };
  133. private int _kind = 0; // the typecode kind
  134. // data members for representing the various kinds of typecodes.
  135. private String _id = ""; // the typecode repository id
  136. private String _name = ""; // the typecode name
  137. private int _memberCount = 0; // member count
  138. private String _memberNames[] = null; // names of members
  139. private TypeCodeImpl _memberTypes[] = null; // types of members
  140. private AnyImpl _unionLabels[] = null; // values of union labels
  141. private TypeCodeImpl _discriminator = null; // union discriminator type
  142. private int _defaultIndex = -1; // union default index
  143. private int _length = 0; // string/seq/array length
  144. private TypeCodeImpl _contentType = null; // seq/array/alias type
  145. // fixed
  146. private short _digits = 0;
  147. private short _scale = 0;
  148. // value type
  149. // _REVISIT_ We might want to keep references to the ValueMember classes
  150. // passed in at initialization instead of copying the relevant data.
  151. // Is the data immutable? What about StructMember, UnionMember etc.?
  152. private short _type_modifier = -1; // VM_NONE, VM_CUSTOM,
  153. // VM_ABSTRACT, VM_TRUNCATABLE
  154. private TypeCodeImpl _concrete_base = null; // concrete base type
  155. private short _memberAccess[] = null; // visibility of ValueMember
  156. // recursive sequence support
  157. private TypeCodeImpl _parent = null; // the enclosing type code
  158. private int _parentOffset = 0; // the level of enclosure
  159. // recursive type code support
  160. private TypeCodeImpl _indirectType = null;
  161. // caches the byte buffer written in write_value for quick remarshaling...
  162. private byte[] outBuffer = null;
  163. // ... but only if caching is enabled
  164. private boolean cachingEnabled = false;
  165. // the ORB instance: may be instanceof ORBSingleton or ORB
  166. private ORB _orb;
  167. private ORBUtilSystemException wrapper ;
  168. ///////////////////////////////////////////////////////////////////////////
  169. // Constructors...
  170. public TypeCodeImpl(ORB orb)
  171. {
  172. // initialized to tk_null
  173. _orb = orb;
  174. wrapper = ORBUtilSystemException.get(
  175. (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PRESENTATION ) ;
  176. }
  177. public TypeCodeImpl(ORB orb, TypeCode tc)
  178. // to handle conversion of "remote" typecodes into "native" style.
  179. // also see the 'convertToNative(ORB orb, TypeCode tc)' function
  180. {
  181. this(orb) ;
  182. // This is a protection against misuse of this constructor.
  183. // Should only be used if tc is not an instance of this class!
  184. // Otherwise we run into problems with recursive/indirect type codes.
  185. // _REVISIT_ We should make this constructor private
  186. if (tc instanceof TypeCodeImpl) {
  187. TypeCodeImpl tci = (TypeCodeImpl)tc;
  188. if (tci._kind == tk_indirect)
  189. throw wrapper.badRemoteTypecode() ;
  190. if (tci._kind == TCKind._tk_sequence && tci._contentType == null)
  191. throw wrapper.badRemoteTypecode() ;
  192. }
  193. // set up kind
  194. _kind = tc.kind().value();
  195. try {
  196. // set up parameters
  197. switch (_kind) {
  198. case TCKind._tk_value:
  199. _type_modifier = tc.type_modifier();
  200. // concrete base may be null
  201. TypeCode tccb = tc.concrete_base_type();
  202. if (tccb != null) {
  203. _concrete_base = convertToNative(_orb, tccb);
  204. } else {
  205. _concrete_base = null;
  206. }
  207. //_memberAccess = tc._memberAccess;
  208. // Need to reconstruct _memberAccess using member_count() and member_visibility()
  209. _memberAccess = new short[tc.member_count()];
  210. for (int i=0; i < tc.member_count(); i++) {
  211. _memberAccess[i] = tc.member_visibility(i);
  212. }
  213. case TCKind._tk_except:
  214. case TCKind._tk_struct:
  215. case TCKind._tk_union:
  216. // set up member types
  217. _memberTypes = new TypeCodeImpl[tc.member_count()];
  218. for (int i=0; i < tc.member_count(); i++) {
  219. _memberTypes[i] = convertToNative(_orb, tc.member_type(i));
  220. _memberTypes[i].setParent(this);
  221. }
  222. case TCKind._tk_enum:
  223. // set up member names
  224. _memberNames = new String[tc.member_count()];
  225. for (int i=0; i < tc.member_count(); i++) {
  226. _memberNames[i] = tc.member_name(i);
  227. }
  228. // set up member count
  229. _memberCount = tc.member_count();
  230. case TCKind._tk_objref:
  231. case TCKind._tk_alias:
  232. case TCKind._tk_value_box:
  233. case TCKind._tk_native:
  234. case TCKind._tk_abstract_interface:
  235. setId(tc.id());
  236. _name = tc.name();
  237. break;
  238. }
  239. // set up stuff for unions
  240. switch (_kind) {
  241. case TCKind._tk_union:
  242. _discriminator = convertToNative(_orb, tc.discriminator_type());
  243. _defaultIndex = tc.default_index();
  244. _unionLabels = new AnyImpl[_memberCount];
  245. for (int i=0; i < _memberCount; i++)
  246. _unionLabels[i] = new AnyImpl(_orb, tc.member_label(i));
  247. break;
  248. }
  249. // set up length
  250. switch (_kind) {
  251. case TCKind._tk_string:
  252. case TCKind._tk_wstring:
  253. case TCKind._tk_sequence:
  254. case TCKind._tk_array:
  255. _length = tc.length();
  256. }
  257. // set up content type
  258. switch (_kind) {
  259. case TCKind._tk_sequence:
  260. case TCKind._tk_array:
  261. case TCKind._tk_alias:
  262. case TCKind._tk_value_box:
  263. _contentType = convertToNative(_orb, tc.content_type());
  264. }
  265. } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
  266. // dont have to worry about these since code ensures we dont step
  267. // out of bounds.
  268. }
  269. public TypeCodeImpl(ORB orb, int creationKind)
  270. // for primitive types
  271. {
  272. this(orb);
  273. // private API. dont bother checking that
  274. // (creationKind < 0 || creationKind > typeTable.length)
  275. _kind = creationKind;
  276. // do initialization for special cases
  277. switch (_kind) {
  278. case TCKind._tk_objref:
  279. {
  280. // this is being used to create typecode for CORBA::Object
  281. setId("IDL:omg.org/CORBA/Object:1.0");
  282. _name = "Object";
  283. break;
  284. }
  285. case TCKind._tk_string:
  286. case TCKind._tk_wstring:
  287. {
  288. _length =0;
  289. break;
  290. }
  291. case TCKind._tk_value:
  292. {
  293. _concrete_base = null;
  294. break;
  295. }
  296. }
  297. }
  298. public TypeCodeImpl(ORB orb,
  299. int creationKind,
  300. String id,
  301. String name,
  302. StructMember[] members)
  303. // for structs and exceptions
  304. {
  305. this(orb);
  306. if ((creationKind == TCKind._tk_struct) || (creationKind == TCKind._tk_except)) {
  307. _kind = creationKind;
  308. setId(id);
  309. _name = name;
  310. _memberCount = members.length;
  311. _memberNames = new String[_memberCount];
  312. _memberTypes = new TypeCodeImpl[_memberCount];
  313. for (int i = 0 ; i < _memberCount ; i++) {
  314. _memberNames[i] = members[i].name;
  315. _memberTypes[i] = convertToNative(_orb, members[i].type);
  316. _memberTypes[i].setParent(this);
  317. }
  318. } // else initializes to null
  319. }
  320. public TypeCodeImpl(ORB orb,
  321. int creationKind,
  322. String id,
  323. String name,
  324. TypeCode discriminator_type,
  325. UnionMember[] members)
  326. // for unions
  327. {
  328. this(orb) ;
  329. if (creationKind == TCKind._tk_union) {
  330. _kind = creationKind;
  331. setId(id);
  332. _name = name;
  333. _memberCount = members.length;
  334. _discriminator = convertToNative(_orb, discriminator_type);
  335. _memberNames = new String[_memberCount];
  336. _memberTypes = new TypeCodeImpl[_memberCount];
  337. _unionLabels = new AnyImpl[_memberCount];
  338. for (int i = 0 ; i < _memberCount ; i++) {
  339. _memberNames[i] = members[i].name;
  340. _memberTypes[i] = convertToNative(_orb, members[i].type);
  341. _memberTypes[i].setParent(this);
  342. _unionLabels[i] = new AnyImpl(_orb, members[i].label);
  343. // check whether this is the default branch.
  344. if (_unionLabels[i].type().kind() == TCKind.tk_octet) {
  345. if (_unionLabels[i].extract_octet() == (byte)0) {
  346. _defaultIndex = i;
  347. }
  348. }
  349. }
  350. } // else initializes to null
  351. }
  352. public TypeCodeImpl(ORB orb,
  353. int creationKind,
  354. String id,
  355. String name,
  356. short type_modifier,
  357. TypeCode concrete_base,
  358. ValueMember[] members)
  359. // for value types
  360. {
  361. this(orb) ;
  362. if (creationKind == TCKind._tk_value) {
  363. _kind = creationKind;
  364. setId(id);
  365. _name = name;
  366. _type_modifier = type_modifier;
  367. if (_concrete_base != null) {
  368. _concrete_base = convertToNative(_orb, concrete_base);
  369. }
  370. _memberCount = members.length;
  371. _memberNames = new String[_memberCount];
  372. _memberTypes = new TypeCodeImpl[_memberCount];
  373. _memberAccess = new short[_memberCount];
  374. for (int i = 0 ; i < _memberCount ; i++) {
  375. _memberNames[i] = members[i].name;
  376. _memberTypes[i] = convertToNative(_orb, members[i].type);
  377. _memberTypes[i].setParent(this);
  378. _memberAccess[i] = members[i].access;
  379. }
  380. } // else initializes to null
  381. }
  382. public TypeCodeImpl(ORB orb,
  383. int creationKind,
  384. String id,
  385. String name,
  386. String[] members)
  387. // for enums
  388. {
  389. this(orb) ;
  390. if (creationKind == TCKind._tk_enum)
  391. {
  392. _kind = creationKind;
  393. setId(id);
  394. _name = name;
  395. _memberCount = members.length;
  396. _memberNames = new String[_memberCount];
  397. for (int i = 0 ; i < _memberCount ; i++)
  398. _memberNames[i] = members[i];
  399. } // else initializes to null
  400. }
  401. public TypeCodeImpl(ORB orb,
  402. int creationKind,
  403. String id,
  404. String name,
  405. TypeCode original_type)
  406. // for aliases and value boxes
  407. {
  408. this(orb) ;
  409. if ( creationKind == TCKind._tk_alias || creationKind == TCKind._tk_value_box )
  410. {
  411. _kind = creationKind;
  412. setId(id);
  413. _name = name;
  414. _contentType = convertToNative(_orb, original_type);
  415. }
  416. // else initializes to null
  417. }
  418. public TypeCodeImpl(ORB orb,
  419. int creationKind,
  420. String id,
  421. String name)
  422. {
  423. this(orb) ;
  424. if (creationKind == TCKind._tk_objref ||
  425. creationKind == TCKind._tk_native ||
  426. creationKind == TCKind._tk_abstract_interface)
  427. {
  428. _kind = creationKind;
  429. setId(id);
  430. _name = name;
  431. } // else initializes to null
  432. }
  433. public TypeCodeImpl(ORB orb,
  434. int creationKind,
  435. int bound)
  436. // for strings
  437. {
  438. this(orb) ;
  439. if (bound < 0)
  440. throw wrapper.negativeBounds() ;
  441. if ((creationKind == TCKind._tk_string) || (creationKind == TCKind._tk_wstring)) {
  442. _kind = creationKind;
  443. _length = bound;
  444. } // else initializes to null
  445. }
  446. public TypeCodeImpl(ORB orb,
  447. int creationKind,
  448. int bound,
  449. TypeCode element_type)
  450. // for sequences and arrays
  451. {
  452. this(orb) ;
  453. if ( creationKind == TCKind._tk_sequence || creationKind == TCKind._tk_array ) {
  454. _kind = creationKind;
  455. _length = bound;
  456. _contentType = convertToNative(_orb, element_type);
  457. } // else initializes to null
  458. }
  459. public TypeCodeImpl(ORB orb,
  460. int creationKind,
  461. int bound,
  462. int offset)
  463. // for recursive sequences
  464. {
  465. this(orb) ;
  466. if (creationKind == TCKind._tk_sequence) {
  467. _kind = creationKind;
  468. _length = bound;
  469. _parentOffset = offset;
  470. } // else initializes to null
  471. }
  472. public TypeCodeImpl(ORB orb,
  473. String id)
  474. // for recursive type codes
  475. {
  476. this(orb) ;
  477. _kind = tk_indirect;
  478. // This is the type code of the type we stand in for, not our own.
  479. _id = id;
  480. // Try to resolve it now. May return null in which case
  481. // we try again later (see indirectType()).
  482. tryIndirectType();
  483. }
  484. public TypeCodeImpl(ORB orb,
  485. int creationKind,
  486. short digits,
  487. short scale)
  488. // for fixed
  489. {
  490. this(orb) ;
  491. //if (digits < 1 || digits > 31)
  492. //throw new BAD_TYPECODE();
  493. if (creationKind == TCKind._tk_fixed) {
  494. _kind = creationKind;
  495. _digits = digits;
  496. _scale = scale;
  497. } // else initializes to null
  498. }
  499. ///////////////////////////////////////////////////////////////////////////
  500. // Other creation functions...
  501. // Optimization:
  502. // If we checked for and returned constant primitive typecodes
  503. // here we could reduce object creation and also enable more
  504. // efficient typecode comparisons for primitive typecodes.
  505. //
  506. protected static TypeCodeImpl convertToNative(ORB orb,
  507. TypeCode tc)
  508. {
  509. if (tc instanceof TypeCodeImpl)
  510. return (TypeCodeImpl) tc;
  511. else
  512. return new TypeCodeImpl(orb, tc);
  513. }
  514. public static CDROutputStream newOutputStream(ORB orb) {
  515. TypeCodeOutputStream tcos = new TypeCodeOutputStream((ORB)orb);
  516. //if (debug) System.out.println("Created TypeCodeOutputStream " + tcos +
  517. // " with no parent");
  518. return tcos;
  519. }
  520. // Support for indirect/recursive type codes
  521. private TypeCodeImpl indirectType() {
  522. _indirectType = tryIndirectType();
  523. if (_indirectType == null) {
  524. // Nothing we can do about that.
  525. throw wrapper.unresolvedRecursiveTypecode() ;
  526. }
  527. return _indirectType;
  528. }
  529. private TypeCodeImpl tryIndirectType() {
  530. // Assert that _kind == tk_indirect
  531. if (_indirectType != null)
  532. return _indirectType;
  533. setIndirectType(_orb.getTypeCode(_id));
  534. return _indirectType;
  535. }
  536. private void setIndirectType(TypeCodeImpl newType) {
  537. _indirectType = newType;
  538. if (_indirectType != null) {
  539. try {
  540. _id = _indirectType.id();
  541. } catch (BadKind e) {
  542. // can't happen
  543. throw wrapper.badkindCannotOccur() ;
  544. }
  545. }
  546. }
  547. private void setId(String newID) {
  548. _id = newID;
  549. if (_orb instanceof TypeCodeFactory) {
  550. ((TypeCodeFactory)_orb).setTypeCode(_id, this);
  551. }
  552. // check whether return value != this which would indicate that the
  553. // repository id isn't unique.
  554. }
  555. private void setParent(TypeCodeImpl parent) {
  556. _parent = parent;
  557. }
  558. private TypeCodeImpl getParentAtLevel(int level) {
  559. if (level == 0)
  560. return this;
  561. if (_parent == null)
  562. throw wrapper.unresolvedRecursiveTypecode() ;
  563. return _parent.getParentAtLevel(level - 1);
  564. }
  565. private TypeCodeImpl lazy_content_type() {
  566. if (_contentType == null) {
  567. if (_kind == TCKind._tk_sequence && _parentOffset > 0 && _parent != null) {
  568. // This is an unresolved recursive sequence tc.
  569. // Try to resolve it now if the hierarchy is complete.
  570. TypeCodeImpl realParent = getParentAtLevel(_parentOffset);
  571. if (realParent != null && realParent._id != null) {
  572. // Create a recursive type code object as the content type.
  573. // This is when the recursive sequence typecode morphes
  574. // into a sequence typecode containing a recursive typecode.
  575. _contentType = new TypeCodeImpl((ORB)_orb, realParent._id);
  576. }
  577. }
  578. }
  579. return _contentType;
  580. }
  581. // Other private functions
  582. private TypeCode realType(TypeCode aType) {
  583. TypeCode realType = aType;
  584. try {
  585. // Note: Indirect types are handled in kind() method
  586. while (realType.kind().value() == TCKind._tk_alias) {
  587. realType = realType.content_type();
  588. }
  589. } catch (BadKind bad) {
  590. // impossible
  591. throw wrapper.badkindCannotOccur() ;
  592. }
  593. return realType;
  594. }
  595. ///////////////////////////////////////////////////////////////////////////
  596. // TypeCode operations
  597. public final boolean equal(TypeCode tc)
  598. // _REVISIT_ for all optional names/ids, we might want to check that
  599. // they are equal in case both are non-nil.
  600. {
  601. if (tc == this)
  602. return true;
  603. try {
  604. if (_kind == tk_indirect) {
  605. //return indirectType().equal(tc);
  606. if (_id != null && tc.id() != null)
  607. return _id.equals(tc.id());
  608. return (_id == null && tc.id() == null);
  609. }
  610. // make sure kinds are identical.
  611. if (_kind != tc.kind().value()) {
  612. return false;
  613. }
  614. switch (typeTable[_kind]) {
  615. case EMPTY:
  616. // no parameters to check.
  617. return true;
  618. case SIMPLE:
  619. switch (_kind) {
  620. case TCKind._tk_string:
  621. case TCKind._tk_wstring:
  622. // check for bound.
  623. return (_length == tc.length());
  624. case TCKind._tk_fixed:
  625. return (_digits == tc.fixed_digits() && _scale == tc.fixed_scale());
  626. default:
  627. return false;
  628. }
  629. case COMPLEX:
  630. switch(_kind) {
  631. case TCKind._tk_objref:
  632. {
  633. // check for logical id.
  634. if (_id.compareTo(tc.id()) == 0) {
  635. return true;
  636. }
  637. if (_id.compareTo(
  638. (_orb.get_primitive_tc(_kind)).id()) == 0)
  639. {
  640. return true;
  641. }
  642. if (tc.id().compareTo(
  643. (_orb.get_primitive_tc(_kind)).id()) == 0)
  644. {
  645. return true;
  646. }
  647. return false;
  648. }
  649. case TCKind._tk_native:
  650. case TCKind._tk_abstract_interface:
  651. {
  652. // check for logical id.
  653. if (_id.compareTo(tc.id()) != 0) {
  654. return false;
  655. }
  656. // ignore name since its optional.
  657. return true;
  658. }
  659. case TCKind._tk_struct:
  660. case TCKind._tk_except:
  661. {
  662. // check for member count
  663. if (_memberCount != tc.member_count())
  664. return false;
  665. // check for repository id
  666. if (_id.compareTo(tc.id()) != 0)
  667. return false;
  668. // check for member types.
  669. for (int i = 0 ; i < _memberCount ; i++)
  670. if (! _memberTypes[i].equal(tc.member_type(i)))
  671. return false;
  672. // ignore id and names since those are optional.
  673. return true;
  674. }
  675. case TCKind._tk_union:
  676. {
  677. // check for member count
  678. if (_memberCount != tc.member_count())
  679. return false;
  680. // check for repository id
  681. if (_id.compareTo(tc.id()) != 0)
  682. return false;
  683. // check for default index
  684. if (_defaultIndex != tc.default_index())
  685. return false;
  686. // check for discriminator type
  687. if (!_discriminator.equal(tc.discriminator_type()))
  688. return false;
  689. // check for label types and values
  690. for (int i = 0 ; i < _memberCount ; i++)
  691. if (! _unionLabels[i].equal(tc.member_label(i)))
  692. return false;
  693. // check for branch types
  694. for (int i = 0 ; i < _memberCount ; i++)
  695. if (! _memberTypes[i].equal(tc.member_type(i)))
  696. return false;
  697. // ignore id and names since those are optional.
  698. return true;
  699. }
  700. case TCKind._tk_enum:
  701. {
  702. // check for repository id
  703. if (_id.compareTo(tc.id()) != 0)
  704. return false;
  705. // check member count
  706. if (_memberCount != tc.member_count())
  707. return false;
  708. // ignore names since those are optional.
  709. return true;
  710. }
  711. case TCKind._tk_sequence:
  712. case TCKind._tk_array:
  713. {
  714. // check bound/length
  715. if (_length != tc.length()) {
  716. return false;
  717. }
  718. // check content type
  719. if (! lazy_content_type().equal(tc.content_type())) {
  720. return false;
  721. }
  722. // ignore id and name since those are optional.
  723. return true;
  724. }
  725. case TCKind._tk_value:
  726. {
  727. // check for member count
  728. if (_memberCount != tc.member_count())
  729. return false;
  730. // check for repository id
  731. if (_id.compareTo(tc.id()) != 0)
  732. return false;
  733. // check for member types.
  734. for (int i = 0 ; i < _memberCount ; i++)
  735. if (_memberAccess[i] != tc.member_visibility(i) ||
  736. ! _memberTypes[i].equal(tc.member_type(i)))
  737. return false;
  738. if (_type_modifier == tc.type_modifier())
  739. return false;
  740. // concrete_base may be null
  741. TypeCode tccb = tc.concrete_base_type();
  742. if ((_concrete_base == null && tccb != null) ||
  743. (_concrete_base != null && tccb == null) ||
  744. ! _concrete_base.equal(tccb))
  745. {
  746. return false;
  747. }
  748. // ignore id and names since those are optional.
  749. return true;
  750. }
  751. case TCKind._tk_alias:
  752. case TCKind._tk_value_box:
  753. {
  754. // check for repository id
  755. if (_id.compareTo(tc.id()) != 0) {
  756. return false;
  757. }
  758. // check for equality with the true type
  759. return _contentType.equal(tc.content_type());
  760. }
  761. }
  762. }
  763. } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
  764. // dont have to worry about these since the code ensures these dont
  765. // arise.
  766. return false;
  767. }
  768. /**
  769. * The equivalent operation is used by the ORB when determining type equivalence
  770. * for values stored in an IDL any.
  771. */
  772. public boolean equivalent(TypeCode tc) {
  773. if (tc == this) {
  774. return true;
  775. }
  776. // If the result of the kind operation on either TypeCode is tk_alias, recursively
  777. // replace the TypeCode with the result of calling content_type, until the kind
  778. // is no longer tk_alias.
  779. // Note: Always resolve indirect types first!
  780. TypeCode myRealType = (_kind == tk_indirect ? indirectType() : this);
  781. myRealType = realType(myRealType);
  782. TypeCode otherRealType = realType(tc);
  783. // If results of the kind operation on each typecode differ,
  784. // equivalent returns false.
  785. if (myRealType.kind().value() != otherRealType.kind().value()) {
  786. return false;
  787. }
  788. String myID = null;
  789. String otherID = null;
  790. try {
  791. myID = this.id();
  792. otherID = tc.id();
  793. // At this point the id operation is valid for both TypeCodes.
  794. // Return true if the results of id for both TypeCodes are non-empty strings
  795. // and both strings are equal.
  796. // If both ids are non-empty but are not equal, then equivalent returns FALSE.
  797. if (myID != null && otherID != null) {
  798. return (myID.equals(otherID));
  799. }
  800. } catch (BadKind e) {
  801. // id operation is not valid for either or both TypeCodes
  802. }
  803. // If either or both id is an empty string, or the TypeCode kind does not support
  804. // the id operation, perform a structural comparison of the TypeCodes.
  805. int myKind = myRealType.kind().value();
  806. try {
  807. if (myKind == TCKind._tk_struct ||
  808. myKind == TCKind._tk_union ||
  809. myKind == TCKind._tk_enum ||
  810. myKind == TCKind._tk_except ||
  811. myKind == TCKind._tk_value)
  812. {
  813. if (myRealType.member_count() != otherRealType.member_count())
  814. return false;
  815. }
  816. if (myKind == TCKind._tk_union)
  817. {
  818. if (myRealType.default_index() != otherRealType.default_index())
  819. return false;
  820. }
  821. if (myKind == TCKind._tk_string ||
  822. myKind == TCKind._tk_wstring ||
  823. myKind == TCKind._tk_sequence ||
  824. myKind == TCKind._tk_array)
  825. {
  826. if (myRealType.length() != otherRealType.length())
  827. return false;
  828. }
  829. if (myKind == TCKind._tk_fixed)
  830. {
  831. if (myRealType.fixed_digits() != otherRealType.fixed_digits() ||
  832. myRealType.fixed_scale() != otherRealType.fixed_scale())
  833. return false;
  834. }
  835. if (myKind == TCKind._tk_union)
  836. {
  837. for (int i=0; i<myRealType.member_count(); i++) {
  838. if (myRealType.member_label(i) != otherRealType.member_label(i))
  839. return false;
  840. }
  841. if ( ! myRealType.discriminator_type().equivalent(
  842. otherRealType.discriminator_type()))
  843. return false;
  844. }
  845. if (myKind == TCKind._tk_alias ||
  846. myKind == TCKind._tk_value_box ||
  847. myKind == TCKind._tk_sequence ||
  848. myKind == TCKind._tk_array)
  849. {
  850. if ( ! myRealType.content_type().equivalent(otherRealType.content_type()))
  851. return false;
  852. }
  853. if (myKind == TCKind._tk_struct ||
  854. myKind == TCKind._tk_union ||
  855. myKind == TCKind._tk_except ||
  856. myKind == TCKind._tk_value)
  857. {
  858. for (int i=0; i<myRealType.member_count(); i++) {
  859. if ( ! myRealType.member_type(i).equivalent(
  860. otherRealType.member_type(i)))
  861. return false;
  862. }
  863. }
  864. } catch (BadKind e) {
  865. // impossible if we checked correctly above
  866. throw wrapper.badkindCannotOccur() ;
  867. } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
  868. // impossible if we checked correctly above
  869. throw wrapper.boundsCannotOccur() ;
  870. }
  871. // Structural comparison succeeded!
  872. return true;
  873. }
  874. public TypeCode get_compact_typecode() {
  875. // _REVISIT_ It isn't clear whether this method should operate on this or a copy.
  876. // For now just return this unmodified because the name and member_name fields
  877. // aren't used for comparison anyways.
  878. return this;
  879. }
  880. public TCKind kind()
  881. {
  882. if (_kind == tk_indirect)
  883. return indirectType().kind();
  884. return TCKind.from_int(_kind);
  885. }
  886. public boolean is_recursive()
  887. {
  888. // Recursive is the only form of indirect type codes right now.
  889. // Indirection can also be used for repeated type codes.
  890. return (_kind == tk_indirect);
  891. }
  892. public String id()
  893. throws BadKind
  894. {
  895. switch (_kind) {
  896. case tk_indirect:
  897. //return indirectType().id(); // same as _id
  898. case TCKind._tk_except:
  899. case TCKind._tk_objref:
  900. case TCKind._tk_struct:
  901. case TCKind._tk_union:
  902. case TCKind._tk_enum:
  903. case TCKind._tk_alias:
  904. case TCKind._tk_value:
  905. case TCKind._tk_value_box:
  906. case TCKind._tk_native:
  907. case TCKind._tk_abstract_interface:
  908. // exception and objref typecodes must have a repository id.
  909. // structs, unions, enums, and aliases may or may not.
  910. return _id;
  911. default:
  912. // all other typecodes throw the BadKind exception.
  913. throw new BadKind();
  914. }
  915. }
  916. public String name()
  917. throws BadKind
  918. {
  919. switch (_kind) {
  920. case tk_indirect:
  921. return indirectType().name();
  922. case TCKind._tk_except:
  923. case TCKind._tk_objref:
  924. case TCKind._tk_struct:
  925. case TCKind._tk_union:
  926. case TCKind._tk_enum:
  927. case TCKind._tk_alias:
  928. case TCKind._tk_value:
  929. case TCKind._tk_value_box:
  930. case TCKind._tk_native:
  931. case TCKind._tk_abstract_interface:
  932. return _name;
  933. default:
  934. throw new BadKind();
  935. }
  936. }
  937. public int member_count()
  938. throws BadKind
  939. {
  940. switch (_kind) {
  941. case tk_indirect:
  942. return indirectType().member_count();
  943. case TCKind._tk_except:
  944. case TCKind._tk_struct:
  945. case TCKind._tk_union:
  946. case TCKind._tk_enum:
  947. case TCKind._tk_value:
  948. return _memberCount;
  949. default:
  950. throw new BadKind();
  951. }
  952. }
  953. public String member_name(int index)
  954. throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
  955. {
  956. switch (_kind) {
  957. case tk_indirect:
  958. return indirectType().member_name(index);
  959. case TCKind._tk_except:
  960. case TCKind._tk_struct:
  961. case TCKind._tk_union:
  962. case TCKind._tk_enum:
  963. case TCKind._tk_value:
  964. try {
  965. return _memberNames[index];
  966. } catch (ArrayIndexOutOfBoundsException e) {
  967. throw new org.omg.CORBA.TypeCodePackage.Bounds();
  968. }
  969. default:
  970. throw new BadKind();
  971. }
  972. }
  973. public TypeCode member_type(int index)
  974. throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
  975. {
  976. switch (_kind) {
  977. case tk_indirect:
  978. return indirectType().member_type(index);
  979. case TCKind._tk_except:
  980. case TCKind._tk_struct:
  981. case TCKind._tk_union:
  982. case TCKind._tk_value:
  983. try {
  984. return _memberTypes[index];
  985. } catch (ArrayIndexOutOfBoundsException e) {
  986. throw new org.omg.CORBA.TypeCodePackage.Bounds();
  987. }
  988. default:
  989. throw new BadKind();
  990. }
  991. }
  992. public Any member_label(int index)
  993. throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
  994. {
  995. switch (_kind) {
  996. case tk_indirect:
  997. return indirectType().member_label(index);
  998. case TCKind._tk_union:
  999. try {
  1000. // _REVISIT_ Why create a new Any for this?
  1001. return new AnyImpl(_orb, _unionLabels[index]);
  1002. } catch (ArrayIndexOutOfBoundsException e) {
  1003. throw new org.omg.CORBA.TypeCodePackage.Bounds();
  1004. }
  1005. default:
  1006. throw new BadKind();
  1007. }
  1008. }
  1009. public TypeCode discriminator_type()
  1010. throws BadKind
  1011. {
  1012. switch (_kind) {
  1013. case tk_indirect:
  1014. return indirectType().discriminator_type();
  1015. case TCKind._tk_union:
  1016. return _discriminator;
  1017. default:
  1018. throw new BadKind();
  1019. }
  1020. }
  1021. public int default_index()
  1022. throws BadKind
  1023. {
  1024. switch (_kind) {
  1025. case tk_indirect:
  1026. return indirectType().default_index();
  1027. case TCKind._tk_union:
  1028. return _defaultIndex;
  1029. default:
  1030. throw new BadKind();
  1031. }
  1032. }
  1033. public int length()
  1034. throws BadKind
  1035. {
  1036. switch (_kind) {
  1037. case tk_indirect:
  1038. return indirectType().length();
  1039. case TCKind._tk_string:
  1040. case TCKind._tk_wstring:
  1041. case TCKind._tk_sequence:
  1042. case TCKind._tk_array:
  1043. return _length;
  1044. default:
  1045. throw new BadKind();
  1046. }
  1047. }
  1048. public TypeCode content_type()
  1049. throws BadKind
  1050. {
  1051. switch (_kind) {
  1052. case tk_indirect:
  1053. return indirectType().content_type();
  1054. case TCKind._tk_sequence:
  1055. return lazy_content_type();
  1056. case TCKind._tk_array:
  1057. case TCKind._tk_alias:
  1058. case TCKind._tk_value_box:
  1059. return _contentType;
  1060. default:
  1061. throw new BadKind();
  1062. }
  1063. }
  1064. public short fixed_digits() throws BadKind {
  1065. switch (_kind) {
  1066. case TCKind._tk_fixed:
  1067. return _digits;
  1068. default:
  1069. throw new BadKind();
  1070. }
  1071. }
  1072. public short fixed_scale() throws BadKind {
  1073. switch (_kind) {
  1074. case TCKind._tk_fixed:
  1075. return _scale;
  1076. default:
  1077. throw new BadKind();
  1078. }
  1079. }
  1080. public short member_visibility(int index) throws BadKind,
  1081. org.omg.CORBA.TypeCodePackage.Bounds {
  1082. switch (_kind) {
  1083. case tk_indirect:
  1084. return indirectType().member_visibility(index);
  1085. case TCKind._tk_value:
  1086. try {
  1087. return _memberAccess[index];
  1088. } catch (ArrayIndexOutOfBoundsException e) {
  1089. throw new org.omg.CORBA.TypeCodePackage.Bounds();
  1090. }
  1091. default:
  1092. throw new BadKind();
  1093. }
  1094. }
  1095. public short type_modifier() throws BadKind {
  1096. switch (_kind) {
  1097. case tk_indirect:
  1098. return indirectType().type_modifier();
  1099. case TCKind._tk_value:
  1100. return _type_modifier;
  1101. default:
  1102. throw new BadKind();
  1103. }
  1104. }
  1105. public TypeCode concrete_base_type() throws BadKind {
  1106. switch (_kind) {
  1107. case tk_indirect:
  1108. return indirectType().concrete_base_type();
  1109. case TCKind._tk_value:
  1110. return _concrete_base;
  1111. default:
  1112. throw new BadKind();
  1113. }
  1114. }
  1115. public void read_value(InputStream is) {
  1116. if (is instanceof TypeCodeReader) {
  1117. // hardly possible unless caller knows our "private" stream classes.
  1118. if (read_value_kind((TypeCodeReader)is))
  1119. read_value_body(is);
  1120. } else if (is instanceof CDRInputStream) {
  1121. WrapperInputStream wrapper = new WrapperInputStream((CDRInputStream)is);
  1122. //if (debug) System.out.println("Created WrapperInputStream " + wrapper +
  1123. // " with no parent");
  1124. if (read_value_kind((TypeCodeReader)wrapper))
  1125. read_value_body(wrapper);
  1126. } else {
  1127. read_value_kind(is);
  1128. read_value_body(is);
  1129. }
  1130. }
  1131. private void read_value_recursive(TypeCodeInputStream is) {
  1132. // don't wrap a CDRInputStream reading "inner" TypeCodes.
  1133. if (is instanceof TypeCodeReader) {
  1134. if (read_value_kind((TypeCodeReader)is))
  1135. read_value_body(is);
  1136. } else {
  1137. read_value_kind((InputStream)is);
  1138. read_value_body(is);
  1139. }
  1140. }
  1141. boolean read_value_kind(TypeCodeReader tcis)
  1142. {
  1143. _kind = tcis.read_long();
  1144. // Bug fix 5034649: allow for padding that precedes the typecode kind.
  1145. int myPosition = tcis.getTopLevelPosition()-4;
  1146. // check validity of kind
  1147. if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
  1148. throw wrapper.cannotMarshalBadTckind() ;
  1149. }
  1150. // Don't do any work if this is native
  1151. if (_kind == TCKind._tk_native)
  1152. throw wrapper.cannotMarshalNative() ;
  1153. // We have to remember the stream and position for EVERY type code
  1154. // in case some recursive or indirect type code references it.
  1155. TypeCodeReader topStream = tcis.getTopLevelStream();
  1156. if (_kind == tk_indirect) {
  1157. int streamOffset = tcis.read_long();
  1158. if (streamOffset > -4)
  1159. throw wrapper.invalidIndirection( new Integer(streamOffset) ) ;
  1160. // The encoding used for indirection is the same as that used for recursive ,
  1161. // TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
  1162. // (in units of octets) from the beginning of the long offset.
  1163. int topPos = tcis.getTopLevelPosition();
  1164. // substract 4 to get back to the beginning of the long offset.
  1165. int indirectTypePosition = topPos - 4 + streamOffset;
  1166. // Now we have to find the referenced type
  1167. // by its indirectTypePosition within topStream.
  1168. //if (debug) System.out.println(
  1169. // "TypeCodeImpl looking up indirection at position topPos " +
  1170. //topPos + " - 4 + offset " + streamOffset + " = " + indirectTypePosition);
  1171. TypeCodeImpl type = topStream.getTypeCodeAtPosition(indirectTypePosition);
  1172. if (type == null)
  1173. throw wrapper.indirectionNotFound( new Integer(indirectTypePosition) ) ;
  1174. setIndirectType(type);
  1175. return false;
  1176. }
  1177. topStream.addTypeCodeAtPosition(this, myPosition);
  1178. return true;
  1179. }
  1180. void read_value_kind(InputStream is) {
  1181. // unmarshal the kind
  1182. _kind = is.read_long();
  1183. // check validity of kind
  1184. if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
  1185. throw wrapper.cannotMarshalBadTckind() ;
  1186. }
  1187. // Don't do any work if this is native
  1188. if (_kind == TCKind._tk_native)
  1189. throw wrapper.cannotMarshalNative() ;
  1190. if (_kind == tk_indirect) {
  1191. throw wrapper.recursiveTypecodeError() ;
  1192. }
  1193. }
  1194. void read_value_body(InputStream is) {
  1195. // start unmarshaling the rest of the typecode, based on the
  1196. // encoding (empty, simple or complex).
  1197. switch (typeTable[_kind]) {
  1198. case EMPTY:
  1199. // nothing to unmarshal
  1200. break;
  1201. case SIMPLE:
  1202. switch (_kind) {
  1203. case TCKind._tk_string:
  1204. case TCKind._tk_wstring:
  1205. _length = is.read_long();
  1206. break;
  1207. case TCKind._tk_fixed:
  1208. _digits = is.read_ushort();
  1209. _scale = is.read_short();
  1210. break;
  1211. default:
  1212. throw wrapper.invalidSimpleTypecode() ;
  1213. }
  1214. break;
  1215. case COMPLEX:
  1216. {
  1217. TypeCodeInputStream _encap = TypeCodeInputStream.readEncapsulation(is,
  1218. is.orb());
  1219. switch(_kind) {
  1220. case TCKind._tk_objref:
  1221. case TCKind._tk_abstract_interface:
  1222. {
  1223. // get the repository id
  1224. setId(_encap.read_string());
  1225. // get the name
  1226. _name = _encap.read_string();
  1227. }
  1228. break;
  1229. case TCKind._tk_union:
  1230. {
  1231. // get the repository id
  1232. setId(_encap.read_string());
  1233. // get the name
  1234. _name = _encap.read_string();
  1235. // discriminant typecode
  1236. _discriminator = new TypeCodeImpl((ORB)is.orb());
  1237. _discriminator.read_value_recursive(_encap);
  1238. // default index
  1239. _defaultIndex = _encap.read_long();
  1240. // get the number of members
  1241. _memberCount = _encap.read_long();
  1242. // create arrays for the label values, names and types of members
  1243. _unionLabels = new AnyImpl[_memberCount];
  1244. _memberNames = new String[_memberCount];
  1245. _memberTypes = new TypeCodeImpl[_memberCount];
  1246. // read off label values, names and types
  1247. for (int i=0; i < _memberCount; i++) {
  1248. _unionLabels[i] = new AnyImpl((ORB)is.orb());
  1249. if (i == _defaultIndex)
  1250. // for the default case, read off the zero octet
  1251. _unionLabels[i].insert_octet(_encap.read_octet());
  1252. else {
  1253. switch (realType(_discriminator).kind().value()) {
  1254. case TCKind._tk_short:
  1255. _unionLabels[i].insert_short(_encap.read_short());
  1256. break;
  1257. case TCKind._tk_long:
  1258. _unionLabels[i].insert_long(_encap.read_long());
  1259. break;
  1260. case TCKind._tk_ushort:
  1261. _unionLabels[i].insert_ushort(_encap.read_short());
  1262. break;
  1263. case TCKind._tk_ulong:
  1264. _unionLabels[i].insert_ulong(_encap.read_long());
  1265. break;
  1266. case TCKind._tk_float:
  1267. _unionLabels[i].insert_float(_encap.read_float());
  1268. break;
  1269. case TCKind._tk_double:
  1270. _unionLabels[i].insert_double(_encap.read_double());
  1271. break;
  1272. case TCKind._tk_boolean:
  1273. _unionLabels[i].insert_boolean(_encap.read_boolean());
  1274. break;
  1275. case