TypeCodeImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1996, 2013, 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
26package com.sun.corba.se.impl.corba;
27
28import java.util.HashMap;
29import java.util.Map;
30import java.util.Iterator;
31import java.util.List;
32import java.util.Collections;
33import java.util.ArrayList;
34import java.io.IOException;
35import java.io.PrintStream;
36import java.io.ByteArrayOutputStream;
37import java.math.BigDecimal;
38import java.math.BigInteger;
39
40import org.omg.CORBA.TypeCode ;
41import org.omg.CORBA.StructMember ;
42import org.omg.CORBA.UnionMember ;
43import org.omg.CORBA.ValueMember ;
44import org.omg.CORBA.TCKind ;
45import org.omg.CORBA.Any ;
46import org.omg.CORBA.Principal ;
47import org.omg.CORBA.BAD_TYPECODE ;
48import org.omg.CORBA.BAD_PARAM ;
49import org.omg.CORBA.BAD_OPERATION ;
50import org.omg.CORBA.INTERNAL ;
51import org.omg.CORBA.MARSHAL ;
52import org.omg.CORBA.TypeCodePackage.BadKind ;
53import org.omg.CORBA_2_3.portable.InputStream;
54import org.omg.CORBA_2_3.portable.OutputStream;
55
56import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
57import com.sun.corba.se.spi.orb.ORB;
58import com.sun.corba.se.spi.logging.CORBALogDomains;
59
60import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
61import com.sun.corba.se.impl.encoding.MarshalInputStream;
62import com.sun.corba.se.impl.encoding.CodeSetConversion;
63import com.sun.corba.se.impl.encoding.CDRInputStream;
64import com.sun.corba.se.impl.encoding.CDROutputStream;
65import com.sun.corba.se.impl.encoding.TypeCodeInputStream;
66import com.sun.corba.se.impl.encoding.TypeCodeOutputStream;
67import com.sun.corba.se.impl.encoding.TypeCodeReader;
68import com.sun.corba.se.impl.encoding.WrapperInputStream;
69
70import com.sun.corba.se.impl.logging.ORBUtilSystemException;
71
72// no chance of subclasses, so no problems with runtime helper lookup
73public 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 =
604            sun.corba.OutputStreamFactory.newTypeCodeOutputStream(orb);
605        //if (debug) System.out.println("Created TypeCodeOutputStream " + tcos +
606        // " with no parent");
607        return tcos;
608    }
609
610    // Support for indirect/recursive type codes
611
612    private TypeCodeImpl indirectType() {
613        _indirectType = tryIndirectType();
614        if (_indirectType == null) {
615            // Nothing we can do about that.
616            throw wrapper.unresolvedRecursiveTypecode() ;
617        }
618        return _indirectType;
619    }
620
621    private TypeCodeImpl tryIndirectType() {
622        // Assert that _kind == tk_indirect
623        if (_indirectType != null)
624            return _indirectType;
625
626        setIndirectType(_orb.getTypeCode(_id));
627
628        return _indirectType;
629    }
630
631    private void setIndirectType(TypeCodeImpl newType) {
632        _indirectType = newType;
633        if (_indirectType != null) {
634            try {
635                _id = _indirectType.id();
636            } catch (BadKind e) {
637                // can't happen
638                throw wrapper.badkindCannotOccur() ;
639            }
640        }
641    }
642
643    private void setId(String newID) {
644        _id = newID;
645        if (_orb instanceof TypeCodeFactory) {
646            ((TypeCodeFactory)_orb).setTypeCode(_id, this);
647        }
648        // check whether return value != this which would indicate that the
649        // repository id isn't unique.
650    }
651
652    private void setParent(TypeCodeImpl parent) {
653        _parent = parent;
654    }
655
656    private TypeCodeImpl getParentAtLevel(int level) {
657        if (level == 0)
658            return this;
659
660        if (_parent == null)
661            throw wrapper.unresolvedRecursiveTypecode() ;
662
663        return _parent.getParentAtLevel(level - 1);
664    }
665
666    private TypeCodeImpl lazy_content_type() {
667        if (_contentType == null) {
668            if (_kind == TCKind._tk_sequence && _parentOffset > 0 && _parent != null) {
669                // This is an unresolved recursive sequence tc.
670                // Try to resolve it now if the hierarchy is complete.
671                TypeCodeImpl realParent = getParentAtLevel(_parentOffset);
672                if (realParent != null && realParent._id != null) {
673                    // Create a recursive type code object as the content type.
674                    // This is when the recursive sequence typecode morphes
675                    // into a sequence typecode containing a recursive typecode.
676                    _contentType = new TypeCodeImpl((ORB)_orb, realParent._id);
677                }
678            }
679        }
680        return _contentType;
681    }
682
683    // Other private functions
684
685    private TypeCode realType(TypeCode aType) {
686        TypeCode realType = aType;
687        try {
688            // Note: Indirect types are handled in kind() method
689            while (realType.kind().value() == TCKind._tk_alias) {
690                realType = realType.content_type();
691            }
692        } catch (BadKind bad) {
693            // impossible
694            throw wrapper.badkindCannotOccur() ;
695        }
696        return realType;
697    }
698
699    ///////////////////////////////////////////////////////////////////////////
700    // TypeCode operations
701
702    public final boolean equal(TypeCode tc)
703    // _REVISIT_ for all optional names/ids, we might want to check that
704    // they are equal in case both are non-nil.
705    {
706        if (tc == this)
707            return true;
708
709        try {
710
711            if (_kind == tk_indirect) {
712                //return indirectType().equal(tc);
713                if (_id != null && tc.id() != null)
714                    return _id.equals(tc.id());
715                return (_id == null && tc.id() == null);
716            }
717
718            // make sure kinds are identical.
719            if (_kind != tc.kind().value()) {
720                return false;
721            }
722
723            switch (typeTable[_kind]) {
724            case EMPTY:
725                // no parameters to check.
726                return true;
727
728            case SIMPLE:
729                switch (_kind) {
730                case TCKind._tk_string:
731                case TCKind._tk_wstring:
732                    // check for bound.
733                    return (_length == tc.length());
734
735                case TCKind._tk_fixed:
736                    return (_digits == tc.fixed_digits() && _scale == tc.fixed_scale());
737                default:
738                    return false;
739                }
740
741            case COMPLEX:
742
743                switch(_kind) {
744
745                case TCKind._tk_objref:
746                    {
747                        // check for logical id.
748                        if (_id.compareTo(tc.id()) == 0) {
749                            return true;
750                        }
751
752                        if (_id.compareTo(
753                            (_orb.get_primitive_tc(_kind)).id()) == 0)
754                        {
755                            return true;
756                        }
757
758                        if (tc.id().compareTo(
759                            (_orb.get_primitive_tc(_kind)).id()) == 0)
760                        {
761                            return true;
762                        }
763
764                        return false;
765                    }
766
767                case TCKind._tk_native:
768                case TCKind._tk_abstract_interface:
769                    {
770                        // check for logical id.
771                        if (_id.compareTo(tc.id()) != 0) {
772                            return false;
773
774                        }
775                        // ignore name since its optional.
776                        return true;
777                    }
778
779                case TCKind._tk_struct:
780                case TCKind._tk_except:
781                    {
782                        // check for member count
783                        if (_memberCount != tc.member_count())
784                            return false;
785                        // check for repository id
786                        if (_id.compareTo(tc.id()) != 0)
787                            return false;
788                        // check for member types.
789                        for (int i = 0 ; i < _memberCount ; i++)
790                            if (! _memberTypes[i].equal(tc.member_type(i)))
791                                return false;
792                        // ignore id and names since those are optional.
793                        return true;
794                    }
795
796                case TCKind._tk_union:
797                    {
798                        // check for member count
799                        if (_memberCount != tc.member_count())
800                            return false;
801                        // check for repository id
802                        if (_id.compareTo(tc.id()) != 0)
803                            return false;
804                        // check for default index
805                        if (_defaultIndex != tc.default_index())
806                            return false;
807                        // check for discriminator type
808                        if (!_discriminator.equal(tc.discriminator_type()))
809                            return false;
810                        // check for label types and values
811                        for (int i = 0 ; i < _memberCount ; i++)
812                            if (! _unionLabels[i].equal(tc.member_label(i)))
813                                return false;
814                        // check for branch types
815                        for (int i = 0 ; i < _memberCount ; i++)
816                            if (! _memberTypes[i].equal(tc.member_type(i)))
817                                return false;
818                        // ignore id and names since those are optional.
819                        return true;
820                    }
821
822                case TCKind._tk_enum:
823                    {
824                        // check for repository id
825                        if (_id.compareTo(tc.id()) != 0)
826                            return false;
827                        // check member count
828                        if (_memberCount != tc.member_count())
829                            return false;
830                        // ignore names since those are optional.
831                        return true;
832                    }
833
834                case TCKind._tk_sequence:
835                case TCKind._tk_array:
836                    {
837                        // check bound/length
838                        if (_length != tc.length()) {
839                            return false;
840                        }
841                        // check content type
842                        if (! lazy_content_type().equal(tc.content_type())) {
843                            return false;
844                        }
845                        // ignore id and name since those are optional.
846                        return true;
847                    }
848
849                case TCKind._tk_value:
850                    {
851                        // check for member count
852                        if (_memberCount != tc.member_count())
853                            return false;
854                        // check for repository id
855                        if (_id.compareTo(tc.id()) != 0)
856                            return false;
857                        // check for member types.
858                        for (int i = 0 ; i < _memberCount ; i++)
859                            if (_memberAccess[i] != tc.member_visibility(i) ||
860                                ! _memberTypes[i].equal(tc.member_type(i)))
861                                return false;
862                        if (_type_modifier == tc.type_modifier())
863                            return false;
864                        // concrete_base may be null
865                        TypeCode tccb = tc.concrete_base_type();
866                        if ((_concrete_base == null && tccb != null) ||
867                            (_concrete_base != null && tccb == null) ||
868                            ! _concrete_base.equal(tccb))
869                        {
870                            return false;
871                        }
872                        // ignore id and names since those are optional.
873                        return true;
874                    }
875
876                case TCKind._tk_alias:
877                case TCKind._tk_value_box:
878                    {
879                        // check for repository id
880                        if (_id.compareTo(tc.id()) != 0) {
881                            return false;
882                        }
883                        // check for equality with the true type
884                        return _contentType.equal(tc.content_type());
885                    }
886                }
887            }
888        } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
889        // dont have to worry about these since the code ensures these dont
890        // arise.
891        return false;
892    }
893
894    /**
895    * The equivalent operation is used by the ORB when determining type equivalence
896    * for values stored in an IDL any.
897    */
898    public boolean equivalent(TypeCode tc) {
899        if (tc == this) {
900            return true;
901        }
902
903        // If the result of the kind operation on either TypeCode is tk_alias, recursively
904        // replace the TypeCode with the result of calling content_type, until the kind
905        // is no longer tk_alias.
906        // Note: Always resolve indirect types first!
907        TypeCode myRealType = (_kind == tk_indirect ? indirectType() : this);
908        myRealType = realType(myRealType);
909        TypeCode otherRealType = realType(tc);
910
911        // If results of the kind operation on each typecode differ,
912        // equivalent returns false.
913        if (myRealType.kind().value() != otherRealType.kind().value()) {
914            return false;
915        }
916
917        String myID = null;
918        String otherID = null;
919        try {
920            myID = this.id();
921            otherID = tc.id();
922            // At this point the id operation is valid for both TypeCodes.
923
924            // Return true if the results of id for both TypeCodes are non-empty strings
925            // and both strings are equal.
926            // If both ids are non-empty but are not equal, then equivalent returns FALSE.
927            if (myID != null && otherID != null) {
928                return (myID.equals(otherID));
929            }
930        } catch (BadKind e) {
931            // id operation is not valid for either or both TypeCodes
932        }
933
934        // If either or both id is an empty string, or the TypeCode kind does not support
935        // the id operation, perform a structural comparison of the TypeCodes.
936
937        int myKind = myRealType.kind().value();
938        try {
939            if (myKind == TCKind._tk_struct ||
940                myKind == TCKind._tk_union ||
941                myKind == TCKind._tk_enum ||
942                myKind == TCKind._tk_except ||
943                myKind == TCKind._tk_value)
944            {
945                if (myRealType.member_count() != otherRealType.member_count())
946                    return false;
947            }
948            if (myKind == TCKind._tk_union)
949            {
950                if (myRealType.default_index() != otherRealType.default_index())
951                    return false;
952            }
953            if (myKind == TCKind._tk_string ||
954                myKind == TCKind._tk_wstring ||
955                myKind == TCKind._tk_sequence ||
956                myKind == TCKind._tk_array)
957            {
958                if (myRealType.length() != otherRealType.length())
959                    return false;
960            }
961            if (myKind == TCKind._tk_fixed)
962            {
963                if (myRealType.fixed_digits() != otherRealType.fixed_digits() ||
964                    myRealType.fixed_scale() != otherRealType.fixed_scale())
965                    return false;
966            }
967            if (myKind == TCKind._tk_union)
968            {
969                for (int i=0; i<myRealType.member_count(); i++) {
970                    if (myRealType.member_label(i) != otherRealType.member_label(i))
971                        return false;
972                }
973                if ( ! myRealType.discriminator_type().equivalent(
974                    otherRealType.discriminator_type()))
975                    return false;
976            }
977            if (myKind == TCKind._tk_alias ||
978                myKind == TCKind._tk_value_box ||
979                myKind == TCKind._tk_sequence ||
980                myKind == TCKind._tk_array)
981            {
982                if ( ! myRealType.content_type().equivalent(otherRealType.content_type()))
983                    return false;
984            }
985            if (myKind == TCKind._tk_struct ||
986                myKind == TCKind._tk_union ||
987                myKind == TCKind._tk_except ||
988                myKind == TCKind._tk_value)
989            {
990                for (int i=0; i<myRealType.member_count(); i++) {
991                    if ( ! myRealType.member_type(i).equivalent(
992                        otherRealType.member_type(i)))
993                        return false;
994                }
995            }
996        } catch (BadKind e) {
997            // impossible if we checked correctly above
998            throw wrapper.badkindCannotOccur() ;
999        } catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
1000            // impossible if we checked correctly above
1001            throw wrapper.boundsCannotOccur() ;
1002        }
1003
1004        // Structural comparison succeeded!
1005        return true;
1006    }
1007
1008    public TypeCode get_compact_typecode() {
1009        // _REVISIT_ It isn't clear whether this method should operate on this or a copy.
1010        // For now just return this unmodified because the name and member_name fields
1011        // aren't used for comparison anyways.
1012        return this;
1013    }
1014
1015    public TCKind kind()
1016    {
1017        if (_kind == tk_indirect)
1018            return indirectType().kind();
1019        return TCKind.from_int(_kind);
1020    }
1021
1022    public boolean is_recursive()
1023    {
1024        // Recursive is the only form of indirect type codes right now.
1025        // Indirection can also be used for repeated type codes.
1026        return (_kind == tk_indirect);
1027    }
1028
1029    public String id()
1030        throws BadKind
1031    {
1032        switch (_kind) {
1033        case tk_indirect:
1034            //return indirectType().id(); // same as _id
1035        case TCKind._tk_except:
1036        case TCKind._tk_objref:
1037        case TCKind._tk_struct:
1038        case TCKind._tk_union:
1039        case TCKind._tk_enum:
1040        case TCKind._tk_alias:
1041        case TCKind._tk_value:
1042        case TCKind._tk_value_box:
1043        case TCKind._tk_native:
1044        case TCKind._tk_abstract_interface:
1045            // exception and objref typecodes must have a repository id.
1046            // structs, unions, enums, and aliases may or may not.
1047            return _id;
1048        default:
1049            // all other typecodes throw the BadKind exception.
1050            throw new BadKind();
1051        }
1052    }
1053
1054    public String name()
1055        throws BadKind
1056    {
1057        switch (_kind) {
1058        case tk_indirect:
1059            return indirectType().name();
1060        case TCKind._tk_except:
1061        case TCKind._tk_objref:
1062        case TCKind._tk_struct:
1063        case TCKind._tk_union:
1064        case TCKind._tk_enum:
1065        case TCKind._tk_alias:
1066        case TCKind._tk_value:
1067        case TCKind._tk_value_box:
1068        case TCKind._tk_native:
1069        case TCKind._tk_abstract_interface:
1070            return _name;
1071        default:
1072            throw new BadKind();
1073        }
1074    }
1075
1076    public int member_count()
1077        throws BadKind
1078    {
1079        switch (_kind) {
1080        case tk_indirect:
1081            return indirectType().member_count();
1082        case TCKind._tk_except:
1083        case TCKind._tk_struct:
1084        case TCKind._tk_union:
1085        case TCKind._tk_enum:
1086        case TCKind._tk_value:
1087            return _memberCount;
1088        default:
1089            throw new BadKind();
1090        }
1091    }
1092
1093    public String member_name(int index)
1094        throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1095    {
1096        switch (_kind) {
1097        case tk_indirect:
1098            return indirectType().member_name(index);
1099        case TCKind._tk_except:
1100        case TCKind._tk_struct:
1101        case TCKind._tk_union:
1102        case TCKind._tk_enum:
1103        case TCKind._tk_value:
1104            try {
1105                return _memberNames[index];
1106            } catch (ArrayIndexOutOfBoundsException e) {
1107                throw new org.omg.CORBA.TypeCodePackage.Bounds();
1108            }
1109        default:
1110            throw new BadKind();
1111        }
1112    }
1113
1114    public TypeCode member_type(int index)
1115        throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1116    {
1117        switch (_kind) {
1118        case tk_indirect:
1119            return indirectType().member_type(index);
1120        case TCKind._tk_except:
1121        case TCKind._tk_struct:
1122        case TCKind._tk_union:
1123        case TCKind._tk_value:
1124            try {
1125                return _memberTypes[index];
1126            } catch (ArrayIndexOutOfBoundsException e) {
1127                throw new org.omg.CORBA.TypeCodePackage.Bounds();
1128            }
1129        default:
1130            throw new BadKind();
1131        }
1132    }
1133
1134    public Any member_label(int index)
1135        throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
1136    {
1137        switch (_kind) {
1138        case tk_indirect:
1139            return indirectType().member_label(index);
1140        case TCKind._tk_union:
1141            try {
1142                // _REVISIT_ Why create a new Any for this?
1143                return new AnyImpl(_orb, _unionLabels[index]);
1144            } catch (ArrayIndexOutOfBoundsException e) {
1145                throw new org.omg.CORBA.TypeCodePackage.Bounds();
1146            }
1147        default:
1148            throw new BadKind();
1149        }
1150    }
1151
1152    public TypeCode discriminator_type()
1153        throws BadKind
1154    {
1155        switch (_kind) {
1156        case tk_indirect:
1157            return indirectType().discriminator_type();
1158        case TCKind._tk_union:
1159            return _discriminator;
1160        default:
1161            throw new BadKind();
1162        }
1163    }
1164
1165    public int default_index()
1166        throws BadKind
1167    {
1168        switch (_kind) {
1169        case tk_indirect:
1170            return indirectType().default_index();
1171        case TCKind._tk_union:
1172            return _defaultIndex;
1173        default:
1174            throw new BadKind();
1175        }
1176    }
1177
1178    public int length()
1179        throws BadKind
1180    {
1181        switch (_kind) {
1182        case tk_indirect:
1183            return indirectType().length();
1184        case TCKind._tk_string:
1185        case TCKind._tk_wstring:
1186        case TCKind._tk_sequence:
1187        case TCKind._tk_array:
1188            return _length;
1189        default:
1190            throw new BadKind();
1191        }
1192    }
1193
1194    public TypeCode content_type()
1195        throws BadKind
1196    {
1197        switch (_kind) {
1198        case tk_indirect:
1199            return indirectType().content_type();
1200        case TCKind._tk_sequence:
1201            return lazy_content_type();
1202        case TCKind._tk_array:
1203        case TCKind._tk_alias:
1204        case TCKind._tk_value_box:
1205            return _contentType;
1206        default:
1207            throw new BadKind();
1208        }
1209    }
1210
1211    public short fixed_digits() throws BadKind {
1212        switch (_kind) {
1213        case TCKind._tk_fixed:
1214            return _digits;
1215        default:
1216            throw new BadKind();
1217        }
1218    }
1219
1220    public short fixed_scale() throws BadKind {
1221        switch (_kind) {
1222        case TCKind._tk_fixed:
1223            return _scale;
1224        default:
1225            throw new BadKind();
1226        }
1227    }
1228
1229    public short member_visibility(int index) throws BadKind,
1230        org.omg.CORBA.TypeCodePackage.Bounds {
1231        switch (_kind) {
1232        case tk_indirect:
1233            return indirectType().member_visibility(index);
1234        case TCKind._tk_value:
1235            try {
1236                return _memberAccess[index];
1237            } catch (ArrayIndexOutOfBoundsException e) {
1238                throw new org.omg.CORBA.TypeCodePackage.Bounds();
1239            }
1240        default:
1241            throw new BadKind();
1242        }
1243    }
1244
1245    public short type_modifier() throws BadKind {
1246        switch (_kind) {
1247        case tk_indirect:
1248            return indirectType().type_modifier();
1249        case TCKind._tk_value:
1250            return _type_modifier;
1251        default:
1252            throw new BadKind();
1253        }
1254    }
1255
1256    public TypeCode concrete_base_type() throws BadKind {
1257        switch (_kind) {
1258        case tk_indirect:
1259            return indirectType().concrete_base_type();
1260        case TCKind._tk_value:
1261            return _concrete_base;
1262        default:
1263            throw new BadKind();
1264        }
1265    }
1266
1267    public void read_value(InputStream is) {
1268        if (is instanceof TypeCodeReader) {
1269            // hardly possible unless caller knows our "private" stream classes.
1270            if (read_value_kind((TypeCodeReader)is))
1271                read_value_body(is);
1272        } else if (is instanceof CDRInputStream) {
1273            WrapperInputStream wrapper = new WrapperInputStream((CDRInputStream)is);
1274            //if (debug) System.out.println("Created WrapperInputStream " + wrapper +
1275            // " with no parent");
1276            if (read_value_kind((TypeCodeReader)wrapper))
1277                read_value_body(wrapper);
1278        } else {
1279            read_value_kind(is);
1280            read_value_body(is);
1281        }
1282    }
1283
1284    private void read_value_recursive(TypeCodeInputStream is) {
1285        // don't wrap a CDRInputStream reading "inner" TypeCodes.
1286        if (is instanceof TypeCodeReader) {
1287            if (read_value_kind((TypeCodeReader)is))
1288                read_value_body(is);
1289        } else {
1290            read_value_kind((InputStream)is);
1291            read_value_body(is);
1292        }
1293    }
1294
1295    boolean read_value_kind(TypeCodeReader tcis)
1296    {
1297        _kind = tcis.read_long();
1298
1299        // Bug fix 5034649: allow for padding that precedes the typecode kind.
1300        int myPosition = tcis.getTopLevelPosition()-4;
1301
1302        // check validity of kind
1303        if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
1304            throw wrapper.cannotMarshalBadTckind() ;
1305        }
1306
1307        // Don't do any work if this is native
1308        if (_kind == TCKind._tk_native)
1309            throw wrapper.cannotMarshalNative() ;
1310
1311        // We have to remember the stream and position for EVERY type code
1312        // in case some recursive or indirect type code references it.
1313        TypeCodeReader topStream = tcis.getTopLevelStream();
1314
1315        if (_kind == tk_indirect) {
1316            int streamOffset = tcis.read_long();
1317            if (streamOffset > -4)
1318                throw wrapper.invalidIndirection( new Integer(streamOffset) ) ;
1319
1320            // The encoding used for indirection is the same as that used for recursive ,
1321            // TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
1322            // (in units of octets) from the beginning of the long offset.
1323            int topPos = tcis.getTopLevelPosition();
1324            // substract 4 to get back to the beginning of the long offset.
1325            int indirectTypePosition = topPos - 4 + streamOffset;
1326
1327            // Now we have to find the referenced type
1328            // by its indirectTypePosition within topStream.
1329            //if (debug) System.out.println(
1330            // "TypeCodeImpl looking up indirection at position topPos " +
1331            //topPos + " - 4 + offset " + streamOffset + " = " + indirectTypePosition);
1332            TypeCodeImpl type = topStream.getTypeCodeAtPosition(indirectTypePosition);
1333            if (type == null)
1334                throw wrapper.indirectionNotFound( new Integer(indirectTypePosition) ) ;
1335            setIndirectType(type);
1336            return false;
1337        }
1338
1339        topStream.addTypeCodeAtPosition(this, myPosition);
1340        return true;
1341    }
1342
1343    void read_value_kind(InputStream is) {
1344        // unmarshal the kind
1345        _kind = is.read_long();
1346
1347        // check validity of kind
1348        if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
1349            throw wrapper.cannotMarshalBadTckind() ;
1350        }
1351        // Don't do any work if this is native
1352        if (_kind == TCKind._tk_native)
1353            throw wrapper.cannotMarshalNative() ;
1354
1355        if (_kind == tk_indirect) {
1356            throw wrapper.recursiveTypecodeError() ;
1357        }
1358    }
1359
1360    void read_value_body(InputStream is) {
1361        // start unmarshaling the rest of the typecode, based on the
1362        // encoding (empty, simple or complex).
1363
1364        switch (typeTable[_kind]) {
1365        case EMPTY:
1366            // nothing to unmarshal
1367            break;
1368
1369        case SIMPLE:
1370            switch (_kind) {
1371            case TCKind._tk_string:
1372            case TCKind._tk_wstring:
1373                _length = is.read_long();
1374                break;
1375            case TCKind._tk_fixed:
1376                _digits = is.read_ushort();
1377                _scale = is.read_short();
1378                break;
1379            default:
1380                throw wrapper.invalidSimpleTypecode() ;
1381            }
1382            break;
1383
1384        case COMPLEX:
1385            {
1386                TypeCodeInputStream _encap = TypeCodeInputStream.readEncapsulation(is,
1387                    is.orb());
1388
1389                switch(_kind) {
1390
1391                case TCKind._tk_objref:
1392                case TCKind._tk_abstract_interface:
1393                    {
1394                        // get the repository id
1395                        setId(_encap.read_string());
1396                        // get the name
1397                        _name = _encap.read_string();
1398                    }
1399                    break;
1400
1401                case TCKind._tk_union:
1402                    {
1403                        // get the repository id
1404                        setId(_encap.read_string());
1405
1406                        // get the name
1407                        _name = _encap.read_string();
1408
1409                        // discriminant typecode
1410                        _discriminator = new TypeCodeImpl((ORB)is.orb());
1411                        _discriminator.read_value_recursive(_encap);
1412
1413                        // default index
1414                        _defaultIndex = _encap.read_long();
1415
1416                        // get the number of members
1417                        _memberCount = _encap.read_long();
1418
1419                        // create arrays for the label values, names and types of members
1420                        _unionLabels = new AnyImpl[_memberCount];
1421                        _memberNames = new String[_memberCount];
1422                        _memberTypes = new TypeCodeImpl[_memberCount];
1423
1424                        // read off label values, names and types
1425                        for (int i=0; i < _memberCount; i++) {
1426                            _unionLabels[i] = new AnyImpl((ORB)is.orb());
1427                            if (i == _defaultIndex)
1428                                // for the default case, read off the zero octet
1429                                _unionLabels[i].insert_octet(_encap.read_octet());
1430                            else {
1431                                switch (realType(_discriminator).kind().value()) {
1432                                case TCKind._tk_short:
1433                                    _unionLabels[i].insert_short(_encap.read_short());
1434                                    break;
1435                                case TCKind._tk_long:
1436                                    _unionLabels[i].insert_long(_encap.read_long());
1437                                    break;
1438                                case TCKind._tk_ushort:
1439                                    _unionLabels[i].insert_ushort(_encap.read_short());
1440                                    break;
1441                                case TCKind._tk_ulong:
1442                                    _unionLabels[i].insert_ulong(_encap.read_long());
1443                                    break;
1444                                case TCKind._tk_float:
1445                                    _unionLabels[i].insert_float(_encap.read_float());
1446                                    break;
1447                                case TCKind._tk_double:
1448                                    _unionLabels[i].insert_double(_encap.read_double());
1449                                    break;
1450                                case TCKind._tk_boolean:
1451                                    _unionLabels[i].insert_boolean(_encap.read_boolean());
1452                                    break;
1453                                case TCKind._tk_char:
1454                                    _unionLabels[i].insert_char(_encap.read_char());
1455                                    break;
1456                                case TCKind._tk_enum:
1457                                    _unionLabels[i].type(_discriminator);
1458                                    _unionLabels[i].insert_long(_encap.read_long());
1459                                    break;
1460                                case TCKind._tk_longlong:
1461                                    _unionLabels[i].insert_longlong(_encap.read_longlong());
1462                                    break;
1463                                case TCKind._tk_ulonglong:
1464                                    _unionLabels[i].insert_ulonglong(_encap.read_longlong());
1465                                    break;
1466                                    // _REVISIT_ figure out long double mapping
1467                                    // case TCKind.tk_longdouble:
1468                                    // _unionLabels[i].insert_longdouble(_encap.getDouble());
1469                                    // break;
1470                                case TCKind._tk_wchar:
1471                                    _unionLabels[i].insert_wchar(_encap.read_wchar());
1472                                    break;
1473                                default:
1474                                    throw wrapper.invalidComplexTypecode() ;
1475                                }
1476                            }
1477                            _memberNames[i] = _encap.read_string();
1478                            _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1479                            _memberTypes[i].read_value_recursive(_encap);
1480                            _memberTypes[i].setParent(this);
1481                        }
1482                    }
1483                    break;
1484
1485                case TCKind._tk_enum:
1486                    {
1487                        // get the repository id
1488                        setId(_encap.read_string());
1489
1490                        // get the name
1491                        _name = _encap.read_string();
1492
1493                        // get the number of members
1494                        _memberCount = _encap.read_long();
1495
1496                        // create arrays for the identifier names
1497                        _memberNames = new String[_memberCount];
1498
1499                        // read off identifier names
1500                        for (int i=0; i < _memberCount; i++)
1501                            _memberNames[i] = _encap.read_string();
1502                    }
1503                    break;
1504
1505                case TCKind._tk_sequence:
1506                    {
1507                        // get the type of the sequence
1508                        _contentType = new TypeCodeImpl((ORB)is.orb());
1509                        _contentType.read_value_recursive(_encap);
1510
1511                        // get the bound on the length of the sequence
1512                        _length = _encap.read_long();
1513                    }
1514                    break;
1515
1516                case TCKind._tk_array:
1517                    {
1518                        // get the type of the array
1519                        _contentType = new TypeCodeImpl((ORB)is.orb());
1520                        _contentType.read_value_recursive(_encap);
1521
1522                        // get the length of the array
1523                        _length = _encap.read_long();
1524                    }
1525                    break;
1526
1527                case TCKind._tk_alias:
1528                case TCKind._tk_value_box:
1529                    {
1530                        // get the repository id
1531                        setId(_encap.read_string());
1532
1533                        // get the name
1534                        _name = _encap.read_string();
1535
1536                        // get the type aliased
1537                        _contentType = new TypeCodeImpl((ORB)is.orb());
1538                        _contentType.read_value_recursive(_encap);
1539                    }
1540                    break;
1541
1542                case TCKind._tk_except:
1543                case TCKind._tk_struct:
1544                    {
1545                        // get the repository id
1546                        setId(_encap.read_string());
1547
1548                        // get the name
1549                        _name = _encap.read_string();
1550
1551                        // get the number of members
1552                        _memberCount = _encap.read_long();
1553
1554                        // create arrays for the names and types of members
1555                        _memberNames = new String[_memberCount];
1556                        _memberTypes = new TypeCodeImpl[_memberCount];
1557
1558                        // read off member names and types
1559                        for (int i=0; i < _memberCount; i++) {
1560                            _memberNames[i] = _encap.read_string();
1561                            _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1562                            //if (debug) System.out.println("TypeCode " + _name +
1563                            // " reading member " + _memberNames[i]);
1564                            _memberTypes[i].read_value_recursive(_encap);
1565                            _memberTypes[i].setParent(this);
1566                        }
1567                    }
1568                    break;
1569
1570                case TCKind._tk_value:
1571                    {
1572                        // get the repository id
1573                        setId(_encap.read_string());
1574
1575                        // get the name
1576                        _name = _encap.read_string();
1577
1578                        // get the type modifier
1579                        _type_modifier = _encap.read_short();
1580
1581                        // get the type aliased
1582                        _concrete_base = new TypeCodeImpl((ORB)is.orb());
1583                        _concrete_base.read_value_recursive(_encap);
1584                        if (_concrete_base.kind().value() == TCKind._tk_null) {
1585                            _concrete_base = null;
1586                        }
1587
1588                        // get the number of members
1589                        _memberCount = _encap.read_long();
1590
1591                        // create arrays for the names, types and visibility of members
1592                        _memberNames = new String[_memberCount];
1593                        _memberTypes = new TypeCodeImpl[_memberCount];
1594                        _memberAccess = new short[_memberCount];
1595
1596                        // read off value member visibilities
1597                        for (int i=0; i < _memberCount; i++) {
1598                            _memberNames[i] = _encap.read_string();
1599                            _memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
1600                            //if (debug) System.out.println("TypeCode " + _name +
1601                            // " reading member " + _memberNames[i]);
1602                            _memberTypes[i].read_value_recursive(_encap);
1603                            _memberTypes[i].setParent(this);
1604                            _memberAccess[i] = _encap.read_short();
1605                        }
1606                    }
1607                    break;
1608
1609                default:
1610                    throw wrapper.invalidTypecodeKindMarshal() ;
1611                }
1612                break;
1613            }
1614        }
1615    }
1616
1617    public void write_value(OutputStream os) {
1618        // Wrap OutputStream into TypeCodeOutputStream.
1619        // This test shouldn't be necessary according to the Java language spec.
1620        if (os instanceof TypeCodeOutputStream) {
1621            this.write_value((TypeCodeOutputStream)os);
1622        } else {
1623            TypeCodeOutputStream wrapperOutStream = null;
1624
1625            if (outBuffer == null) {
1626                wrapperOutStream = TypeCodeOutputStream.wrapOutputStream(os);
1627                this.write_value(wrapperOutStream);
1628                if (cachingEnabled) {
1629                    // Cache the buffer for repeated writes
1630                    outBuffer = wrapperOutStream.getTypeCodeBuffer();
1631                    //if (outBuffer != null)
1632                        //System.out.println("Caching outBuffer with length = " +
1633                        //outBuffer.length + " for id = " + _id);
1634                }
1635            } else {
1636                //System.out.println("Using cached outBuffer: length = " + outBuffer.length +
1637                                   //", id = " + _id);
1638            }
1639            // Write the first 4 bytes first to trigger alignment.
1640            // We know that it is the kind.
1641            if (cachingEnabled && outBuffer != null) {
1642                os.write_long(_kind);
1643                os.write_octet_array(outBuffer, 0, outBuffer.length);
1644            } else {
1645                //System.out.println("Buffer is empty for " + _id);
1646                wrapperOutStream.writeRawBuffer(os, _kind);
1647            }
1648        }
1649    }
1650
1651    public void write_value(TypeCodeOutputStream tcos) {
1652
1653        // Don't do any work if this is native
1654        if (_kind == TCKind._tk_native)
1655            throw wrapper.cannotMarshalNative() ;
1656
1657        TypeCodeOutputStream topStream = tcos.getTopLevelStream();
1658        //if (debug) tcos.printBuffer();
1659
1660        if (_kind == tk_indirect) {
1661            //if (debug) System.out.println("Writing indirection " + _name + "to " + _id);
1662            // The encoding used for indirection is the same as that used for recursive ,
1663            // TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
1664            // (in units of octets) from the beginning of the long offset.
1665            int pos = topStream.getPositionForID(_id);
1666            int topPos = tcos.getTopLevelPosition();
1667            //if (debug) System.out.println("TypeCodeImpl " + tcos +
1668            // " writing indirection " + _id +
1669                //" to position " + pos + " at position " + topPos);
1670            tcos.writeIndirection(tk_indirect, pos);
1671            // All that gets written is _kind and offset.
1672            return;
1673        }
1674
1675        // The original approach changed for 5034649
1676        // topStream.addIDAtPosition(_id, tcos.getTopLevelPosition());
1677
1678        // marshal the kind
1679        tcos.write_long(_kind);
1680
1681        //if (debug) System.out.println("Writing " + _name + " with id " + _id);
1682        // We have to remember the stream and position for EVERY type code
1683        // in case some recursive or indirect type code references it.
1684        //
1685        // Bug fix 5034649:
1686        // Do this AFTER the write of the _kind in case the alignment
1687        // for the long changes the position.
1688        topStream.addIDAtPosition(_id, tcos.getTopLevelPosition()-4);
1689
1690        switch (typeTable[_kind]) {
1691        case EMPTY:
1692            // nothing more to marshal
1693            break;
1694
1695        case SIMPLE:
1696            switch (_kind) {
1697            case TCKind._tk_string:
1698            case TCKind._tk_wstring:
1699                // marshal the bound on string length
1700                tcos.write_long(_length);
1701                break;
1702            case TCKind._tk_fixed:
1703                tcos.write_ushort(_digits);
1704                tcos.write_short(_scale);
1705                break;
1706            default:
1707                // unknown typecode kind
1708                throw wrapper.invalidSimpleTypecode() ;
1709            }
1710            break;
1711
1712        case COMPLEX:
1713            {
1714                // create an encapsulation
1715                TypeCodeOutputStream _encap = tcos.createEncapsulation(tcos.orb());
1716
1717                switch(_kind) {
1718
1719                case TCKind._tk_objref:
1720                case TCKind._tk_abstract_interface:
1721                    {
1722                        // put the repository id
1723                        _encap.write_string(_id);
1724
1725                        // put the name
1726                        _encap.write_string(_name);
1727                    }
1728                    break;
1729
1730                case TCKind._tk_union:
1731                    {
1732                        // put the repository id
1733                        _encap.write_string(_id);
1734
1735                        // put the name
1736                        _encap.write_string(_name);
1737
1738                        // discriminant typecode
1739                        _discriminator.write_value(_encap);
1740
1741                        // default index
1742                        _encap.write_long(_defaultIndex);
1743
1744                        // put the number of members
1745                        _encap.write_long(_memberCount);
1746
1747                        // marshal label values, names and types
1748                        for (int i=0; i < _memberCount; i++) {
1749
1750                            // for the default case, marshal the zero octet
1751                            if (i == _defaultIndex)
1752                                _encap.write_octet(_unionLabels[i].extract_octet());
1753
1754                            else {
1755                                switch (realType(_discriminator).kind().value()) {
1756                                case TCKind._tk_short:
1757                                    _encap.write_short(_unionLabels[i].extract_short());
1758                                    break;
1759                                case TCKind._tk_long:
1760                                    _encap.write_long(_unionLabels[i].extract_long());
1761                                    break;
1762                                case TCKind._tk_ushort:
1763                                    _encap.write_short(_unionLabels[i].extract_ushort());
1764                                    break;
1765                                case TCKind._tk_ulong:
1766                                    _encap.write_long(_unionLabels[i].extract_ulong());
1767                                    break;
1768                                case TCKind._tk_float:
1769                                    _encap.write_float(_unionLabels[i].extract_float());
1770                                    break;
1771                                case TCKind._tk_double:
1772                                    _encap.write_double(_unionLabels[i].extract_double());
1773                                    break;
1774                                case TCKind._tk_boolean:
1775                                    _encap.write_boolean(_unionLabels[i].extract_boolean());
1776                                    break;
1777                                case TCKind._tk_char:
1778                                    _encap.write_char(_unionLabels[i].extract_char());
1779                                    break;
1780                                case TCKind._tk_enum:
1781                                    _encap.write_long(_unionLabels[i].extract_long());
1782                                    break;
1783                                case TCKind._tk_longlong:
1784                                    _encap.write_longlong(_unionLabels[i].extract_longlong());
1785                                    break;
1786                                case TCKind._tk_ulonglong:
1787                                    _encap.write_longlong(_unionLabels[i].extract_ulonglong());
1788                                    break;
1789                                    // _REVISIT_ figure out long double mapping
1790                                    // case TCKind.tk_longdouble:
1791                                    // _encap.putDouble(_unionLabels[i].extract_longdouble());
1792                                    // break;
1793                                case TCKind._tk_wchar:
1794                                    _encap.write_wchar(_unionLabels[i].extract_wchar());
1795                                    break;
1796                                default:
1797                                    throw wrapper.invalidComplexTypecode() ;
1798                                }
1799                            }
1800                            _encap.write_string(_memberNames[i]);
1801                            _memberTypes[i].write_value(_encap);
1802                        }
1803                    }
1804                    break;
1805
1806                case TCKind._tk_enum:
1807                    {
1808                        // put the repository id
1809                        _encap.write_string(_id);
1810
1811                        // put the name
1812                        _encap.write_string(_name);
1813
1814                        // put the number of members
1815                        _encap.write_long(_memberCount);
1816
1817                        // marshal identifier names
1818                        for (int i=0; i < _memberCount; i++)
1819                            _encap.write_string(_memberNames[i]);
1820                    }
1821                    break;
1822
1823                case TCKind._tk_sequence:
1824                    {
1825                        // put the type of the sequence
1826                        lazy_content_type().write_value(_encap);
1827
1828                        // put the bound on the length of the sequence
1829                        _encap.write_long(_length);
1830                    }
1831                    break;
1832
1833                case TCKind._tk_array:
1834                    {
1835                        // put the type of the array
1836                        _contentType.write_value(_encap);
1837
1838                        // put the length of the array
1839                        _encap.write_long(_length);
1840                    }
1841                    break;
1842
1843                case TCKind._tk_alias:
1844                case TCKind._tk_value_box:
1845                    {
1846                        // put the repository id
1847                        _encap.write_string(_id);
1848
1849                        // put the name
1850                        _encap.write_string(_name);
1851
1852                        // put the type aliased
1853                        _contentType.write_value(_encap);
1854                    }
1855                    break;
1856
1857                case TCKind._tk_struct:
1858                case TCKind._tk_except:
1859                    {
1860                        // put the repository id
1861                        _encap.write_string(_id);
1862
1863                        // put the name
1864                        _encap.write_string(_name);
1865
1866                        // put the number of members
1867                        _encap.write_long(_memberCount);
1868
1869                        // marshal member names and types
1870                        for (int i=0; i < _memberCount; i++) {
1871                            _encap.write_string(_memberNames[i]);
1872                            //if (debug) System.out.println("TypeCode " + _name +
1873                            // " writing member " + _memberNames[i]);
1874                            _memberTypes[i].write_value(_encap);
1875                        }
1876                    }
1877                    break;
1878
1879                case TCKind._tk_value:
1880                    {
1881                        // put the repository id
1882                        _encap.write_string(_id);
1883
1884                        // put the name
1885                        _encap.write_string(_name);
1886
1887                        // put the type modifier
1888                        _encap.write_short(_type_modifier);
1889
1890                        // put the type aliased
1891                        if (_concrete_base == null) {
1892                            _orb.get_primitive_tc(TCKind._tk_null).write_value(_encap);
1893                        } else {
1894                            _concrete_base.write_value(_encap);
1895                        }
1896
1897                        // put the number of members
1898                        _encap.write_long(_memberCount);
1899
1900                        // marshal member names and types
1901                        for (int i=0; i < _memberCount; i++) {
1902                            _encap.write_string(_memberNames[i]);
1903                            //if (debug) System.out.println("TypeCode " + _name +
1904                            // " writing member " + _memberNames[i]);
1905                            _memberTypes[i].write_value(_encap);
1906                            _encap.write_short(_memberAccess[i]);
1907                        }
1908                    }
1909                    break;
1910
1911                default:
1912                    throw wrapper.invalidTypecodeKindMarshal() ;
1913                }
1914
1915                // marshal the encapsulation
1916                _encap.writeOctetSequenceTo(tcos);
1917                break;
1918            }
1919        }
1920    }
1921
1922    /**
1923     * This is not a copy of the TypeCodeImpl objects, but instead it
1924     * copies the value this type code is representing.
1925     * See AnyImpl read_value and write_value for usage.
1926     * The state of this TypeCodeImpl instance isn't changed, only used
1927     * by the Any to do the correct copy.
1928     */
1929    protected void copy(org.omg.CORBA.portable.InputStream src,
1930        org.omg.CORBA.portable.OutputStream dst)
1931    {
1932        switch (_kind) {
1933
1934        case TCKind._tk_null:
1935        case TCKind._tk_void:
1936        case TCKind._tk_native:
1937        case TCKind._tk_abstract_interface:
1938            break;
1939
1940        case TCKind._tk_short:
1941        case TCKind._tk_ushort:
1942            dst.write_short(src.read_short());
1943            break;
1944
1945        case TCKind._tk_long:
1946        case TCKind._tk_ulong:
1947            dst.write_long(src.read_long());
1948            break;
1949
1950        case TCKind._tk_float:
1951            dst.write_float(src.read_float());
1952            break;
1953
1954        case TCKind._tk_double:
1955            dst.write_double(src.read_double());
1956            break;
1957
1958        case TCKind._tk_longlong:
1959        case TCKind._tk_ulonglong:
1960            dst.write_longlong(src.read_longlong());
1961            break;
1962
1963        case TCKind._tk_longdouble:
1964            throw wrapper.tkLongDoubleNotSupported() ;
1965
1966        case TCKind._tk_boolean:
1967            dst.write_boolean(src.read_boolean());
1968            break;
1969
1970        case TCKind._tk_char:
1971            dst.write_char(src.read_char());
1972            break;
1973
1974        case TCKind._tk_wchar:
1975            dst.write_wchar(src.read_wchar());
1976            break;
1977
1978        case TCKind._tk_octet:
1979            dst.write_octet(src.read_octet());
1980            break;
1981
1982        case TCKind._tk_string:
1983            {
1984                String s;
1985                s = src.read_string();
1986                // make sure length bound in typecode is not violated
1987                if ((_length != 0) && (s.length() > _length))
1988                    throw wrapper.badStringBounds( new Integer(s.length()),
1989                        new Integer(_length) ) ;
1990                dst.write_string(s);
1991            }
1992            break;
1993
1994        case TCKind._tk_wstring:
1995            {
1996                String s;
1997                s = src.read_wstring();
1998                // make sure length bound in typecode is not violated
1999                if ((_length != 0) && (s.length() > _length))
2000                    throw wrapper.badStringBounds( new Integer(s.length()),
2001                        new Integer(_length) ) ;
2002                dst.write_wstring(s);
2003            }
2004            break;
2005
2006        case TCKind._tk_fixed:
2007            {
2008                dst.write_ushort(src.read_ushort());
2009                dst.write_short(src.read_short());
2010            }
2011            break;
2012
2013        case TCKind._tk_any:
2014            {
2015                //Any tmp = new AnyImpl(_orb);
2016                Any tmp =  ((CDRInputStream)src).orb().create_any();
2017                TypeCodeImpl t = new TypeCodeImpl((ORB)dst.orb());
2018                t.read_value((org.omg.CORBA_2_3.portable.InputStream)src);
2019                t.write_value((org.omg.CORBA_2_3.portable.OutputStream)dst);
2020                tmp.read_value(src, t);
2021                tmp.write_value(dst);
2022                break;
2023            }
2024
2025        case TCKind._tk_TypeCode:
2026            {
2027                dst.write_TypeCode(src.read_TypeCode());
2028                break;
2029            }
2030
2031        case TCKind._tk_Principal:
2032            {
2033                dst.write_Principal(src.read_Principal());
2034                break;
2035            }
2036
2037        case TCKind._tk_objref:
2038            {
2039                dst.write_Object(src.read_Object());
2040                break;
2041            }
2042
2043        case TCKind._tk_except:
2044            // Copy repositoryId
2045            dst.write_string(src.read_string());
2046
2047            // Fall into ...
2048        // _REVISIT_ what about the inherited members of this values concrete base type?
2049        case TCKind._tk_value:
2050        case TCKind._tk_struct:
2051            {
2052                // copy each element, using the corresponding member type
2053                for (int i=0; i < _memberTypes.length; i++) {
2054                    _memberTypes[i].copy(src, dst);
2055                }
2056                break;
2057            }
2058        case TCKind._tk_union:
2059    /* _REVISIT_ More generic code?
2060            {
2061                Any discriminator = new AnyImpl(_orb);
2062                discriminator.read_value(src, _discriminator);
2063                discriminator.write_value(dst);
2064                int labelIndex = currentUnionMemberIndex(discriminator);
2065                if (labelIndex == -1) {
2066                    // check if label has not been found
2067                    if (_defaultIndex == -1)
2068                        // throw exception if default was not expected
2069                        throw new MARSHAL();
2070                    else
2071                        // must be of the default branch type
2072                        _memberTypes[_defaultIndex].copy(src, dst);
2073                } else {
2074                    _memberTypes[labelIndex].copy(src, dst);
2075                }
2076            }
2077    */
2078            {
2079                Any tagValue = new AnyImpl( (ORB)src.orb());
2080
2081                switch  (realType(_discriminator).kind().value()) {
2082                case TCKind._tk_short:
2083                    {
2084                        short value = src.read_short();
2085                        tagValue.insert_short(value);
2086                        dst.write_short(value);
2087                        break;
2088                    }
2089                case TCKind._tk_long:
2090                    {
2091                        int value = src.read_long();
2092                        tagValue.insert_long(value);
2093                        dst.write_long(value);
2094                        break;
2095                    }
2096                case TCKind._tk_ushort:
2097                    {
2098                        short value = src.read_short();
2099                        tagValue.insert_ushort(value);
2100                        dst.write_short(value);
2101                        break;
2102                    }
2103                case TCKind._tk_ulong:
2104                    {
2105                        int value = src.read_long();
2106                        tagValue.insert_ulong(value);
2107                        dst.write_long(value);
2108                        break;
2109                    }
2110                case TCKind._tk_float:
2111                    {
2112                        float value = src.read_float();
2113                        tagValue.insert_float(value);
2114                        dst.write_float(value);
2115                        break;
2116                    }
2117                case TCKind._tk_double:
2118                    {
2119                        double value = src.read_double();
2120                        tagValue.insert_double(value);
2121                        dst.write_double(value);
2122                        break;
2123                    }
2124                case TCKind._tk_boolean:
2125                    {
2126                        boolean value = src.read_boolean();
2127                        tagValue.insert_boolean(value);
2128                        dst.write_boolean(value);
2129                        break;
2130                    }
2131                case TCKind._tk_char:
2132                    {
2133                        char value = src.read_char();
2134                        tagValue.insert_char(value);
2135                        dst.write_char(value);
2136                        break;
2137                    }
2138                case TCKind._tk_enum:
2139                    {
2140                        int value = src.read_long();
2141                        tagValue.type(_discriminator);
2142                        tagValue.insert_long(value);
2143                        dst.write_long(value);
2144                        break;
2145                    }
2146                case TCKind._tk_longlong:
2147                    {
2148                        long value = src.read_longlong();
2149                        tagValue.insert_longlong(value);
2150                        dst.write_longlong(value);
2151                        break;
2152                    }
2153                case TCKind._tk_ulonglong:
2154                    {
2155                        long value = src.read_longlong();
2156                        tagValue.insert_ulonglong(value);
2157                        dst.write_longlong(value);
2158                        break;
2159                    }
2160                    // _REVISIT_ figure out long double mapping
2161                    // case TCKind.tk_longdouble:
2162                    // {
2163                    // double value = src.read_double();
2164                    //  tagValue.insert_longdouble(value);
2165                    //  dst.putDouble(value);
2166                    //  break;
2167                    //}
2168                case TCKind._tk_wchar:
2169                    {
2170                        char value = src.read_wchar();
2171                        tagValue.insert_wchar(value);
2172                        dst.write_wchar(value);
2173                        break;
2174                    }
2175                default:
2176                    throw wrapper.illegalUnionDiscriminatorType() ;
2177                }
2178
2179                // using the value of the tag, find out the type of the value
2180                // following.
2181
2182                int labelIndex;
2183                for (labelIndex = 0; labelIndex < _unionLabels.length; labelIndex++) {
2184                    // use equality over anys
2185                    if (tagValue.equal(_unionLabels[labelIndex])) {
2186                        _memberTypes[labelIndex].copy(src, dst);
2187                        break;
2188                    }
2189                }
2190
2191                if (labelIndex == _unionLabels.length) {
2192                    // check if label has not been found
2193                    if (_defaultIndex != -1)
2194                        // must be of the default branch type
2195                        _memberTypes[_defaultIndex].copy(src, dst);
2196                }
2197                break;
2198            }
2199
2200        case TCKind._tk_enum:
2201            dst.write_long(src.read_long());
2202            break;
2203
2204        case TCKind._tk_sequence:
2205            // get the length of the sequence
2206            int seqLength = src.read_long();
2207
2208            // check for sequence bound violated
2209            if ((_length != 0) && (seqLength > _length))
2210                throw wrapper.badSequenceBounds( new Integer(seqLength),
2211                    new Integer(_length) ) ;
2212
2213            // write the length of the sequence
2214            dst.write_long(seqLength);
2215
2216            // copy each element of the seq using content type
2217            lazy_content_type(); // make sure it's resolved
2218            for (int i=0; i < seqLength; i++)
2219                _contentType.copy(src, dst);
2220            break;
2221
2222        case TCKind._tk_array:
2223            // copy each element of the array using content type
2224            for (int i=0; i < _length; i++)
2225                _contentType.copy(src, dst);
2226            break;
2227
2228        case TCKind._tk_alias:
2229        case TCKind._tk_value_box:
2230            // follow the alias
2231            _contentType.copy(src, dst);
2232            break;
2233
2234        case tk_indirect:
2235            // need to follow offset, get unmarshal typecode from that
2236            // offset, and use that to do the copy
2237            // Don't need to read type code before using it to do the copy.
2238            // It should be fully usable.
2239            indirectType().copy(src, dst);
2240            break;
2241
2242        default:
2243            throw wrapper.invalidTypecodeKindMarshal() ;
2244        }
2245    }
2246
2247
2248    static protected short digits(java.math.BigDecimal value) {
2249        if (value == null)
2250            return 0;
2251        short length = (short)value.unscaledValue().toString().length();
2252        if (value.signum() == -1)
2253            length--;
2254        return length;
2255    }
2256
2257    static protected short scale(java.math.BigDecimal value) {
2258        if (value == null)
2259            return 0;
2260        return (short)value.scale();
2261    }
2262
2263    // Utility methods
2264
2265    // Only for union type. Returns the index of the union member
2266    // corresponding to the discriminator. If not found returns the
2267    // default index or -1 if there is no default index.
2268    int currentUnionMemberIndex(Any discriminatorValue) throws BadKind {
2269        if (_kind != TCKind._tk_union)
2270            throw new BadKind();
2271
2272        try {
2273            for (int i=0; i<member_count(); i++) {
2274                if (member_label(i).equal(discriminatorValue)) {
2275                    return i;
2276                }
2277            }
2278            if (_defaultIndex != -1) {
2279                return _defaultIndex;
2280            }
2281        } catch (BadKind bad) {
2282        } catch (org.omg.CORBA.TypeCodePackage.Bounds bounds) {
2283        }
2284        return -1;
2285    }
2286
2287    public String description() {
2288        return "TypeCodeImpl with kind " + _kind + " and id " + _id;
2289    }
2290
2291    public String toString() {
2292        ByteArrayOutputStream byteOut = new ByteArrayOutputStream(1024);
2293        PrintStream printOut = new PrintStream(byteOut, true);
2294        printStream(printOut);
2295        return super.toString() + " =\n" + byteOut.toString();
2296    }
2297
2298    public void printStream(PrintStream s) {
2299        printStream(s, 0);
2300    }
2301
2302    private void printStream(PrintStream s, int level) {
2303        if (_kind == tk_indirect) {
2304            s.print("indirect " + _id);
2305            return;
2306        }
2307
2308        switch (_kind) {
2309            case TCKind._tk_null:
2310            case TCKind._tk_void:
2311            case TCKind._tk_short:
2312            case TCKind._tk_long:
2313            case TCKind._tk_ushort:
2314            case TCKind._tk_ulong:
2315            case TCKind._tk_float:
2316            case TCKind._tk_double:
2317            case TCKind._tk_boolean:
2318            case TCKind._tk_char:
2319            case TCKind._tk_octet:
2320            case TCKind._tk_any:
2321            case TCKind._tk_TypeCode:
2322            case TCKind._tk_Principal:
2323            case TCKind._tk_objref:
2324            case TCKind._tk_longlong:
2325            case TCKind._tk_ulonglong:
2326            case TCKind._tk_longdouble:
2327            case TCKind._tk_wchar:
2328            case TCKind._tk_native:
2329                s.print(kindNames[_kind] + " " + _name);
2330                break;
2331
2332            case TCKind._tk_struct:
2333            case TCKind._tk_except:
2334            case TCKind._tk_value:
2335                s.println(kindNames[_kind] + " " + _name + " = {");
2336                for(int i=0; i<_memberCount; i++) {
2337                    // memberName might differ from the name of the member.
2338                    s.print(indent(level + 1));
2339                    if (_memberTypes[i] != null)
2340                        _memberTypes[i].printStream(s, level + 1);
2341                    else
2342                        s.print("<unknown type>");
2343                    s.println(" " + _memberNames[i] + ";");
2344                }
2345                s.print(indent(level) + "}");
2346                break;
2347
2348            case TCKind._tk_union:
2349                s.print("union " + _name + "...");
2350                break;
2351
2352            case TCKind._tk_enum:
2353                s.print("enum " + _name + "...");
2354                break;
2355
2356            case TCKind._tk_string:
2357                if (_length == 0)
2358                    s.print("unbounded string " + _name);
2359                else
2360                    s.print("bounded string(" + _length + ") " + _name);
2361                break;
2362
2363            case TCKind._tk_sequence:
2364            case TCKind._tk_array:
2365                s.println(kindNames[_kind] + "[" + _length + "] " + _name + " = {");
2366                s.print(indent(level + 1));
2367                if (lazy_content_type() != null) {
2368                    lazy_content_type().printStream(s, level + 1);
2369                }
2370                s.println(indent(level) + "}");
2371                break;
2372
2373            case TCKind._tk_alias:
2374                s.print("alias " + _name + " = " +
2375                    (_contentType != null ? _contentType._name : "<unresolved>"));
2376                break;
2377
2378            case TCKind._tk_wstring:
2379                s.print("wstring[" + _length + "] " + _name);
2380                break;
2381
2382            case TCKind._tk_fixed:
2383                s.print("fixed(" + _digits + ", " + _scale + ") " + _name);
2384                break;
2385
2386            case TCKind._tk_value_box:
2387                s.print("valueBox " + _name + "...");
2388                break;
2389
2390            case TCKind._tk_abstract_interface:
2391                s.print("abstractInterface " + _name + "...");
2392                break;
2393
2394            default:
2395                s.print("<unknown type>");
2396                break;
2397        }
2398    }
2399
2400    private String indent(int level) {
2401        String indent = "";
2402        for(int i=0; i<level; i++) {
2403            indent += "  ";
2404        }
2405        return indent;
2406    }
2407
2408    protected void setCaching(boolean enableCaching) {
2409        cachingEnabled = enableCaching;
2410        if (enableCaching == false)
2411            outBuffer = null;
2412    }
2413}
2414