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