1 /* 2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 /* 26 * Licensed Materials - Property of IBM 27 * RMI-IIOP v1.0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved 29 * 30 */ 31 32 package com.sun.corba.se.impl.corba; 33 34 import java.io.Serializable; 35 import java.math.BigDecimal; 36 import java.util.List ; 37 import java.util.ArrayList ; 38 39 import org.omg.CORBA.Principal ; 40 import org.omg.CORBA.TypeCode ; 41 import org.omg.CORBA.Any ; 42 import org.omg.CORBA.CompletionStatus ; 43 import org.omg.CORBA.TCKind ; 44 45 import org.omg.CORBA.portable.Streamable; 46 import org.omg.CORBA.portable.InputStream; 47 import org.omg.CORBA.portable.OutputStream; 48 import org.omg.CORBA.TypeCodePackage.BadKind; 49 import org.omg.CORBA.TypeCodePackage.Bounds; 50 51 import com.sun.corba.se.spi.orb.ORB; 52 import com.sun.corba.se.spi.orb.ORBVersionFactory; 53 import com.sun.corba.se.spi.logging.CORBALogDomains; 54 import com.sun.corba.se.spi.presentation.rmi.StubAdapter; 55 56 import com.sun.corba.se.impl.encoding.CDRInputStream; 57 import com.sun.corba.se.impl.encoding.EncapsInputStream; 58 import com.sun.corba.se.impl.encoding.EncapsOutputStream; 59 import com.sun.corba.se.impl.io.ValueUtility; 60 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory; 61 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings; 62 import com.sun.corba.se.impl.orbutil.ORBUtility; 63 import com.sun.corba.se.impl.logging.ORBUtilSystemException; 64 65 // subclasses must provide a matching helper class 66 public class AnyImpl extends Any 67 { 68 private static final class AnyInputStream extends EncapsInputStream 69 { 70 public AnyInputStream(EncapsInputStream theStream ) 71 { 72 super( theStream ); 73 } 74 } 75 76 private static final class AnyOutputStream extends EncapsOutputStream 77 { 78 public AnyOutputStream(ORB orb) 79 { 80 super((ORB)orb); 81 } 82 83 public org.omg.CORBA.portable.InputStream create_input_stream() 84 { 85 return new AnyInputStream( 86 (com.sun.corba.se.impl.encoding.EncapsInputStream) 87 super.create_input_stream()); 88 } 89 } 90 91 // 92 // Always valid. 93 // 94 private TypeCodeImpl typeCode; 95 protected ORB orb; 96 private ORBUtilSystemException wrapper ; 97 98 // 99 // Validity depends upon typecode. The 'value' and 'object' instance 100 // members are used to hold immutable types as defined by the 101 // isStreamed[] table below. Otherwise, 'stream' is non-null and 102 // holds the value in CDR marshaled format. As an optimization, the 103 // stream type is an Any extension of CDR stream that is used to 104 // detect an optimization in read_value(). 105 // 106 private CDRInputStream stream; 107 private long value; 108 private java.lang.Object object; 109 110 // Setting the typecode via the type() accessor wipes out the value. 111 // An attempt to extract before the value is set will result 112 // in a BAD_OPERATION exception being raised. 113 private boolean isInitialized = false; 114 115 private static final int DEFAULT_BUFFER_SIZE = 32; 116 117 /* 118 * This boolean array tells us if a given typecode must be 119 * streamed. Objects that are immutable don't have to be streamed. 120 */ 121 static boolean isStreamed[] = { 122 false, // null 123 false, // void 124 false, // short 125 false, // long 126 false, // ushort 127 false, // ulong 128 false, // float 129 false, // double 130 false, // boolean 131 false, // char 132 false, // octet 133 false, // any 134 false, // TypeCode 135 true, // Principal 136 false, // objref 137 true, // struct 138 true, // union 139 false, // enum 140 false, // string 141 true, // sequence 142 true, // array 143 true, // alias 144 true, // except 145 false, // longlong 146 false, // ulonglong 147 false, // longdouble 148 false, // wchar 149 false, // wstring 150 false, // fixed 151 false, // value 152 false, // value_box (used to be true) 153 false, // native 154 false // abstract interface 155 }; 156 157 static AnyImpl convertToNative(ORB orb, Any any) { 158 if (any instanceof AnyImpl) { 159 return (AnyImpl)any; 160 } else { 161 AnyImpl anyImpl = new AnyImpl(orb, any); 162 anyImpl.typeCode = TypeCodeImpl.convertToNative(orb, anyImpl.typeCode); 163 return anyImpl; 164 } 165 } 166 167 /////////////////////////////////////////////////////////////////////////// 168 // Constructors 169 170 /** 171 * A constructor that sets the Any to contain a null. It also marks 172 * the value as being invalid so that extractions throw an exception 173 * until an insertion has been performed. 174 */ 175 public AnyImpl(ORB orb) 176 { 177 this.orb = orb; 178 wrapper = ORBUtilSystemException.get( (com.sun.corba.se.spi.orb.ORB)orb, 179 CORBALogDomains.RPC_PRESENTATION ) ; 180 181 typeCode = orb.get_primitive_tc(TCKind._tk_null); 182 stream = null; 183 object = null; 184 value = 0; 185 // null is a valid value 186 isInitialized = true; 187 } 188 189 // 190 // Create a new AnyImpl which is a copy of obj. 191 // 192 public AnyImpl(ORB orb, Any obj) { 193 this(orb); 194 195 if ((obj instanceof AnyImpl)) { 196 AnyImpl objImpl = (AnyImpl)obj; 197 typeCode = objImpl.typeCode; 198 value = objImpl.value; 199 object = objImpl.object; 200 isInitialized = objImpl.isInitialized; 201 202 if (objImpl.stream != null) 203 stream = objImpl.stream.dup(); 204 205 } else { 206 read_value(obj.create_input_stream(), obj.type()); 207 } 208 } 209 210 /////////////////////////////////////////////////////////////////////////// 211 // basic accessors 212 213 /** 214 * returns the type of the element contained in the Any. 215 * 216 * @result the TypeCode for the element in the Any 217 */ 218 public TypeCode type() { 219 return typeCode; 220 } 221 222 private TypeCode realType() { 223 return realType(typeCode); 224 } 225 226 private TypeCode realType(TypeCode aType) { 227 TypeCode realType = aType; 228 try { 229 // Note: Indirect types are handled in kind() method 230 while (realType.kind().value() == TCKind._tk_alias) { 231 realType = realType.content_type(); 232 } 233 } catch (BadKind bad) { // impossible 234 throw wrapper.badkindCannotOccur( bad ) ; 235 } 236 return realType; 237 } 238 239 /** 240 * sets the type of the element to be contained in the Any. 241 * 242 * @param tc the TypeCode for the element in the Any 243 */ 244 public void type(TypeCode tc) 245 { 246 //debug.log ("type2"); 247 // set the typecode 248 typeCode = TypeCodeImpl.convertToNative(orb, tc); 249 250 stream = null; 251 value = 0; 252 object = null; 253 // null is the only legal value this Any can have after resetting the type code 254 isInitialized = (tc.kind().value() == TCKind._tk_null); 255 } 256 257 /** 258 * checks for equality between Anys. 259 * 260 * @param otherAny the Any to be compared with. 261 * @result true if the Anys are equal, false otherwise. 262 */ 263 public boolean equal(Any otherAny) 264 { 265 //debug.log ("equal"); 266 267 if (otherAny == this) 268 return true; 269 270 // first check for typecode equality. 271 // note that this will take aliases into account 272 if (!typeCode.equal(otherAny.type())) 273 return false; 274 275 // Resolve aliases here 276 TypeCode realType = realType(); 277 278 // _REVISIT_ Possible optimization for the case where 279 // otherAny is a AnyImpl and the endianesses match. 280 // Need implementation of CDRInputStream.equals() 281 // For now we disable this to encourage testing the generic, 282 // unoptimized code below. 283 // Unfortunately this generic code needs to copy the whole stream 284 // at least once. 285 // if (AnyImpl.isStreamed[realType.kind().value()]) { 286 // if (otherAny instanceof AnyImpl) { 287 // return ((AnyImpl)otherAny).stream.equals(stream); 288 // } 289 // } 290 switch (realType.kind().value()) { 291 // handle primitive types 292 case TCKind._tk_null: 293 case TCKind._tk_void: 294 return true; 295 case TCKind._tk_short: 296 return (extract_short() == otherAny.extract_short()); 297 case TCKind._tk_long: 298 return (extract_long() == otherAny.extract_long()); 299 case TCKind._tk_ushort: 300 return (extract_ushort() == otherAny.extract_ushort()); 301 case TCKind._tk_ulong: 302 return (extract_ulong() == otherAny.extract_ulong()); 303 case TCKind._tk_float: 304 return (extract_float() == otherAny.extract_float()); 305 case TCKind._tk_double: 306 return (extract_double() == otherAny.extract_double()); 307 case TCKind._tk_boolean: 308 return (extract_boolean() == otherAny.extract_boolean()); 309 case TCKind._tk_char: 310 return (extract_char() == otherAny.extract_char()); 311 case TCKind._tk_wchar: 312 return (extract_wchar() == otherAny.extract_wchar()); 313 case TCKind._tk_octet: 314 return (extract_octet() == otherAny.extract_octet()); 315 case TCKind._tk_any: 316 return extract_any().equal(otherAny.extract_any()); 317 case TCKind._tk_TypeCode: 318 return extract_TypeCode().equal(otherAny.extract_TypeCode()); 319 case TCKind._tk_string: 320 return extract_string().equals(otherAny.extract_string()); 321 case TCKind._tk_wstring: 322 return (extract_wstring().equals(otherAny.extract_wstring())); 323 case TCKind._tk_longlong: 324 return (extract_longlong() == otherAny.extract_longlong()); 325 case TCKind._tk_ulonglong: 326 return (extract_ulonglong() == otherAny.extract_ulonglong()); 327 328 case TCKind._tk_objref: 329 return (extract_Object().equals(otherAny.extract_Object())); 330 case TCKind._tk_Principal: 331 return (extract_Principal().equals(otherAny.extract_Principal())); 332 333 case TCKind._tk_enum: 334 return (extract_long() == otherAny.extract_long()); 335 case TCKind._tk_fixed: 336 return (extract_fixed().compareTo(otherAny.extract_fixed()) == 0); 337 case TCKind._tk_except: 338 case TCKind._tk_struct: 339 case TCKind._tk_union: 340 case TCKind._tk_sequence: 341 case TCKind._tk_array: 342 InputStream copyOfMyStream = this.create_input_stream(); 343 InputStream copyOfOtherStream = otherAny.create_input_stream(); 344 return equalMember(realType, copyOfMyStream, copyOfOtherStream); 345 346 // Too complicated to handle value types the way we handle 347 // other complex types above. Don't try to decompose it here 348 // for faster comparison, just use Object.equals(). 349 case TCKind._tk_value: 350 case TCKind._tk_value_box: 351 return extract_Value().equals(otherAny.extract_Value()); 352 353 case TCKind._tk_alias: 354 throw wrapper.errorResolvingAlias() ; 355 356 case TCKind._tk_longdouble: 357 // Unspecified for Java 358 throw wrapper.tkLongDoubleNotSupported() ; 359 360 default: 361 throw wrapper.typecodeNotSupported() ; 362 } 363 } 364 365 // Needed for equal() in order to achieve linear performance for complex types. 366 // Uses up (recursively) copies of the InputStream in both Anys that got created in equal(). 367 private boolean equalMember(TypeCode memberType, InputStream myStream, InputStream otherStream) { 368 // Resolve aliases here 369 TypeCode realType = realType(memberType); 370 371 try { 372 switch (realType.kind().value()) { 373 // handle primitive types 374 case TCKind._tk_null: 375 case TCKind._tk_void: 376 return true; 377 case TCKind._tk_short: 378 return (myStream.read_short() == otherStream.read_short()); 379 case TCKind._tk_long: 380 return (myStream.read_long() == otherStream.read_long()); 381 case TCKind._tk_ushort: 382 return (myStream.read_ushort() == otherStream.read_ushort()); 383 case TCKind._tk_ulong: 384 return (myStream.read_ulong() == otherStream.read_ulong()); 385 case TCKind._tk_float: 386 return (myStream.read_float() == otherStream.read_float()); 387 case TCKind._tk_double: 388 return (myStream.read_double() == otherStream.read_double()); 389 case TCKind._tk_boolean: 390 return (myStream.read_boolean() == otherStream.read_boolean()); 391 case TCKind._tk_char: 392 return (myStream.read_char() == otherStream.read_char()); 393 case TCKind._tk_wchar: 394 return (myStream.read_wchar() == otherStream.read_wchar()); 395 case TCKind._tk_octet: 396 return (myStream.read_octet() == otherStream.read_octet()); 397 case TCKind._tk_any: 398 return myStream.read_any().equal(otherStream.read_any()); 399 case TCKind._tk_TypeCode: 400 return myStream.read_TypeCode().equal(otherStream.read_TypeCode()); 401 case TCKind._tk_string: 402 return myStream.read_string().equals(otherStream.read_string()); 403 case TCKind._tk_wstring: 404 return (myStream.read_wstring().equals(otherStream.read_wstring())); 405 case TCKind._tk_longlong: 406 return (myStream.read_longlong() == otherStream.read_longlong()); 407 case TCKind._tk_ulonglong: 408 return (myStream.read_ulonglong() == otherStream.read_ulonglong()); 409 410 case TCKind._tk_objref: 411 return (myStream.read_Object().equals(otherStream.read_Object())); 412 case TCKind._tk_Principal: 413 return (myStream.read_Principal().equals(otherStream.read_Principal())); 414 415 case TCKind._tk_enum: 416 return (myStream.read_long() == otherStream.read_long()); 417 case TCKind._tk_fixed: 418 return (myStream.read_fixed().compareTo(otherStream.read_fixed()) == 0); 419 case TCKind._tk_except: 420 case TCKind._tk_struct: { 421 int length = realType.member_count(); 422 for (int i=0; i<length; i++) { 423 if ( ! equalMember(realType.member_type(i), myStream, otherStream)) { 424 return false; 425 } 426 } 427 return true; 428 } 429 case TCKind._tk_union: { 430 Any myDiscriminator = orb.create_any(); 431 Any otherDiscriminator = orb.create_any(); 432 myDiscriminator.read_value(myStream, realType.discriminator_type()); 433 otherDiscriminator.read_value(otherStream, realType.discriminator_type()); 434 435 if ( ! myDiscriminator.equal(otherDiscriminator)) { 436 return false; 437 } 438 TypeCodeImpl realTypeCodeImpl = TypeCodeImpl.convertToNative(orb, realType); 439 int memberIndex = realTypeCodeImpl.currentUnionMemberIndex(myDiscriminator); 440 if (memberIndex == -1) 441 throw wrapper.unionDiscriminatorError() ; 442 443 if ( ! equalMember(realType.member_type(memberIndex), myStream, otherStream)) { 444 return false; 445 } 446 return true; 447 } 448 case TCKind._tk_sequence: { 449 int length = myStream.read_long(); 450 otherStream.read_long(); // just so that the two stream are in sync 451 for (int i=0; i<length; i++) { 452 if ( ! equalMember(realType.content_type(), myStream, otherStream)) { 453 return false; 454 } 455 } 456 return true; 457 } 458 case TCKind._tk_array: { 459 int length = realType.member_count(); 460 for (int i=0; i<length; i++) { 461 if ( ! equalMember(realType.content_type(), myStream, otherStream)) { 462 return false; 463 } 464 } 465 return true; 466 } 467 468 // Too complicated to handle value types the way we handle 469 // other complex types above. Don't try to decompose it here 470 // for faster comparison, just use Object.equals(). 471 case TCKind._tk_value: 472 case TCKind._tk_value_box: 473 org.omg.CORBA_2_3.portable.InputStream mine = 474 (org.omg.CORBA_2_3.portable.InputStream)myStream; 475 org.omg.CORBA_2_3.portable.InputStream other = 476 (org.omg.CORBA_2_3.portable.InputStream)otherStream; 477 return mine.read_value().equals(other.read_value()); 478 479 case TCKind._tk_alias: 480 // error resolving alias above 481 throw wrapper.errorResolvingAlias() ; 482 483 case TCKind._tk_longdouble: 484 throw wrapper.tkLongDoubleNotSupported() ; 485 486 default: 487 throw wrapper.typecodeNotSupported() ; 488 } 489 } catch (BadKind badKind) { // impossible 490 throw wrapper.badkindCannotOccur() ; 491 } catch (Bounds bounds) { // impossible 492 throw wrapper.boundsCannotOccur() ; 493 } 494 } 495 496 /////////////////////////////////////////////////////////////////////////// 497 // accessors for marshaling/unmarshaling 498 499 /** 500 * returns an output stream that an Any value can be marshaled into. 501 * 502 * @result the OutputStream to marshal value of Any into 503 */ 504 public org.omg.CORBA.portable.OutputStream create_output_stream() 505 { 506 //debug.log ("create_output_stream"); 507 return new AnyOutputStream(orb); 508 } 509 510 /** 511 * returns an input stream that an Any value can be marshaled out of. 512 * 513 * @result the InputStream to marshal value of Any out of. 514 */ 515 public org.omg.CORBA.portable.InputStream create_input_stream() 516 { 517 // 518 // We create a new InputStream so that multiple threads can call here 519 // and read the streams in parallel without thread safety problems. 520 // 521 //debug.log ("create_input_stream"); 522 if (AnyImpl.isStreamed[realType().kind().value()]) { 523 return stream.dup(); 524 } else { 525 OutputStream os = (OutputStream)orb.create_output_stream(); 526 TCUtility.marshalIn(os, realType(), value, object); 527 528 return os.create_input_stream(); 529 } 530 } 531 532 /////////////////////////////////////////////////////////////////////////// 533 // marshaling/unmarshaling routines 534 535 // 536 // If the InputStream is a CDRInputStream then we can copy the bytes 537 // since it is in our format and does not have alignment issues. 538 // 539 public void read_value(org.omg.CORBA.portable.InputStream in, TypeCode tc) 540 { 541 //debug.log ("read_value"); 542 // 543 // Assume that someone isn't going to think they can keep reading 544 // from this stream after calling us. That would be likely for 545 // an IIOPInputStream but if it is an AnyInputStream then they 546 // presumably obtained it via our create_output_stream() so they could 547 // write the contents of an IDL data type to it and then call 548 // create_input_stream() for us to read it. This is how Helper classes 549 // typically implement the insert() method. 550 // We should probably document this behavior in the 1.1 revision 551 // task force. 552 // 553 554 typeCode = TypeCodeImpl.convertToNative(orb, tc); 555 int kind = realType().kind().value(); 556 if (kind >= isStreamed.length) { 557 throw wrapper.invalidIsstreamedTckind( CompletionStatus.COMPLETED_MAYBE, 558 new Integer(kind)) ; 559 } 560 561 if (AnyImpl.isStreamed[kind]) { 562 if ( in instanceof AnyInputStream ) { 563 // could only have been created here 564 stream = (CDRInputStream)in; 565 } else { 566 org.omg.CORBA_2_3.portable.OutputStream out = 567 (org.omg.CORBA_2_3.portable.OutputStream)orb.create_output_stream(); 568 typeCode.copy((org.omg.CORBA_2_3.portable.InputStream)in, out); 569 stream = (CDRInputStream)out.create_input_stream(); 570 } 571 } else { 572 java.lang.Object[] objholder = new java.lang.Object[1]; 573 objholder[0] = object; 574 long[] longholder = new long[1]; 575 TCUtility.unmarshalIn(in, typeCode, longholder, objholder); 576 value = longholder[0]; 577 object = objholder[0]; 578 stream = null; 579 } 580 isInitialized = true; 581 } 582 583 584 // 585 // We could optimize this by noticing whether the target stream 586 // has ever had anything marshaled on it that required an 587 // alignment of greater than 4 (was write_double() ever called on it). 588 // If not, then we can just do a byte array copy without having to 589 // drive the remarshaling through typecode interpretation. 590 // 591 public void write_value(OutputStream out) 592 { 593 //debug.log ("write_value"); 594 if (AnyImpl.isStreamed[realType().kind().value()]) { 595 typeCode.copy(stream.dup(), out); 596 } else { 597 // _REVISIT_ check isInitialized whether all we write is TypeCode! 598 TCUtility.marshalIn(out, realType(), value, object); 599 } 600 } 601 602 /** 603 * takes a streamable and inserts its reference into the any 604 * 605 * @param s the streamable to insert 606 */ 607 public void insert_Streamable(Streamable s) 608 { 609 //debug.log ("insert_Streamable"); 610 typeCode = TypeCodeImpl.convertToNative(orb, s._type()); 611 object = s; 612 isInitialized = true; 613 } 614 615 public Streamable extract_Streamable() 616 { 617 //debug.log( "extract_Streamable" ) ; 618 return (Streamable)object; 619 } 620 621 /////////////////////////////////////////////////////////////////////////// 622 // insertion/extraction/replacement for all basic types 623 624 /** 625 * See the description of the <a href="#anyOps">general Any operations.</a> 626 */ 627 public void insert_short(short s) 628 { 629 //debug.log ("insert_short"); 630 typeCode = orb.get_primitive_tc(TCKind._tk_short); 631 value = s; 632 isInitialized = true; 633 } 634 635 private String getTCKindName( int tc ) 636 { 637 if ((tc >= 0) && (tc < TypeCodeImpl.kindNames.length)) 638 return TypeCodeImpl.kindNames[tc] ; 639 else 640 return "UNKNOWN(" + tc + ")" ; 641 } 642 643 private void checkExtractBadOperation( int expected ) 644 { 645 if (!isInitialized) 646 throw wrapper.extractNotInitialized() ; 647 648 int tc = realType().kind().value() ; 649 if (tc != expected) { 650 String tcName = getTCKindName( tc ) ; 651 String expectedName = getTCKindName( expected ) ; 652 throw wrapper.extractWrongType( expectedName, tcName ) ; 653 } 654 } 655 656 private void checkExtractBadOperationList( int[] expected ) 657 { 658 if (!isInitialized) 659 throw wrapper.extractNotInitialized() ; 660 661 int tc = realType().kind().value() ; 662 for (int ctr=0; ctr<expected.length; ctr++) 663 if (tc == expected[ctr]) 664 return ; 665 666 List list = new ArrayList() ; 667 for (int ctr=0; ctr<expected.length; ctr++) 668 list.add( getTCKindName( expected[ctr] ) ) ; 669 670 String tcName = getTCKindName( tc ) ; 671 throw wrapper.extractWrongTypeList( list, tcName ) ; 672 } 673 674 /** 675 * See the description of the <a href="#anyOps">general Any operations.</a> 676 */ 677 public short extract_short() 678 { 679 //debug.log ("extract_short"); 680 checkExtractBadOperation( TCKind._tk_short ) ; 681 return (short)value; 682 } 683 684 /** 685 * See the description of the <a href="#anyOps">general Any operations.</a> 686 */ 687 public void insert_long(int l) 688 { 689 //debug.log ("insert_long"); 690 // A long value is applicable to enums as well, so don't erase the enum type code 691 // in case it was initialized that way before. 692 int kind = realType().kind().value(); 693 if (kind != TCKind._tk_long && kind != TCKind._tk_enum) { 694 typeCode = orb.get_primitive_tc(TCKind._tk_long); 695 } 696 value = l; 697 isInitialized = true; 698 } 699 700 /** 701 * See the description of the <a href="#anyOps">general Any operations.</a> 702 */ 703 public int extract_long() 704 { 705 //debug.log ("extract_long"); 706 checkExtractBadOperationList( new int[] { TCKind._tk_long, TCKind._tk_enum } ) ; 707 return (int)value; 708 } 709 710 /** 711 * See the description of the <a href="#anyOps">general Any operations.</a> 712 */ 713 public void insert_ushort(short s) 714 { 715 //debug.log ("insert_ushort"); 716 typeCode = orb.get_primitive_tc(TCKind._tk_ushort); 717 value = s; 718 isInitialized = true; 719 } 720 721 /** 722 * See the description of the <a href="#anyOps">general Any operations.</a> 723 */ 724 public short extract_ushort() 725 { 726 //debug.log ("extract_ushort"); 727 checkExtractBadOperation( TCKind._tk_ushort ) ; 728 return (short)value; 729 } 730 731 /** 732 * See the description of the <a href="#anyOps">general Any operations.</a> 733 */ 734 public void insert_ulong(int l) 735 { 736 //debug.log ("insert_ulong"); 737 typeCode = orb.get_primitive_tc(TCKind._tk_ulong); 738 value = l; 739 isInitialized = true; 740 } 741 742 /** 743 * See the description of the <a href="#anyOps">general Any operations.</a> 744 */ 745 public int extract_ulong() 746 { 747 //debug.log ("extract_ulong"); 748 checkExtractBadOperation( TCKind._tk_ulong ) ; 749 return (int)value; 750 } 751 752 /** 753 * See the description of the <a href="#anyOps">general Any operations.</a> 754 */ 755 public void insert_float(float f) 756 { 757 //debug.log ("insert_float"); 758 typeCode = orb.get_primitive_tc(TCKind._tk_float); 759 value = Float.floatToIntBits(f); 760 isInitialized = true; 761 } 762 763 /** 764 * See the description of the <a href="#anyOps">general Any operations.</a> 765 */ 766 public float extract_float() 767 { 768 //debug.log ("extract_float"); 769 checkExtractBadOperation( TCKind._tk_float ) ; 770 return Float.intBitsToFloat((int)value); 771 } 772 773 /** 774 * See the description of the <a href="#anyOps">general Any operations.</a> 775 */ 776 public void insert_double(double d) 777 { 778 //debug.log ("insert_double"); 779 typeCode = orb.get_primitive_tc(TCKind._tk_double); 780 value = Double.doubleToLongBits(d); 781 isInitialized = true; 782 } 783 784 /** 785 * See the description of the <a href="#anyOps">general Any operations.</a> 786 */ 787 public double extract_double() 788 { 789 //debug.log ("extract_double"); 790 checkExtractBadOperation( TCKind._tk_double ) ; 791 return Double.longBitsToDouble(value); 792 } 793 794 /** 795 * See the description of the <a href="#anyOps">general Any operations.</a> 796 */ 797 public void insert_longlong(long l) 798 { 799 //debug.log ("insert_longlong"); 800 typeCode = orb.get_primitive_tc(TCKind._tk_longlong); 801 value = l; 802 isInitialized = true; 803 } 804 805 /** 806 * See the description of the <a href="#anyOps">general Any operations.</a> 807 */ 808 public long extract_longlong() 809 { 810 //debug.log ("extract_longlong"); 811 checkExtractBadOperation( TCKind._tk_longlong ) ; 812 return value; 813 } 814 815 /** 816 * See the description of the <a href="#anyOps">general Any operations.</a> 817 */ 818 public void insert_ulonglong(long l) 819 { 820 //debug.log ("insert_ulonglong"); 821 typeCode = orb.get_primitive_tc(TCKind._tk_ulonglong); 822 value = l; 823 isInitialized = true; 824 } 825 826 /** 827 * See the description of the <a href="#anyOps">general Any operations.</a> 828 */ 829 public long extract_ulonglong() 830 { 831 //debug.log ("extract_ulonglong"); 832 checkExtractBadOperation( TCKind._tk_ulonglong ) ; 833 return value; 834 } 835 836 /** 837 * See the description of the <a href="#anyOps">general Any operations.</a> 838 */ 839 public void insert_boolean(boolean b) 840 { 841 //debug.log ("insert_boolean"); 842 typeCode = orb.get_primitive_tc(TCKind._tk_boolean); 843 value = (b)? 1:0; 844 isInitialized = true; 845 } 846 847 /** 848 * See the description of the <a href="#anyOps">general Any operations.</a> 849 */ 850 public boolean extract_boolean() 851 { 852 //debug.log ("extract_boolean"); 853 checkExtractBadOperation( TCKind._tk_boolean ) ; 854 return (value == 0)? false: true; 855 } 856 857 /** 858 * See the description of the <a href="#anyOps">general Any operations.</a> 859 */ 860 public void insert_char(char c) 861 { 862 //debug.log ("insert_char"); 863 typeCode = orb.get_primitive_tc(TCKind._tk_char); 864 value = c; 865 isInitialized = true; 866 } 867 868 /** 869 * See the description of the <a href="#anyOps">general Any operations.</a> 870 */ 871 public char extract_char() 872 { 873 //debug.log ("extract_char"); 874 checkExtractBadOperation( TCKind._tk_char ) ; 875 return (char)value; 876 } 877 878 /** 879 * See the description of the <a href="#anyOps">general Any operations.</a> 880 */ 881 public void insert_wchar(char c) 882 { 883 //debug.log ("insert_wchar"); 884 typeCode = orb.get_primitive_tc(TCKind._tk_wchar); 885 value = c; 886 isInitialized = true; 887 } 888 889 /** 890 * See the description of the <a href="#anyOps">general Any operations.</a> 891 */ 892 public char extract_wchar() 893 { 894 //debug.log ("extract_wchar"); 895 checkExtractBadOperation( TCKind._tk_wchar ) ; 896 return (char)value; 897 } 898 899 900 /** 901 * See the description of the <a href="#anyOps">general Any operations.</a> 902 */ 903 public void insert_octet(byte b) 904 { 905 //debug.log ("insert_octet"); 906 typeCode = orb.get_primitive_tc(TCKind._tk_octet); 907 value = b; 908 isInitialized = true; 909 } 910 911 /** 912 * See the description of the <a href="#anyOps">general Any operations.</a> 913 */ 914 public byte extract_octet() 915 { 916 //debug.log ("extract_octet"); 917 checkExtractBadOperation( TCKind._tk_octet ) ; 918 return (byte)value; 919 } 920 921 /** 922 * See the description of the <a href="#anyOps">general Any operations.</a> 923 */ 924 public void insert_string(String s) 925 { 926 //debug.log ("insert_string"); 927 // Make sure type code information for bounded strings is not erased 928 if (typeCode.kind() == TCKind.tk_string) { 929 int length = 0; 930 try { 931 length = typeCode.length(); 932 } catch (BadKind bad) { 933 throw wrapper.badkindCannotOccur() ; 934 } 935 936 // Check if bounded strings length is not exceeded 937 if (length != 0 && s != null && s.length() > length) { 938 throw wrapper.badStringBounds( new Integer(s.length()), 939 new Integer(length) ) ; 940 } 941 } else { 942 typeCode = orb.get_primitive_tc(TCKind._tk_string); 943 } 944 object = s; 945 isInitialized = true; 946 } 947 948 /** 949 * See the description of the <a href="#anyOps">general Any operations.</a> 950 */ 951 public String extract_string() 952 { 953 //debug.log ("extract_string"); 954 checkExtractBadOperation( TCKind._tk_string ) ; 955 return (String)object; 956 } 957 958 /** 959 * See the description of the <a href="#anyOps">general Any operations.</a> 960 */ 961 public void insert_wstring(String s) 962 { 963 //debug.log ("insert_wstring"); 964 // Make sure type code information for bounded strings is not erased 965 if (typeCode.kind() == TCKind.tk_wstring) { 966 int length = 0; 967 try { 968 length = typeCode.length(); 969 } catch (BadKind bad) { 970 throw wrapper.badkindCannotOccur() ; 971 } 972 973 // Check if bounded strings length is not exceeded 974 if (length != 0 && s != null && s.length() > length) { 975 throw wrapper.badStringBounds( new Integer(s.length()), 976 new Integer(length) ) ; 977 } 978 } else { 979 typeCode = orb.get_primitive_tc(TCKind._tk_wstring); 980 } 981 object = s; 982 isInitialized = true; 983 } 984 985 /** 986 * See the description of the <a href="#anyOps">general Any operations.</a> 987 */ 988 public String extract_wstring() 989 { 990 //debug.log ("extract_wstring"); 991 checkExtractBadOperation( TCKind._tk_wstring ) ; 992 return (String)object; 993 } 994 995 /** 996 * See the description of the <a href="#anyOps">general Any operations.</a> 997 */ 998 public void insert_any(Any a) 999 { 1000 //debug.log ("insert_any"); 1001 typeCode = orb.get_primitive_tc(TCKind._tk_any); 1002 object = a; 1003 stream = null; 1004 isInitialized = true; 1005 } 1006 1007 /** 1008 * See the description of the <a href="#anyOps">general Any operations.</a> 1009 */ 1010 public Any extract_any() 1011 { 1012 //debug.log ("extract_any"); 1013 checkExtractBadOperation( TCKind._tk_any ) ; 1014 return (Any)object; 1015 } 1016 1017 /** 1018 * See the description of the <a href="#anyOps">general Any operations.</a> 1019 */ 1020 public void insert_Object(org.omg.CORBA.Object o) 1021 { 1022 //debug.log ("insert_Object"); 1023 if ( o == null ) { 1024 typeCode = orb.get_primitive_tc(TCKind._tk_objref); 1025 } else { 1026 if (StubAdapter.isStub(o)) { 1027 String[] ids = StubAdapter.getTypeIds( o ) ; 1028 typeCode = new TypeCodeImpl(orb, TCKind._tk_objref, ids[0], ""); 1029 } else { 1030 throw wrapper.badInsertobjParam( 1031 CompletionStatus.COMPLETED_MAYBE, o.getClass().getName() ) ; 1032 } 1033 } 1034 1035 object = o; 1036 isInitialized = true; 1037 } 1038 1039 /** 1040 * A variant of the insertion operation that takes a typecode 1041 * argument as well. 1042 */ 1043 public void insert_Object(org.omg.CORBA.Object o, TypeCode tc) 1044 { 1045 //debug.log ("insert_Object2"); 1046 try { 1047 if ( tc.id().equals("IDL:omg.org/CORBA/Object:1.0") || o._is_a(tc.id()) ) 1048 { 1049 typeCode = TypeCodeImpl.convertToNative(orb, tc); 1050 object = o; 1051 } 1052 else { 1053 throw wrapper.insertObjectIncompatible() ; 1054 } 1055 } catch ( Exception ex ) { 1056 throw wrapper.insertObjectFailed(ex) ; 1057 } 1058 isInitialized = true; 1059 } 1060 1061 /** 1062 * See the description of the <a href="#anyOps">general Any operations.</a> 1063 */ 1064 public org.omg.CORBA.Object extract_Object() 1065 { 1066 //debug.log ("extract_Object"); 1067 if (!isInitialized) 1068 throw wrapper.extractNotInitialized() ; 1069 1070 // Check if the object contained here is of the type in typeCode 1071 org.omg.CORBA.Object obj = null; 1072 try { 1073 obj = (org.omg.CORBA.Object) object; 1074 if (typeCode.id().equals("IDL:omg.org/CORBA/Object:1.0") || obj._is_a(typeCode.id())) { 1075 return obj; 1076 } else { 1077 throw wrapper.extractObjectIncompatible() ; 1078 } 1079 } catch ( Exception ex ) { 1080 throw wrapper.extractObjectFailed(ex); 1081 } 1082 } 1083 1084 /** 1085 * See the description of the <a href="#anyOps">general Any operations.</a> 1086 */ 1087 public void insert_TypeCode(TypeCode tc) 1088 { 1089 //debug.log ("insert_TypeCode"); 1090 typeCode = orb.get_primitive_tc(TCKind._tk_TypeCode); 1091 object = tc; 1092 isInitialized = true; 1093 } 1094 1095 /** 1096 * See the description of the <a href="#anyOps">general Any operations.</a> 1097 */ 1098 public TypeCode extract_TypeCode() 1099 { 1100 //debug.log ("extract_TypeCode"); 1101 checkExtractBadOperation( TCKind._tk_TypeCode ) ; 1102 return (TypeCode)object; 1103 } 1104 1105 /** 1106 * @deprecated 1107 */ 1108 @Deprecated 1109 public void insert_Principal(Principal p) 1110 { 1111 typeCode = orb.get_primitive_tc(TCKind._tk_Principal); 1112 object = p; 1113 isInitialized = true; 1114 } 1115 1116 /** 1117 * @deprecated 1118 */ 1119 @Deprecated 1120 public Principal extract_Principal() 1121 { 1122 checkExtractBadOperation( TCKind._tk_Principal ) ; 1123 return (Principal)object; 1124 } 1125 1126 /** 1127 * Note that the Serializable really should be an IDLEntity of 1128 * some kind. It shouldn't just be an RMI-IIOP type. Currently, 1129 * we accept and will produce RMI repIds with the latest 1130 * calculations if given a non-IDLEntity Serializable. 1131 */ 1132 public Serializable extract_Value() 1133 { 1134 //debug.log ("extract_Value"); 1135 checkExtractBadOperationList( new int[] { TCKind._tk_value, 1136 TCKind._tk_value_box, TCKind._tk_abstract_interface } ) ; 1137 return (Serializable)object; 1138 } 1139 1140 public void insert_Value(Serializable v) 1141 { 1142 //debug.log ("insert_Value"); 1143 object = v; 1144 1145 TypeCode tc; 1146 1147 if ( v == null ) { 1148 tc = orb.get_primitive_tc (TCKind.tk_value); 1149 } else { 1150 // See note in getPrimitiveTypeCodeForClass. We 1151 // have to use the latest type code fixes in this 1152 // case since there is no way to know what ORB will 1153 // actually send this Any. In RMI-IIOP, when using 1154 // Util.writeAny, we can do the versioning correctly, 1155 // and use the insert_Value(Serializable, TypeCode) 1156 // method. 1157 // 1158 // The ORB singleton uses the latest version. 1159 tc = createTypeCodeForClass (v.getClass(), (ORB)ORB.init()); 1160 } 1161 1162 typeCode = TypeCodeImpl.convertToNative(orb, tc); 1163 isInitialized = true; 1164 } 1165 1166 public void insert_Value(Serializable v, org.omg.CORBA.TypeCode t) 1167 { 1168 //debug.log ("insert_Value2"); 1169 object = v; 1170 typeCode = TypeCodeImpl.convertToNative(orb, t); 1171 isInitialized = true; 1172 } 1173 1174 public void insert_fixed(java.math.BigDecimal value) { 1175 typeCode = TypeCodeImpl.convertToNative(orb, 1176 orb.create_fixed_tc(TypeCodeImpl.digits(value), TypeCodeImpl.scale(value))); 1177 object = value; 1178 isInitialized = true; 1179 } 1180 1181 public void insert_fixed(java.math.BigDecimal value, org.omg.CORBA.TypeCode type) 1182 { 1183 try { 1184 if (TypeCodeImpl.digits(value) > type.fixed_digits() || 1185 TypeCodeImpl.scale(value) > type.fixed_scale()) 1186 { 1187 throw wrapper.fixedNotMatch() ; 1188 } 1189 } catch (org.omg.CORBA.TypeCodePackage.BadKind bk) { 1190 // type isn't even of kind fixed 1191 throw wrapper.fixedBadTypecode( bk ) ; 1192 } 1193 typeCode = TypeCodeImpl.convertToNative(orb, type); 1194 object = value; 1195 isInitialized = true; 1196 } 1197 1198 public java.math.BigDecimal extract_fixed() { 1199 checkExtractBadOperation( TCKind._tk_fixed ) ; 1200 return (BigDecimal)object; 1201 } 1202 1203 /** 1204 * Utility method for insert_Value and Util.writeAny. 1205 * 1206 * The ORB passed in should have the desired ORBVersion. It 1207 * is used to generate the type codes. 1208 */ 1209 public TypeCode createTypeCodeForClass (java.lang.Class c, ORB tcORB) 1210 { 1211 // Look in the cache first 1212 TypeCodeImpl classTC = tcORB.getTypeCodeForClass(c); 1213 if (classTC != null) 1214 return classTC; 1215 1216 // All cases need to be able to create repository IDs. 1217 // 1218 // See bug 4391648 for more info about the tcORB in this 1219 // case. 1220 RepositoryIdStrings repStrs 1221 = RepositoryIdFactory.getRepIdStringsFactory(tcORB); 1222 1223 1224 // Assertion: c instanceof Serializable? 1225 1226 if ( c.isArray() ) { 1227 // Arrays - may recurse for multi-dimensional arrays 1228 Class componentClass = c.getComponentType(); 1229 TypeCode embeddedType; 1230 if ( componentClass.isPrimitive() ) { 1231 embeddedType = getPrimitiveTypeCodeForClass(componentClass, 1232 tcORB); 1233 } else { 1234 embeddedType = createTypeCodeForClass (componentClass, 1235 tcORB); 1236 } 1237 TypeCode t = tcORB.create_sequence_tc (0, embeddedType); 1238 1239 String id = repStrs.createForJavaType(c); 1240 1241 return tcORB.create_value_box_tc (id, "Sequence", t); 1242 } else if ( c == java.lang.String.class ) { 1243 // Strings 1244 TypeCode t = tcORB.create_string_tc (0); 1245 1246 String id = repStrs.createForJavaType(c); 1247 1248 return tcORB.create_value_box_tc (id, "StringValue", t); 1249 } 1250 1251 // Anything else 1252 // We know that this is a TypeCodeImpl since it is our ORB 1253 classTC = (TypeCodeImpl)ValueUtility.createTypeCodeForClass( 1254 tcORB, c, ORBUtility.createValueHandler(tcORB)); 1255 // Intruct classTC to store its buffer 1256 classTC.setCaching(true); 1257 // Update the cache 1258 tcORB.setTypeCodeForClass(c, classTC); 1259 return classTC; 1260 } 1261 1262 /** 1263 * It looks like this was copied from io.ValueUtility at some 1264 * point. 1265 * 1266 * It's used by createTypeCodeForClass. The tcORB passed in 1267 * should have the desired ORB version, and is used to 1268 * create the type codes. 1269 */ 1270 private TypeCode getPrimitiveTypeCodeForClass (Class c, ORB tcORB) 1271 { 1272 //debug.log ("getPrimitiveTypeCodeForClass"); 1273 1274 if (c == Integer.TYPE) { 1275 return tcORB.get_primitive_tc (TCKind.tk_long); 1276 } else if (c == Byte.TYPE) { 1277 return tcORB.get_primitive_tc (TCKind.tk_octet); 1278 } else if (c == Long.TYPE) { 1279 return tcORB.get_primitive_tc (TCKind.tk_longlong); 1280 } else if (c == Float.TYPE) { 1281 return tcORB.get_primitive_tc (TCKind.tk_float); 1282 } else if (c == Double.TYPE) { 1283 return tcORB.get_primitive_tc (TCKind.tk_double); 1284 } else if (c == Short.TYPE) { 1285 return tcORB.get_primitive_tc (TCKind.tk_short); 1286 } else if (c == Character.TYPE) { 1287 // For Merlin or later JDKs, or for foreign ORBs, 1288 // we correctly say that a Java char maps to a 1289 // CORBA wchar. For backwards compatibility 1290 // with our older ORBs, we say it maps to a 1291 // CORBA char. This is only used in RMI-IIOP 1292 // in our javax.rmi.CORBA.Util delegate's 1293 // writeAny method. In Java IDL, there's no way 1294 // to know the ORB version that the Any will be 1295 // sent out with -- it could be different than 1296 // the one used to create the Any -- so we use the 1297 // most recent version (see insert_Value). 1298 if (ORBVersionFactory.getFOREIGN().compareTo(tcORB.getORBVersion()) == 0 || 1299 ORBVersionFactory.getNEWER().compareTo(tcORB.getORBVersion()) <= 0) 1300 return tcORB.get_primitive_tc(TCKind.tk_wchar); 1301 else 1302 return tcORB.get_primitive_tc(TCKind.tk_char); 1303 } else if (c == Boolean.TYPE) { 1304 return tcORB.get_primitive_tc (TCKind.tk_boolean); 1305 } else { 1306 // _REVISIT_ Not sure if this is right. 1307 return tcORB.get_primitive_tc (TCKind.tk_any); 1308 } 1309 } 1310 1311 // Extracts a member value according to the given TypeCode from the given complex Any 1312 // (at the Anys current internal stream position, consuming the anys stream on the way) 1313 // and returns it wrapped into a new Any 1314 public Any extractAny(TypeCode memberType, ORB orb) { 1315 Any returnValue = orb.create_any(); 1316 OutputStream out = returnValue.create_output_stream(); 1317 TypeCodeImpl.convertToNative(orb, memberType).copy((InputStream)stream, out); 1318 returnValue.read_value(out.create_input_stream(), memberType); 1319 return returnValue; 1320 } 1321 1322 // This method could very well be moved into TypeCodeImpl or a common utility class, 1323 // but is has to be in this package. 1324 static public Any extractAnyFromStream(TypeCode memberType, InputStream input, ORB orb) { 1325 Any returnValue = orb.create_any(); 1326 OutputStream out = returnValue.create_output_stream(); 1327 TypeCodeImpl.convertToNative(orb, memberType).copy(input, out); 1328 returnValue.read_value(out.create_input_stream(), memberType); 1329 return returnValue; 1330 } 1331 1332 // There is no other way for DynAnys to find out whether the Any is initialized. 1333 public boolean isInitialized() { 1334 return isInitialized; 1335 } 1336 }