0001: package org.jacorb.orb;
0002:
0003: /*
0004: * JacORB - a free Java ORB
0005: *
0006: * Copyright (C) 1997-2004 Gerald Brose.
0007: *
0008: * This library is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU Library General Public
0010: * License as published by the Free Software Foundation; either
0011: * version 2 of the License, or (at your option) any later version.
0012: *
0013: * This library is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016: * Library General Public License for more details.
0017: *
0018: * You should have received a copy of the GNU Library General Public
0019: * License along with this library; if not, write to the Free
0020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0021: */
0022:
0023: import java.lang.reflect.Field;
0024: import java.lang.reflect.Method;
0025: import java.lang.reflect.Modifier;
0026: import java.util.ArrayList;
0027: import java.util.HashMap;
0028: import java.util.List;
0029: import java.util.Map;
0030:
0031: import org.jacorb.ir.RepositoryID;
0032: import org.jacorb.util.ObjectUtil;
0033: import org.omg.CORBA.INTERNAL;
0034: import org.omg.CORBA.TCKind;
0035: import org.omg.CORBA.ValueMember;
0036:
0037: /**
0038: * JacORB implementation of CORBA TypeCodes
0039: *
0040: * @author Gerald Brose, FU Berlin
0041: * @version $Id: TypeCode.java,v 1.48 2006/07/10 13:34:12 alphonse.bendt Exp $
0042: */
0043:
0044: public class TypeCode extends org.omg.CORBA.TypeCode {
0045: private final int kind;
0046:
0047: private String id = null;
0048: private String name = null;
0049:
0050: private int member_count = 0;
0051: private String[] member_name = null;
0052: private org.omg.CORBA.TypeCode[] member_type = null;
0053: private short[] member_visibility = null;
0054: private Any[] member_label = null;
0055: private short value_modifier = 0;
0056:
0057: private org.omg.CORBA.TypeCode discriminator_type = null;
0058: private int default_index = -1;
0059: private int length = -1;
0060: private org.omg.CORBA.TypeCode content_type = null;
0061:
0062: /** for fixed point types */
0063: private short scale;
0064: private short digits;
0065:
0066: /** if this TC is recursive */
0067: private boolean recursive = false;
0068: private TypeCode actualTypecode = null;
0069: private boolean secondIteration = false;
0070:
0071: private static org.omg.CORBA.TypeCode[] primitive_tcs = new TypeCode[34];
0072:
0073: /**
0074: * Maps the java.lang.Class objects for primitive types to
0075: * their corresponding TypeCode objects.
0076: */
0077: private static Map primitive_tcs_map = new HashMap();
0078:
0079: static {
0080: /** statically create primitive TypeCodes for fast lookup */
0081: for (int i = 0; i <= 13; i++) {
0082: primitive_tcs[i] = new TypeCode(i);
0083: }
0084: for (int i = 23; i <= 26; i++) {
0085: primitive_tcs[i] = new TypeCode(i);
0086: }
0087: primitive_tcs[TCKind._tk_string] = new TypeCode(
0088: TCKind._tk_string, 0);
0089: primitive_tcs[TCKind._tk_wstring] = new TypeCode(
0090: TCKind._tk_wstring, 0);
0091: primitive_tcs[TCKind._tk_fixed] = new TypeCode((short) 1,
0092: (short) 0);
0093:
0094: // Sun's ValueHandler in JDK 1.3 and 1.4 calls
0095: // ORB.get_primitive_tc() for TCKind._tk_objref and TCKind._tk_value.
0096: // These don't exactly look "primitive" to us, but as a courtesy to
0097: // Sun we provide the following bogus TypeCode objects so that
0098: // we can return something in these cases.
0099: primitive_tcs[TCKind._tk_objref] = new TypeCode(
0100: TCKind._tk_objref, "IDL:omg.org/CORBA/Object:1.0",
0101: "Object");
0102: primitive_tcs[TCKind._tk_value] = new TypeCode(
0103: "IDL:omg.org/CORBA/portable/ValueBase:1.0",
0104: "ValueBase", org.omg.CORBA.VM_NONE.value, null,
0105: new org.omg.CORBA.ValueMember[0]);
0106:
0107: put_primitive_tcs(Boolean.TYPE, TCKind._tk_boolean);
0108: put_primitive_tcs(Character.TYPE, TCKind._tk_wchar);
0109: put_primitive_tcs(Byte.TYPE, TCKind._tk_octet);
0110: put_primitive_tcs(Short.TYPE, TCKind._tk_short);
0111: put_primitive_tcs(Integer.TYPE, TCKind._tk_long);
0112: put_primitive_tcs(Long.TYPE, TCKind._tk_longlong);
0113: put_primitive_tcs(Float.TYPE, TCKind._tk_float);
0114: put_primitive_tcs(Double.TYPE, TCKind._tk_double);
0115: }
0116:
0117: /**
0118: * Internal method for populating `primitive_tcs_map'.
0119: */
0120: private static void put_primitive_tcs(Class clz, int kind) {
0121: primitive_tcs_map.put(clz, primitive_tcs[kind]);
0122: }
0123:
0124: /**
0125: * @param _kind kind identifying a primitive TypeCode
0126: * @return TypeCode with integer kind _kind
0127: */
0128:
0129: static org.omg.CORBA.TypeCode get_primitive_tc(int _kind) {
0130: if (primitive_tcs[_kind] == null) {
0131: throw new org.omg.CORBA.BAD_PARAM(
0132: "No primitive TypeCode for kind " + _kind);
0133: }
0134:
0135: return primitive_tcs[_kind];
0136: }
0137:
0138: /**
0139: * @return True if this TypeCode represents a primitive type,
0140: * false otherwise
0141: */
0142:
0143: public boolean is_primitive() {
0144: return (!is_recursive() && primitive_tcs[kind] != null);
0145: }
0146:
0147: /**
0148: * Constructor for primitive types, called only from
0149: * static initializer and org.jacorb.ir.TypeCodeUtil
0150: */
0151:
0152: public TypeCode(int _kind) {
0153: super ();
0154:
0155: kind = _kind;
0156: }
0157:
0158: // TypeCode constructors for every conceivable type follow.
0159: // These are called exclusively by the ORBSingleton, which is
0160: // the only legal TypeCode factory
0161:
0162: /**
0163: * Constructor for recursive types
0164: */
0165: public TypeCode(String id) {
0166: this (-1);
0167: this .id = id;
0168: recursive = true;
0169: }
0170:
0171: /**
0172: * Constructor for tk_struct and tk_except
0173: */
0174:
0175: public TypeCode(int _kind, String _id, String _name,
0176: org.omg.CORBA.StructMember[] _members) {
0177: this (_kind);
0178:
0179: id = _id;
0180: if (_name != null) {
0181: name = _name.replace('.', '_'); // for orbixWeb Interop
0182: } else {
0183: name = "";
0184: }
0185: member_count = _members.length;
0186: member_name = new String[member_count];
0187: member_type = new org.omg.CORBA.TypeCode[member_count];
0188: for (int i = 0; i < member_count; i++) {
0189: member_name[i] = _members[i].name;
0190: member_type[i] = _members[i].type;
0191: }
0192: }
0193:
0194: /**
0195: * Constructor for tk_union
0196: */
0197:
0198: public TypeCode(String _id, String _name,
0199: org.omg.CORBA.TypeCode _discriminator_type,
0200: org.omg.CORBA.UnionMember[] _members) {
0201: this (TCKind._tk_union);
0202:
0203: id = _id;
0204: if (_name != null) {
0205: name = _name.replace('.', '_'); // for orbixWeb Interop
0206: } else {
0207: name = "";
0208: }
0209: discriminator_type = _discriminator_type;
0210:
0211: member_count = _members.length;
0212: member_name = new String[member_count];
0213: member_label = new Any[member_count];
0214: member_type = new org.omg.CORBA.TypeCode[member_count];
0215:
0216: for (int i = 0; i < member_count; i++) {
0217: member_name[i] = _members[i].name;
0218: member_label[i] = (Any) _members[i].label;
0219: if (member_label[i].kind().equals(TCKind.tk_octet)
0220: && ((Byte) member_label[i].value()).byteValue() == (byte) 0) {
0221: default_index = i;
0222: }
0223: member_type[i] = _members[i].type;
0224: }
0225: }
0226:
0227: /**
0228: * Constructor for tk_enum
0229: */
0230:
0231: public TypeCode(java.lang.String _id, java.lang.String _name,
0232: java.lang.String[] _members) {
0233: this (TCKind._tk_enum);
0234:
0235: id = _id;
0236: if (_name != null) {
0237: name = _name.replace('.', '_'); // for orbixWeb Interop
0238: } else {
0239: name = "";
0240: }
0241: member_count = _members.length;
0242: member_name = new String[member_count];
0243:
0244: System.arraycopy(_members, 0, member_name, 0, member_count);
0245: }
0246:
0247: /**
0248: * Constructor for tk_alias, tk_value_box
0249: */
0250:
0251: public TypeCode(int _kind, String _id, String _name,
0252: org.omg.CORBA.TypeCode _original_type) {
0253: this (_kind);
0254:
0255: id = _id;
0256: if (_name != null) {
0257: name = _name.replace('.', '_'); // for orbixWeb Interop
0258: } else {
0259: name = "";
0260: }
0261: content_type = _original_type;
0262: }
0263:
0264: /**
0265: * Constructor for tk_objref, tk_abstract_interface, tk_native,
0266: * tk_local_interface
0267: */
0268:
0269: public TypeCode(int _kind, java.lang.String _id,
0270: java.lang.String _name) {
0271: this (_kind);
0272:
0273: id = _id;
0274: if (_name != null) {
0275: name = _name.replace('.', '_'); // for orbixWeb Interop
0276: } else {
0277: name = "";
0278: }
0279: }
0280:
0281: /**
0282: * Constructor for tk_string, tk_wstring
0283: */
0284:
0285: public TypeCode(int _kind, int _bound) {
0286: this (_kind);
0287:
0288: length = _bound;
0289: }
0290:
0291: /**
0292: * Constructor for tk_sequence, tk_array
0293: */
0294:
0295: public TypeCode(int _kind, int _bound,
0296: org.omg.CORBA.TypeCode _element_type) {
0297: this (_kind);
0298:
0299: length = _bound;
0300: content_type = _element_type;
0301: if (content_type == null) {
0302: throw new org.omg.CORBA.BAD_PARAM(
0303: "TypeCode.ctor, content_type null");
0304: }
0305: }
0306:
0307: /**
0308: * Constructor for tk_fixed
0309: */
0310:
0311: public TypeCode(short _digits, short _scale) {
0312: this (TCKind._tk_fixed);
0313:
0314: digits = _digits;
0315: scale = _scale;
0316: }
0317:
0318: /**
0319: * Constructor for tk_value
0320: */
0321:
0322: public TypeCode(String id, String _name, short type_modifier,
0323: org.omg.CORBA.TypeCode concrete_base,
0324: org.omg.CORBA.ValueMember[] members) {
0325: this (TCKind._tk_value);
0326:
0327: this .id = id;
0328: if (_name != null) {
0329: name = _name.replace('.', '_'); // for orbixWeb Interop
0330: } else {
0331: name = "";
0332: }
0333: value_modifier = type_modifier;
0334: content_type = concrete_base;
0335: setValueMembers(members);
0336: resolveRecursion(this );
0337: }
0338:
0339: /**
0340: * Auxiliary method that sets the members of a tk_value.
0341: */
0342:
0343: private void setValueMembers(org.omg.CORBA.ValueMember[] members) {
0344: member_count = (members != null) ? members.length : 0;
0345: member_name = new String[member_count];
0346: member_type = new org.omg.CORBA.TypeCode[member_count];
0347: member_visibility = new short[member_count];
0348: for (int i = 0; i < member_count; i++) {
0349: member_name[i] = members[i].name;
0350: member_type[i] = members[i].type;
0351: member_visibility[i] = members[i].access;
0352: }
0353: }
0354:
0355: /**
0356: * check TypeCodes for equality
0357: */
0358:
0359: public boolean equal(org.omg.CORBA.TypeCode tc) {
0360: try {
0361: if (is_recursive()) {
0362: checkActualTC();
0363: if (tc instanceof org.jacorb.orb.TypeCode
0364: && ((org.jacorb.orb.TypeCode) tc)
0365: .is_recursive()) {
0366: org.jacorb.orb.TypeCode jtc = (org.jacorb.orb.TypeCode) tc;
0367:
0368: jtc.checkActualTC();
0369: if (secondIteration) {
0370: return true;
0371: }
0372:
0373: secondIteration = true;
0374: boolean result = actualTypecode
0375: .equal(jtc.actualTypecode);
0376: secondIteration = false;
0377: return result;
0378: }
0379: return tc.equal(actualTypecode);
0380: } else if (tc instanceof org.jacorb.orb.TypeCode
0381: && ((org.jacorb.orb.TypeCode) tc).is_recursive()) {
0382: org.jacorb.orb.TypeCode jtc = (org.jacorb.orb.TypeCode) tc;
0383:
0384: jtc.checkActualTC();
0385: return equal(jtc.actualTypecode);
0386: }
0387:
0388: if (kind().value() != tc.kind().value()) {
0389: return false;
0390: }
0391:
0392: if (kind == TCKind._tk_objref || kind == TCKind._tk_struct
0393: || kind == TCKind._tk_union
0394: || kind == TCKind._tk_enum
0395: || kind == TCKind._tk_alias
0396: || kind == TCKind._tk_except
0397: || kind == TCKind._tk_value
0398: || kind == TCKind._tk_value_box
0399: || kind == TCKind._tk_native
0400: || kind == TCKind._tk_abstract_interface
0401: || kind == TCKind._tk_local_interface) {
0402: if (!id().equals(tc.id()) || !name().equals(tc.name())) {
0403: return false;
0404: }
0405: }
0406:
0407: if (kind == TCKind._tk_struct || kind == TCKind._tk_union
0408: || kind == TCKind._tk_enum
0409: || kind == TCKind._tk_value
0410: || kind == TCKind._tk_except) {
0411: if (member_count() != tc.member_count()) {
0412: return false;
0413: }
0414:
0415: for (int i = 0; i < member_count(); i++) {
0416: if (!member_name(i).equals(tc.member_name(i))) {
0417: return false;
0418: }
0419:
0420: if (kind != TCKind._tk_enum
0421: && !member_type(i).equal(tc.member_type(i))) {
0422: return false;
0423: }
0424:
0425: if (kind == TCKind._tk_union
0426: && !member_label(i).equal(
0427: tc.member_label(i))) {
0428: return false;
0429: }
0430:
0431: if (kind == TCKind._tk_value
0432: && member_visibility(i) != tc
0433: .member_visibility(i)) {
0434: return false;
0435: }
0436: }
0437: }
0438:
0439: if (kind == TCKind._tk_union) {
0440: if (!discriminator_type()
0441: .equal(tc.discriminator_type())
0442: || default_index() != tc.default_index()) {
0443: return false;
0444: }
0445: }
0446:
0447: if (kind == TCKind._tk_string || kind == TCKind._tk_wstring
0448: || kind == TCKind._tk_array
0449: || kind == TCKind._tk_sequence) {
0450: if (length() != tc.length()) {
0451: return false;
0452: }
0453: }
0454:
0455: if (kind == TCKind._tk_array || kind == TCKind._tk_sequence
0456: || kind == TCKind._tk_alias
0457: || kind == TCKind._tk_value_box) {
0458: if (!content_type().equal(tc.content_type())) {
0459: return false;
0460: }
0461: }
0462:
0463: if (kind == TCKind._tk_fixed) {
0464: if (fixed_digits() != tc.fixed_digits()
0465: || fixed_scale() != tc.fixed_scale()) {
0466: return false;
0467: }
0468: }
0469:
0470: if (kind == TCKind._tk_value) {
0471: if (type_modifier() != tc.type_modifier()) {
0472: return false;
0473: }
0474: if (concrete_base_type() != null
0475: || tc.concrete_base_type() != null) {
0476: if (concrete_base_type() == null
0477: || tc.concrete_base_type() == null) {
0478: return false;
0479: }
0480: if (!concrete_base_type().equal(
0481: tc.concrete_base_type())) {
0482: return false;
0483: }
0484: }
0485: }
0486: }
0487: // Equal does not raise Bounds or BadKind so just return false.
0488: catch (org.omg.CORBA.TypeCodePackage.Bounds b) {
0489: return false;
0490: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
0491: return false;
0492: }
0493:
0494: return true;
0495: }
0496:
0497: public org.omg.CORBA.TCKind kind() {
0498: if (is_recursive()) {
0499: checkActualTC();
0500: return actualTypecode.kind();
0501: }
0502:
0503: return org.omg.CORBA.TCKind.from_int(kind);
0504: }
0505:
0506: public int _kind() {
0507: if (is_recursive()) {
0508: checkActualTC();
0509: return actualTypecode._kind();
0510: }
0511:
0512: return kind;
0513: }
0514:
0515: public java.lang.String id()
0516: throws org.omg.CORBA.TypeCodePackage.BadKind {
0517: if (is_recursive()) {
0518: return id;
0519: }
0520:
0521: switch (kind) {
0522: case TCKind._tk_objref: //14
0523: case TCKind._tk_struct: //15
0524: case TCKind._tk_union: //16
0525: case TCKind._tk_enum: //17
0526: {
0527: return id;
0528: }
0529: case TCKind._tk_string: //18
0530: case TCKind._tk_sequence: //19
0531: case TCKind._tk_array: //20
0532: {
0533: //dummy cases for optimized switch
0534: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0535: }
0536: case TCKind._tk_alias: //21
0537: case TCKind._tk_except: //22
0538: {
0539: return id;
0540: }
0541: case TCKind._tk_longlong: // 23
0542: case TCKind._tk_ulonglong: // 24
0543: case TCKind._tk_longdouble:// 25
0544: case TCKind._tk_wchar: // 26
0545: case TCKind._tk_wstring: // 27
0546: case TCKind._tk_fixed: // 28
0547: {
0548: //dummy cases for optimized switch
0549: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0550: }
0551: case TCKind._tk_value: // 29
0552: case TCKind._tk_value_box: // 30
0553: {
0554: return id;
0555: }
0556: case TCKind._tk_native: // 31
0557: {
0558: //dummy cases for optimized switch
0559: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0560: }
0561: case TCKind._tk_abstract_interface: //32
0562: case TCKind._tk_local_interface: //33
0563: {
0564: return id;
0565: }
0566: default: {
0567: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0568: }
0569: }
0570: }
0571:
0572: public java.lang.String name()
0573: throws org.omg.CORBA.TypeCodePackage.BadKind {
0574: if (is_recursive()) {
0575: checkActualTC();
0576: return actualTypecode.name();
0577: }
0578:
0579: switch (kind) {
0580: case TCKind._tk_objref:
0581: case TCKind._tk_struct:
0582: case TCKind._tk_union:
0583: case TCKind._tk_enum:
0584: case TCKind._tk_alias:
0585: case TCKind._tk_value:
0586: case TCKind._tk_value_box:
0587: case TCKind._tk_native:
0588: case TCKind._tk_abstract_interface:
0589: case TCKind._tk_local_interface:
0590: case TCKind._tk_except:
0591: return name;
0592: default:
0593: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0594: }
0595: }
0596:
0597: public int member_count()
0598: throws org.omg.CORBA.TypeCodePackage.BadKind {
0599: if (is_recursive()) {
0600: checkActualTC();
0601: return actualTypecode.member_count();
0602: }
0603:
0604: switch (kind) {
0605: case TCKind._tk_struct:
0606: case TCKind._tk_except:
0607: case TCKind._tk_union:
0608: case TCKind._tk_value:
0609: case TCKind._tk_enum:
0610: return member_count;
0611: default:
0612: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0613: }
0614: }
0615:
0616: public java.lang.String member_name(int index)
0617: throws org.omg.CORBA.TypeCodePackage.BadKind,
0618: org.omg.CORBA.TypeCodePackage.Bounds {
0619: if (is_recursive()) {
0620: checkActualTC();
0621: return actualTypecode.member_name(index);
0622: }
0623:
0624: switch (kind) {
0625: case TCKind._tk_struct:
0626: case TCKind._tk_except:
0627: case TCKind._tk_union:
0628: case TCKind._tk_value:
0629: case TCKind._tk_enum: {
0630: if (index >= 0 && index < member_count) {
0631: return member_name[index];
0632: }
0633: throw new org.omg.CORBA.TypeCodePackage.Bounds();
0634: }
0635: default:
0636: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0637: }
0638: }
0639:
0640: public org.omg.CORBA.TypeCode member_type(int index)
0641: throws org.omg.CORBA.TypeCodePackage.BadKind,
0642: org.omg.CORBA.TypeCodePackage.Bounds {
0643: if (is_recursive()) {
0644: checkActualTC();
0645: return actualTypecode.member_type(index);
0646: }
0647:
0648: switch (kind) {
0649: case TCKind._tk_struct:
0650: case TCKind._tk_except:
0651: case TCKind._tk_union:
0652: case TCKind._tk_value: {
0653: if (index >= 0 && index < member_count) {
0654: return member_type[index];
0655: }
0656:
0657: throw new org.omg.CORBA.TypeCodePackage.Bounds();
0658: }
0659: default:
0660: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0661: }
0662: }
0663:
0664: public org.omg.CORBA.Any member_label(int index)
0665: throws org.omg.CORBA.TypeCodePackage.BadKind,
0666: org.omg.CORBA.TypeCodePackage.Bounds {
0667: if (is_recursive()) {
0668: checkActualTC();
0669: return actualTypecode.member_label(index);
0670: }
0671:
0672: if (kind != TCKind._tk_union) {
0673: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0674: }
0675: if (index < 0 || index >= member_count) {
0676: throw new org.omg.CORBA.TypeCodePackage.Bounds();
0677: }
0678: return member_label[index];
0679: }
0680:
0681: public org.omg.CORBA.TypeCode discriminator_type()
0682: throws org.omg.CORBA.TypeCodePackage.BadKind {
0683: if (is_recursive()) {
0684: checkActualTC();
0685: return actualTypecode.discriminator_type();
0686: }
0687:
0688: if (kind != TCKind._tk_union) {
0689: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0690: }
0691: return discriminator_type;
0692: }
0693:
0694: public int default_index()
0695: throws org.omg.CORBA.TypeCodePackage.BadKind {
0696: if (is_recursive()) {
0697: checkActualTC();
0698: return actualTypecode.default_index();
0699: }
0700:
0701: if (kind != TCKind._tk_union) {
0702: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0703: }
0704:
0705: return default_index;
0706: }
0707:
0708: public int length() throws org.omg.CORBA.TypeCodePackage.BadKind {
0709: switch (kind) {
0710: case TCKind._tk_string:
0711: case TCKind._tk_wstring:
0712: case TCKind._tk_sequence:
0713: case TCKind._tk_array:
0714: return length;
0715: default:
0716: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0717: }
0718: }
0719:
0720: public org.omg.CORBA.TypeCode content_type()
0721: throws org.omg.CORBA.TypeCodePackage.BadKind {
0722: switch (kind) {
0723: case TCKind._tk_array:
0724: case TCKind._tk_sequence:
0725: case TCKind._tk_alias:
0726: case TCKind._tk_value_box:
0727: return content_type;
0728: default:
0729: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0730: }
0731: }
0732:
0733: public short fixed_digits()
0734: throws org.omg.CORBA.TypeCodePackage.BadKind {
0735: if (kind != TCKind._tk_fixed) {
0736: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0737: }
0738: return digits;
0739: }
0740:
0741: public short fixed_scale()
0742: throws org.omg.CORBA.TypeCodePackage.BadKind {
0743: if (kind != TCKind._tk_fixed) {
0744: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0745: }
0746: return scale;
0747: }
0748:
0749: /**
0750: * <code>get_compact_typecode</code> returns a new TypeCode with all
0751: * type and member information removed. RepositoryID and alias are
0752: * preserved.
0753: * This method effectively clones the original typecode - simpler than
0754: * trying to work out what type so what to duplicate (and compact).
0755: *
0756: * @return an <code>org.omg.CORBA.TypeCode</code> value
0757: */
0758: public org.omg.CORBA.TypeCode get_compact_typecode() {
0759: // New typecode with same kind, id and a blank name.
0760: TypeCode result = new TypeCode(kind, id, "");
0761:
0762: // Duplicate the original typecode.
0763: result.member_count = member_count;
0764:
0765: // Member names are optional, so compact them down for transmission.
0766: // Check whether we are doing full compaction or not.
0767: // if (Environment.getCompactTypecodes() > 1 && member_name != null)
0768: if (member_name != null) {
0769: result.member_name = new String[member_name.length];
0770: for (int i = 0; i < result.member_name.length; i++) {
0771: result.member_name[i] = "";
0772: }
0773: } else {
0774: result.member_name = member_name;
0775: }
0776:
0777: // Compact the member types down as well.
0778: if (member_type != null) {
0779: result.member_type = new TypeCode[member_type.length];
0780: for (int i = 0; i < result.member_type.length; i++) {
0781: result.member_type[i] = member_type[i]
0782: .get_compact_typecode();
0783: }
0784: }
0785:
0786: result.member_visibility = member_visibility;
0787: result.member_label = member_label;
0788: result.value_modifier = value_modifier;
0789:
0790: result.discriminator_type = discriminator_type;
0791: result.default_index = default_index;
0792: result.length = length;
0793: result.content_type = content_type;
0794:
0795: result.scale = scale;
0796: result.digits = digits;
0797:
0798: result.recursive = recursive;
0799: result.actualTypecode = actualTypecode;
0800: result.secondIteration = secondIteration;
0801:
0802: result.resolveRecursion();
0803: return result;
0804: }
0805:
0806: public short member_visibility(int index)
0807: throws org.omg.CORBA.TypeCodePackage.BadKind,
0808: org.omg.CORBA.TypeCodePackage.Bounds {
0809: if (kind != TCKind._tk_value) {
0810: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0811: }
0812: if (index < 0 || index >= member_count) {
0813: throw new org.omg.CORBA.TypeCodePackage.Bounds();
0814: }
0815:
0816: return member_visibility[index];
0817: }
0818:
0819: public short type_modifier()
0820: throws org.omg.CORBA.TypeCodePackage.BadKind {
0821: if (kind != TCKind._tk_value) {
0822: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0823: }
0824:
0825: return value_modifier;
0826: }
0827:
0828: public org.omg.CORBA.TypeCode concrete_base_type()
0829: throws org.omg.CORBA.TypeCodePackage.BadKind {
0830: if (kind != TCKind._tk_value) {
0831: throw new org.omg.CORBA.TypeCodePackage.BadKind();
0832: }
0833:
0834: return content_type;
0835: }
0836:
0837: /**
0838: * less strict equivalence check, unwinds aliases
0839: */
0840: public boolean equivalent(org.omg.CORBA.TypeCode tc) {
0841: try {
0842: if (is_recursive()) {
0843: checkActualTC();
0844: if (tc instanceof org.jacorb.orb.TypeCode
0845: && ((org.jacorb.orb.TypeCode) tc)
0846: .is_recursive()) {
0847: org.jacorb.orb.TypeCode jtc = (org.jacorb.orb.TypeCode) tc;
0848:
0849: jtc.checkActualTC();
0850: if (secondIteration) {
0851: return true;
0852: }
0853:
0854: secondIteration = true;
0855: boolean result = actualTypecode
0856: .equivalent(jtc.actualTypecode);
0857: secondIteration = false;
0858: return result;
0859: }
0860: return tc.equivalent(actualTypecode);
0861: } else if (tc instanceof org.jacorb.orb.TypeCode
0862: && ((org.jacorb.orb.TypeCode) tc).is_recursive()) {
0863: org.jacorb.orb.TypeCode jtc = (org.jacorb.orb.TypeCode) tc;
0864:
0865: jtc.checkActualTC();
0866: return equivalent(jtc.actualTypecode);
0867: }
0868:
0869: /* unalias any typedef'd types */
0870:
0871: if (kind().value() == TCKind._tk_alias) {
0872: return content_type().equivalent(tc);
0873: }
0874:
0875: if (tc.kind().value() == TCKind._tk_alias) {
0876: return equivalent(tc.content_type());
0877: }
0878:
0879: if (kind().value() != tc.kind().value()) {
0880: return false;
0881: }
0882:
0883: if (kind == TCKind._tk_objref || kind == TCKind._tk_struct
0884: || kind == TCKind._tk_union
0885: || kind == TCKind._tk_enum
0886: || kind == TCKind._tk_alias
0887: || kind == TCKind._tk_except
0888: || kind == TCKind._tk_value
0889: || kind == TCKind._tk_value_box
0890: || kind == TCKind._tk_native
0891: || kind == TCKind._tk_abstract_interface
0892: || kind == TCKind._tk_local_interface) {
0893: if (id().length() > 0 && tc.id().length() > 0) {
0894: if (id().equals(tc.id())) {
0895: return true;
0896: }
0897: return false;
0898: }
0899: }
0900:
0901: if (kind == TCKind._tk_struct || kind == TCKind._tk_union
0902: || kind == TCKind._tk_enum
0903: || kind == TCKind._tk_value
0904: || kind == TCKind._tk_except) {
0905: if (member_count() != tc.member_count()) {
0906: return false;
0907: }
0908:
0909: for (int i = 0; i < member_count(); i++) {
0910: if (kind != TCKind._tk_enum
0911: && !member_type(i).equivalent(
0912: tc.member_type(i))) {
0913: return false;
0914: }
0915:
0916: if (kind == TCKind._tk_union
0917: && !member_label(i).equal(
0918: tc.member_label(i))) {
0919: return false;
0920: }
0921:
0922: if (kind == TCKind._tk_value
0923: && member_visibility(i) != tc
0924: .member_visibility(i)) {
0925: return false;
0926: }
0927: }
0928: }
0929:
0930: if (kind == TCKind._tk_union) {
0931: if (!discriminator_type().equivalent(
0932: tc.discriminator_type())
0933: || default_index() != tc.default_index()) {
0934: return false;
0935: }
0936: }
0937:
0938: if (kind == TCKind._tk_string || kind == TCKind._tk_wstring
0939: || kind == TCKind._tk_array
0940: || kind == TCKind._tk_sequence) {
0941: if (length() != tc.length()) {
0942: return false;
0943: }
0944: }
0945:
0946: if (kind == TCKind._tk_array || kind == TCKind._tk_sequence
0947: || kind == TCKind._tk_alias
0948: || kind == TCKind._tk_value_box) {
0949: if (!content_type().equivalent(tc.content_type())) {
0950: return false;
0951: }
0952: }
0953:
0954: if (kind == TCKind._tk_fixed) {
0955: if (fixed_digits() != tc.fixed_digits()
0956: || fixed_scale() != tc.fixed_scale()) {
0957: return false;
0958: }
0959: }
0960:
0961: if (kind == TCKind._tk_value) {
0962: if (type_modifier() != tc.type_modifier()
0963: || !concrete_base_type().equivalent(
0964: tc.concrete_base_type())) {
0965: return false;
0966: }
0967: }
0968: }
0969: // Equivalent does not raise Bounds or BadKind so just return false.
0970: catch (org.omg.CORBA.TypeCodePackage.Bounds b) {
0971: return false;
0972: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
0973: return false;
0974: }
0975:
0976: return true;
0977: }
0978:
0979: // useful additional functionality
0980:
0981: public String toString() {
0982: return idlTypeName();
0983: }
0984:
0985: /**
0986: * @return TRUE is this TypeCode is recursive. Both the initial
0987: * place holder TypeCode and the real TypeCode which replaces
0988: * the place holder return TRUE.
0989: */
0990:
0991: public boolean is_recursive() {
0992: return recursive;
0993: }
0994:
0995: /**
0996: * @return TRUE if the argument is a JacORB typecode and is recursive.
0997: */
0998: public static boolean isRecursive(org.omg.CORBA.TypeCode typeCode) {
0999: return (typeCode instanceof TypeCode) ? ((TypeCode) typeCode)
1000: .is_recursive() : false;
1001: }
1002:
1003: /**
1004: * convenience method
1005: */
1006: public static String idlTypeName(org.omg.CORBA.TypeCode typeCode) {
1007: return (typeCode instanceof org.jacorb.orb.TypeCode) ? ((org.jacorb.orb.TypeCode) typeCode)
1008: .idlTypeName()
1009: : "(foreign typecode)";
1010: }
1011:
1012: /** convenience method */
1013:
1014: public String idlTypeName() {
1015: if (is_recursive()) {
1016: checkActualTC();
1017: return actualTypecode.idlTypeName();
1018: }
1019:
1020: switch (kind().value()) {
1021: case TCKind._tk_objref:
1022: case TCKind._tk_struct:
1023: case TCKind._tk_union:
1024: case TCKind._tk_enum:
1025: case TCKind._tk_alias:
1026: case TCKind._tk_except:
1027: case TCKind._tk_native:
1028: case TCKind._tk_abstract_interface:
1029: case TCKind._tk_local_interface: {
1030: try {
1031: return idToIDL(id());
1032: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
1033: throw new INTERNAL("should never happen");
1034: }
1035: }
1036: case TCKind._tk_void:
1037: return "void";
1038: case TCKind._tk_string:
1039: return "string";
1040: case TCKind._tk_wstring:
1041: return "wstring";
1042: case TCKind._tk_array: {
1043: try {
1044: return idlTypeName(content_type()) + "[]";
1045: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
1046: throw new INTERNAL("should never happen");
1047: }
1048: }
1049: case TCKind._tk_long:
1050: return "long";
1051: case TCKind._tk_ulong:
1052: return "ulong";
1053: case TCKind._tk_longlong:
1054: return "long long";
1055: case TCKind._tk_ulonglong:
1056: return "ulong long";
1057: case TCKind._tk_ushort:
1058: return "ushort";
1059: case TCKind._tk_short:
1060: return "short";
1061: case TCKind._tk_float:
1062: return "float";
1063: case TCKind._tk_double:
1064: return "double";
1065: case TCKind._tk_fixed: {
1066: try {
1067: return "fixed <" + fixed_digits() + "," + fixed_scale()
1068: + ">";
1069: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
1070: throw new INTERNAL("should never happen");
1071: }
1072: }
1073: case TCKind._tk_boolean:
1074: return "boolean";
1075: case TCKind._tk_octet:
1076: return "octet";
1077: case TCKind._tk_char:
1078: return "char";
1079: case TCKind._tk_wchar: {
1080: return "wchar";
1081: }
1082: case TCKind._tk_any: {
1083: return "any";
1084: }
1085: case TCKind._tk_sequence: {
1086: try {
1087: return "sequence <" + idlTypeName(content_type()) + ">";
1088: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
1089: throw new INTERNAL("should never happen");
1090: }
1091: }
1092: default: {
1093: return "* no typeName for TK " + kind().value() + " *";
1094: }
1095: }
1096: }
1097:
1098: private static String idToIDL(String id) {
1099: if (id.length() > 4) {
1100: if (id.startsWith("IDL:")) {
1101: id = id.substring(4, id.lastIndexOf(":"));
1102: } else {
1103: id = id.replace('.', '/') + ":1.0";
1104: }
1105: }
1106:
1107: StringBuffer sb = new StringBuffer(id);
1108: int i = 0;
1109: while (i < sb.length()) {
1110: if (sb.charAt(i) == '/') {
1111: sb.setCharAt(i, ':');
1112: sb.insert(i, ':');
1113: }
1114: i++;
1115: }
1116: return sb.toString();
1117: }
1118:
1119: /**
1120: * @return the content type if the argument is an alias, or the argument
1121: * itself otherwise
1122: */
1123: public static final org.omg.CORBA.TypeCode originalType(
1124: org.omg.CORBA.TypeCode typeCode) {
1125: if (isRecursive(typeCode)) {
1126: // Recursive typecodes must be structs or unions so there is no
1127: // unwinding of aliases to be done. By returning here we avoid
1128: // calling kind() on a recursive typecode that might not have been
1129: // resolved yet. (If you remove the return statement below, you
1130: // will get org.omg.CORBA.BAD_INV_ORDER exceptions within kind()
1131: // calls on non-resolved recursive typecodes!)
1132: return typeCode;
1133: }
1134:
1135: try {
1136: while (typeCode.kind() == org.omg.CORBA.TCKind.tk_alias
1137: || typeCode.kind() == org.omg.CORBA.TCKind.tk_value_box) {
1138: typeCode = typeCode.content_type();
1139: }
1140: } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) {
1141: throw new INTERNAL("should never happen");
1142: }
1143: return typeCode;
1144: }
1145:
1146: /**
1147: * Creates a TypeCode for an arbitrary Java class.
1148: * Right now, this only covers RMI classes, not those derived from IDL.
1149: */
1150: public static TypeCode create_tc(Class clazz) {
1151: return create_tc(clazz, new HashMap());
1152: }
1153:
1154: /**
1155: * Creates a TypeCode for class `clazz'. `knownTypes' is a map
1156: * containing classes as keys and their corresponding type codes
1157: * as values. If there is an entry for `clz' in `knownTypes',
1158: * then a recursive type code is returned for it. If there is no
1159: * entry for `clz' in `knownTypes', and a value type code is
1160: * created for it, then an entry for `clz' is also inserted into
1161: * `knownTypes'.
1162: */
1163: private static TypeCode create_tc(Class clazz, Map knownTypes) {
1164: if (clazz.isPrimitive()) {
1165: return (TypeCode) primitive_tcs_map.get(clazz);
1166: } else if (knownTypes.containsKey(clazz)) {
1167: // recursive type code
1168: TypeCode newTypeCode = new TypeCode(RepositoryID
1169: .repId(clazz));
1170: newTypeCode.setActualTC((TypeCode) knownTypes.get(clazz));
1171: return newTypeCode;
1172: } else if (clazz.isArray()) {
1173: // a Java array is mapped to a valuebox containing an IDL sequence
1174: TypeCode newTypeCode = new TypeCode(TCKind._tk_value_box,
1175: RepositoryID.repId(clazz), "Java_array",
1176: new TypeCode(TCKind._tk_sequence, 0, create_tc(
1177: clazz.getComponentType(), knownTypes)));
1178: knownTypes.put(clazz, newTypeCode);
1179: return newTypeCode;
1180: } else if (java.rmi.Remote.class.isAssignableFrom(clazz)) {
1181: return new TypeCode(TCKind._tk_objref, RepositoryID
1182: .repId(clazz), clazz.getName());
1183: } else if (org.omg.CORBA.portable.IDLEntity.class
1184: .isAssignableFrom(clazz)) {
1185: // an IDL entity has a helper class with a static method type()
1186: String helperClassName = clazz.getName() + "Helper";
1187: try {
1188: final ClassLoader classLoader = clazz.getClassLoader();
1189: final Class helperClass;
1190:
1191: if (classLoader == null) {
1192: helperClass = ObjectUtil
1193: .classForName(helperClassName);
1194: } else {
1195: helperClass = classLoader
1196: .loadClass(helperClassName);
1197: }
1198:
1199: Method typeMethod = helperClass.getMethod("type",
1200: (Class[]) null);
1201: TypeCode newTypeCode = (TypeCode) typeMethod.invoke(
1202: null, (Object[]) null);
1203: knownTypes.put(clazz, newTypeCode);
1204: return newTypeCode;
1205: } catch (ClassNotFoundException e) {
1206: throw new IllegalArgumentException(
1207: "Cannot create TypeCode for class "
1208: + clazz
1209: + "\nReason: Error loading helper class "
1210: + helperClassName + "\n" + e);
1211: } catch (NoSuchMethodException e) {
1212: throw new IllegalArgumentException(
1213: "Cannot create TypeCode for class: "
1214: + clazz
1215: + "\nReason: no type() method in helper class "
1216: + helperClassName + "\n" + e);
1217: } catch (IllegalAccessException e) {
1218: throw new IllegalArgumentException(
1219: "Cannot create TypeCode for class: " + clazz
1220: + "\n" + e);
1221: } catch (java.lang.reflect.InvocationTargetException e) {
1222: throw new IllegalArgumentException(
1223: "Cannot create TypeCode for class: "
1224: + clazz
1225: + "\nReason: exception in type() method\n "
1226: + e.getTargetException());
1227: }
1228: } else if (clazz == java.io.Serializable.class
1229: || clazz == java.io.Externalizable.class
1230: || clazz == java.lang.Object.class) {
1231: // Each such Java type is mapped to an IDL typedef for an IDL any
1232: return (TypeCode) get_primitive_tc(TCKind._tk_any);
1233: } else if (isMappedToAnAbstractInterface(clazz)) {
1234: TypeCode newTypeCode = new TypeCode(
1235: TCKind._tk_abstract_interface, RepositoryID
1236: .repId(clazz), clazz.getName());
1237: knownTypes.put(clazz, newTypeCode);
1238: return newTypeCode;
1239: } else // clz is mapped to a valuetype
1240: {
1241: Class super Class = clazz.getSuperclass();
1242: TypeCode super TypeCode = null;
1243: if (super Class != null
1244: && super Class != java.lang.Object.class) {
1245: super TypeCode = create_tc(super Class, knownTypes);
1246: }
1247: TypeCode newTypeCode = new TypeCode(RepositoryID
1248: .repId(clazz), clazz.getName(),
1249: org.omg.CORBA.VM_NONE.value, super TypeCode,
1250: new ValueMember[0]);
1251: knownTypes.put(clazz, newTypeCode);
1252: newTypeCode.setValueMembers(getValueMembers(clazz,
1253: knownTypes));
1254: return newTypeCode;
1255: }
1256: }
1257:
1258: /*
1259: * Java interfaces whose method definitions (including inherited method
1260: * definitions) all throw java.rmi.RemoteException or a superclass of
1261: * java.rmi.RemoteException are mapped to IDL abstract interfaces.
1262: */
1263: private static boolean isMappedToAnAbstractInterface(Class clazz) {
1264: if (!clazz.isInterface()) {
1265: return false;
1266: }
1267: Method[] methods = clazz.getMethods();
1268: for (int i = 0; i < methods.length; i++) {
1269: Class[] exceps = methods[i].getExceptionTypes();
1270: int j = 0;
1271: while (j < exceps.length) {
1272: if (exceps[j]
1273: .isAssignableFrom(java.rmi.RemoteException.class)) {
1274: break;
1275: }
1276: j++;
1277: }
1278: if (j == exceps.length) {
1279: // method[i] does not throw java.rmi.RemoteException
1280: // or a superclass of java.rmi.RemoteException
1281: return false;
1282: }
1283: }
1284: // every method throws java.rmi.RemoteException
1285: // or a superclass of java.rmi.RemoteException
1286: return true;
1287: }
1288:
1289: /**
1290: * Returns the array of ValueMembers of class `clz'. `knownTypes'
1291: * is a map of classes and corresponding type codes for which
1292: * recursive type codes must be created; this is passed through
1293: * from `create_tc (Class, Map)' above.
1294: */
1295: private static ValueMember[] getValueMembers(Class clazz,
1296: Map knownTypes) {
1297: final List result = new ArrayList();
1298: final Field[] fields = clazz.getDeclaredFields();
1299: for (int i = 0; i < fields.length; i++) {
1300: if ((fields[i].getModifiers() & (Modifier.STATIC
1301: | Modifier.FINAL | Modifier.TRANSIENT)) == 0) {
1302: result.add(createValueMember(fields[i], knownTypes));
1303: }
1304: }
1305: return (ValueMember[]) result.toArray(new ValueMember[result
1306: .size()]);
1307: }
1308:
1309: /**
1310: * Creates a ValueMember for field `f'. `knownTypes' is a map of
1311: * classes and their corresponding type codes for which recursive
1312: * type codes must be created; this is passed through from
1313: * `create_tc (Class, Map)' above.
1314: */
1315: private static ValueMember createValueMember(Field field,
1316: Map knownTypes) {
1317: final Class type = field.getType();
1318: final String id = RepositoryID.repId(type);
1319: final TypeCode tc = create_tc(type, knownTypes);
1320: final short access = ((field.getModifiers() & Modifier.PUBLIC) != 0) ? org.omg.CORBA.PUBLIC_MEMBER.value
1321: : org.omg.CORBA.PRIVATE_MEMBER.value;
1322: return new ValueMember(field.getName(), id, "", "1.0", tc,
1323: null, access);
1324: }
1325:
1326: /*
1327: * Resolve any recursive TypeCodes contained within this TypeCode. This
1328: * TypeCode is the actual (non-recursive) TypeCode that replaces any
1329: * recursive TypeCodes with the same RepositoryId. This operation should
1330: * only be called on union or struct TypeCodes since it is only these
1331: * TypeCodes that can be recursive.
1332: */
1333: void resolveRecursion() {
1334: if (kind == TCKind._tk_struct || kind == TCKind._tk_union) {
1335: resolveRecursion(this );
1336: }
1337: }
1338:
1339: /*
1340: * Resolve any recursive TypeCodes contained within this TypeCode.
1341: * @param actual The actual (non-recursive) TypeCode that replaces any
1342: * recursive TypeCodes contained in the actual TypeCode that have the same
1343: * RepositoryId
1344: */
1345: private void resolveRecursion(TypeCode actual) {
1346: if (member_type == null) {
1347: return;
1348: }
1349:
1350: org.omg.CORBA.TypeCode typeCode;
1351: TypeCode tc;
1352: for (int i = 0; i < member_type.length; i++) {
1353: typeCode = TypeCode.originalType(member_type[i]);
1354: if (typeCode instanceof TypeCode) {
1355: tc = (TypeCode) typeCode;
1356:
1357: switch (tc.kind) {
1358: case TCKind._tk_struct:
1359: case TCKind._tk_union:
1360: case TCKind._tk_value: {
1361: tc.resolveRecursion(actual);
1362: break;
1363: }
1364: case TCKind._tk_sequence: {
1365: typeCode = originalType(tc.content_type);
1366: if (typeCode instanceof TypeCode) {
1367: tc = (TypeCode) typeCode;
1368:
1369: if (tc.is_recursive()
1370: && tc.id.equals(actual.id)) {
1371: tc.setActualTC(actual);
1372: } else {
1373: tc.resolveRecursion(actual);
1374: }
1375: }
1376: break;
1377: }
1378: case -1: // create_recursive_tc sets kind to -1
1379: {
1380: if (tc.id.equals(actual.id)) {
1381: tc.setActualTC(actual);
1382: }
1383: break;
1384: }
1385: }
1386: }
1387: }
1388: }
1389:
1390: /*
1391: * Set the actual TypeCode if this TypeCode is recursive.
1392: * @param tc The actual TypeCode
1393: */
1394: private void setActualTC(TypeCode typeCode) {
1395: if (is_recursive()) {
1396: actualTypecode = typeCode;
1397: }
1398: }
1399:
1400: /*
1401: * Check that the actual TypeCode is set if this TypeCode is recursive.
1402: * This method ensures that operations aren't called on a recursive TypeCode
1403: * until the enclosing TypeCode has been fully resolved.
1404: * @exception BAD_INV_ORDER if this TypeCode is recursive and an operation
1405: * is called on it before the enclosing TypeCode has been fully resolved
1406: */
1407: private void checkActualTC() {
1408: if (is_recursive() && actualTypecode == null) {
1409: throw new org.omg.CORBA.BAD_INV_ORDER();
1410: }
1411: }
1412: }
|