blob: 4e90f7f2a323bf0a14faeef8c17cfa073d2d45fb [file] [log] [blame]
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.corba.se.impl.corba;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
import java.io.IOException;
import java.io.PrintStream;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.omg.CORBA.TypeCode ;
import org.omg.CORBA.StructMember ;
import org.omg.CORBA.UnionMember ;
import org.omg.CORBA.ValueMember ;
import org.omg.CORBA.TCKind ;
import org.omg.CORBA.Any ;
import org.omg.CORBA.Principal ;
import org.omg.CORBA.BAD_TYPECODE ;
import org.omg.CORBA.BAD_PARAM ;
import org.omg.CORBA.BAD_OPERATION ;
import org.omg.CORBA.INTERNAL ;
import org.omg.CORBA.MARSHAL ;
import org.omg.CORBA.TypeCodePackage.BadKind ;
import org.omg.CORBA_2_3.portable.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;
import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
import com.sun.corba.se.impl.encoding.MarshalInputStream;
import com.sun.corba.se.impl.encoding.CodeSetConversion;
import com.sun.corba.se.impl.encoding.CDRInputStream;
import com.sun.corba.se.impl.encoding.CDROutputStream;
import com.sun.corba.se.impl.encoding.TypeCodeInputStream;
import com.sun.corba.se.impl.encoding.TypeCodeOutputStream;
import com.sun.corba.se.impl.encoding.TypeCodeReader;
import com.sun.corba.se.impl.encoding.WrapperInputStream;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
// no chance of subclasses, so no problems with runtime helper lookup
public final class TypeCodeImpl extends TypeCode
{
//static final boolean debug = false;
// the indirection TCKind, needed for recursive typecodes.
protected static final int tk_indirect = 0xFFFFFFFF;
// typecode encodings have three different categories that determine
// how the encoding should be done.
private static final int EMPTY = 0; // no parameters
private static final int SIMPLE = 1; // simple parameters.
private static final int COMPLEX = 2; // complex parameters. need to
// use CDR encapsulation for
// parameters
// a table storing the encoding category for the various typecodes.
private static final int typeTable[] = {
EMPTY, // tk_null
EMPTY, // tk_void
EMPTY, // tk_short
EMPTY, // tk_long
EMPTY, // tk_ushort
EMPTY, // tk_ulong
EMPTY, // tk_float
EMPTY, // tk_double
EMPTY, // tk_boolean
EMPTY, // tk_char
EMPTY, // tk_octet
EMPTY, // tk_any
EMPTY, // tk_typecode
EMPTY, // tk_principal
COMPLEX, // tk_objref
COMPLEX, // tk_struct
COMPLEX, // tk_union
COMPLEX, // tk_enum
SIMPLE, // tk_string
COMPLEX, // tk_sequence
COMPLEX, // tk_array
COMPLEX, // tk_alias
COMPLEX, // tk_except
EMPTY, // tk_longlong
EMPTY, // tk_ulonglong
EMPTY, // tk_longdouble
EMPTY, // tk_wchar
SIMPLE, // tk_wstring
SIMPLE, // tk_fixed
COMPLEX, // tk_value
COMPLEX, // tk_value_box
COMPLEX, // tk_native
COMPLEX // tk_abstract_interface
};
// Maps TCKind values to names
// This is also used in AnyImpl.
static final String[] kindNames = {
"null",
"void",
"short",
"long",
"ushort",
"ulong",
"float",
"double",
"boolean",
"char",
"octet",
"any",
"typecode",
"principal",
"objref",
"struct",
"union",
"enum",
"string",
"sequence",
"array",
"alias",
"exception",
"longlong",
"ulonglong",
"longdouble",
"wchar",
"wstring",
"fixed",
"value",
"valueBox",
"native",
"abstractInterface"
};
private int _kind = 0; // the typecode kind
// data members for representing the various kinds of typecodes.
private String _id = ""; // the typecode repository id
private String _name = ""; // the typecode name
private int _memberCount = 0; // member count
private String _memberNames[] = null; // names of members
private TypeCodeImpl _memberTypes[] = null; // types of members
private AnyImpl _unionLabels[] = null; // values of union labels
private TypeCodeImpl _discriminator = null; // union discriminator type
private int _defaultIndex = -1; // union default index
private int _length = 0; // string/seq/array length
private TypeCodeImpl _contentType = null; // seq/array/alias type
// fixed
private short _digits = 0;
private short _scale = 0;
// value type
// _REVISIT_ We might want to keep references to the ValueMember classes
// passed in at initialization instead of copying the relevant data.
// Is the data immutable? What about StructMember, UnionMember etc.?
private short _type_modifier = -1; // VM_NONE, VM_CUSTOM,
// VM_ABSTRACT, VM_TRUNCATABLE
private TypeCodeImpl _concrete_base = null; // concrete base type
private short _memberAccess[] = null; // visibility of ValueMember
// recursive sequence support
private TypeCodeImpl _parent = null; // the enclosing type code
private int _parentOffset = 0; // the level of enclosure
// recursive type code support
private TypeCodeImpl _indirectType = null;
// caches the byte buffer written in write_value for quick remarshaling...
private byte[] outBuffer = null;
// ... but only if caching is enabled
private boolean cachingEnabled = false;
// the ORB instance: may be instanceof ORBSingleton or ORB
private ORB _orb;
private ORBUtilSystemException wrapper ;
///////////////////////////////////////////////////////////////////////////
// Constructors...
public TypeCodeImpl(ORB orb)
{
// initialized to tk_null
_orb = orb;
wrapper = ORBUtilSystemException.get(
(com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PRESENTATION ) ;
}
public TypeCodeImpl(ORB orb, TypeCode tc)
// to handle conversion of "remote" typecodes into "native" style.
// also see the 'convertToNative(ORB orb, TypeCode tc)' function
{
this(orb) ;
// This is a protection against misuse of this constructor.
// Should only be used if tc is not an instance of this class!
// Otherwise we run into problems with recursive/indirect type codes.
// _REVISIT_ We should make this constructor private
if (tc instanceof TypeCodeImpl) {
TypeCodeImpl tci = (TypeCodeImpl)tc;
if (tci._kind == tk_indirect)
throw wrapper.badRemoteTypecode() ;
if (tci._kind == TCKind._tk_sequence && tci._contentType == null)
throw wrapper.badRemoteTypecode() ;
}
// set up kind
_kind = tc.kind().value();
try {
// set up parameters
switch (_kind) {
case TCKind._tk_value:
_type_modifier = tc.type_modifier();
// concrete base may be null
TypeCode tccb = tc.concrete_base_type();
if (tccb != null) {
_concrete_base = convertToNative(_orb, tccb);
} else {
_concrete_base = null;
}
//_memberAccess = tc._memberAccess;
// Need to reconstruct _memberAccess using member_count() and member_visibility()
_memberAccess = new short[tc.member_count()];
for (int i=0; i < tc.member_count(); i++) {
_memberAccess[i] = tc.member_visibility(i);
}
case TCKind._tk_except:
case TCKind._tk_struct:
case TCKind._tk_union:
// set up member types
_memberTypes = new TypeCodeImpl[tc.member_count()];
for (int i=0; i < tc.member_count(); i++) {
_memberTypes[i] = convertToNative(_orb, tc.member_type(i));
_memberTypes[i].setParent(this);
}
case TCKind._tk_enum:
// set up member names
_memberNames = new String[tc.member_count()];
for (int i=0; i < tc.member_count(); i++) {
_memberNames[i] = tc.member_name(i);
}
// set up member count
_memberCount = tc.member_count();
case TCKind._tk_objref:
case TCKind._tk_alias:
case TCKind._tk_value_box:
case TCKind._tk_native:
case TCKind._tk_abstract_interface:
setId(tc.id());
_name = tc.name();
break;
}
// set up stuff for unions
switch (_kind) {
case TCKind._tk_union:
_discriminator = convertToNative(_orb, tc.discriminator_type());
_defaultIndex = tc.default_index();
_unionLabels = new AnyImpl[_memberCount];
for (int i=0; i < _memberCount; i++)
_unionLabels[i] = new AnyImpl(_orb, tc.member_label(i));
break;
}
// set up length
switch (_kind) {
case TCKind._tk_string:
case TCKind._tk_wstring:
case TCKind._tk_sequence:
case TCKind._tk_array:
_length = tc.length();
}
// set up content type
switch (_kind) {
case TCKind._tk_sequence:
case TCKind._tk_array:
case TCKind._tk_alias:
case TCKind._tk_value_box:
_contentType = convertToNative(_orb, tc.content_type());
}
} catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
// dont have to worry about these since code ensures we dont step
// out of bounds.
}
public TypeCodeImpl(ORB orb, int creationKind)
// for primitive types
{
this(orb);
// private API. dont bother checking that
// (creationKind < 0 || creationKind > typeTable.length)
_kind = creationKind;
// do initialization for special cases
switch (_kind) {
case TCKind._tk_objref:
{
// this is being used to create typecode for CORBA::Object
setId("IDL:omg.org/CORBA/Object:1.0");
_name = "Object";
break;
}
case TCKind._tk_string:
case TCKind._tk_wstring:
{
_length =0;
break;
}
case TCKind._tk_value:
{
_concrete_base = null;
break;
}
}
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name,
StructMember[] members)
// for structs and exceptions
{
this(orb);
if ((creationKind == TCKind._tk_struct) || (creationKind == TCKind._tk_except)) {
_kind = creationKind;
setId(id);
_name = name;
_memberCount = members.length;
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
for (int i = 0 ; i < _memberCount ; i++) {
_memberNames[i] = members[i].name;
_memberTypes[i] = convertToNative(_orb, members[i].type);
_memberTypes[i].setParent(this);
}
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name,
TypeCode discriminator_type,
UnionMember[] members)
// for unions
{
this(orb) ;
if (creationKind == TCKind._tk_union) {
_kind = creationKind;
setId(id);
_name = name;
_memberCount = members.length;
_discriminator = convertToNative(_orb, discriminator_type);
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
_unionLabels = new AnyImpl[_memberCount];
for (int i = 0 ; i < _memberCount ; i++) {
_memberNames[i] = members[i].name;
_memberTypes[i] = convertToNative(_orb, members[i].type);
_memberTypes[i].setParent(this);
_unionLabels[i] = new AnyImpl(_orb, members[i].label);
// check whether this is the default branch.
if (_unionLabels[i].type().kind() == TCKind.tk_octet) {
if (_unionLabels[i].extract_octet() == (byte)0) {
_defaultIndex = i;
}
}
}
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name,
short type_modifier,
TypeCode concrete_base,
ValueMember[] members)
// for value types
{
this(orb) ;
if (creationKind == TCKind._tk_value) {
_kind = creationKind;
setId(id);
_name = name;
_type_modifier = type_modifier;
if (concrete_base != null) {
_concrete_base = convertToNative(_orb, concrete_base);
}
_memberCount = members.length;
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
_memberAccess = new short[_memberCount];
for (int i = 0 ; i < _memberCount ; i++) {
_memberNames[i] = members[i].name;
_memberTypes[i] = convertToNative(_orb, members[i].type);
_memberTypes[i].setParent(this);
_memberAccess[i] = members[i].access;
}
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name,
String[] members)
// for enums
{
this(orb) ;
if (creationKind == TCKind._tk_enum)
{
_kind = creationKind;
setId(id);
_name = name;
_memberCount = members.length;
_memberNames = new String[_memberCount];
for (int i = 0 ; i < _memberCount ; i++)
_memberNames[i] = members[i];
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name,
TypeCode original_type)
// for aliases and value boxes
{
this(orb) ;
if ( creationKind == TCKind._tk_alias || creationKind == TCKind._tk_value_box )
{
_kind = creationKind;
setId(id);
_name = name;
_contentType = convertToNative(_orb, original_type);
}
// else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
String id,
String name)
{
this(orb) ;
if (creationKind == TCKind._tk_objref ||
creationKind == TCKind._tk_native ||
creationKind == TCKind._tk_abstract_interface)
{
_kind = creationKind;
setId(id);
_name = name;
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
int bound)
// for strings
{
this(orb) ;
if (bound < 0)
throw wrapper.negativeBounds() ;
if ((creationKind == TCKind._tk_string) || (creationKind == TCKind._tk_wstring)) {
_kind = creationKind;
_length = bound;
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
int bound,
TypeCode element_type)
// for sequences and arrays
{
this(orb) ;
if ( creationKind == TCKind._tk_sequence || creationKind == TCKind._tk_array ) {
_kind = creationKind;
_length = bound;
_contentType = convertToNative(_orb, element_type);
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
int creationKind,
int bound,
int offset)
// for recursive sequences
{
this(orb) ;
if (creationKind == TCKind._tk_sequence) {
_kind = creationKind;
_length = bound;
_parentOffset = offset;
} // else initializes to null
}
public TypeCodeImpl(ORB orb,
String id)
// for recursive type codes
{
this(orb) ;
_kind = tk_indirect;
// This is the type code of the type we stand in for, not our own.
_id = id;
// Try to resolve it now. May return null in which case
// we try again later (see indirectType()).
tryIndirectType();
}
public TypeCodeImpl(ORB orb,
int creationKind,
short digits,
short scale)
// for fixed
{
this(orb) ;
//if (digits < 1 || digits > 31)
//throw new BAD_TYPECODE();
if (creationKind == TCKind._tk_fixed) {
_kind = creationKind;
_digits = digits;
_scale = scale;
} // else initializes to null
}
///////////////////////////////////////////////////////////////////////////
// Other creation functions...
// Optimization:
// If we checked for and returned constant primitive typecodes
// here we could reduce object creation and also enable more
// efficient typecode comparisons for primitive typecodes.
//
protected static TypeCodeImpl convertToNative(ORB orb,
TypeCode tc)
{
if (tc instanceof TypeCodeImpl)
return (TypeCodeImpl) tc;
else
return new TypeCodeImpl(orb, tc);
}
public static CDROutputStream newOutputStream(ORB orb) {
TypeCodeOutputStream tcos =
sun.corba.OutputStreamFactory.newTypeCodeOutputStream(orb);
//if (debug) System.out.println("Created TypeCodeOutputStream " + tcos +
// " with no parent");
return tcos;
}
// Support for indirect/recursive type codes
private TypeCodeImpl indirectType() {
_indirectType = tryIndirectType();
if (_indirectType == null) {
// Nothing we can do about that.
throw wrapper.unresolvedRecursiveTypecode() ;
}
return _indirectType;
}
private TypeCodeImpl tryIndirectType() {
// Assert that _kind == tk_indirect
if (_indirectType != null)
return _indirectType;
setIndirectType(_orb.getTypeCode(_id));
return _indirectType;
}
private void setIndirectType(TypeCodeImpl newType) {
_indirectType = newType;
if (_indirectType != null) {
try {
_id = _indirectType.id();
} catch (BadKind e) {
// can't happen
throw wrapper.badkindCannotOccur() ;
}
}
}
private void setId(String newID) {
_id = newID;
if (_orb instanceof TypeCodeFactory) {
((TypeCodeFactory)_orb).setTypeCode(_id, this);
}
// check whether return value != this which would indicate that the
// repository id isn't unique.
}
private void setParent(TypeCodeImpl parent) {
_parent = parent;
}
private TypeCodeImpl getParentAtLevel(int level) {
if (level == 0)
return this;
if (_parent == null)
throw wrapper.unresolvedRecursiveTypecode() ;
return _parent.getParentAtLevel(level - 1);
}
private TypeCodeImpl lazy_content_type() {
if (_contentType == null) {
if (_kind == TCKind._tk_sequence && _parentOffset > 0 && _parent != null) {
// This is an unresolved recursive sequence tc.
// Try to resolve it now if the hierarchy is complete.
TypeCodeImpl realParent = getParentAtLevel(_parentOffset);
if (realParent != null && realParent._id != null) {
// Create a recursive type code object as the content type.
// This is when the recursive sequence typecode morphes
// into a sequence typecode containing a recursive typecode.
_contentType = new TypeCodeImpl((ORB)_orb, realParent._id);
}
}
}
return _contentType;
}
// Other private functions
private TypeCode realType(TypeCode aType) {
TypeCode realType = aType;
try {
// Note: Indirect types are handled in kind() method
while (realType.kind().value() == TCKind._tk_alias) {
realType = realType.content_type();
}
} catch (BadKind bad) {
// impossible
throw wrapper.badkindCannotOccur() ;
}
return realType;
}
///////////////////////////////////////////////////////////////////////////
// TypeCode operations
public final boolean equal(TypeCode tc)
// _REVISIT_ for all optional names/ids, we might want to check that
// they are equal in case both are non-nil.
{
if (tc == this)
return true;
try {
if (_kind == tk_indirect) {
//return indirectType().equal(tc);
if (_id != null && tc.id() != null)
return _id.equals(tc.id());
return (_id == null && tc.id() == null);
}
// make sure kinds are identical.
if (_kind != tc.kind().value()) {
return false;
}
switch (typeTable[_kind]) {
case EMPTY:
// no parameters to check.
return true;
case SIMPLE:
switch (_kind) {
case TCKind._tk_string:
case TCKind._tk_wstring:
// check for bound.
return (_length == tc.length());
case TCKind._tk_fixed:
return (_digits == tc.fixed_digits() && _scale == tc.fixed_scale());
default:
return false;
}
case COMPLEX:
switch(_kind) {
case TCKind._tk_objref:
{
// check for logical id.
if (_id.compareTo(tc.id()) == 0) {
return true;
}
if (_id.compareTo(
(_orb.get_primitive_tc(_kind)).id()) == 0)
{
return true;
}
if (tc.id().compareTo(
(_orb.get_primitive_tc(_kind)).id()) == 0)
{
return true;
}
return false;
}
case TCKind._tk_native:
case TCKind._tk_abstract_interface:
{
// check for logical id.
if (_id.compareTo(tc.id()) != 0) {
return false;
}
// ignore name since its optional.
return true;
}
case TCKind._tk_struct:
case TCKind._tk_except:
{
// check for member count
if (_memberCount != tc.member_count())
return false;
// check for repository id
if (_id.compareTo(tc.id()) != 0)
return false;
// check for member types.
for (int i = 0 ; i < _memberCount ; i++)
if (! _memberTypes[i].equal(tc.member_type(i)))
return false;
// ignore id and names since those are optional.
return true;
}
case TCKind._tk_union:
{
// check for member count
if (_memberCount != tc.member_count())
return false;
// check for repository id
if (_id.compareTo(tc.id()) != 0)
return false;
// check for default index
if (_defaultIndex != tc.default_index())
return false;
// check for discriminator type
if (!_discriminator.equal(tc.discriminator_type()))
return false;
// check for label types and values
for (int i = 0 ; i < _memberCount ; i++)
if (! _unionLabels[i].equal(tc.member_label(i)))
return false;
// check for branch types
for (int i = 0 ; i < _memberCount ; i++)
if (! _memberTypes[i].equal(tc.member_type(i)))
return false;
// ignore id and names since those are optional.
return true;
}
case TCKind._tk_enum:
{
// check for repository id
if (_id.compareTo(tc.id()) != 0)
return false;
// check member count
if (_memberCount != tc.member_count())
return false;
// ignore names since those are optional.
return true;
}
case TCKind._tk_sequence:
case TCKind._tk_array:
{
// check bound/length
if (_length != tc.length()) {
return false;
}
// check content type
if (! lazy_content_type().equal(tc.content_type())) {
return false;
}
// ignore id and name since those are optional.
return true;
}
case TCKind._tk_value:
{
// check for member count
if (_memberCount != tc.member_count())
return false;
// check for repository id
if (_id.compareTo(tc.id()) != 0)
return false;
// check for member types.
for (int i = 0 ; i < _memberCount ; i++)
if (_memberAccess[i] != tc.member_visibility(i) ||
! _memberTypes[i].equal(tc.member_type(i)))
return false;
if (_type_modifier == tc.type_modifier())
return false;
// concrete_base may be null
TypeCode tccb = tc.concrete_base_type();
if ((_concrete_base == null && tccb != null) ||
(_concrete_base != null && tccb == null) ||
! _concrete_base.equal(tccb))
{
return false;
}
// ignore id and names since those are optional.
return true;
}
case TCKind._tk_alias:
case TCKind._tk_value_box:
{
// check for repository id
if (_id.compareTo(tc.id()) != 0) {
return false;
}
// check for equality with the true type
return _contentType.equal(tc.content_type());
}
}
}
} catch (org.omg.CORBA.TypeCodePackage.Bounds e) {} catch (BadKind e) {}
// dont have to worry about these since the code ensures these dont
// arise.
return false;
}
/**
* The equivalent operation is used by the ORB when determining type equivalence
* for values stored in an IDL any.
*/
public boolean equivalent(TypeCode tc) {
if (tc == this) {
return true;
}
// If the result of the kind operation on either TypeCode is tk_alias, recursively
// replace the TypeCode with the result of calling content_type, until the kind
// is no longer tk_alias.
// Note: Always resolve indirect types first!
TypeCode myRealType = (_kind == tk_indirect ? indirectType() : this);
myRealType = realType(myRealType);
TypeCode otherRealType = realType(tc);
// If results of the kind operation on each typecode differ,
// equivalent returns false.
if (myRealType.kind().value() != otherRealType.kind().value()) {
return false;
}
String myID = null;
String otherID = null;
try {
myID = this.id();
otherID = tc.id();
// At this point the id operation is valid for both TypeCodes.
// Return true if the results of id for both TypeCodes are non-empty strings
// and both strings are equal.
// If both ids are non-empty but are not equal, then equivalent returns FALSE.
if (myID != null && otherID != null) {
return (myID.equals(otherID));
}
} catch (BadKind e) {
// id operation is not valid for either or both TypeCodes
}
// If either or both id is an empty string, or the TypeCode kind does not support
// the id operation, perform a structural comparison of the TypeCodes.
int myKind = myRealType.kind().value();
try {
if (myKind == TCKind._tk_struct ||
myKind == TCKind._tk_union ||
myKind == TCKind._tk_enum ||
myKind == TCKind._tk_except ||
myKind == TCKind._tk_value)
{
if (myRealType.member_count() != otherRealType.member_count())
return false;
}
if (myKind == TCKind._tk_union)
{
if (myRealType.default_index() != otherRealType.default_index())
return false;
}
if (myKind == TCKind._tk_string ||
myKind == TCKind._tk_wstring ||
myKind == TCKind._tk_sequence ||
myKind == TCKind._tk_array)
{
if (myRealType.length() != otherRealType.length())
return false;
}
if (myKind == TCKind._tk_fixed)
{
if (myRealType.fixed_digits() != otherRealType.fixed_digits() ||
myRealType.fixed_scale() != otherRealType.fixed_scale())
return false;
}
if (myKind == TCKind._tk_union)
{
for (int i=0; i<myRealType.member_count(); i++) {
if (myRealType.member_label(i) != otherRealType.member_label(i))
return false;
}
if ( ! myRealType.discriminator_type().equivalent(
otherRealType.discriminator_type()))
return false;
}
if (myKind == TCKind._tk_alias ||
myKind == TCKind._tk_value_box ||
myKind == TCKind._tk_sequence ||
myKind == TCKind._tk_array)
{
if ( ! myRealType.content_type().equivalent(otherRealType.content_type()))
return false;
}
if (myKind == TCKind._tk_struct ||
myKind == TCKind._tk_union ||
myKind == TCKind._tk_except ||
myKind == TCKind._tk_value)
{
for (int i=0; i<myRealType.member_count(); i++) {
if ( ! myRealType.member_type(i).equivalent(
otherRealType.member_type(i)))
return false;
}
}
} catch (BadKind e) {
// impossible if we checked correctly above
throw wrapper.badkindCannotOccur() ;
} catch (org.omg.CORBA.TypeCodePackage.Bounds e) {
// impossible if we checked correctly above
throw wrapper.boundsCannotOccur() ;
}
// Structural comparison succeeded!
return true;
}
public TypeCode get_compact_typecode() {
// _REVISIT_ It isn't clear whether this method should operate on this or a copy.
// For now just return this unmodified because the name and member_name fields
// aren't used for comparison anyways.
return this;
}
public TCKind kind()
{
if (_kind == tk_indirect)
return indirectType().kind();
return TCKind.from_int(_kind);
}
public boolean is_recursive()
{
// Recursive is the only form of indirect type codes right now.
// Indirection can also be used for repeated type codes.
return (_kind == tk_indirect);
}
public String id()
throws BadKind
{
switch (_kind) {
case tk_indirect:
//return indirectType().id(); // same as _id
case TCKind._tk_except:
case TCKind._tk_objref:
case TCKind._tk_struct:
case TCKind._tk_union:
case TCKind._tk_enum:
case TCKind._tk_alias:
case TCKind._tk_value:
case TCKind._tk_value_box:
case TCKind._tk_native:
case TCKind._tk_abstract_interface:
// exception and objref typecodes must have a repository id.
// structs, unions, enums, and aliases may or may not.
return _id;
default:
// all other typecodes throw the BadKind exception.
throw new BadKind();
}
}
public String name()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().name();
case TCKind._tk_except:
case TCKind._tk_objref:
case TCKind._tk_struct:
case TCKind._tk_union:
case TCKind._tk_enum:
case TCKind._tk_alias:
case TCKind._tk_value:
case TCKind._tk_value_box:
case TCKind._tk_native:
case TCKind._tk_abstract_interface:
return _name;
default:
throw new BadKind();
}
}
public int member_count()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().member_count();
case TCKind._tk_except:
case TCKind._tk_struct:
case TCKind._tk_union:
case TCKind._tk_enum:
case TCKind._tk_value:
return _memberCount;
default:
throw new BadKind();
}
}
public String member_name(int index)
throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
{
switch (_kind) {
case tk_indirect:
return indirectType().member_name(index);
case TCKind._tk_except:
case TCKind._tk_struct:
case TCKind._tk_union:
case TCKind._tk_enum:
case TCKind._tk_value:
try {
return _memberNames[index];
} catch (ArrayIndexOutOfBoundsException e) {
throw new org.omg.CORBA.TypeCodePackage.Bounds();
}
default:
throw new BadKind();
}
}
public TypeCode member_type(int index)
throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
{
switch (_kind) {
case tk_indirect:
return indirectType().member_type(index);
case TCKind._tk_except:
case TCKind._tk_struct:
case TCKind._tk_union:
case TCKind._tk_value:
try {
return _memberTypes[index];
} catch (ArrayIndexOutOfBoundsException e) {
throw new org.omg.CORBA.TypeCodePackage.Bounds();
}
default:
throw new BadKind();
}
}
public Any member_label(int index)
throws BadKind, org.omg.CORBA.TypeCodePackage.Bounds
{
switch (_kind) {
case tk_indirect:
return indirectType().member_label(index);
case TCKind._tk_union:
try {
// _REVISIT_ Why create a new Any for this?
return new AnyImpl(_orb, _unionLabels[index]);
} catch (ArrayIndexOutOfBoundsException e) {
throw new org.omg.CORBA.TypeCodePackage.Bounds();
}
default:
throw new BadKind();
}
}
public TypeCode discriminator_type()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().discriminator_type();
case TCKind._tk_union:
return _discriminator;
default:
throw new BadKind();
}
}
public int default_index()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().default_index();
case TCKind._tk_union:
return _defaultIndex;
default:
throw new BadKind();
}
}
public int length()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().length();
case TCKind._tk_string:
case TCKind._tk_wstring:
case TCKind._tk_sequence:
case TCKind._tk_array:
return _length;
default:
throw new BadKind();
}
}
public TypeCode content_type()
throws BadKind
{
switch (_kind) {
case tk_indirect:
return indirectType().content_type();
case TCKind._tk_sequence:
return lazy_content_type();
case TCKind._tk_array:
case TCKind._tk_alias:
case TCKind._tk_value_box:
return _contentType;
default:
throw new BadKind();
}
}
public short fixed_digits() throws BadKind {
switch (_kind) {
case TCKind._tk_fixed:
return _digits;
default:
throw new BadKind();
}
}
public short fixed_scale() throws BadKind {
switch (_kind) {
case TCKind._tk_fixed:
return _scale;
default:
throw new BadKind();
}
}
public short member_visibility(int index) throws BadKind,
org.omg.CORBA.TypeCodePackage.Bounds {
switch (_kind) {
case tk_indirect:
return indirectType().member_visibility(index);
case TCKind._tk_value:
try {
return _memberAccess[index];
} catch (ArrayIndexOutOfBoundsException e) {
throw new org.omg.CORBA.TypeCodePackage.Bounds();
}
default:
throw new BadKind();
}
}
public short type_modifier() throws BadKind {
switch (_kind) {
case tk_indirect:
return indirectType().type_modifier();
case TCKind._tk_value:
return _type_modifier;
default:
throw new BadKind();
}
}
public TypeCode concrete_base_type() throws BadKind {
switch (_kind) {
case tk_indirect:
return indirectType().concrete_base_type();
case TCKind._tk_value:
return _concrete_base;
default:
throw new BadKind();
}
}
public void read_value(InputStream is) {
if (is instanceof TypeCodeReader) {
// hardly possible unless caller knows our "private" stream classes.
if (read_value_kind((TypeCodeReader)is))
read_value_body(is);
} else if (is instanceof CDRInputStream) {
WrapperInputStream wrapper = new WrapperInputStream((CDRInputStream)is);
//if (debug) System.out.println("Created WrapperInputStream " + wrapper +
// " with no parent");
if (read_value_kind((TypeCodeReader)wrapper))
read_value_body(wrapper);
} else {
read_value_kind(is);
read_value_body(is);
}
}
private void read_value_recursive(TypeCodeInputStream is) {
// don't wrap a CDRInputStream reading "inner" TypeCodes.
if (is instanceof TypeCodeReader) {
if (read_value_kind((TypeCodeReader)is))
read_value_body(is);
} else {
read_value_kind((InputStream)is);
read_value_body(is);
}
}
boolean read_value_kind(TypeCodeReader tcis)
{
_kind = tcis.read_long();
// Bug fix 5034649: allow for padding that precedes the typecode kind.
int myPosition = tcis.getTopLevelPosition()-4;
// check validity of kind
if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
throw wrapper.cannotMarshalBadTckind() ;
}
// Don't do any work if this is native
if (_kind == TCKind._tk_native)
throw wrapper.cannotMarshalNative() ;
// We have to remember the stream and position for EVERY type code
// in case some recursive or indirect type code references it.
TypeCodeReader topStream = tcis.getTopLevelStream();
if (_kind == tk_indirect) {
int streamOffset = tcis.read_long();
if (streamOffset > -4)
throw wrapper.invalidIndirection( new Integer(streamOffset) ) ;
// The encoding used for indirection is the same as that used for recursive ,
// TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
// (in units of octets) from the beginning of the long offset.
int topPos = tcis.getTopLevelPosition();
// substract 4 to get back to the beginning of the long offset.
int indirectTypePosition = topPos - 4 + streamOffset;
// Now we have to find the referenced type
// by its indirectTypePosition within topStream.
//if (debug) System.out.println(
// "TypeCodeImpl looking up indirection at position topPos " +
//topPos + " - 4 + offset " + streamOffset + " = " + indirectTypePosition);
TypeCodeImpl type = topStream.getTypeCodeAtPosition(indirectTypePosition);
if (type == null)
throw wrapper.indirectionNotFound( new Integer(indirectTypePosition) ) ;
setIndirectType(type);
return false;
}
topStream.addTypeCodeAtPosition(this, myPosition);
return true;
}
void read_value_kind(InputStream is) {
// unmarshal the kind
_kind = is.read_long();
// check validity of kind
if ((_kind < 0 || _kind > typeTable.length) && _kind != tk_indirect) {
throw wrapper.cannotMarshalBadTckind() ;
}
// Don't do any work if this is native
if (_kind == TCKind._tk_native)
throw wrapper.cannotMarshalNative() ;
if (_kind == tk_indirect) {
throw wrapper.recursiveTypecodeError() ;
}
}
void read_value_body(InputStream is) {
// start unmarshaling the rest of the typecode, based on the
// encoding (empty, simple or complex).
switch (typeTable[_kind]) {
case EMPTY:
// nothing to unmarshal
break;
case SIMPLE:
switch (_kind) {
case TCKind._tk_string:
case TCKind._tk_wstring:
_length = is.read_long();
break;
case TCKind._tk_fixed:
_digits = is.read_ushort();
_scale = is.read_short();
break;
default:
throw wrapper.invalidSimpleTypecode() ;
}
break;
case COMPLEX:
{
TypeCodeInputStream _encap = TypeCodeInputStream.readEncapsulation(is,
is.orb());
switch(_kind) {
case TCKind._tk_objref:
case TCKind._tk_abstract_interface:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
}
break;
case TCKind._tk_union:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
// discriminant typecode
_discriminator = new TypeCodeImpl((ORB)is.orb());
_discriminator.read_value_recursive(_encap);
// default index
_defaultIndex = _encap.read_long();
// get the number of members
_memberCount = _encap.read_long();
// create arrays for the label values, names and types of members
_unionLabels = new AnyImpl[_memberCount];
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
// read off label values, names and types
for (int i=0; i < _memberCount; i++) {
_unionLabels[i] = new AnyImpl((ORB)is.orb());
if (i == _defaultIndex)
// for the default case, read off the zero octet
_unionLabels[i].insert_octet(_encap.read_octet());
else {
switch (realType(_discriminator).kind().value()) {
case TCKind._tk_short:
_unionLabels[i].insert_short(_encap.read_short());
break;
case TCKind._tk_long:
_unionLabels[i].insert_long(_encap.read_long());
break;
case TCKind._tk_ushort:
_unionLabels[i].insert_ushort(_encap.read_short());
break;
case TCKind._tk_ulong:
_unionLabels[i].insert_ulong(_encap.read_long());
break;
case TCKind._tk_float:
_unionLabels[i].insert_float(_encap.read_float());
break;
case TCKind._tk_double:
_unionLabels[i].insert_double(_encap.read_double());
break;
case TCKind._tk_boolean:
_unionLabels[i].insert_boolean(_encap.read_boolean());
break;
case TCKind._tk_char:
_unionLabels[i].insert_char(_encap.read_char());
break;
case TCKind._tk_enum:
_unionLabels[i].type(_discriminator);
_unionLabels[i].insert_long(_encap.read_long());
break;
case TCKind._tk_longlong:
_unionLabels[i].insert_longlong(_encap.read_longlong());
break;
case TCKind._tk_ulonglong:
_unionLabels[i].insert_ulonglong(_encap.read_longlong());
break;
// _REVISIT_ figure out long double mapping
// case TCKind.tk_longdouble:
// _unionLabels[i].insert_longdouble(_encap.getDouble());
// break;
case TCKind._tk_wchar:
_unionLabels[i].insert_wchar(_encap.read_wchar());
break;
default:
throw wrapper.invalidComplexTypecode() ;
}
}
_memberNames[i] = _encap.read_string();
_memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
_memberTypes[i].read_value_recursive(_encap);
_memberTypes[i].setParent(this);
}
}
break;
case TCKind._tk_enum:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
// get the number of members
_memberCount = _encap.read_long();
// create arrays for the identifier names
_memberNames = new String[_memberCount];
// read off identifier names
for (int i=0; i < _memberCount; i++)
_memberNames[i] = _encap.read_string();
}
break;
case TCKind._tk_sequence:
{
// get the type of the sequence
_contentType = new TypeCodeImpl((ORB)is.orb());
_contentType.read_value_recursive(_encap);
// get the bound on the length of the sequence
_length = _encap.read_long();
}
break;
case TCKind._tk_array:
{
// get the type of the array
_contentType = new TypeCodeImpl((ORB)is.orb());
_contentType.read_value_recursive(_encap);
// get the length of the array
_length = _encap.read_long();
}
break;
case TCKind._tk_alias:
case TCKind._tk_value_box:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
// get the type aliased
_contentType = new TypeCodeImpl((ORB)is.orb());
_contentType.read_value_recursive(_encap);
}
break;
case TCKind._tk_except:
case TCKind._tk_struct:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
// get the number of members
_memberCount = _encap.read_long();
// create arrays for the names and types of members
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
// read off member names and types
for (int i=0; i < _memberCount; i++) {
_memberNames[i] = _encap.read_string();
_memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
//if (debug) System.out.println("TypeCode " + _name +
// " reading member " + _memberNames[i]);
_memberTypes[i].read_value_recursive(_encap);
_memberTypes[i].setParent(this);
}
}
break;
case TCKind._tk_value:
{
// get the repository id
setId(_encap.read_string());
// get the name
_name = _encap.read_string();
// get the type modifier
_type_modifier = _encap.read_short();
// get the type aliased
_concrete_base = new TypeCodeImpl((ORB)is.orb());
_concrete_base.read_value_recursive(_encap);
if (_concrete_base.kind().value() == TCKind._tk_null) {
_concrete_base = null;
}
// get the number of members
_memberCount = _encap.read_long();
// create arrays for the names, types and visibility of members
_memberNames = new String[_memberCount];
_memberTypes = new TypeCodeImpl[_memberCount];
_memberAccess = new short[_memberCount];
// read off value member visibilities
for (int i=0; i < _memberCount; i++) {
_memberNames[i] = _encap.read_string();
_memberTypes[i] = new TypeCodeImpl((ORB)is.orb());
//if (debug) System.out.println("TypeCode " + _name +
// " reading member " + _memberNames[i]);
_memberTypes[i].read_value_recursive(_encap);
_memberTypes[i].setParent(this);
_memberAccess[i] = _encap.read_short();
}
}
break;
default:
throw wrapper.invalidTypecodeKindMarshal() ;
}
break;
}
}
}
public void write_value(OutputStream os) {
// Wrap OutputStream into TypeCodeOutputStream.
// This test shouldn't be necessary according to the Java language spec.
if (os instanceof TypeCodeOutputStream) {
this.write_value((TypeCodeOutputStream)os);
} else {
TypeCodeOutputStream wrapperOutStream = null;
if (outBuffer == null) {
wrapperOutStream = TypeCodeOutputStream.wrapOutputStream(os);
this.write_value(wrapperOutStream);
if (cachingEnabled) {
// Cache the buffer for repeated writes
outBuffer = wrapperOutStream.getTypeCodeBuffer();
//if (outBuffer != null)
//System.out.println("Caching outBuffer with length = " +
//outBuffer.length + " for id = " + _id);
}
} else {
//System.out.println("Using cached outBuffer: length = " + outBuffer.length +
//", id = " + _id);
}
// Write the first 4 bytes first to trigger alignment.
// We know that it is the kind.
if (cachingEnabled && outBuffer != null) {
os.write_long(_kind);
os.write_octet_array(outBuffer, 0, outBuffer.length);
} else {
//System.out.println("Buffer is empty for " + _id);
wrapperOutStream.writeRawBuffer(os, _kind);
}
}
}
public void write_value(TypeCodeOutputStream tcos) {
// Don't do any work if this is native
if (_kind == TCKind._tk_native)
throw wrapper.cannotMarshalNative() ;
TypeCodeOutputStream topStream = tcos.getTopLevelStream();
//if (debug) tcos.printBuffer();
if (_kind == tk_indirect) {
//if (debug) System.out.println("Writing indirection " + _name + "to " + _id);
// The encoding used for indirection is the same as that used for recursive ,
// TypeCodes i.e., a 0xffffffff indirection marker followed by a long offset
// (in units of octets) from the beginning of the long offset.
int pos = topStream.getPositionForID(_id);
int topPos = tcos.getTopLevelPosition();
//if (debug) System.out.println("TypeCodeImpl " + tcos +
// " writing indirection " + _id +
//" to position " + pos + " at position " + topPos);
tcos.writeIndirection(tk_indirect, pos);
// All that gets written is _kind and offset.
return;
}
// The original approach changed for 5034649
// topStream.addIDAtPosition(_id, tcos.getTopLevelPosition());
// marshal the kind
tcos.write_long(_kind);
//if (debug) System.out.println("Writing " + _name + " with id " + _id);
// We have to remember the stream and position for EVERY type code
// in case some recursive or indirect type code references it.
//
// Bug fix 5034649:
// Do this AFTER the write of the _kind in case the alignment
// for the long changes the position.
topStream.addIDAtPosition(_id, tcos.getTopLevelPosition()-4);
switch (typeTable[_kind]) {
case EMPTY:
// nothing more to marshal
break;
case SIMPLE:
switch (_kind) {
case TCKind._tk_string:
case TCKind._tk_wstring:
// marshal the bound on string length
tcos.write_long(_length);
break;
case TCKind._tk_fixed:
tcos.write_ushort(_digits);
tcos.write_short(_scale);
break;
default:
// unknown typecode kind
throw wrapper.invalidSimpleTypecode() ;
}
break;
case COMPLEX:
{
// create an encapsulation
TypeCodeOutputStream _encap = tcos.createEncapsulation(tcos.orb());
switch(_kind) {
case TCKind._tk_objref:
case TCKind._tk_abstract_interface:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
}
break;
case TCKind._tk_union:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
// discriminant typecode
_discriminator.write_value(_encap);
// default index
_encap.write_long(_defaultIndex);
// put the number of members
_encap.write_long(_memberCount);
// marshal label values, names and types
for (int i=0; i < _memberCount; i++) {
// for the default case, marshal the zero octet
if (i == _defaultIndex)
_encap.write_octet(_unionLabels[i].extract_octet());
else {
switch (realType(_discriminator).kind().value()) {
case TCKind._tk_short:
_encap.write_short(_unionLabels[i].extract_short());
break;
case TCKind._tk_long:
_encap.write_long(_unionLabels[i].extract_long());
break;
case TCKind._tk_ushort:
_encap.write_short(_unionLabels[i].extract_ushort());
break;
case TCKind._tk_ulong:
_encap.write_long(_unionLabels[i].extract_ulong());
break;
case TCKind._tk_float:
_encap.write_float(_unionLabels[i].extract_float());
break;
case TCKind._tk_double:
_encap.write_double(_unionLabels[i].extract_double());
break;
case TCKind._tk_boolean:
_encap.write_boolean(_unionLabels[i].extract_boolean());
break;
case TCKind._tk_char:
_encap.write_char(_unionLabels[i].extract_char());
break;
case TCKind._tk_enum:
_encap.write_long(_unionLabels[i].extract_long());
break;
case TCKind._tk_longlong:
_encap.write_longlong(_unionLabels[i].extract_longlong());
break;
case TCKind._tk_ulonglong:
_encap.write_longlong(_unionLabels[i].extract_ulonglong());
break;
// _REVISIT_ figure out long double mapping
// case TCKind.tk_longdouble:
// _encap.putDouble(_unionLabels[i].extract_longdouble());
// break;
case TCKind._tk_wchar:
_encap.write_wchar(_unionLabels[i].extract_wchar());
break;
default:
throw wrapper.invalidComplexTypecode() ;
}
}
_encap.write_string(_memberNames[i]);
_memberTypes[i].write_value(_encap);
}
}
break;
case TCKind._tk_enum:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
// put the number of members
_encap.write_long(_memberCount);
// marshal identifier names
for (int i=0; i < _memberCount; i++)
_encap.write_string(_memberNames[i]);
}
break;
case TCKind._tk_sequence:
{
// put the type of the sequence
lazy_content_type().write_value(_encap);
// put the bound on the length of the sequence
_encap.write_long(_length);
}
break;
case TCKind._tk_array:
{
// put the type of the array
_contentType.write_value(_encap);
// put the length of the array
_encap.write_long(_length);
}
break;
case TCKind._tk_alias:
case TCKind._tk_value_box:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
// put the type aliased
_contentType.write_value(_encap);
}
break;
case TCKind._tk_struct:
case TCKind._tk_except:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
// put the number of members
_encap.write_long(_memberCount);
// marshal member names and types
for (int i=0; i < _memberCount; i++) {
_encap.write_string(_memberNames[i]);
//if (debug) System.out.println("TypeCode " + _name +
// " writing member " + _memberNames[i]);
_memberTypes[i].write_value(_encap);
}
}
break;
case TCKind._tk_value:
{
// put the repository id
_encap.write_string(_id);
// put the name
_encap.write_string(_name);
// put the type modifier
_encap.write_short(_type_modifier);
// put the type aliased
if (_concrete_base == null) {
_orb.get_primitive_tc(TCKind._tk_null).write_value(_encap);
} else {
_concrete_base.write_value(_encap);
}
// put the number of members
_encap.write_long(_memberCount);
// marshal member names and types
for (int i=0; i < _memberCount; i++) {
_encap.write_string(_memberNames[i]);
//if (debug) System.out.println("TypeCode " + _name +
// " writing member " + _memberNames[i]);
_memberTypes[i].write_value(_encap);
_encap.write_short(_memberAccess[i]);
}
}
break;
default:
throw wrapper.invalidTypecodeKindMarshal() ;
}
// marshal the encapsulation
_encap.writeOctetSequenceTo(tcos);
break;
}
}
}
/**
* This is not a copy of the TypeCodeImpl objects, but instead it
* copies the value this type code is representing.
* See AnyImpl read_value and write_value for usage.
* The state of this TypeCodeImpl instance isn't changed, only used
* by the Any to do the correct copy.
*/
protected void copy(org.omg.CORBA.portable.InputStream src,
org.omg.CORBA.portable.OutputStream dst)
{
switch (_kind) {
case TCKind._tk_null:
case TCKind._tk_void:
case TCKind._tk_native:
case TCKind._tk_abstract_interface:
break;
case TCKind._tk_short:
case TCKind._tk_ushort:
dst.write_short(src.read_short());
break;
case TCKind._tk_long:
case TCKind._tk_ulong:
dst.write_long(src.read_long());
break;
case TCKind._tk_float:
dst.write_float(src.read_float());
break;
case TCKind._tk_double:
dst.write_double(src.read_double());
break;
case TCKind._tk_longlong:
case TCKind._tk_ulonglong:
dst.write_longlong(src.read_longlong());
break;
case TCKind._tk_longdouble:
throw wrapper.tkLongDoubleNotSupported() ;
case TCKind._tk_boolean:
dst.write_boolean(src.read_boolean());
break;
case TCKind._tk_char:
dst.write_char(src.read_char());
break;
case TCKind._tk_wchar:
dst.write_wchar(src.read_wchar());
break;
case TCKind._tk_octet:
dst.write_octet(src.read_octet());
break;
case TCKind._tk_string:
{
String s;
s = src.read_string();
// make sure length bound in typecode is not violated
if ((_length != 0) && (s.length() > _length))
throw wrapper.badStringBounds( new Integer(s.length()),
new Integer(_length) ) ;
dst.write_string(s);
}
break;
case TCKind._tk_wstring:
{
String s;
s = src.read_wstring();
// make sure length bound in typecode is not violated
if ((_length != 0) && (s.length() > _length))
throw wrapper.badStringBounds( new Integer(s.length()),
new Integer(_length) ) ;
dst.write_wstring(s);
}
break;
case TCKind._tk_fixed:
{
dst.write_ushort(src.read_ushort());
dst.write_short(src.read_short());
}
break;
case TCKind._tk_any:
{
//Any tmp = new AnyImpl(_orb);
Any tmp = ((CDRInputStream)src).orb().create_any();
TypeCodeImpl t = new TypeCodeImpl((ORB)dst.orb());
t.read_value((org.omg.CORBA_2_3.portable.InputStream)src);
t.write_value((org.omg.CORBA_2_3.portable.OutputStream)dst);
tmp.read_value(src, t);
tmp.write_value(dst);
break;
}
case TCKind._tk_TypeCode:
{
dst.write_TypeCode(src.read_TypeCode());
break;
}
case TCKind._tk_Principal:
{
dst.write_Principal(src.read_Principal());
break;
}
case TCKind._tk_objref:
{
dst.write_Object(src.read_Object());
break;
}
case TCKind._tk_except:
// Copy repositoryId
dst.write_string(src.read_string());
// Fall into ...
// _REVISIT_ what about the inherited members of this values concrete base type?
case TCKind._tk_value:
case TCKind._tk_struct:
{
// copy each element, using the corresponding member type
for (int i=0; i < _memberTypes.length; i++) {
_memberTypes[i].copy(src, dst);
}
break;
}
case TCKind._tk_union:
/* _REVISIT_ More generic code?
{
Any discriminator = new AnyImpl(_orb);
discriminator.read_value(src, _discriminator);
discriminator.write_value(dst);
int labelIndex = currentUnionMemberIndex(discriminator);
if (labelIndex == -1) {
// check if label has not been found
if (_defaultIndex == -1)
// throw exception if default was not expected
throw new MARSHAL();
else
// must be of the default branch type
_memberTypes[_defaultIndex].copy(src, dst);
} else {
_memberTypes[labelIndex].copy(src, dst);
}
}
*/
{
Any tagValue = new AnyImpl( (ORB)src.orb());
switch (realType(_discriminator).kind().value()) {
case TCKind._tk_short:
{
short value = src.read_short();
tagValue.insert_short(value);
dst.write_short(value);
break;
}
case TCKind._tk_long:
{
int value = src.read_long();
tagValue.insert_long(value);
dst.write_long(value);
break;
}
case TCKind._tk_ushort:
{
short value = src.read_short();
tagValue.insert_ushort(value);
dst.write_short(value);
break;
}
case TCKind._tk_ulong:
{
int value = src.read_long();
tagValue.insert_ulong(value);
dst.write_long(value);
break;
}
case TCKind._tk_float:
{
float value = src.read_float();
tagValue.insert_float(value);
dst.write_float(value);
break;
}
case TCKind._tk_double:
{
double value = src.read_double();
tagValue.insert_double(value);
dst.write_double(value);
break;
}
case TCKind._tk_boolean:
{
boolean value = src.read_boolean();
tagValue.insert_boolean(value);
dst.write_boolean(value);
break;
}
case TCKind._tk_char:
{
char value = src.read_char();
tagValue.insert_char(value);
dst.write_char(value);
break;
}
case TCKind._tk_enum:
{
int value = src.read_long();
tagValue.type(_discriminator);
tagValue.insert_long(value);
dst.write_long(value);
break;
}
case TCKind._tk_longlong:
{
long value = src.read_longlong();
tagValue.insert_longlong(value);
dst.write_longlong(value);
break;
}
case TCKind._tk_ulonglong:
{
long value = src.read_longlong();
tagValue.insert_ulonglong(value);
dst.write_longlong(value);
break;
}
// _REVISIT_ figure out long double mapping
// case TCKind.tk_longdouble:
// {
// double value = src.read_double();
// tagValue.insert_longdouble(value);
// dst.putDouble(value);
// break;
//}
case TCKind._tk_wchar:
{
char value = src.read_wchar();
tagValue.insert_wchar(value);
dst.write_wchar(value);
break;
}
default:
throw wrapper.illegalUnionDiscriminatorType() ;
}
// using the value of the tag, find out the type of the value
// following.
int labelIndex;
for (labelIndex = 0; labelIndex < _unionLabels.length; labelIndex++) {
// use equality over anys
if (tagValue.equal(_unionLabels[labelIndex])) {
_memberTypes[labelIndex].copy(src, dst);
break;
}
}
if (labelIndex == _unionLabels.length) {
// check if label has not been found
if (_defaultIndex != -1)
// must be of the default branch type
_memberTypes[_defaultIndex].copy(src, dst);
}
break;
}
case TCKind._tk_enum:
dst.write_long(src.read_long());
break;
case TCKind._tk_sequence:
// get the length of the sequence
int seqLength = src.read_long();
// check for sequence bound violated
if ((_length != 0) && (seqLength > _length))
throw wrapper.badSequenceBounds( new Integer(seqLength),
new Integer(_length) ) ;
// write the length of the sequence
dst.write_long(seqLength);
// copy each element of the seq using content type
lazy_content_type(); // make sure it's resolved
for (int i=0; i < seqLength; i++)
_contentType.copy(src, dst);
break;
case TCKind._tk_array:
// copy each element of the array using content type
for (int i=0; i < _length; i++)
_contentType.copy(src, dst);
break;
case TCKind._tk_alias:
case TCKind._tk_value_box:
// follow the alias
_contentType.copy(src, dst);
break;
case tk_indirect:
// need to follow offset, get unmarshal typecode from that
// offset, and use that to do the copy
// Don't need to read type code before using it to do the copy.
// It should be fully usable.
indirectType().copy(src, dst);
break;
default:
throw wrapper.invalidTypecodeKindMarshal() ;
}
}
static protected short digits(java.math.BigDecimal value) {
if (value == null)
return 0;
short length = (short)value.unscaledValue().toString().length();
if (value.signum() == -1)
length--;
return length;
}
static protected short scale(java.math.BigDecimal value) {
if (value == null)
return 0;
return (short)value.scale();
}
// Utility methods
// Only for union type. Returns the index of the union member
// corresponding to the discriminator. If not found returns the
// default index or -1 if there is no default index.
int currentUnionMemberIndex(Any discriminatorValue) throws BadKind {
if (_kind != TCKind._tk_union)
throw new BadKind();
try {
for (int i=0; i<member_count(); i++) {
if (member_label(i).equal(discriminatorValue)) {
return i;
}
}
if (_defaultIndex != -1) {
return _defaultIndex;
}
} catch (BadKind bad) {
} catch (org.omg.CORBA.TypeCodePackage.Bounds bounds) {
}
return -1;
}
public String description() {
return "TypeCodeImpl with kind " + _kind + " and id " + _id;
}
public String toString() {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream(1024);
PrintStream printOut = new PrintStream(byteOut, true);
printStream(printOut);
return super.toString() + " =\n" + byteOut.toString();
}
public void printStream(PrintStream s) {
printStream(s, 0);
}
private void printStream(PrintStream s, int level) {
if (_kind == tk_indirect) {
s.print("indirect " + _id);
return;
}
switch (_kind) {
case TCKind._tk_null:
case TCKind._tk_void:
case TCKind._tk_short:
case TCKind._tk_long:
case TCKind._tk_ushort:
case TCKind._tk_ulong:
case TCKind._tk_float:
case TCKind._tk_double:
case TCKind._tk_boolean:
case TCKind._tk_char:
case TCKind._tk_octet:
case TCKind._tk_any:
case TCKind._tk_TypeCode:
case TCKind._tk_Principal:
case TCKind._tk_objref:
case TCKind._tk_longlong:
case TCKind._tk_ulonglong:
case TCKind._tk_longdouble:
case TCKind._tk_wchar:
case TCKind._tk_native:
s.print(kindNames[_kind] + " " + _name);
break;
case TCKind._tk_struct:
case TCKind._tk_except:
case TCKind._tk_value:
s.println(kindNames[_kind] + " " + _name + " = {");
for(int i=0; i<_memberCount; i++) {
// memberName might differ from the name of the member.
s.print(indent(level + 1));
if (_memberTypes[i] != null)
_memberTypes[i].printStream(s, level + 1);
else
s.print("<unknown type>");
s.println(" " + _memberNames[i] + ";");
}
s.print(indent(level) + "}");
break;
case TCKind._tk_union:
s.print("union " + _name + "...");
break;
case TCKind._tk_enum:
s.print("enum " + _name + "...");
break;
case TCKind._tk_string:
if (_length == 0)
s.print("unbounded string " + _name);
else
s.print("bounded string(" + _length + ") " + _name);
break;
case TCKind._tk_sequence:
case TCKind._tk_array:
s.println(kindNames[_kind] + "[" + _length + "] " + _name + " = {");
s.print(indent(level + 1));
if (lazy_content_type() != null) {
lazy_content_type().printStream(s, level + 1);
}
s.println(indent(level) + "}");
break;
case TCKind._tk_alias:
s.print("alias " + _name + " = " +
(_contentType != null ? _contentType._name : "<unresolved>"));
break;
case TCKind._tk_wstring:
s.print("wstring[" + _length + "] " + _name);
break;
case TCKind._tk_fixed:
s.print("fixed(" + _digits + ", " + _scale + ") " + _name);
break;
case TCKind._tk_value_box:
s.print("valueBox " + _name + "...");
break;
case TCKind._tk_abstract_interface:
s.print("abstractInterface " + _name + "...");
break;
default:
s.print("<unknown type>");
break;
}
}
private String indent(int level) {
String indent = "";
for(int i=0; i<level; i++) {
indent += " ";
}
return indent;
}
protected void setCaching(boolean enableCaching) {
cachingEnabled = enableCaching;
if (enableCaching == false)
outBuffer = null;
}
}