1 /*
   2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.corba;
  27 
  28 import java.util.HashMap;
  29 import java.util.Map;
  30 import java.util.Iterator;
  31 import java.util.List;
  32 import java.util.Collections;
  33 import java.util.ArrayList;
  34 import java.io.IOException;
  35 import java.io.PrintStream;
  36 import java.io.ByteArrayOutputStream;
  37 import java.math.BigDecimal;
  38 import java.math.BigInteger;
  39 
  40 import org.omg.CORBA.TypeCode ;
  41 import org.omg.CORBA.StructMember ;
  42 import org.omg.CORBA.UnionMember ;
  43 import org.omg.CORBA.ValueMember ;
  44 import org.omg.CORBA.TCKind ;
  45 import org.omg.CORBA.Any ;
  46 import org.omg.CORBA.Principal ;
  47 import org.omg.CORBA.BAD_TYPECODE ;
  48 import org.omg.CORBA.BAD_PARAM ;
  49 import org.omg.CORBA.BAD_OPERATION ;
  50 import org.omg.CORBA.INTERNAL ;
  51 import org.omg.CORBA.MARSHAL ;
  52 import org.omg.CORBA.TypeCodePackage.BadKind ;
  53 import org.omg.CORBA_2_3.portable.InputStream;
  54 import org.omg.CORBA_2_3.portable.OutputStream;
  55 
  56 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  57 import com.sun.corba.se.spi.orb.ORB;
  58 import com.sun.corba.se.spi.logging.CORBALogDomains;
  59 
  60 import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
  61 import com.sun.corba.se.impl.encoding.MarshalInputStream;
  62 import com.sun.corba.se.impl.encoding.CodeSetConversion;
  63 import com.sun.corba.se.impl.encoding.CDRInputStream;
  64 import com.sun.corba.se.impl.encoding.CDROutputStream;
  65 import com.sun.corba.se.impl.encoding.TypeCodeInputStream;
  66 import com.sun.corba.se.impl.encoding.TypeCodeOutputStream;
  67 import com.sun.corba.se.impl.encoding.TypeCodeReader;
  68 import com.sun.corba.se.impl.encoding.WrapperInputStream;
  69 
  70 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  71 
  72 // no chance of subclasses, so no problems with runtime helper lookup
  73 public final class TypeCodeImpl extends TypeCode
  74 {
  75     //static final boolean debug = false;
  76 
  77     // the indirection TCKind, needed for recursive typecodes.
  78     protected static final int tk_indirect = 0xFFFFFFFF;
  79 
  80     // typecode encodings have three different categories that determine
  81     // how the encoding should be done.
  82 
  83     private static final int EMPTY = 0; // no parameters
  84     private static final int SIMPLE = 1;        // simple parameters.
  85     private static final int COMPLEX = 2; // complex parameters. need to
  86     // use CDR encapsulation for
  87     // parameters
  88 
  89     // a table storing the encoding category for the various typecodes.
  90 
  91     private static final int typeTable[] = {
  92         EMPTY,  // tk_null
  93         EMPTY,  // tk_void
  94         EMPTY,  // tk_short
  95         EMPTY,  // tk_long
  96         EMPTY,  // tk_ushort
  97         EMPTY,  // tk_ulong
  98         EMPTY,  // tk_float
  99         EMPTY,  // tk_double
 100         EMPTY,  // tk_boolean
 101         EMPTY,  // tk_char
 102         EMPTY,  // tk_octet
 103         EMPTY,  // tk_any
 104         EMPTY,  // tk_typecode
 105         EMPTY,  // tk_principal
 106         COMPLEX,        // tk_objref
 107         COMPLEX,        // tk_struct
 108         COMPLEX,        // tk_union
 109         COMPLEX,        // tk_enum
 110         SIMPLE, // tk_string
 111         COMPLEX,        // tk_sequence
 112         COMPLEX,        // tk_array
 113         COMPLEX,        // tk_alias
 114         COMPLEX,        // tk_except
 115         EMPTY,  // tk_longlong
 116         EMPTY,  // tk_ulonglong
 117         EMPTY,  // tk_longdouble
 118         EMPTY,  // tk_wchar
 119         SIMPLE, // tk_wstring
 120         SIMPLE, // tk_fixed
 121         COMPLEX,        // tk_value
 122         COMPLEX,        // tk_value_box
 123         COMPLEX,        // tk_native
 124         COMPLEX // tk_abstract_interface
 125     };
 126 
 127     // Maps TCKind values to names
 128     // This is also used in AnyImpl.
 129     static final String[] kindNames = {
 130         "null",
 131         "void",
 132         "short",
 133         "long",
 134         "ushort",
 135         "ulong",
 136         "float",
 137         "double",
 138         "boolean",
 139         "char",
 140         "octet",
 141         "any",
 142         "typecode",
 143         "principal",
 144         "objref",
 145         "struct",
 146         "union",
 147         "enum",
 148         "string",
 149         "sequence",
 150         "array",
 151         "alias",
 152         "exception",
 153         "longlong",
 154         "ulonglong",
 155         "longdouble",
 156         "wchar",
 157         "wstring",
 158         "fixed",
 159         "value",
 160         "valueBox",
 161         "native",
 162         "abstractInterface"
 163     };
 164 
 165     private int                 _kind           = 0;    // the typecode kind
 166 
 167     // data members for representing the various kinds of typecodes.
 168     private String          _id             = "";   // the typecode repository id
 169     private String          _name           = "";   // the typecode name
 170     private int             _memberCount    = 0;    // member count
 171     private String          _memberNames[]  = null; // names of members
 172     private TypeCodeImpl    _memberTypes[]  = null; // types of members
 173     private AnyImpl         _unionLabels[]  = null; // values of union labels
 174     private TypeCodeImpl    _discriminator  = null; // union discriminator type
 175     private int             _defaultIndex   = -1;   // union default index
 176     private int             _length         = 0;    // string/seq/array length
 177     private TypeCodeImpl    _contentType    = null; // seq/array/alias type
 178     // fixed
 179     private short           _digits         = 0;
 180     private short           _scale          = 0;
 181     // value type
 182     // _REVISIT_ We might want to keep references to the ValueMember classes
 183     // passed in at initialization instead of copying the relevant data.
 184     // Is the data immutable? What about StructMember, UnionMember etc.?
 185     private short           _type_modifier  = -1;   // VM_NONE, VM_CUSTOM,
 186     // VM_ABSTRACT, VM_TRUNCATABLE
 187     private TypeCodeImpl    _concrete_base  = null; // concrete base type
 188     private short           _memberAccess[] = null; // visibility of ValueMember
 189     // recursive sequence support
 190     private TypeCodeImpl    _parent         = null; // the enclosing type code
 191     private int             _parentOffset   = 0;    // the level of enclosure
 192     // recursive type code support
 193     private TypeCodeImpl    _indirectType   = null;
 194 
 195     // caches the byte buffer written in write_value for quick remarshaling...
 196     private byte[] outBuffer                = null;
 197     // ... but only if caching is enabled
 198     private boolean cachingEnabled          = false;
 199 
 200     // the ORB instance: may be instanceof ORBSingleton or ORB
 201     private ORB _orb;
 202     private ORBUtilSystemException wrapper ;
 203 
 204     ///////////////////////////////////////////////////////////////////////////
 205     // Constructors...
 206 
 207     public TypeCodeImpl(ORB orb)
 208     {
 209         // initialized to tk_null
 210         _orb = orb;
 211         wrapper = ORBUtilSystemException.get(
 212             (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PRESENTATION ) ;
 213     }
 214 
 215     public TypeCodeImpl(ORB orb, TypeCode tc)
 216     // to handle conversion of "remote" typecodes into "native" style.
 217     // also see the 'convertToNative(ORB orb, TypeCode tc)' function
 218     {
 219         this(orb) ;
 220 
 221         // This is a protection against misuse of this constructor.
 222         // Should only be used if tc is not an instance of this class!
 223         // Otherwise we run into problems with recursive/indirect type codes.
 224         // _REVISIT_ We should make this constructor private
 225         if (tc instanceof TypeCodeImpl) {
 226             TypeCodeImpl tci = (TypeCodeImpl)tc;
 227             if (tci._kind == tk_indirect)
 228                 throw wrapper.badRemoteTypecode() ;
 229             if (tci._kind == TCKind._tk_sequence && tci._contentType == null)
 230                 throw wrapper.badRemoteTypecode() ;
 231         }
 232 
 233         // set up kind
 234         _kind   = tc.kind().value();
 235 
 236         try {
 237             // set up parameters
 238             switch (_kind) {
 239             case TCKind._tk_value:
 240                 _type_modifier = tc.type_modifier();
 241                 // concrete base may be null
 242                 TypeCode tccb = tc.concrete_base_type();
 243                 if (tccb != null) {
 244                     _concrete_base = convertToNative(_orb, tccb);
 245                 } else {
 246                     _concrete_base = null;
 247                 }
 248                 //_memberAccess = tc._memberAccess;
 249                 // Need to reconstruct _memberAccess using member_count() and member_visibility()
 250                 _memberAccess = new short[tc.member_count()];
 251                 for (int i=0; i < tc.member_count(); i++) {
 252                     _memberAccess[i] = tc.member_visibility(i);
 253                 }
 254             case TCKind._tk_except:
 255             case TCKind._tk_struct:
 256             case TCKind._tk_union:
 257                 // set up member types
 258                 _memberTypes = new TypeCodeImpl[tc.member_count()];
 259                 for (int i=0; i < tc.member_count(); i++) {
 260                     _memberTypes[i] = convertToNative(_orb, tc.member_type(i));
 261                     _memberTypes[i].setParent(this);
 262                 }
 263             case TCKind._tk_enum:
 264                 // set up member names
 265                 _memberNames = new String[tc.member_count()];
 266                 for (int i=0; i < tc.member_count(); i++) {
 267                     _memberNames[i] = tc.member_name(i);
 268                 }
 269                 // set up member count
 270                 _memberCount = tc.member_count();
 271             case TCKind._tk_objref:
 272             case TCKind._tk_alias:
 273             case TCKind._tk_value_box:
 274             case TCKind._tk_native:
 275             case TCKind._tk_abstract_interface:
 276                 setId(tc.id());
 277                 _name = tc.name();
 278                 break;
 279             }
 280 
 281             // set up stuff for unions
 282             switch (_kind) {
 283             case TCKind._tk_union:
 284                 _discriminator = convertToNative(_orb, tc.discriminator_type());
 285                 _defaultIndex  = tc.default_index();
 286                 _unionLabels = new AnyImpl[_memberCount];
 287                 for (int i=0; i < _memberCount; i++)
 288                     _unionLabels[i] = new AnyImpl(_orb, tc.member_label(i));
 289                 break;
 290             }
 291 
 292             // set up length
 293             switch (_kind) {
 294             case TCKind._tk_string:
 295             case TCKind._tk_wstring:
 296             case TCKind._tk_sequence:
 297             case TCKind._tk_array:
 298                 _length = tc.length();
 299             }
 300 
 301             // set up content type
 302             switch (_kind) {
 303             case TCKind._tk_sequence:
 304             case TCKind._tk_array:
 305             case TCKind._tk_alias:
 306             case TCKind._tk_value_box:
 307                 _contentType = convertToNative(_orb, tc.content_type());
 308             }
 309         } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
 310         // dont have to worry about these since code ensures we dont step
 311         // out of bounds.
 312     }
 313 
 314     public TypeCodeImpl(ORB orb, int creationKind)
 315     // for primitive types
 316     {
 317         this(orb);
 318 
 319         // private API. dont bother checking that
 320         //     (creationKind < 0 || creationKind > typeTable.length)
 321 
 322         _kind = creationKind;
 323 
 324         // do initialization for special cases
 325         switch (_kind) {
 326         case TCKind._tk_objref:
 327             {
 328                 // this is being used to create typecode for CORBA::Object
 329                 setId("IDL:omg.org/CORBA/Object:1.0");
 330                 _name = "Object";
 331                 break;
 332             }
 333 
 334         case TCKind._tk_string:
 335         case TCKind._tk_wstring:
 336             {
 337                 _length =0;
 338                 break;
 339             }
 340 
 341         case TCKind._tk_value:
 342             {
 343                 _concrete_base = null;
 344                 break;
 345             }
 346         }
 347     }
 348 
 349     public TypeCodeImpl(ORB orb,
 350                         int creationKind,
 351                         String id,
 352                         String name,
 353                         StructMember[] members)
 354                         // for structs and exceptions
 355     {
 356         this(orb);
 357 
 358         if ((creationKind == TCKind._tk_struct) || (creationKind == TCKind._tk_except)) {
 359             _kind               = creationKind;
 360             setId(id);
 361             _name               = name;
 362             _memberCount        = members.length;
 363 
 364             _memberNames = new String[_memberCount];
 365             _memberTypes = new TypeCodeImpl[_memberCount];
 366 
 367             for (int i = 0 ; i < _memberCount ; i++) {
 368                 _memberNames[i] = members[i].name;
 369                 _memberTypes[i] = convertToNative(_orb, members[i].type);
 370                 _memberTypes[i].setParent(this);
 371             }
 372         } // else initializes to null
 373     }
 374 
 375     public TypeCodeImpl(ORB orb,
 376                         int creationKind,
 377                         String id,
 378                         String name,
 379                         TypeCode discriminator_type,
 380                         UnionMember[] members)
 381                         // for unions
 382     {
 383         this(orb) ;
 384 
 385         if (creationKind == TCKind._tk_union) {
 386             _kind               = creationKind;
 387             setId(id);
 388             _name               = name;
 389             _memberCount        = members.length;
 390             _discriminator      = convertToNative(_orb, discriminator_type);
 391 
 392             _memberNames = new String[_memberCount];
 393             _memberTypes = new TypeCodeImpl[_memberCount];
 394             _unionLabels = new AnyImpl[_memberCount];
 395 
 396             for (int i = 0 ; i < _memberCount ; i++) {
 397                 _memberNames[i] = members[i].name;
 398                 _memberTypes[i] = convertToNative(_orb, members[i].type);
 399                 _memberTypes[i].setParent(this);
 400                 _unionLabels[i] = new AnyImpl(_orb, members[i].label);
 401                 // check whether this is the default branch.
 402                 if (_unionLabels[i].type().kind() == TCKind.tk_octet) {
 403                     if (_unionLabels[i].extract_octet() == (byte)0) {
 404                         _defaultIndex = i;
 405                     }
 406                 }
 407             }
 408         } // else initializes to null
 409     }
 410 
 411     public TypeCodeImpl(ORB orb,
 412                         int creationKind,
 413                         String id,
 414                         String name,
 415                         short type_modifier,
 416                         TypeCode concrete_base,
 417                         ValueMember[] members)
 418                         // for value types
 419     {
 420         this(orb) ;
 421 
 422         if (creationKind == TCKind._tk_value) {
 423             _kind               = creationKind;
 424             setId(id);
 425             _name               = name;
 426             _type_modifier      = type_modifier;
 427             if (concrete_base != null) {
 428                 _concrete_base = convertToNative(_orb, concrete_base);
 429             }
 430             _memberCount        = members.length;
 431 
 432             _memberNames = new String[_memberCount];
 433             _memberTypes = new TypeCodeImpl[_memberCount];
 434             _memberAccess = new short[_memberCount];
 435 
 436             for (int i = 0 ; i < _memberCount ; i++) {
 437                 _memberNames[i] = members[i].name;
 438                 _memberTypes[i] = convertToNative(_orb, members[i].type);
 439                 _memberTypes[i].setParent(this);
 440                 _memberAccess[i] = members[i].access;
 441             }
 442         } // else initializes to null
 443     }
 444 
 445 
 446     public TypeCodeImpl(ORB orb,
 447                         int creationKind,
 448                         String id,
 449                         String name,
 450                         String[] members)
 451                         // for enums
 452     {
 453         this(orb) ;
 454 
 455         if (creationKind == TCKind._tk_enum)
 456             {
 457                 _kind           = creationKind;
 458                 setId(id);
 459                 _name           = name;
 460                 _memberCount    = members.length;
 461 
 462                 _memberNames = new String[_memberCount];
 463 
 464                 for (int i = 0 ; i < _memberCount ; i++)
 465                     _memberNames[i] = members[i];
 466             } // else initializes to null
 467     }
 468 
 469     public TypeCodeImpl(ORB orb,
 470                         int creationKind,
 471                         String id,
 472                         String name,
 473                         TypeCode original_type)
 474                         // for aliases and value boxes
 475     {
 476         this(orb) ;
 477 
 478         if ( creationKind == TCKind._tk_alias || creationKind == TCKind._tk_value_box )
 479             {
 480                 _kind           = creationKind;
 481                 setId(id);
 482                 _name           = name;
 483                 _contentType    = convertToNative(_orb, original_type);
 484             }
 485         // else initializes to null
 486 
 487     }
 488 
 489     public TypeCodeImpl(ORB orb,
 490                         int creationKind,
 491                         String id,
 492                         String name)
 493     {
 494         this(orb) ;
 495 
 496         if (creationKind == TCKind._tk_objref ||
 497             creationKind == TCKind._tk_native ||
 498             creationKind == TCKind._tk_abstract_interface)
 499             {
 500                 _kind           = creationKind;
 501                 setId(id);
 502                 _name           = name;
 503             } // else initializes to null
 504     }
 505 
 506 
 507     public TypeCodeImpl(ORB orb,
 508                         int creationKind,
 509                         int bound)
 510                         // for strings
 511     {
 512         this(orb) ;
 513 
 514         if (bound < 0)
 515             throw wrapper.negativeBounds() ;
 516 
 517         if ((creationKind == TCKind._tk_string) || (creationKind == TCKind._tk_wstring)) {
 518             _kind               = creationKind;
 519             _length             = bound;
 520         } // else initializes to null
 521     }
 522 
 523     public TypeCodeImpl(ORB orb,
 524                         int creationKind,
 525                         int bound,
 526                         TypeCode element_type)
 527                         // for sequences and arrays
 528     {
 529         this(orb) ;
 530 
 531         if ( creationKind == TCKind._tk_sequence || creationKind == TCKind._tk_array ) {
 532             _kind               = creationKind;
 533             _length             = bound;
 534             _contentType        = convertToNative(_orb, element_type);
 535         } // else initializes to null
 536     }
 537 
 538     public TypeCodeImpl(ORB orb,
 539                         int creationKind,
 540                         int bound,
 541                         int offset)
 542                         // for recursive sequences
 543     {
 544         this(orb) ;
 545 
 546         if (creationKind == TCKind._tk_sequence) {
 547             _kind               = creationKind;
 548             _length             = bound;
 549             _parentOffset       = offset;
 550         } // else initializes to null
 551     }
 552 
 553     public TypeCodeImpl(ORB orb,
 554                         String id)
 555                         // for recursive type codes
 556     {
 557         this(orb) ;
 558 
 559         _kind   = tk_indirect;
 560         // This is the type code of the type we stand in for, not our own.
 561         _id             = id;
 562         // Try to resolve it now. May return null in which case
 563         // we try again later (see indirectType()).
 564         tryIndirectType();
 565     }
 566 
 567     public TypeCodeImpl(ORB orb,
 568                         int creationKind,
 569                         short digits,
 570                         short scale)
 571                         // for fixed
 572     {
 573         this(orb) ;
 574 
 575         //if (digits < 1 || digits > 31)
 576         //throw new BAD_TYPECODE();
 577 
 578         if (creationKind == TCKind._tk_fixed) {
 579             _kind               = creationKind;
 580             _digits             = digits;
 581             _scale              = scale;
 582         } // else initializes to null
 583     }
 584 
 585     ///////////////////////////////////////////////////////////////////////////
 586     // Other creation functions...
 587 
 588     // Optimization:
 589     // If we checked for and returned constant primitive typecodes
 590     // here we could reduce object creation and also enable more
 591     // efficient typecode comparisons for primitive typecodes.
 592     //
 593     protected static TypeCodeImpl convertToNative(ORB orb,
 594                                                   TypeCode tc)
 595     {
 596         if (tc instanceof TypeCodeImpl)
 597             return (TypeCodeImpl) tc;
 598         else
 599             return new TypeCodeImpl(orb, tc);
 600     }
 601 
 602     public static CDROutputStream newOutputStream(ORB orb) {
 603         TypeCodeOutputStream tcos = new TypeCodeOutputStream((ORB)orb);
 604         //if (debug) System.out.println("Created TypeCodeOutputStream " + tcos +
 605         // " with no parent");
 606         return tcos;
 607     }
 608 
 609     // Support for indirect/recursive type codes
 610 
 611     private TypeCodeImpl indirectType() {
 612         _indirectType = tryIndirectType();
 613         if (_indirectType == null) {
 614             // Nothing we can do about that.
 615             throw wrapper.unresolvedRecursiveTypecode() ;
 616         }
 617         return _indirectType;
 618     }
 619 
 620     private TypeCodeImpl tryIndirectType() {
 621         // Assert that _kind == tk_indirect
 622         if (_indirectType != null)
 623             return _indirectType;
 624 
 625         setIndirectType(_orb.getTypeCode(_id));
 626 
 627         return _indirectType;
 628     }
 629 
 630     private void setIndirectType(TypeCodeImpl newType) {
 631         _indirectType = newType;
 632         if (_indirectType != null) {
 633             try {
 634                 _id = _indirectType.id();
 635             } catch (BadKind e) {
 636                 // can't happen
 637                 throw wrapper.badkindCannotOccur() ;
 638             }
 639         }
 640     }
 641 
 642     private void setId(String newID) {
 643         _id = newID;
 644         if (_orb instanceof TypeCodeFactory) {
 645             ((TypeCodeFactory)_orb).setTypeCode(_id, this);
 646         }
 647         // check whether return value != this which would indicate that the
 648         // repository id isn't unique.
 649     }
 650 
 651     private void setParent(TypeCodeImpl parent) {
 652         _parent = parent;
 653     }
 654 
 655     private TypeCodeImpl getParentAtLevel(int level) {
 656         if (level == 0)
 657             return this;
 658 
 659         if (_parent == null)
 660             throw wrapper.unresolvedRecursiveTypecode() ;
 661 
 662         return _parent.getParentAtLevel(level - 1);
 663     }
 664 
 665     private TypeCodeImpl lazy_content_type() {
 666         if (_contentType == null) {
 667             if (_kind == TCKind._tk_sequence && _parentOffset > 0 && _parent != null) {
 668                 // This is an unresolved recursive sequence tc.
 669                 // Try to resolve it now if the hierarchy is complete.
 670                 TypeCodeImpl realParent = getParentAtLevel(_parentOffset);
 671                 if (realParent != null && realParent._id != null) {
 672                     // Create a recursive type code object as the content type.
 673                     // This is when the recursive sequence typecode morphes
 674                     // into a sequence typecode containing a recursive typecode.
 675                     _contentType = new TypeCodeImpl((ORB)_orb, realParent._id);
 676                 }
 677             }
 678         }
 679         return _contentType;
 680     }
 681 
 682     // Other private functions
 683 
 684     private TypeCode realType(TypeCode aType) {
 685         TypeCode realType = aType;
 686         try {
 687             // Note: Indirect types are handled in kind() method
 688             while (realType.kind().value() == TCKind._tk_alias) {
 689                 realType = realType.content_type();
 690             }
 691         } catch (BadKind bad) {
 692             // impossible
 693             throw wrapper.badkindCannotOccur() ;
 694         }
 695         return realType;
 696     }
 697 
 698     ///////////////////////////////////////////////////////////////////////////
 699     // TypeCode operations
 700 
 701     public final boolean equal(TypeCode tc)
 702     // _REVISIT_ for all optional names/ids, we might want to check that
 703     // they are equal in case both are non-nil.
 704     {
 705         if (tc == this)
 706             return true;
 707 
 708         try {
 709 
 710             if (_kind == tk_indirect) {
 711                 //return indirectType().equal(tc);
 712                 if (_id != null && tc.id() != null)
 713                     return _id.equals(tc.id());
 714                 return (_id == null && tc.id() == null);
 715             }
 716 
 717             // make sure kinds are identical.
 718             if (_kind != tc.kind().value()) {
 719                 return false;
 720             }
 721 
 722             switch (typeTable[_kind]) {
 723             case EMPTY:
 724                 // no parameters to check.
 725                 return true;
 726 
 727             case SIMPLE:
 728                 switch (_kind) {
 729                 case TCKind._tk_string:
 730                 case TCKind._tk_wstring:
 731                     // check for bound.
 732                     return (_length == tc.length());
 733 
 734                 case TCKind._tk_fixed:
 735                     return (_digits == tc.fixed_digits() && _scale == tc.fixed_scale());
 736                 default:
 737                     return false;
 738                 }
 739 
 740             case COMPLEX:
 741 
 742                 switch(_kind) {
 743 
 744                 case TCKind._tk_objref:
 745                     {
 746                         // check for logical id.
 747                         if (_id.compareTo(tc.id()) == 0) {
 748                             return true;
 749                         }
 750 
 751                         if (_id.compareTo(
 752                             (_orb.get_primitive_tc(_kind)).id()) == 0)
 753                         {
 754                             return true;
 755                         }
 756 
 757                         if (tc.id().compareTo(
 758                             (_orb.get_primitive_tc(_kind)).id()) == 0)
 759                         {
 760                             return true;
 761                         }
 762 
 763                         return false;
 764                     }
 765 
 766                 case TCKind._tk_native:
 767                 case TCKind._tk_abstract_interface:
 768                     {
 769                         // check for logical id.
 770                         if (_id.compareTo(tc.id()) != 0) {
 771                             return false;
 772 
 773                         }
 774                         // ignore name since its optional.
 775                         return true;
 776                     }
 777 
 778                 case TCKind._tk_struct:
 779                 case TCKind._tk_except:
 780                     {
 781                         // check for member count
 782                         if (_memberCount != tc.member_count())
 783                             return false;
 784                         // check for repository id
 785                         if (_id.compareTo(tc.id()) != 0)
 786                             return false;
 787                         // check for member types.
 788                         for (int i = 0 ; i < _memberCount ; i++)
 789                             if (! _memberTypes[i].equal(tc.member_type(i)))
 790                                 return false;
 791                         // ignore id and names since those are optional.
 792                         return true;
 793                     }
 794 
 795                 case TCKind._tk_union:
 796                     {
 797                         // check for member count
 798                         if (_memberCount != tc.member_count())
 799                             return false;
 800                         // check for repository id
 801                         if (_id.compareTo(tc.id()) != 0)
 802                             return false;
 803                         // check for default index
 804                         if (_defaultIndex != tc.default_index())
 805                             return false;
 806                         // check for discriminator type
 807                         if (!_discriminator.equal(tc.discriminator_type()))
 808                             return false;
 809                         // check for label types and values
 810                         for (int i = 0 ; i < _memberCount ; i++)
 811                             if (! _unionLabels[i].equal(tc.member_label(i)))
 812                                 return false;
 813                         // check for branch types
 814                         for (int i = 0 ; i < _memberCount ; i++)
 815                             if (! _memberTypes[i].equal(tc.member_type(i)))
 816                                 return false;
 817                         // ignore id and names since those are optional.
 818                         return true;
 819                     }
 820 
 821                 case TCKind._tk_enum:
 822                     {
 823                         // check for repository id
 824                         if (_id.compareTo(tc.id()) != 0)
 825                             return false;
 826                         // check member count
 827                         if (_memberCount != tc.member_count())
 828                             return false;
 829                         // ignore names since those are optional.
 830                         return true;
 831                     }
 832 
 833                 case TCKind._tk_sequence:
 834                 case TCKind._tk_array:
 835                     {
 836                         // check bound/length
 837                         if (_length != tc.length()) {
 838                             return false;
 839                         }
 840                         // check content type
 841                         if (! lazy_content_type().equal(tc.content_type())) {
 842                             return false;
 843                         }
 844                         // ignore id and name since those are optional.
 845                         return true;
 846                     }
 847 
 848                 case TCKind._tk_value:
 849                     {
 850                         // check for member count
 851                         if (_memberCount != tc.member_count())
 852                             return false;
 853                         // check for repository id
 854                         if (_id.compareTo(tc.id()) != 0)
 855                             return false;
 856                         // check for member types.
 857                         for (int i = 0 ; i < _memberCount ; i++)
 858                             if (_memberAccess[i] != tc.member_visibility(i) ||
 859                                 ! _memberTypes[i].equal(tc.member_type(i)))
 860                                 return false;
 861                         if (_type_modifier == tc.type_modifier())
 862                             return false;
 863                         // concrete_base may be null
 864                         TypeCode tccb = tc.concrete_base_type();
 865                         if ((_concrete_base == null && tccb != null) ||
 866                             (_concrete_base != null && tccb == null) ||
 867                             ! _concrete_base.equal(tccb))
 868                         {
 869                             return false;
 870                         }
 871                         // ignore id and names since those are optional.
 872                         return true;
 873                     }
 874 
 875                 case TCKind._tk_alias:
 876                 case TCKind._tk_value_box:
 877                     {
 878                         // check for repository id
 879                         if (_id.compareTo(tc.id()) != 0) {
 880                             return false;
 881                         }
 882                         // check for equality with the true type
 883                         return _contentType.equal(tc.content_type());
 884                     }
 885                 }
 886             }
 887         } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
 888         // dont have to worry about these since the code ensures these dont
 889         // arise.
 890         return false;
 891     }
 892 
 893     /**
 894     * The equivalent operation is used by the ORB when determining type equivalence
 895     * for values stored in an IDL any.
 896     */
 897     public boolean equivalent(TypeCode tc) {
 898         if (tc == this) {
 899             return true;
 900         }
 901 
 902         // If the result of the kind operation on either TypeCode is tk_alias, recursively
 903         // replace the TypeCode with the result of calling content_type, until the kind
 904         // is no longer tk_alias.
 905         // Note: Always resolve indirect types first!
 906         TypeCode myRealType = (_kind == tk_indirect ? indirectType() : this);
 907         myRealType = realType(myRealType);
 908         TypeCode otherRealType = realType(tc);
 909 
 910         // If results of the kind operation on each typecode differ,
 911         // equivalent returns false.
 912         if (myRealType.kind().value() != otherRealType.kind().value()) {
 913             return false;
 914         }
 915 
 916         String myID = null;
 917         String otherID = null;
 918         try {
 919             myID = this.id();
 920             otherID = tc.id();
 921             // At this point the id operation is valid for both TypeCodes.
 922 
 923             // Return true if the results of id for both TypeCodes are non-empty strings
 924             // and both strings are equal.
 925             // If both ids are non-empty but are not equal, then equivalent returns FALSE.
 926             if (myID != null && otherID != null) {
 927                 return (myID.equals(otherID));
 928             }
 929         } catch (BadKind e) {
 930             // id operation is not valid for either or both TypeCodes
 931         }
 932 
 933         // If either or both id is an empty string, or the TypeCode kind does not support
 934         // the id operation, perform a structural comparison of the TypeCodes.
 935 
 936         int myKind = myRealType.kind().value();
 937         try {
 938             if (myKind == TCKind._tk_struct ||
 939                 myKind == TCKind._tk_union ||
 940                 myKind == TCKind._tk_enum ||
 941                 myKind == TCKind._tk_except ||
 942                 myKind == TCKind._tk_value)
 943             {
 944                 if (myRealType.member_count() != otherRealType.member_count())
 945                     return false;
 946             }
 947             if (myKind == TCKind._tk_union)
 948             {
 949                 if (myRealType.default_index() != otherRealType.default_index())
 950                     return false;
 951             }
 952             if (myKind == TCKind._tk_string ||
 953                 myKind == TCKind._tk_wstring ||
 954                 myKind == TCKind._tk_sequence ||
 955                 myKind == TCKind._tk_array)
 956             {
 957                 if (myRealType.length() != otherRealType.length())
 958                     return false;
 959             }
 960             if (myKind == TCKind._tk_fixed)
 961             {
 962                 if (myRealType.fixed_digits() != otherRealType.fixed_digits() ||
 963                     myRealType.fixed_scale() != otherRealType.fixed_scale())
 964                     return false;
 965             }
 966             if (myKind == TCKind._tk_union)
 967             {
 968                 for (int i=0; i<myRealType.member_count(); i++) {
 969                     if (myRealType.member_label(i) != otherRealType.member_label(i))
 970                         return false;
 971                 }
 972                 if ( ! myRealType.discriminator_type().equivalent(
 973                     otherRealType.discriminator_type()))
 974                     return false;
 975             }
 976             if (myKind == TCKind._tk_alias ||
 977                 myKind == TCKind._tk_value_box ||
 978                 myKind == TCKind._tk_sequence ||
 979                 myKind == TCKind._tk_array)
 980             {
 981                 if ( ! myRealType.content_type().equivalent(otherRealType.content_type()))
 982                     return false;
 983             }
 984             if (myKind == TCKind._tk_struct ||
 985                 myKind == TCKind._tk_union ||
 986                 myKind == TCKind._tk_except ||
 987                 myKind == TCKind._tk_value)
 988             {
 989                 for (int i=0; i<myRealType.member_count(); i++) {
 990                     if ( ! myRealType.member_type(i).equivalent(
 991                         otherRealType.member_type(i)))
 992                         return false;
 993                 }
 994             }
 995         } catch (BadKind e) {
 996             // impossible if we checked correctly above
 997             throw wrapper.badkindCannotOccur() ;
 998         } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
 999             // impossible if we checked correctly above
1000             throw wrapper.boundsCannotOccur() ;
1001         }
1002 
1003         // Structural comparison succeeded!
1004         return true;
1005     }
1006 
1007     public TypeCode get_compact_typecode() {
1008         // _REVISIT_ It isn't clear whether this method should operate on this or a copy.
1009         // For now just return this unmodified because the name and member_name fields
1010         // aren't used for comparison anyways.
1011         return this;
1012     }
1013 
1014     public TCKind kind()
1015     {
1016         if (_kind == tk_indirect)
1017             return indirectType().kind();
1018         return TCKind.from_int(_kind);
1019     }
1020 
1021     public boolean is_recursive()
1022     {
1023         // Recursive is the only form of indirect type codes right now.
1024         // Indirection can also be used for repeated type codes.
1025         return (_kind == tk_indirect);
1026     }
1027 
1028     public String id()
1029         throws BadKind
1030     {
1031         switch (_kind) {
1032         case tk_indirect:
1033             //return indirectType().id(); // same as _id
1034         case TCKind._tk_except:
1035         case TCKind._tk_objref:
1036         case TCKind._tk_struct:
1037         case TCKind._tk_union:
1038         case TCKind._tk_enum:
1039         case TCKind._tk_alias:
1040         case TCKind._tk_value:
1041         case TCKind._tk_value_box:
1042         case TCKind._tk_native:
1043         case TCKind._tk_abstract_interface:
1044             // exception and objref typecodes must have a repository id.
1045             // structs, unions, enums, and aliases may or may not.
1046             return _id;
1047         default:
1048             // all other typecodes throw the BadKind exception.
1049             throw new BadKind();
1050         }
1051     }
1052 
1053     public String name()
1054         throws BadKind
1055     {
1056         switch (_kind) {
1057         case tk_indirect:
1058             return indirectType().name();
1059         case TCKind._tk_except:
1060         case TCKind._tk_objref:
1061         case TCKind._tk_struct:
1062         case TCKind._tk_union:
1063         case TCKind._tk_enum:
1064         case TCKind._tk_alias:
1065         case TCKind._tk_value:
1066         case TCKind._tk_value_box:
1067         case TCKind._tk_native:
1068         case TCKind._tk_abstract_interface:
1069             return _name;
1070         default:
1071             throw new BadKind();
1072         }
1073     }
1074 
1075     public int member_count()
1076         throws BadKind
1077     {
1078         switch (_kind) {
1079         case tk_indirect:
1080             return indirectType().member_count();
1081         case TCKind._tk_except:
1082         case TCKind._tk_struct:
1083         case TCKind._tk_union:
1084         case TCKind._tk_enum:
1085         case TCKind._tk_value:
1086             return _memberCount;
1087         default:
1088             throw new BadKind();
1089         }
1090     }
1091 
1092     public String member_name(int index)
1093         throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1094     {
1095         switch (_kind) {
1096         case tk_indirect:
1097             return indirectType().member_name(index);
1098         case TCKind._tk_except:
1099         case TCKind._tk_struct:
1100         case TCKind._tk_union:
1101         case TCKind._tk_enum:
1102         case TCKind._tk_value:
1103             try {
1104                 return _memberNames[index];
1105             } catch (ArrayIndexOutOfBoundsException e) {
1106                 throw new org.omg.CORBA.TypeCodePackage.Bounds();
1107             }
1108         default:
1109             throw new BadKind();
1110         }
1111     }
1112 
1113     public TypeCode member_type(int index)
1114         throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1115     {
1116         switch (_kind) {
1117         case tk_indirect:
1118             return indirectType().member_type(index);
1119         case TCKind._tk_except:
1120         case TCKind._tk_struct:
1121         case TCKind._tk_union:
1122         case TCKind._tk_value:
1123             try {
1124                 return _memberTypes[index];
1125             } catch (ArrayIndexOutOfBoundsException e) {
1126                 throw new org.omg.CORBA.TypeCodePackage.Bounds();
1127             }
1128         default:
1129             throw new BadKind();
1130         }
1131     }
1132 
1133     public Any member_label(int index)
1134         throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1135     {
1136         switch (_kind) {
1137         case tk_indirect:
1138             return indirectType().member_label(index);
1139         case TCKind._tk_union:
1140             try {
1141                 // _REVISIT_ Why create a new Any for this?
1142                 return new AnyImpl(_orb, _unionLabels[index]);
1143             } catch (ArrayIndexOutOfBoundsException e) {
1144                 throw new org.omg.CORBA.TypeCodePackage.Bounds();
1145             }
1146         default:
1147             throw new BadKind();
1148         }
1149     }
1150 
1151     public TypeCode discriminator_type()
1152         throws BadKind
1153     {
1154         switch (_kind) {
1155         case tk_indirect:
1156             return indirectType().discriminator_type();
1157         case TCKind._tk_union:
1158             return _discriminator;
1159         default:
1160             throw new BadKind();
1161         }
1162     }
1163 
1164     public int default_index()
1165         throws BadKind
1166     {
1167         switch (_kind) {
1168         case tk_indirect:
1169             return indirectType().default_index();
1170         case TCKind._tk_union:
1171             return _defaultIndex;
1172         default:
1173             throw new BadKind();
1174         }
1175     }
1176 
1177     public int length()
1178         throws BadKind
1179     {
1180         switch (_kind) {
1181         case tk_indirect:
1182             return indirectType().length();
1183         case TCKind._tk_string:
1184         case TCKind._tk_wstring:
1185         case TCKind._tk_sequence:
1186         case TCKind._tk_array:
1187             return _length;
1188         default:
1189             throw new BadKind();
1190         }
1191     }
1192 
1193     public TypeCode content_type()
1194         throws BadKind
1195     {
1196         switch (_kind) {
1197         case tk_indirect:
1198             return indirectType().content_type();
1199         case TCKind._tk_sequence:
1200             return lazy_content_type();
1201         case TCKind._tk_array:
1202         case TCKind._tk_alias:
1203         case TCKind._tk_value_box:
1204             return _contentType;
1205         default:
1206             throw new BadKind();
1207         }
1208     }
1209 
1210     public short fixed_digits() throws BadKind {
1211         switch (_kind) {
1212         case TCKind._tk_fixed:
1213             return _digits;
1214         default:
1215             throw new BadKind();
1216         }
1217     }
1218 
1219     public short fixed_scale() throws BadKind {
1220         switch (_kind) {
1221         case TCKind._tk_fixed:
1222             return _scale;
1223         default:
1224             throw new BadKind();
1225         }
1226     }
1227 
1228     public short member_visibility(int index) throws BadKind,
1229         org.omg.CORBA.TypeCodePackage.Bounds {
1230         switch (_kind) {
1231         case tk_indirect:
1232             return indirectType().member_visibility(index);
1233         case TCKind._tk_value:
1234             try {
1235                 return _memberAccess[index];
1236             } catch (ArrayIndexOutOfBoundsException e) {
1237                 throw new org.omg.CORBA.TypeCodePackage.Bounds();
1238             }
1239         default:
1240             throw new BadKind();
1241         }
1242     }
1243 
1244     public short type_modifier() throws BadKind {
1245         switch (_kind) {
1246         case tk_indirect:
1247             return indirectType().type_modifier();
1248         case TCKind._tk_value:
1249             return _type_modifier;
1250         default:
1251             throw new BadKind();
1252         }
1253     }
1254 
1255     public TypeCode concrete_base_type() throws BadKind {
1256         switch (_kind) {
1257         case tk_indirect:
1258             return indirectType().concrete_base_type();
1259         case TCKind._tk_value:
1260             return _concrete_base;
1261         default:
1262             throw new BadKind();
1263         }
1264     }
1265 
1266     public void read_value(InputStream is) {
1267         if (is instanceof TypeCodeReader) {
1268             // hardly possible unless caller knows our "private" stream classes.
1269             if (read_value_kind((TypeCodeReader)is))
1270                 read_value_body(is);
1271         } else if (is instanceof CDRInputStream) {
1272             WrapperInputStream wrapper = new WrapperInputStream((CDRInputStream)is);
1273             //if (debug) System.out.println("Created WrapperInputStream " + wrapper +
1274             // " with no parent");
1275             if (read_value_kind((TypeCodeReader)wrapper))
1276                 read_value_body(wrapper);
1277         } else {
1278             read_value_kind(is);
1279             read_value_body(is);
1280         }
1281     }
1282 
1283     private void read_value_recursive(TypeCodeInputStream is) {
1284         // don't wrap a CDRInputStream reading "inner" TypeCodes.
1285         if (is instanceof TypeCodeReader) {
1286             if (read_value_kind((TypeCodeReader)is))
1287                 read_value_body(is);
1288         } else {
1289             read_value_kind((InputStream)is);
1290             read_value_body(is);
1291         }
1292     }
1293 
1294     boolean read_value_kind(TypeCodeReader tcis)
1295     {
1296         _kind = tcis.read_long();
1297 
1298         // Bug fix 5034649: allow for padding that precedes the typecode kind.
1299         int myPosition = tcis.getTopLevelPosition()-4;
1300 
1301         // check validity of kind
1302         if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
1303             throw wrapper.cannotMarshalBadTckind() ;
1304         }
1305 
1306         // Don't do any work if this is native
1307         if (_kind == TCKind._tk_native)
1308             throw wrapper.cannotMarshalNative() ;
1309 
1310         // We have to remember the stream and position for EVERY type code
1311         // in case some recursive or indirect type code references it.
1312         TypeCodeReader topStream = tcis.getTopLevelStream();
1313 
1314         if (_kind == tk_indirect) {
1315             int streamOffset = tcis.read_long();
1316             if (streamOffset > -4)
1317                 throw wrapper.invalidIndirection( new Integer(streamOffset) ) ;
1318 
1319             // The encoding used for indirection is the same as that used for recursive ,
1320             // TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
1321             // (in units of octets) from the beginning of the long offset.
1322             int topPos = tcis.getTopLevelPosition();
1323             // substract 4 to get back to the beginning of the long offset.
1324             int indirectTypePosition = topPos - 4 + streamOffset;
1325 
1326             // Now we have to find the referenced type
1327             // by its indirectTypePosition within topStream.
1328             //if (debug) System.out.println(
1329             // "TypeCodeImpl looking up indirection at position topPos " +
1330             //topPos + " - 4 + offset " + streamOffset + " = " + indirectTypePosition);
1331             TypeCodeImpl type = topStream.getTypeCodeAtPosition(indirectTypePosition);
1332             if (type == null)
1333                 throw wrapper.indirectionNotFound( new Integer(indirectTypePosition) ) ;
1334             setIndirectType(type);
1335             return false;
1336         }
1337 
1338         topStream.addTypeCodeAtPosition(this, myPosition);
1339         return true;
1340     }
1341 
1342     void read_value_kind(InputStream is) {
1343         // unmarshal the kind
1344         _kind = is.read_long();
1345 
1346         // check validity of kind
1347         if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
1348             throw wrapper.cannotMarshalBadTckind() ;
1349         }
1350         // Don't do any work if this is native
1351         if (_kind == TCKind._tk_native)
1352             throw wrapper.cannotMarshalNative() ;
1353 
1354         if (_kind == tk_indirect) {
1355             throw wrapper.recursiveTypecodeError() ;
1356         }
1357     }
1358 
1359     void read_value_body(InputStream is) {
1360         // start unmarshaling the rest of the typecode, based on the
1361         // encoding (empty, simple or complex).
1362 
1363         switch (typeTable[_kind]) {
1364         case EMPTY:
1365             // nothing to unmarshal
1366             break;
1367 
1368         case SIMPLE:
1369             switch (_kind) {
1370             case TCKind._tk_string:
1371             case TCKind._tk_wstring:
1372                 _length = is.read_long();
1373                 break;
1374             case TCKind._tk_fixed:
1375                 _digits = is.read_ushort();
1376                 _scale = is.read_short();
1377                 break;
1378             default:
1379                 throw wrapper.invalidSimpleTypecode() ;
1380             }
1381             break;
1382 
1383         case COMPLEX:
1384             {
1385                 TypeCodeInputStream _encap = TypeCodeInputStream.readEncapsulation(is,
1386                     is.orb());
1387 
1388                 switch(_kind) {
1389 
1390                 case TCKind._tk_objref:
1391                 case TCKind._tk_abstract_interface:
1392                     {
1393                         // get the repository id
1394                         setId(_encap.read_string());
1395                         // get the name
1396                         _name = _encap.read_string();
1397                     }
1398                     break;
1399 
1400                 case TCKind._tk_union:
1401                     {
1402                         // get the repository id
1403                         setId(_encap.read_string());
1404 
1405                         // get the name
1406                         _name = _encap.read_string();
1407 
1408                         // discriminant typecode
1409                         _discriminator = new TypeCodeImpl((ORB)is.orb());
1410                         _discriminator.read_value_recursive(_encap);
1411 
1412                         // default index
1413                         _defaultIndex = _encap.read_long();
1414 
1415                         // get the number of members
1416                         _memberCount = _encap.read_long();
1417 
1418                         // create arrays for the label values, names and types of members
1419                         _unionLabels = new AnyImpl[_memberCount];
1420                         _memberNames = new String[_memberCount];
1421                         _memberTypes = new TypeCodeImpl[_memberCount];
1422 
1423                         // read off label values, names and types
1424                         for (int i=0; i < _memberCount; i++) {
1425                             _unionLabels[i] = new AnyImpl((ORB)is.orb());
1426                             if (i == _defaultIndex)
1427                                 // for the default case, read off the zero octet
1428                                 _unionLabels[i].insert_octet(_encap.read_octet());
1429                             else {
1430                                 switch (realType(_discriminator).kind().value()) {
1431                                 case TCKind._tk_short:
1432                                     _unionLabels[i].insert_short(_encap.read_short());
1433                                     break;
1434                                 case TCKind._tk_long:
1435                                     _unionLabels[i].insert_long(_encap.read_long());
1436                                     break;
1437                                 case TCKind._tk_ushort:
1438                                     _unionLabels[i].insert_ushort(_encap.read_short());
1439                                     break;
1440                                 case TCKind._tk_ulong:
1441                                     _unionLabels[i].insert_ulong(_encap.read_long());
1442                                     break;
1443                                 case TCKind._tk_float:
1444                                     _unionLabels[i].insert_float(_encap.read_float());
1445                                     break;
1446                                 case TCKind._tk_double:
1447                                     _unionLabels[i].insert_double(_encap.read_double());
1448                                     break;
1449                                 case TCKind._tk_boolean:
1450                                     _unionLabels[i].insert_boolean(_encap.read_boolean());
1451                                     break;
1452                                 case TCKind._tk_char:
1453                                     _unionLabels[i].insert_char(_encap.read_char());
1454                                     break;
1455                                 case TCKind._tk_enum:
1456                                     _unionLabels[i].type(_discriminator);
1457                                     _unionLabels[i].insert_long(_encap.read_long());
1458                                     break;
1459                                 case TCKind._tk_longlong:
1460                                     _unionLabels[i].insert_longlong(_encap.read_longlong());
1461                                     break;
1462                                 case TCKind._tk_ulonglong:
1463                                     _unionLabels[i].insert_ulonglong(_encap.read_longlong());
1464                                     break;
1465                                     // _REVISIT_ figure out long double mapping
1466                                     // case TCKind.tk_longdouble:
1467                                     // _unionLabels[i].insert_longdouble(_encap.getDouble());
1468                                     // break;
1469                                 case TCKind._tk_wchar:
1470                                     _unionLabels[i].insert_wchar(_encap.read_wchar());
1471                                     break;
1472                                 default:
1473                                     throw wrapper.invalidComplexTypecode() ;
1474                                 }
1475                             }
1476                             _memberNames[i] = _encap.read_string();
1477                             _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1478                             _memberTypes[i].read_value_recursive(_encap);
1479                             _memberTypes[i].setParent(this);
1480                         }
1481                     }
1482                     break;
1483 
1484                 case TCKind._tk_enum:
1485                     {
1486                         // get the repository id
1487                         setId(_encap.read_string());
1488 
1489                         // get the name
1490                         _name = _encap.read_string();
1491 
1492                         // get the number of members
1493                         _memberCount = _encap.read_long();
1494 
1495                         // create arrays for the identifier names
1496                         _memberNames = new String[_memberCount];
1497 
1498                         // read off identifier names
1499                         for (int i=0; i < _memberCount; i++)
1500                             _memberNames[i] = _encap.read_string();
1501                     }
1502                     break;
1503 
1504                 case TCKind._tk_sequence:
1505                     {
1506                         // get the type of the sequence
1507                         _contentType = new TypeCodeImpl((ORB)is.orb());
1508                         _contentType.read_value_recursive(_encap);
1509 
1510                         // get the bound on the length of the sequence
1511                         _length = _encap.read_long();
1512                     }
1513                     break;
1514 
1515                 case TCKind._tk_array:
1516                     {
1517                         // get the type of the array
1518                         _contentType = new TypeCodeImpl((ORB)is.orb());
1519                         _contentType.read_value_recursive(_encap);
1520 
1521                         // get the length of the array
1522                         _length = _encap.read_long();
1523                     }
1524                     break;
1525 
1526                 case TCKind._tk_alias:
1527                 case TCKind._tk_value_box:
1528                     {
1529                         // get the repository id
1530                         setId(_encap.read_string());
1531 
1532                         // get the name
1533                         _name = _encap.read_string();
1534 
1535                         // get the type aliased
1536                         _contentType = new TypeCodeImpl((ORB)is.orb());
1537                         _contentType.read_value_recursive(_encap);
1538                     }
1539                     break;
1540 
1541                 case TCKind._tk_except:
1542                 case TCKind._tk_struct:
1543                     {
1544                         // get the repository id
1545                         setId(_encap.read_string());
1546 
1547                         // get the name
1548                         _name = _encap.read_string();
1549 
1550                         // get the number of members
1551                         _memberCount = _encap.read_long();
1552 
1553                         // create arrays for the names and types of members
1554                         _memberNames = new String[_memberCount];
1555                         _memberTypes = new TypeCodeImpl[_memberCount];
1556 
1557                         // read off member names and types
1558                         for (int i=0; i < _memberCount; i++) {
1559                             _memberNames[i] = _encap.read_string();
1560                             _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1561                             //if (debug) System.out.println("TypeCode " + _name +
1562                             // " reading member " + _memberNames[i]);
1563                             _memberTypes[i].read_value_recursive(_encap);
1564                             _memberTypes[i].setParent(this);
1565                         }
1566                     }
1567                     break;
1568 
1569                 case TCKind._tk_value:
1570                     {
1571                         // get the repository id
1572                         setId(_encap.read_string());
1573 
1574                         // get the name
1575                         _name = _encap.read_string();
1576 
1577                         // get the type modifier
1578                         _type_modifier = _encap.read_short();
1579 
1580                         // get the type aliased
1581                         _concrete_base = new TypeCodeImpl((ORB)is.orb());
1582                         _concrete_base.read_value_recursive(_encap);
1583                         if (_concrete_base.kind().value() == TCKind._tk_null) {
1584                             _concrete_base = null;
1585                         }
1586 
1587                         // get the number of members
1588                         _memberCount = _encap.read_long();
1589 
1590                         // create arrays for the names, types and visibility of members
1591                         _memberNames = new String[_memberCount];
1592                         _memberTypes = new TypeCodeImpl[_memberCount];
1593                         _memberAccess = new short[_memberCount];
1594 
1595                         // read off value member visibilities
1596                         for (int i=0; i < _memberCount; i++) {
1597                             _memberNames[i] = _encap.read_string();
1598                             _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1599                             //if (debug) System.out.println("TypeCode " + _name +
1600                             // " reading member " + _memberNames[i]);
1601                             _memberTypes[i].read_value_recursive(_encap);
1602                             _memberTypes[i].setParent(this);
1603                             _memberAccess[i] = _encap.read_short();
1604                         }
1605                     }
1606                     break;
1607 
1608                 default:
1609                     throw wrapper.invalidTypecodeKindMarshal() ;
1610                 }
1611                 break;
1612             }
1613         }
1614     }
1615 
1616     public void write_value(OutputStream os) {
1617         // Wrap OutputStream into TypeCodeOutputStream.
1618         // This test shouldn't be necessary according to the Java language spec.
1619         if (os instanceof TypeCodeOutputStream) {
1620             this.write_value((TypeCodeOutputStream)os);
1621         } else {
1622             TypeCodeOutputStream wrapperOutStream = null;
1623 
1624             if (outBuffer == null) {
1625                 wrapperOutStream = TypeCodeOutputStream.wrapOutputStream(os);
1626                 this.write_value(wrapperOutStream);
1627                 if (cachingEnabled) {
1628                     // Cache the buffer for repeated writes
1629                     outBuffer = wrapperOutStream.getTypeCodeBuffer();
1630                     //if (outBuffer != null)
1631                         //System.out.println("Caching outBuffer with length = " +
1632                         //outBuffer.length + " for id = " + _id);
1633                 }
1634             } else {
1635                 //System.out.println("Using cached outBuffer: length = " + outBuffer.length +
1636                                    //", id = " + _id);
1637             }
1638             // Write the first 4 bytes first to trigger alignment.
1639             // We know that it is the kind.
1640             if (cachingEnabled && outBuffer != null) {
1641                 os.write_long(_kind);
1642                 os.write_octet_array(outBuffer, 0, outBuffer.length);
1643             } else {
1644                 //System.out.println("Buffer is empty for " + _id);
1645                 wrapperOutStream.writeRawBuffer(os, _kind);
1646             }
1647         }
1648     }
1649 
1650     public void write_value(TypeCodeOutputStream tcos) {
1651 
1652         // Don't do any work if this is native
1653         if (_kind == TCKind._tk_native)
1654             throw wrapper.cannotMarshalNative() ;
1655 
1656         TypeCodeOutputStream topStream = tcos.getTopLevelStream();
1657         //if (debug) tcos.printBuffer();
1658 
1659         if (_kind == tk_indirect) {
1660             //if (debug) System.out.println("Writing indirection " + _name + "to " + _id);
1661             // The encoding used for indirection is the same as that used for recursive ,
1662             // TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
1663             // (in units of octets) from the beginning of the long offset.
1664             int pos = topStream.getPositionForID(_id);
1665             int topPos = tcos.getTopLevelPosition();
1666             //if (debug) System.out.println("TypeCodeImpl " + tcos +
1667             // " writing indirection " + _id +
1668                 //" to position " + pos + " at position " + topPos);
1669             tcos.writeIndirection(tk_indirect, pos);
1670             // All that gets written is _kind and offset.
1671             return;
1672         }
1673 
1674         // The original approach changed for 5034649
1675         // topStream.addIDAtPosition(_id, tcos.getTopLevelPosition());
1676 
1677         // marshal the kind
1678         tcos.write_long(_kind);
1679 
1680         //if (debug) System.out.println("Writing " + _name + " with id " + _id);
1681         // We have to remember the stream and position for EVERY type code
1682         // in case some recursive or indirect type code references it.
1683         //
1684         // Bug fix 5034649:
1685         // Do this AFTER the write of the _kind in case the alignment
1686         // for the long changes the position.
1687         topStream.addIDAtPosition(_id, tcos.getTopLevelPosition()-4);
1688 
1689         switch (typeTable[_kind]) {
1690         case EMPTY:
1691             // nothing more to marshal
1692             break;
1693 
1694         case SIMPLE:
1695             switch (_kind) {
1696             case TCKind._tk_string:
1697             case TCKind._tk_wstring:
1698                 // marshal the bound on string length
1699                 tcos.write_long(_length);
1700                 break;
1701             case TCKind._tk_fixed:
1702                 tcos.write_ushort(_digits);
1703                 tcos.write_short(_scale);
1704                 break;
1705             default:
1706                 // unknown typecode kind
1707                 throw wrapper.invalidSimpleTypecode() ;
1708             }
1709             break;
1710 
1711         case COMPLEX:
1712             {
1713                 // create an encapsulation
1714                 TypeCodeOutputStream _encap = tcos.createEncapsulation(tcos.orb());
1715 
1716                 switch(_kind) {
1717 
1718                 case TCKind._tk_objref:
1719                 case TCKind._tk_abstract_interface:
1720                     {
1721                         // put the repository id
1722                         _encap.write_string(_id);
1723 
1724                         // put the name
1725                         _encap.write_string(_name);
1726                     }
1727                     break;
1728 
1729                 case TCKind._tk_union:
1730                     {
1731                         // put the repository id
1732                         _encap.write_string(_id);
1733 
1734                         // put the name
1735                         _encap.write_string(_name);
1736 
1737                         // discriminant typecode
1738                         _discriminator.write_value(_encap);
1739 
1740                         // default index
1741                         _encap.write_long(_defaultIndex);
1742 
1743                         // put the number of members
1744                         _encap.write_long(_memberCount);
1745 
1746                         // marshal label values, names and types
1747                         for (int i=0; i < _memberCount; i++) {
1748 
1749                             // for the default case, marshal the zero octet
1750                             if (i == _defaultIndex)
1751                                 _encap.write_octet(_unionLabels[i].extract_octet());
1752 
1753                             else {
1754                                 switch (realType(_discriminator).kind().value()) {
1755                                 case TCKind._tk_short:
1756                                     _encap.write_short(_unionLabels[i].extract_short());
1757                                     break;
1758                                 case TCKind._tk_long:
1759                                     _encap.write_long(_unionLabels[i].extract_long());
1760                                     break;
1761                                 case TCKind._tk_ushort:
1762                                     _encap.write_short(_unionLabels[i].extract_ushort());
1763                                     break;
1764                                 case TCKind._tk_ulong:
1765                                     _encap.write_long(_unionLabels[i].extract_ulong());
1766                                     break;
1767                                 case TCKind._tk_float:
1768                                     _encap.write_float(_unionLabels[i].extract_float());
1769                                     break;
1770                                 case TCKind._tk_double:
1771                                     _encap.write_double(_unionLabels[i].extract_double());
1772                                     break;
1773                                 case TCKind._tk_boolean:
1774                                     _encap.write_boolean(_unionLabels[i].extract_boolean());
1775                                     break;
1776                                 case TCKind._tk_char:
1777                                     _encap.write_char(_unionLabels[i].extract_char());
1778                                     break;
1779                                 case TCKind._tk_enum:
1780                                     _encap.write_long(_unionLabels[i].extract_long());
1781                                     break;
1782                                 case TCKind._tk_longlong:
1783                                     _encap.write_longlong(_unionLabels[i].extract_longlong());
1784                                     break;
1785                                 case TCKind._tk_ulonglong:
1786                                     _encap.write_longlong(_unionLabels[i].extract_ulonglong());
1787                                     break;
1788                                     // _REVISIT_ figure out long double mapping
1789                                     // case TCKind.tk_longdouble:
1790                                     // _encap.putDouble(_unionLabels[i].extract_longdouble());
1791                                     // break;
1792                                 case TCKind._tk_wchar:
1793                                     _encap.write_wchar(_unionLabels[i].extract_wchar());
1794                                     break;
1795                                 default:
1796                                     throw wrapper.invalidComplexTypecode() ;
1797                                 }
1798                             }
1799                             _encap.write_string(_memberNames[i]);
1800                             _memberTypes[i].write_value(_encap);
1801                         }
1802                     }
1803                     break;
1804 
1805                 case TCKind._tk_enum:
1806                     {
1807                         // put the repository id
1808                         _encap.write_string(_id);
1809 
1810                         // put the name
1811                         _encap.write_string(_name);
1812 
1813                         // put the number of members
1814                         _encap.write_long(_memberCount);
1815 
1816                         // marshal identifier names
1817                         for (int i=0; i < _memberCount; i++)
1818                             _encap.write_string(_memberNames[i]);
1819                     }
1820                     break;
1821 
1822                 case TCKind._tk_sequence:
1823                     {
1824                         // put the type of the sequence
1825                         lazy_content_type().write_value(_encap);
1826 
1827                         // put the bound on the length of the sequence
1828                         _encap.write_long(_length);
1829                     }
1830                     break;
1831 
1832                 case TCKind._tk_array:
1833                     {
1834                         // put the type of the array
1835                         _contentType.write_value(_encap);
1836 
1837                         // put the length of the array
1838                         _encap.write_long(_length);
1839                     }
1840                     break;
1841 
1842                 case TCKind._tk_alias:
1843                 case TCKind._tk_value_box:
1844                     {
1845                         // put the repository id
1846                         _encap.write_string(_id);
1847 
1848                         // put the name
1849                         _encap.write_string(_name);
1850 
1851                         // put the type aliased
1852                         _contentType.write_value(_encap);
1853                     }
1854                     break;
1855 
1856                 case TCKind._tk_struct:
1857                 case TCKind._tk_except:
1858                     {
1859                         // put the repository id
1860                         _encap.write_string(_id);
1861 
1862                         // put the name
1863                         _encap.write_string(_name);
1864 
1865                         // put the number of members
1866                         _encap.write_long(_memberCount);
1867 
1868                         // marshal member names and types
1869                         for (int i=0; i < _memberCount; i++) {
1870                             _encap.write_string(_memberNames[i]);
1871                             //if (debug) System.out.println("TypeCode " + _name +
1872                             // " writing member " + _memberNames[i]);
1873                             _memberTypes[i].write_value(_encap);
1874                         }
1875                     }
1876                     break;
1877 
1878                 case TCKind._tk_value:
1879                     {
1880                         // put the repository id
1881                         _encap.write_string(_id);
1882 
1883                         // put the name
1884                         _encap.write_string(_name);
1885 
1886                         // put the type modifier
1887                         _encap.write_short(_type_modifier);
1888 
1889                         // put the type aliased
1890                         if (_concrete_base == null) {
1891                             _orb.get_primitive_tc(TCKind._tk_null).write_value(_encap);
1892                         } else {
1893                             _concrete_base.write_value(_encap);
1894                         }
1895 
1896                         // put the number of members
1897                         _encap.write_long(_memberCount);
1898 
1899                         // marshal member names and types
1900                         for (int i=0; i < _memberCount; i++) {
1901                             _encap.write_string(_memberNames[i]);
1902                             //if (debug) System.out.println("TypeCode " + _name +
1903                             // " writing member " + _memberNames[i]);
1904                             _memberTypes[i].write_value(_encap);
1905                             _encap.write_short(_memberAccess[i]);
1906                         }
1907                     }
1908                     break;
1909 
1910                 default:
1911                     throw wrapper.invalidTypecodeKindMarshal() ;
1912                 }
1913 
1914                 // marshal the encapsulation
1915                 _encap.writeOctetSequenceTo(tcos);
1916                 break;
1917             }
1918         }
1919     }
1920 
1921     /**
1922      * This is not a copy of the TypeCodeImpl objects, but instead it
1923      * copies the value this type code is representing.
1924      * See AnyImpl read_value and write_value for usage.
1925      * The state of this TypeCodeImpl instance isn't changed, only used
1926      * by the Any to do the correct copy.
1927      */
1928     protected void copy(org.omg.CORBA.portable.InputStream src,
1929         org.omg.CORBA.portable.OutputStream dst)
1930     {
1931         switch (_kind) {
1932 
1933         case TCKind._tk_null:
1934         case TCKind._tk_void:
1935         case TCKind._tk_native:
1936         case TCKind._tk_abstract_interface:
1937             break;
1938 
1939         case TCKind._tk_short:
1940         case TCKind._tk_ushort:
1941             dst.write_short(src.read_short());
1942             break;
1943 
1944         case TCKind._tk_long:
1945         case TCKind._tk_ulong:
1946             dst.write_long(src.read_long());
1947             break;
1948 
1949         case TCKind._tk_float:
1950             dst.write_float(src.read_float());
1951             break;
1952 
1953         case TCKind._tk_double:
1954             dst.write_double(src.read_double());
1955             break;
1956 
1957         case TCKind._tk_longlong:
1958         case TCKind._tk_ulonglong:
1959             dst.write_longlong(src.read_longlong());
1960             break;
1961 
1962         case TCKind._tk_longdouble:
1963             throw wrapper.tkLongDoubleNotSupported() ;
1964 
1965         case TCKind._tk_boolean:
1966             dst.write_boolean(src.read_boolean());
1967             break;
1968 
1969         case TCKind._tk_char:
1970             dst.write_char(src.read_char());
1971             break;
1972 
1973         case TCKind._tk_wchar:
1974             dst.write_wchar(src.read_wchar());
1975             break;
1976 
1977         case TCKind._tk_octet:
1978             dst.write_octet(src.read_octet());
1979             break;
1980 
1981         case TCKind._tk_string:
1982             {
1983                 String s;
1984                 s = src.read_string();
1985                 // make sure length bound in typecode is not violated
1986                 if ((_length != 0) && (s.length() > _length))
1987                     throw wrapper.badStringBounds( new Integer(s.length()),
1988                         new Integer(_length) ) ;
1989                 dst.write_string(s);
1990             }
1991             break;
1992 
1993         case TCKind._tk_wstring:
1994             {
1995                 String s;
1996                 s = src.read_wstring();
1997                 // make sure length bound in typecode is not violated
1998                 if ((_length != 0) && (s.length() > _length))
1999                     throw wrapper.badStringBounds( new Integer(s.length()),
2000                         new Integer(_length) ) ;
2001                 dst.write_wstring(s);
2002             }
2003             break;
2004 
2005         case TCKind._tk_fixed:
2006             {
2007                 dst.write_ushort(src.read_ushort());
2008                 dst.write_short(src.read_short());
2009             }
2010             break;
2011 
2012         case TCKind._tk_any:
2013             {
2014                 //Any tmp = new AnyImpl(_orb);
2015                 Any tmp =  ((CDRInputStream)src).orb().create_any();
2016                 TypeCodeImpl t = new TypeCodeImpl((ORB)dst.orb());
2017                 t.read_value((org.omg.CORBA_2_3.portable.InputStream)src);
2018                 t.write_value((org.omg.CORBA_2_3.portable.OutputStream)dst);
2019                 tmp.read_value(src, t);
2020                 tmp.write_value(dst);
2021                 break;
2022             }
2023 
2024         case TCKind._tk_TypeCode:
2025             {
2026                 dst.write_TypeCode(src.read_TypeCode());
2027                 break;
2028             }
2029 
2030         case TCKind._tk_Principal:
2031             {
2032                 dst.write_Principal(src.read_Principal());
2033                 break;
2034             }
2035 
2036         case TCKind._tk_objref:
2037             {
2038                 dst.write_Object(src.read_Object());
2039                 break;
2040             }
2041 
2042         case TCKind._tk_except:
2043             // Copy repositoryId
2044             dst.write_string(src.read_string());
2045 
2046             // Fall into ...
2047         // _REVISIT_ what about the inherited members of this values concrete base type?
2048         case TCKind._tk_value:
2049         case TCKind._tk_struct:
2050             {
2051                 // copy each element, using the corresponding member type
2052                 for (int i=0; i < _memberTypes.length; i++) {
2053                     _memberTypes[i].copy(src, dst);
2054                 }
2055                 break;
2056             }
2057         case TCKind._tk_union:
2058     /* _REVISIT_ More generic code?
2059             {
2060                 Any discriminator = new AnyImpl(_orb);
2061                 discriminator.read_value(src, _discriminator);
2062                 discriminator.write_value(dst);
2063                 int labelIndex = currentUnionMemberIndex(discriminator);
2064                 if (labelIndex == -1) {
2065                     // check if label has not been found
2066                     if (_defaultIndex == -1)
2067                         // throw exception if default was not expected
2068                         throw new MARSHAL();
2069                     else
2070                         // must be of the default branch type
2071                         _memberTypes[_defaultIndex].copy(src, dst);
2072                 } else {
2073                     _memberTypes[labelIndex].copy(src, dst);
2074                 }
2075             }
2076     */
2077             {
2078                 Any tagValue = new AnyImpl( (ORB)src.orb());
2079 
2080                 switch  (realType(_discriminator).kind().value()) {
2081                 case TCKind._tk_short:
2082                     {
2083                         short value = src.read_short();
2084                         tagValue.insert_short(value);
2085                         dst.write_short(value);
2086                         break;
2087                     }
2088                 case TCKind._tk_long:
2089                     {
2090                         int value = src.read_long();
2091                         tagValue.insert_long(value);
2092                         dst.write_long(value);
2093                         break;
2094                     }
2095                 case TCKind._tk_ushort:
2096                     {
2097                         short value = src.read_short();
2098                         tagValue.insert_ushort(value);
2099                         dst.write_short(value);
2100                         break;
2101                     }
2102                 case TCKind._tk_ulong:
2103                     {
2104                         int value = src.read_long();
2105                         tagValue.insert_ulong(value);
2106                         dst.write_long(value);
2107                         break;
2108                     }
2109                 case TCKind._tk_float:
2110                     {
2111                         float value = src.read_float();
2112                         tagValue.insert_float(value);
2113                         dst.write_float(value);
2114                         break;
2115                     }
2116                 case TCKind._tk_double:
2117                     {
2118                         double value = src.read_double();
2119                         tagValue.insert_double(value);
2120                         dst.write_double(value);
2121                         break;
2122                     }
2123                 case TCKind._tk_boolean:
2124                     {
2125                         boolean value = src.read_boolean();
2126                         tagValue.insert_boolean(value);
2127                         dst.write_boolean(value);
2128                         break;
2129                     }
2130                 case TCKind._tk_char:
2131                     {
2132                         char value = src.read_char();
2133                         tagValue.insert_char(value);
2134                         dst.write_char(value);
2135                         break;
2136                     }
2137                 case TCKind._tk_enum:
2138                     {
2139                         int value = src.read_long();
2140                         tagValue.type(_discriminator);
2141                         tagValue.insert_long(value);
2142                         dst.write_long(value);
2143                         break;
2144                     }
2145                 case TCKind._tk_longlong:
2146                     {
2147                         long value = src.read_longlong();
2148                         tagValue.insert_longlong(value);
2149                         dst.write_longlong(value);
2150                         break;
2151                     }
2152                 case TCKind._tk_ulonglong:
2153                     {
2154                         long value = src.read_longlong();
2155                         tagValue.insert_ulonglong(value);
2156                         dst.write_longlong(value);
2157                         break;
2158                     }
2159                     // _REVISIT_ figure out long double mapping
2160                     // case TCKind.tk_longdouble:
2161                     // {
2162                     // double value = src.read_double();
2163                     //  tagValue.insert_longdouble(value);
2164                     //  dst.putDouble(value);
2165                     //  break;
2166                     //}
2167                 case TCKind._tk_wchar:
2168                     {
2169                         char value = src.read_wchar();
2170                         tagValue.insert_wchar(value);
2171                         dst.write_wchar(value);
2172                         break;
2173                     }
2174                 default:
2175                     throw wrapper.illegalUnionDiscriminatorType() ;
2176                 }
2177 
2178                 // using the value of the tag, find out the type of the value
2179                 // following.
2180 
2181                 int labelIndex;
2182                 for (labelIndex = 0; labelIndex < _unionLabels.length; labelIndex++) {
2183                     // use equality over anys
2184                     if (tagValue.equal(_unionLabels[labelIndex])) {
2185                         _memberTypes[labelIndex].copy(src, dst);
2186                         break;
2187                     }
2188                 }
2189 
2190                 if (labelIndex == _unionLabels.length) {
2191                     // check if label has not been found
2192                     if (_defaultIndex != -1)



2193                         // must be of the default branch type
2194                         _memberTypes[_defaultIndex].copy(src, dst);
2195                 }
2196                 break;
2197             }
2198 
2199         case TCKind._tk_enum:
2200             dst.write_long(src.read_long());
2201             break;
2202 
2203         case TCKind._tk_sequence:
2204             // get the length of the sequence
2205             int seqLength = src.read_long();
2206 
2207             // check for sequence bound violated
2208             if ((_length != 0) && (seqLength > _length))
2209                 throw wrapper.badSequenceBounds( new Integer(seqLength),
2210                     new Integer(_length) ) ;
2211 
2212             // write the length of the sequence
2213             dst.write_long(seqLength);
2214 
2215             // copy each element of the seq using content type
2216             lazy_content_type(); // make sure it's resolved
2217             for (int i=0; i < seqLength; i++)
2218                 _contentType.copy(src, dst);
2219             break;
2220 
2221         case TCKind._tk_array:
2222             // copy each element of the array using content type
2223             for (int i=0; i < _length; i++)
2224                 _contentType.copy(src, dst);
2225             break;
2226 
2227         case TCKind._tk_alias:
2228         case TCKind._tk_value_box:
2229             // follow the alias
2230             _contentType.copy(src, dst);
2231             break;
2232 
2233         case tk_indirect:
2234             // need to follow offset, get unmarshal typecode from that
2235             // offset, and use that to do the copy
2236             // Don't need to read type code before using it to do the copy.
2237             // It should be fully usable.
2238             indirectType().copy(src, dst);
2239             break;
2240 
2241         default:
2242             throw wrapper.invalidTypecodeKindMarshal() ;
2243         }
2244     }
2245 
2246 
2247     static protected short digits(java.math.BigDecimal value) {
2248         if (value == null)
2249             return 0;
2250         short length = (short)value.unscaledValue().toString().length();
2251         if (value.signum() == -1)
2252             length--;
2253         return length;
2254     }
2255 
2256     static protected short scale(java.math.BigDecimal value) {
2257         if (value == null)
2258             return 0;
2259         return (short)value.scale();
2260     }
2261 
2262     // Utility methods
2263 
2264     // Only for union type. Returns the index of the union member
2265     // corresponding to the discriminator. If not found returns the
2266     // default index or -1 if there is no default index.
2267     int currentUnionMemberIndex(Any discriminatorValue) throws BadKind {
2268         if (_kind != TCKind._tk_union)
2269             throw new BadKind();
2270 
2271         try {
2272             for (int i=0; i<member_count(); i++) {
2273                 if (member_label(i).equal(discriminatorValue)) {
2274                     return i;
2275                 }
2276             }
2277             if (_defaultIndex != -1) {
2278                 return _defaultIndex;
2279             }
2280         } catch (BadKind bad) {
2281         } catch (org.omg.CORBA.TypeCodePackage.Bounds bounds) {
2282         }
2283         return -1;
2284     }
2285 
2286     public String description() {
2287         return "TypeCodeImpl with kind " + _kind + " and id " + _id;
2288     }
2289 
2290     public String toString() {
2291         ByteArrayOutputStream byteOut = new ByteArrayOutputStream(1024);
2292         PrintStream printOut = new PrintStream(byteOut, true);
2293         printStream(printOut);
2294         return super.toString() + " =\n" + byteOut.toString();
2295     }
2296 
2297     public void printStream(PrintStream s) {
2298         printStream(s, 0);
2299     }
2300 
2301     private void printStream(PrintStream s, int level) {
2302         if (_kind == tk_indirect) {
2303             s.print("indirect " + _id);
2304             return;
2305         }
2306 
2307         switch (_kind) {
2308             case TCKind._tk_null:
2309             case TCKind._tk_void:
2310             case TCKind._tk_short:
2311             case TCKind._tk_long:
2312             case TCKind._tk_ushort:
2313             case TCKind._tk_ulong:
2314             case TCKind._tk_float:
2315             case TCKind._tk_double:
2316             case TCKind._tk_boolean:
2317             case TCKind._tk_char:
2318             case TCKind._tk_octet:
2319             case TCKind._tk_any:
2320             case TCKind._tk_TypeCode:
2321             case TCKind._tk_Principal:
2322             case TCKind._tk_objref:
2323             case TCKind._tk_longlong:
2324             case TCKind._tk_ulonglong:
2325             case TCKind._tk_longdouble:
2326             case TCKind._tk_wchar:
2327             case TCKind._tk_native:
2328                 s.print(kindNames[_kind] + " " + _name);
2329                 break;
2330 
2331             case TCKind._tk_struct:
2332             case TCKind._tk_except:
2333             case TCKind._tk_value:
2334                 s.println(kindNames[_kind] + " " + _name + " = {");
2335                 for(int i=0; i<_memberCount; i++) {
2336                     // memberName might differ from the name of the member.
2337                     s.print(indent(level + 1));
2338                     if (_memberTypes[i] != null)
2339                         _memberTypes[i].printStream(s, level + 1);
2340                     else
2341                         s.print("<unknown type>");
2342                     s.println(" " + _memberNames[i] + ";");
2343                 }
2344                 s.print(indent(level) + "}");
2345                 break;
2346 
2347             case TCKind._tk_union:
2348                 s.print("union " + _name + "...");
2349                 break;
2350 
2351             case TCKind._tk_enum:
2352                 s.print("enum " + _name + "...");
2353                 break;
2354 
2355             case TCKind._tk_string:
2356                 if (_length == 0)
2357                     s.print("unbounded string " + _name);
2358                 else
2359                     s.print("bounded string(" + _length + ") " + _name);
2360                 break;
2361 
2362             case TCKind._tk_sequence:
2363             case TCKind._tk_array:
2364                 s.println(kindNames[_kind] + "[" + _length + "] " + _name + " = {");
2365                 s.print(indent(level + 1));
2366                 if (lazy_content_type() != null) {
2367                     lazy_content_type().printStream(s, level + 1);
2368                 }
2369                 s.println(indent(level) + "}");
2370                 break;
2371 
2372             case TCKind._tk_alias:
2373                 s.print("alias " + _name + " = " +
2374                     (_contentType != null ? _contentType._name : "<unresolved>"));
2375                 break;
2376 
2377             case TCKind._tk_wstring:
2378                 s.print("wstring[" + _length + "] " + _name);
2379                 break;
2380 
2381             case TCKind._tk_fixed:
2382                 s.print("fixed(" + _digits + ", " + _scale + ") " + _name);
2383                 break;
2384 
2385             case TCKind._tk_value_box:
2386                 s.print("valueBox " + _name + "...");
2387                 break;
2388 
2389             case TCKind._tk_abstract_interface:
2390                 s.print("abstractInterface " + _name + "...");
2391                 break;
2392 
2393             default:
2394                 s.print("<unknown type>");
2395                 break;
2396         }
2397     }
2398 
2399     private String indent(int level) {
2400         String indent = "";
2401         for(int i=0; i<level; i++) {
2402             indent += "  ";
2403         }
2404         return indent;
2405     }
2406 
2407     protected void setCaching(boolean enableCaching) {
2408         cachingEnabled = enableCaching;
2409         if (enableCaching == false)
2410             outBuffer = null;
2411     }
2412 }
--- EOF ---