/* * Copyright (c) 1997, 2004, 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. */ /* * Licensed Materials - Property of IBM * RMI-IIOP v1.0 * Copyright IBM Corp. 1998 1999 All Rights Reserved * */ package org.jboss.com.sun.corba.se.impl.corba; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import org.jboss.com.sun.corba.se.impl.encoding.CDRInputStream; import org.jboss.com.sun.corba.se.impl.encoding.EncapsInputStream; import org.jboss.com.sun.corba.se.impl.encoding.EncapsOutputStream; import org.jboss.com.sun.corba.se.impl.io.ValueUtility; import org.jboss.com.sun.corba.se.impl.logging.ORBUtilSystemException; import org.jboss.com.sun.corba.se.impl.orbutil.ORBUtility; import org.jboss.com.sun.corba.se.impl.orbutil.RepositoryIdFactory; import org.jboss.com.sun.corba.se.impl.orbutil.RepositoryIdStrings; import org.jboss.com.sun.corba.se.spi.logging.CORBALogDomains; import org.jboss.com.sun.corba.se.spi.orb.ORB; import org.jboss.com.sun.corba.se.spi.orb.ORBVersionFactory; import org.jboss.com.sun.corba.se.spi.presentation.rmi.StubAdapter; import org.omg.CORBA.Any; import org.omg.CORBA.CompletionStatus; import org.omg.CORBA.Principal; import org.omg.CORBA.TCKind; import org.omg.CORBA.TypeCode; import org.omg.CORBA.TypeCodePackage.BadKind; import org.omg.CORBA.TypeCodePackage.Bounds; import org.omg.CORBA.portable.InputStream; import org.omg.CORBA.portable.OutputStream; import org.omg.CORBA.portable.Streamable; // subclasses must provide a matching helper class @SuppressWarnings("deprecation") public class AnyImpl extends Any { private static final long serialVersionUID = 5085834738845046320L; private static final class AnyInputStream extends EncapsInputStream { public AnyInputStream(EncapsInputStream theStream) { super(theStream); } } private static final class AnyOutputStream extends EncapsOutputStream { public AnyOutputStream(ORB orb) { super(orb); } public org.omg.CORBA.portable.InputStream create_input_stream() { return new AnyInputStream((EncapsInputStream) super.create_input_stream()); } } // // Always valid. // private TypeCodeImpl typeCode; protected ORB orb; private ORBUtilSystemException wrapper; // // Validity depends upon typecode. The 'value' and 'object' instance // members are used to hold immutable types as defined by the // isStreamed[] table below. Otherwise, 'stream' is non-null and // holds the value in CDR marshaled format. As an optimization, the // stream type is an Any extension of CDR stream that is used to // detect an optimization in read_value(). // private CDRInputStream stream; private long value; private java.lang.Object object; // Setting the typecode via the type() accessor wipes out the value. // An attempt to extract before the value is set will result // in a BAD_OPERATION exception being raised. private boolean isInitialized = false; /* * This boolean array tells us if a given typecode must be streamed. Objects that are immutable don't have to be * streamed. */ static boolean isStreamed[] = {false, // null false, // void false, // short false, // long false, // ushort false, // ulong false, // float false, // double false, // boolean false, // char false, // octet false, // any false, // TypeCode true, // Principal false, // objref true, // struct true, // union false, // enum false, // string true, // sequence true, // array true, // alias true, // except false, // longlong false, // ulonglong false, // longdouble false, // wchar false, // wstring false, // fixed false, // value false, // value_box (used to be true) false, // native false // abstract interface }; static AnyImpl convertToNative(ORB orb, Any any) { if (any instanceof AnyImpl) { return (AnyImpl) any; } else { AnyImpl anyImpl = new AnyImpl(orb, any); anyImpl.typeCode = TypeCodeImpl.convertToNative(orb, anyImpl.typeCode); return anyImpl; } } // ///////////////////////////////////////////////////////////////////////// // Constructors /** * A constructor that sets the Any to contain a null. It also marks the value as being invalid so that extractions * throw an exception until an insertion has been performed. */ public AnyImpl(ORB orb) { this.orb = orb; wrapper = ORBUtilSystemException.get(orb, CORBALogDomains.RPC_PRESENTATION); typeCode = orb.get_primitive_tc(TCKind._tk_null); stream = null; object = null; value = 0; // null is a valid value isInitialized = true; } // // Create a new AnyImpl which is a copy of obj. // public AnyImpl(ORB orb, Any obj) { this(orb); if ((obj instanceof AnyImpl)) { AnyImpl objImpl = (AnyImpl) obj; typeCode = objImpl.typeCode; value = objImpl.value; object = objImpl.object; isInitialized = objImpl.isInitialized; if (objImpl.stream != null) stream = objImpl.stream.dup(); } else { read_value(obj.create_input_stream(), obj.type()); } } // ///////////////////////////////////////////////////////////////////////// // basic accessors /** * returns the type of the element contained in the Any. * * @result the TypeCode for the element in the Any */ public TypeCode type() { return typeCode; } private TypeCode realType() { return realType(typeCode); } 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(bad); } return realType; } /** * sets the type of the element to be contained in the Any. * * @param tc * the TypeCode for the element in the Any */ public void type(TypeCode tc) { // debug.log ("type2"); // set the typecode typeCode = TypeCodeImpl.convertToNative(orb, tc); stream = null; value = 0; object = null; // null is the only legal value this Any can have after resetting the type code isInitialized = (tc.kind().value() == TCKind._tk_null); } /** * checks for equality between Anys. * * @param otherAny * the Any to be compared with. * @result true if the Anys are equal, false otherwise. */ public boolean equal(Any otherAny) { // debug.log ("equal"); if (otherAny == this) return true; // first check for typecode equality. // note that this will take aliases into account if (!typeCode.equal(otherAny.type())) return false; // Resolve aliases here TypeCode realType = realType(); // _REVISIT_ Possible optimization for the case where // otherAny is a AnyImpl and the endianesses match. // Need implementation of CDRInputStream.equals() // For now we disable this to encourage testing the generic, // unoptimized code below. // Unfortunately this generic code needs to copy the whole stream // at least once. // if (AnyImpl.isStreamed[realType.kind().value()]) { // if (otherAny instanceof AnyImpl) { // return ((AnyImpl)otherAny).stream.equals(stream); // } // } switch (realType.kind().value()) { // handle primitive types case TCKind._tk_null : case TCKind._tk_void : return true; case TCKind._tk_short : return (extract_short() == otherAny.extract_short()); case TCKind._tk_long : return (extract_long() == otherAny.extract_long()); case TCKind._tk_ushort : return (extract_ushort() == otherAny.extract_ushort()); case TCKind._tk_ulong : return (extract_ulong() == otherAny.extract_ulong()); case TCKind._tk_float : return (extract_float() == otherAny.extract_float()); case TCKind._tk_double : return (extract_double() == otherAny.extract_double()); case TCKind._tk_boolean : return (extract_boolean() == otherAny.extract_boolean()); case TCKind._tk_char : return (extract_char() == otherAny.extract_char()); case TCKind._tk_wchar : return (extract_wchar() == otherAny.extract_wchar()); case TCKind._tk_octet : return (extract_octet() == otherAny.extract_octet()); case TCKind._tk_any : return extract_any().equal(otherAny.extract_any()); case TCKind._tk_TypeCode : return extract_TypeCode().equal(otherAny.extract_TypeCode()); case TCKind._tk_string : return extract_string().equals(otherAny.extract_string()); case TCKind._tk_wstring : return (extract_wstring().equals(otherAny.extract_wstring())); case TCKind._tk_longlong : return (extract_longlong() == otherAny.extract_longlong()); case TCKind._tk_ulonglong : return (extract_ulonglong() == otherAny.extract_ulonglong()); case TCKind._tk_objref : return (extract_Object().equals(otherAny.extract_Object())); case TCKind._tk_Principal : return (extract_Principal().equals(otherAny.extract_Principal())); case TCKind._tk_enum : return (extract_long() == otherAny.extract_long()); case TCKind._tk_fixed : return (extract_fixed().compareTo(otherAny.extract_fixed()) == 0); case TCKind._tk_except : case TCKind._tk_struct : case TCKind._tk_union : case TCKind._tk_sequence : case TCKind._tk_array : InputStream copyOfMyStream = this.create_input_stream(); InputStream copyOfOtherStream = otherAny.create_input_stream(); return equalMember(realType, copyOfMyStream, copyOfOtherStream); // Too complicated to handle value types the way we handle // other complex types above. Don't try to decompose it here // for faster comparison, just use Object.equals(). case TCKind._tk_value : case TCKind._tk_value_box : return extract_Value().equals(otherAny.extract_Value()); case TCKind._tk_alias : throw wrapper.errorResolvingAlias(); case TCKind._tk_longdouble : // Unspecified for Java throw wrapper.tkLongDoubleNotSupported(); default : throw wrapper.typecodeNotSupported(); } } // Needed for equal() in order to achieve linear performance for complex types. // Uses up (recursively) copies of the InputStream in both Anys that got created in equal(). private boolean equalMember(TypeCode memberType, InputStream myStream, InputStream otherStream) { // Resolve aliases here TypeCode realType = realType(memberType); try { switch (realType.kind().value()) { // handle primitive types case TCKind._tk_null : case TCKind._tk_void : return true; case TCKind._tk_short : return (myStream.read_short() == otherStream.read_short()); case TCKind._tk_long : return (myStream.read_long() == otherStream.read_long()); case TCKind._tk_ushort : return (myStream.read_ushort() == otherStream.read_ushort()); case TCKind._tk_ulong : return (myStream.read_ulong() == otherStream.read_ulong()); case TCKind._tk_float : return (myStream.read_float() == otherStream.read_float()); case TCKind._tk_double : return (myStream.read_double() == otherStream.read_double()); case TCKind._tk_boolean : return (myStream.read_boolean() == otherStream.read_boolean()); case TCKind._tk_char : return (myStream.read_char() == otherStream.read_char()); case TCKind._tk_wchar : return (myStream.read_wchar() == otherStream.read_wchar()); case TCKind._tk_octet : return (myStream.read_octet() == otherStream.read_octet()); case TCKind._tk_any : return myStream.read_any().equal(otherStream.read_any()); case TCKind._tk_TypeCode : return myStream.read_TypeCode().equal(otherStream.read_TypeCode()); case TCKind._tk_string : return myStream.read_string().equals(otherStream.read_string()); case TCKind._tk_wstring : return (myStream.read_wstring().equals(otherStream.read_wstring())); case TCKind._tk_longlong : return (myStream.read_longlong() == otherStream.read_longlong()); case TCKind._tk_ulonglong : return (myStream.read_ulonglong() == otherStream.read_ulonglong()); case TCKind._tk_objref : return (myStream.read_Object().equals(otherStream.read_Object())); case TCKind._tk_Principal : return (myStream.read_Principal().equals(otherStream.read_Principal())); case TCKind._tk_enum : return (myStream.read_long() == otherStream.read_long()); case TCKind._tk_fixed : return (myStream.read_fixed().compareTo(otherStream.read_fixed()) == 0); case TCKind._tk_except : case TCKind._tk_struct : { int length = realType.member_count(); for (int i = 0; i < length; i++) { if (!equalMember(realType.member_type(i), myStream, otherStream)) { return false; } } return true; } case TCKind._tk_union : { Any myDiscriminator = orb.create_any(); Any otherDiscriminator = orb.create_any(); myDiscriminator.read_value(myStream, realType.discriminator_type()); otherDiscriminator.read_value(otherStream, realType.discriminator_type()); if (!myDiscriminator.equal(otherDiscriminator)) { return false; } TypeCodeImpl realTypeCodeImpl = TypeCodeImpl.convertToNative(orb, realType); int memberIndex = realTypeCodeImpl.currentUnionMemberIndex(myDiscriminator); if (memberIndex == -1) throw wrapper.unionDiscriminatorError(); if (!equalMember(realType.member_type(memberIndex), myStream, otherStream)) { return false; } return true; } case TCKind._tk_sequence : { int length = myStream.read_long(); otherStream.read_long(); // just so that the two stream are in sync for (int i = 0; i < length; i++) { if (!equalMember(realType.content_type(), myStream, otherStream)) { return false; } } return true; } case TCKind._tk_array : { int length = realType.member_count(); for (int i = 0; i < length; i++) { if (!equalMember(realType.content_type(), myStream, otherStream)) { return false; } } return true; } // Too complicated to handle value types the way we handle // other complex types above. Don't try to decompose it here // for faster comparison, just use Object.equals(). case TCKind._tk_value : case TCKind._tk_value_box : org.omg.CORBA_2_3.portable.InputStream mine = (org.omg.CORBA_2_3.portable.InputStream) myStream; org.omg.CORBA_2_3.portable.InputStream other = (org.omg.CORBA_2_3.portable.InputStream) otherStream; return mine.read_value().equals(other.read_value()); case TCKind._tk_alias : // error resolving alias above throw wrapper.errorResolvingAlias(); case TCKind._tk_longdouble : throw wrapper.tkLongDoubleNotSupported(); default : throw wrapper.typecodeNotSupported(); } } catch (BadKind badKind) { // impossible throw wrapper.badkindCannotOccur(); } catch (Bounds bounds) { // impossible throw wrapper.boundsCannotOccur(); } } // ///////////////////////////////////////////////////////////////////////// // accessors for marshaling/unmarshaling /** * returns an output stream that an Any value can be marshaled into. * * @result the OutputStream to marshal value of Any into */ public org.omg.CORBA.portable.OutputStream create_output_stream() { // debug.log ("create_output_stream"); return new AnyOutputStream(orb); } /** * returns an input stream that an Any value can be marshaled out of. * * @result the InputStream to marshal value of Any out of. */ public org.omg.CORBA.portable.InputStream create_input_stream() { // // We create a new InputStream so that multiple threads can call here // and read the streams in parallel without thread safety problems. // // debug.log ("create_input_stream"); if (AnyImpl.isStreamed[realType().kind().value()]) { return stream.dup(); } else { OutputStream os = orb.create_output_stream(); TCUtility.marshalIn(os, realType(), value, object); return os.create_input_stream(); } } // ///////////////////////////////////////////////////////////////////////// // marshaling/unmarshaling routines // // If the InputStream is a CDRInputStream then we can copy the bytes // since it is in our format and does not have alignment issues. // public void read_value(org.omg.CORBA.portable.InputStream in, TypeCode tc) { // debug.log ("read_value"); // // Assume that someone isn't going to think they can keep reading // from this stream after calling us. That would be likely for // an IIOPInputStream but if it is an AnyInputStream then they // presumably obtained it via our create_output_stream() so they could // write the contents of an IDL data type to it and then call // create_input_stream() for us to read it. This is how Helper classes // typically implement the insert() method. // We should probably document this behavior in the 1.1 revision // task force. // typeCode = TypeCodeImpl.convertToNative(orb, tc); int kind = realType().kind().value(); if (kind >= isStreamed.length) { throw wrapper.invalidIsstreamedTckind(CompletionStatus.COMPLETED_MAYBE, new Integer(kind)); } if (AnyImpl.isStreamed[kind]) { if (in instanceof AnyInputStream) { // could only have been created here stream = (CDRInputStream) in; } else { org.omg.CORBA_2_3.portable.OutputStream out = (org.omg.CORBA_2_3.portable.OutputStream) orb .create_output_stream(); typeCode.copy(in, out); stream = (CDRInputStream) out.create_input_stream(); } } else { java.lang.Object[] objholder = new java.lang.Object[1]; objholder[0] = object; long[] longholder = new long[1]; TCUtility.unmarshalIn(in, typeCode, longholder, objholder); value = longholder[0]; object = objholder[0]; stream = null; } isInitialized = true; } // // We could optimize this by noticing whether the target stream // has ever had anything marshaled on it that required an // alignment of greater than 4 (was write_double() ever called on it). // If not, then we can just do a byte array copy without having to // drive the remarshaling through typecode interpretation. // public void write_value(OutputStream out) { // debug.log ("write_value"); if (AnyImpl.isStreamed[realType().kind().value()]) { typeCode.copy(stream.dup(), out); } else { // _REVISIT_ check isInitialized whether all we write is TypeCode! TCUtility.marshalIn(out, realType(), value, object); } } /** * takes a streamable and inserts its reference into the any * * @param s * the streamable to insert */ public void insert_Streamable(Streamable s) { // debug.log ("insert_Streamable"); typeCode = TypeCodeImpl.convertToNative(orb, s._type()); object = s; isInitialized = true; } public Streamable extract_Streamable() { // debug.log( "extract_Streamable" ) ; return (Streamable) object; } // ///////////////////////////////////////////////////////////////////////// // insertion/extraction/replacement for all basic types /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_short(short s) { // debug.log ("insert_short"); typeCode = orb.get_primitive_tc(TCKind._tk_short); value = s; isInitialized = true; } private String getTCKindName(int tc) { if ((tc >= 0) && (tc < TypeCodeImpl.kindNames.length)) return TypeCodeImpl.kindNames[tc]; else return "UNKNOWN(" + tc + ")"; } private void checkExtractBadOperation(int expected) { if (!isInitialized) throw wrapper.extractNotInitialized(); int tc = realType().kind().value(); if (tc != expected) { String tcName = getTCKindName(tc); String expectedName = getTCKindName(expected); throw wrapper.extractWrongType(expectedName, tcName); } } private void checkExtractBadOperationList(int[] expected) { if (!isInitialized) throw wrapper.extractNotInitialized(); int tc = realType().kind().value(); for (int ctr = 0; ctr < expected.length; ctr++) if (tc == expected[ctr]) return; List<String> list = new ArrayList<String>(); for (int ctr = 0; ctr < expected.length; ctr++) list.add(getTCKindName(expected[ctr])); String tcName = getTCKindName(tc); throw wrapper.extractWrongTypeList(list, tcName); } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public short extract_short() { // debug.log ("extract_short"); checkExtractBadOperation(TCKind._tk_short); return (short) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_long(int l) { // debug.log ("insert_long"); // A long value is applicable to enums as well, so don't erase the enum type code // in case it was initialized that way before. int kind = realType().kind().value(); if (kind != TCKind._tk_long && kind != TCKind._tk_enum) { typeCode = orb.get_primitive_tc(TCKind._tk_long); } value = l; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public int extract_long() { // debug.log ("extract_long"); checkExtractBadOperationList(new int[]{TCKind._tk_long, TCKind._tk_enum}); return (int) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_ushort(short s) { // debug.log ("insert_ushort"); typeCode = orb.get_primitive_tc(TCKind._tk_ushort); value = s; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public short extract_ushort() { // debug.log ("extract_ushort"); checkExtractBadOperation(TCKind._tk_ushort); return (short) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_ulong(int l) { // debug.log ("insert_ulong"); typeCode = orb.get_primitive_tc(TCKind._tk_ulong); value = l; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public int extract_ulong() { // debug.log ("extract_ulong"); checkExtractBadOperation(TCKind._tk_ulong); return (int) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_float(float f) { // debug.log ("insert_float"); typeCode = orb.get_primitive_tc(TCKind._tk_float); value = Float.floatToIntBits(f); isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public float extract_float() { // debug.log ("extract_float"); checkExtractBadOperation(TCKind._tk_float); return Float.intBitsToFloat((int) value); } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_double(double d) { // debug.log ("insert_double"); typeCode = orb.get_primitive_tc(TCKind._tk_double); value = Double.doubleToLongBits(d); isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public double extract_double() { // debug.log ("extract_double"); checkExtractBadOperation(TCKind._tk_double); return Double.longBitsToDouble(value); } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_longlong(long l) { // debug.log ("insert_longlong"); typeCode = orb.get_primitive_tc(TCKind._tk_longlong); value = l; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public long extract_longlong() { // debug.log ("extract_longlong"); checkExtractBadOperation(TCKind._tk_longlong); return value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_ulonglong(long l) { // debug.log ("insert_ulonglong"); typeCode = orb.get_primitive_tc(TCKind._tk_ulonglong); value = l; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public long extract_ulonglong() { // debug.log ("extract_ulonglong"); checkExtractBadOperation(TCKind._tk_ulonglong); return value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_boolean(boolean b) { // debug.log ("insert_boolean"); typeCode = orb.get_primitive_tc(TCKind._tk_boolean); value = (b) ? 1 : 0; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public boolean extract_boolean() { // debug.log ("extract_boolean"); checkExtractBadOperation(TCKind._tk_boolean); return (value == 0) ? false : true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_char(char c) { // debug.log ("insert_char"); typeCode = orb.get_primitive_tc(TCKind._tk_char); value = c; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public char extract_char() { // debug.log ("extract_char"); checkExtractBadOperation(TCKind._tk_char); return (char) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_wchar(char c) { // debug.log ("insert_wchar"); typeCode = orb.get_primitive_tc(TCKind._tk_wchar); value = c; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public char extract_wchar() { // debug.log ("extract_wchar"); checkExtractBadOperation(TCKind._tk_wchar); return (char) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_octet(byte b) { // debug.log ("insert_octet"); typeCode = orb.get_primitive_tc(TCKind._tk_octet); value = b; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public byte extract_octet() { // debug.log ("extract_octet"); checkExtractBadOperation(TCKind._tk_octet); return (byte) value; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_string(String s) { // debug.log ("insert_string"); // Make sure type code information for bounded strings is not erased if (typeCode.kind() == TCKind.tk_string) { int length = 0; try { length = typeCode.length(); } catch (BadKind bad) { throw wrapper.badkindCannotOccur(); } // Check if bounded strings length is not exceeded if (length != 0 && s != null && s.length() > length) { throw wrapper.badStringBounds(new Integer(s.length()), new Integer(length)); } } else { typeCode = orb.get_primitive_tc(TCKind._tk_string); } object = s; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public String extract_string() { // debug.log ("extract_string"); checkExtractBadOperation(TCKind._tk_string); return (String) object; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_wstring(String s) { // debug.log ("insert_wstring"); // Make sure type code information for bounded strings is not erased if (typeCode.kind() == TCKind.tk_wstring) { int length = 0; try { length = typeCode.length(); } catch (BadKind bad) { throw wrapper.badkindCannotOccur(); } // Check if bounded strings length is not exceeded if (length != 0 && s != null && s.length() > length) { throw wrapper.badStringBounds(new Integer(s.length()), new Integer(length)); } } else { typeCode = orb.get_primitive_tc(TCKind._tk_wstring); } object = s; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public String extract_wstring() { // debug.log ("extract_wstring"); checkExtractBadOperation(TCKind._tk_wstring); return (String) object; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_any(Any a) { // debug.log ("insert_any"); typeCode = orb.get_primitive_tc(TCKind._tk_any); object = a; stream = null; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public Any extract_any() { // debug.log ("extract_any"); checkExtractBadOperation(TCKind._tk_any); return (Any) object; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_Object(org.omg.CORBA.Object o) { // debug.log ("insert_Object"); if (o == null) { typeCode = orb.get_primitive_tc(TCKind._tk_objref); } else { if (StubAdapter.isStub(o)) { String[] ids = StubAdapter.getTypeIds(o); typeCode = new TypeCodeImpl(orb, TCKind._tk_objref, ids[0], ""); } else { throw wrapper.badInsertobjParam(CompletionStatus.COMPLETED_MAYBE, o.getClass().getName()); } } object = o; isInitialized = true; } /** * A variant of the insertion operation that takes a typecode argument as well. */ public void insert_Object(org.omg.CORBA.Object o, TypeCode tc) { // debug.log ("insert_Object2"); try { if (tc.id().equals("IDL:omg.org/CORBA/Object:1.0") || o._is_a(tc.id())) { typeCode = TypeCodeImpl.convertToNative(orb, tc); object = o; } else { throw wrapper.insertObjectIncompatible(); } } catch (Exception ex) { throw wrapper.insertObjectFailed(ex); } isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public org.omg.CORBA.Object extract_Object() { // debug.log ("extract_Object"); if (!isInitialized) throw wrapper.extractNotInitialized(); // Check if the object contained here is of the type in typeCode org.omg.CORBA.Object obj = null; try { obj = (org.omg.CORBA.Object) object; if (typeCode.id().equals("IDL:omg.org/CORBA/Object:1.0") || obj._is_a(typeCode.id())) { return obj; } else { throw wrapper.extractObjectIncompatible(); } } catch (Exception ex) { throw wrapper.extractObjectFailed(ex); } } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public void insert_TypeCode(TypeCode tc) { // debug.log ("insert_TypeCode"); typeCode = orb.get_primitive_tc(TCKind._tk_TypeCode); object = tc; isInitialized = true; } /** * See the description of the <a href="#anyOps">general Any operations.</a> */ public TypeCode extract_TypeCode() { // debug.log ("extract_TypeCode"); checkExtractBadOperation(TCKind._tk_TypeCode); return (TypeCode) object; } /** * @deprecated */ @Deprecated public void insert_Principal(Principal p) { typeCode = orb.get_primitive_tc(TCKind._tk_Principal); object = p; isInitialized = true; } /** * @deprecated */ @Deprecated public Principal extract_Principal() { checkExtractBadOperation(TCKind._tk_Principal); return (Principal) object; } /** * Note that the Serializable really should be an IDLEntity of some kind. It shouldn't just be an RMI-IIOP type. * Currently, we accept and will produce RMI repIds with the latest calculations if given a non-IDLEntity * Serializable. */ public Serializable extract_Value() { // debug.log ("extract_Value"); checkExtractBadOperationList(new int[]{TCKind._tk_value, TCKind._tk_value_box, TCKind._tk_abstract_interface}); return (Serializable) object; } public void insert_Value(Serializable v) { // debug.log ("insert_Value"); object = v; TypeCode tc; if (v == null) { tc = orb.get_primitive_tc(TCKind.tk_value); } else { // See note in getPrimitiveTypeCodeForClass. We // have to use the latest type code fixes in this // case since there is no way to know what ORB will // actually send this Any. In RMI-IIOP, when using // Util.writeAny, we can do the versioning correctly, // and use the insert_Value(Serializable, TypeCode) // method. // // The ORB singleton uses the latest version. tc = createTypeCodeForClass(v.getClass(), (ORB) ORB.init()); } typeCode = TypeCodeImpl.convertToNative(orb, tc); isInitialized = true; } public void insert_Value(Serializable v, org.omg.CORBA.TypeCode t) { // debug.log ("insert_Value2"); object = v; typeCode = TypeCodeImpl.convertToNative(orb, t); isInitialized = true; } public void insert_fixed(java.math.BigDecimal value) { typeCode = TypeCodeImpl.convertToNative(orb, orb.create_fixed_tc(TypeCodeImpl.digits(value), TypeCodeImpl.scale(value))); object = value; isInitialized = true; } public void insert_fixed(java.math.BigDecimal value, org.omg.CORBA.TypeCode type) { try { if (TypeCodeImpl.digits(value) > type.fixed_digits() || TypeCodeImpl.scale(value) > type.fixed_scale()) { throw wrapper.fixedNotMatch(); } } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) { // type isn't even of kind fixed throw wrapper.fixedBadTypecode(bk); } typeCode = TypeCodeImpl.convertToNative(orb, type); object = value; isInitialized = true; } public java.math.BigDecimal extract_fixed() { checkExtractBadOperation(TCKind._tk_fixed); return (BigDecimal) object; } /** * Utility method for insert_Value and Util.writeAny. * * The ORB passed in should have the desired ORBVersion. It is used to generate the type codes. */ public TypeCode createTypeCodeForClass(java.lang.Class<?> c, ORB tcORB) { // Look in the cache first TypeCodeImpl classTC = tcORB.getTypeCodeForClass(c); if (classTC != null) return classTC; // All cases need to be able to create repository IDs. // // See bug 4391648 for more info about the tcORB in this // case. RepositoryIdStrings repStrs = RepositoryIdFactory.getRepIdStringsFactory(tcORB); // Assertion: c instanceof Serializable? if (c.isArray()) { // Arrays - may recurse for multi-dimensional arrays Class<?> componentClass = c.getComponentType(); TypeCode embeddedType; if (componentClass.isPrimitive()) { embeddedType = getPrimitiveTypeCodeForClass(componentClass, tcORB); } else { embeddedType = createTypeCodeForClass(componentClass, tcORB); } TypeCode t = tcORB.create_sequence_tc(0, embeddedType); String id = repStrs.createForJavaType(c); return tcORB.create_value_box_tc(id, "Sequence", t); } else if (c == java.lang.String.class) { // Strings TypeCode t = tcORB.create_string_tc(0); String id = repStrs.createForJavaType(c); return tcORB.create_value_box_tc(id, "StringValue", t); } // Anything else // We know that this is a TypeCodeImpl since it is our ORB classTC = (TypeCodeImpl) ValueUtility.createTypeCodeForClass(tcORB, c, ORBUtility.createValueHandler(tcORB)); // Intruct classTC to store its buffer classTC.setCaching(true); // Update the cache tcORB.setTypeCodeForClass(c, classTC); return classTC; } /** * It looks like this was copied from io.ValueUtility at some point. * * It's used by createTypeCodeForClass. The tcORB passed in should have the desired ORB version, and is used to * create the type codes. */ private TypeCode getPrimitiveTypeCodeForClass(Class<?> c, ORB tcORB) { // debug.log ("getPrimitiveTypeCodeForClass"); if (c == Integer.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_long); } else if (c == Byte.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_octet); } else if (c == Long.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_longlong); } else if (c == Float.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_float); } else if (c == Double.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_double); } else if (c == Short.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_short); } else if (c == Character.TYPE) { // For Merlin or later JDKs, or for foreign ORBs, // we correctly say that a Java char maps to a // CORBA wchar. For backwards compatibility // with our older ORBs, we say it maps to a // CORBA char. This is only used in RMI-IIOP // in our javax.rmi.CORBA.Util delegate's // writeAny method. In Java IDL, there's no way // to know the ORB version that the Any will be // sent out with -- it could be different than // the one used to create the Any -- so we use the // most recent version (see insert_Value). if (ORBVersionFactory.getFOREIGN().compareTo(tcORB.getORBVersion()) == 0 || ORBVersionFactory.getNEWER().compareTo(tcORB.getORBVersion()) <= 0) return tcORB.get_primitive_tc(TCKind.tk_wchar); else return tcORB.get_primitive_tc(TCKind.tk_char); } else if (c == Boolean.TYPE) { return tcORB.get_primitive_tc(TCKind.tk_boolean); } else { // _REVISIT_ Not sure if this is right. return tcORB.get_primitive_tc(TCKind.tk_any); } } // Extracts a member value according to the given TypeCode from the given complex Any // (at the Anys current internal stream position, consuming the anys stream on the way) // and returns it wrapped into a new Any public Any extractAny(TypeCode memberType, ORB orb) { Any returnValue = orb.create_any(); OutputStream out = returnValue.create_output_stream(); TypeCodeImpl.convertToNative(orb, memberType).copy(stream, out); returnValue.read_value(out.create_input_stream(), memberType); return returnValue; } // This method could very well be moved into TypeCodeImpl or a common utility class, // but is has to be in this package. static public Any extractAnyFromStream(TypeCode memberType, InputStream input, ORB orb) { Any returnValue = orb.create_any(); OutputStream out = returnValue.create_output_stream(); TypeCodeImpl.convertToNative(orb, memberType).copy(input, out); returnValue.read_value(out.create_input_stream(), memberType); return returnValue; } // There is no other way for DynAnys to find out whether the Any is initialized. public boolean isInitialized() { return isInitialized; } }