1 /* 2 * Copyright (c) 1997, 2011, 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 /* 27 * Licensed Materials - Property of IBM 28 * RMI-IIOP v1.0 29 * Copyright IBM Corp. 1998 1999 All Rights Reserved 30 * 31 */ 32 33 package com.sun.corba.se.impl.encoding; 34 35 import java.io.IOException; 36 import java.io.Serializable; 37 import java.io.ByteArrayInputStream; 38 import java.io.ObjectInputStream; 39 import java.io.IOException; 40 import java.io.StreamCorruptedException; 41 import java.io.OptionalDataException; 42 import java.io.IOException; 43 44 import java.util.Stack; 45 46 import java.net.URL; 47 import java.net.MalformedURLException; 48 49 import java.nio.ByteBuffer; 50 51 import java.lang.reflect.InvocationTargetException; 52 import java.lang.reflect.Method; 53 54 import java.math.BigDecimal; 55 56 import java.rmi.Remote; 57 import java.rmi.StubNotFoundException; 58 59 import java.security.AccessController; 60 import java.security.PrivilegedExceptionAction; 61 import java.security.PrivilegedActionException; 62 63 import org.omg.CORBA.SystemException; 64 import org.omg.CORBA.Object; 65 import org.omg.CORBA.Principal; 66 import org.omg.CORBA.TypeCode; 67 import org.omg.CORBA.Any; 68 import org.omg.CORBA.portable.Delegate; 69 import org.omg.CORBA.portable.ValueBase; 70 import org.omg.CORBA.portable.IndirectionException; 71 import org.omg.CORBA.CompletionStatus; 72 import org.omg.CORBA.TCKind; 73 import org.omg.CORBA.TypeCodePackage.BadKind; 74 import org.omg.CORBA.CustomMarshal; 75 import org.omg.CORBA.TypeCode; 76 import org.omg.CORBA.Principal; 77 import org.omg.CORBA.Any; 78 import org.omg.CORBA.portable.BoxedValueHelper; 79 import org.omg.CORBA.portable.ValueFactory; 80 import org.omg.CORBA.portable.CustomValue; 81 import org.omg.CORBA.portable.StreamableValue; 82 import org.omg.CORBA.MARSHAL; 83 import org.omg.CORBA.portable.IDLEntity; 84 85 import javax.rmi.PortableRemoteObject; 86 import javax.rmi.CORBA.Tie; 87 import javax.rmi.CORBA.Util; 88 import javax.rmi.CORBA.ValueHandler; 89 90 import com.sun.corba.se.pept.protocol.MessageMediator; 91 import com.sun.corba.se.pept.transport.ByteBufferPool; 92 93 import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; 94 import com.sun.corba.se.spi.protocol.CorbaClientDelegate; 95 96 import com.sun.corba.se.spi.ior.IOR; 97 import com.sun.corba.se.spi.ior.IORFactories; 98 import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 99 100 import com.sun.corba.se.spi.orb.ORB; 101 import com.sun.corba.se.spi.orb.ORBVersionFactory; 102 import com.sun.corba.se.spi.orb.ORBVersion; 103 104 import com.sun.corba.se.spi.protocol.CorbaMessageMediator; 105 106 import com.sun.corba.se.spi.logging.CORBALogDomains; 107 import com.sun.corba.se.spi.presentation.rmi.PresentationManager; 108 import com.sun.corba.se.spi.presentation.rmi.StubAdapter; 109 import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults; 110 111 import com.sun.corba.se.impl.logging.ORBUtilSystemException; 112 import com.sun.corba.se.impl.logging.OMGSystemException; 113 114 import com.sun.corba.se.impl.corba.PrincipalImpl; 115 import com.sun.corba.se.impl.corba.TypeCodeImpl; 116 import com.sun.corba.se.impl.corba.CORBAObjectImpl; 117 118 import com.sun.corba.se.impl.encoding.CDROutputObject; 119 import com.sun.corba.se.impl.encoding.CodeSetConversion; 120 121 import com.sun.corba.se.impl.util.Utility; 122 import com.sun.corba.se.impl.util.RepositoryId; 123 124 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings; 125 import com.sun.corba.se.impl.orbutil.RepositoryIdInterface; 126 import com.sun.corba.se.impl.orbutil.RepositoryIdUtility; 127 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory; 128 129 import com.sun.corba.se.impl.orbutil.ORBUtility; 130 import com.sun.corba.se.impl.orbutil.CacheTable; 131 132 133 import com.sun.org.omg.CORBA.portable.ValueHelper; 134 135 import com.sun.org.omg.SendingContext.CodeBase; 136 137 public class CDRInputStream_1_0 extends CDRInputStreamBase 138 implements RestorableInputStream 139 { 140 private static final String kReadMethod = "read"; 141 private static final int maxBlockLength = 0x7fffff00; 142 143 protected BufferManagerRead bufferManagerRead; 144 protected ByteBufferWithInfo bbwi; 145 146 // Set to the ORB's transportDebugFlag value. This value is 147 // used if the ORB is null. 148 private boolean debug = false; 149 150 protected boolean littleEndian; 151 protected ORB orb; 152 protected ORBUtilSystemException wrapper ; 153 protected OMGSystemException omgWrapper ; 154 protected ValueHandler valueHandler = null; 155 156 // Value cache 157 private CacheTable valueCache = null; 158 159 // Repository ID cache 160 private CacheTable repositoryIdCache = null; 161 162 // codebase cache 163 private CacheTable codebaseCache = null; 164 165 // Current Class Stack (repository Ids of current class being read) 166 // private Stack currentStack = null; 167 168 // Length of current chunk, or a large positive number if not in a chunk 169 protected int blockLength = maxBlockLength; 170 171 // Read end flag (value nesting depth) 172 protected int end_flag = 0; 173 174 // Beginning with the resolution to interop issue 3526 (4328?), 175 // only enclosing chunked valuetypes are taken into account 176 // when computing the nesting level. However, we still need 177 // the old computation around for interoperability with our 178 // older ORBs. 179 private int chunkedValueNestingLevel = 0; 180 181 // Flag used to determine whether blocksize was zero 182 // private int checkForNullBlock = -1; 183 184 // In block flag 185 // private boolean inBlock = false; 186 187 // Indicates whether we are inside a value 188 // private boolean outerValueDone = true; 189 190 // Int used by read_value(Serializable) that is set by this class 191 // before calling ValueFactory.read_value 192 protected int valueIndirection = 0; 193 194 // Int set by readStringOrIndirection to communicate the actual 195 // offset of the string length field back to the caller 196 protected int stringIndirection = 0; 197 198 // Flag indicating whether we are unmarshalling a chunked value 199 protected boolean isChunked = false; 200 201 // Repository ID handlers 202 private RepositoryIdUtility repIdUtil; 203 private RepositoryIdStrings repIdStrs; 204 205 // Code set converters (created when first needed) 206 private CodeSetConversion.BTCConverter charConverter; 207 private CodeSetConversion.BTCConverter wcharConverter; 208 209 // RMI-IIOP stream format version 2 case in which we know 210 // that there is no more optional data available. If the 211 // Serializable's readObject method tries to read anything, 212 // we must throw a MARSHAL with the special minor code 213 // so that the ValueHandler can give the correct exception 214 // to readObject. The state is cleared when the ValueHandler 215 // calls end_value after the readObject method exits. 216 private boolean specialNoOptionalDataState = false; 217 218 // Template method 219 public CDRInputStreamBase dup() 220 { 221 CDRInputStreamBase result = null ; 222 223 try { 224 result = (CDRInputStreamBase)this.getClass().newInstance(); 225 } catch (Exception e) { 226 throw wrapper.couldNotDuplicateCdrInputStream( e ) ; 227 } 228 result.init(this.orb, 229 this.bbwi.byteBuffer, 230 this.bbwi.buflen, 231 this.littleEndian, 232 this.bufferManagerRead); 233 234 ((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position()); 235 // To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen. 236 ((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen); 237 238 return result; 239 } 240 241 /** 242 * NOTE: size passed to init means buffer size 243 */ 244 public void init(org.omg.CORBA.ORB orb, 245 ByteBuffer byteBuffer, 246 int size, 247 boolean littleEndian, 248 BufferManagerRead bufferManager) 249 { 250 this.orb = (ORB)orb; 251 this.wrapper = ORBUtilSystemException.get( (ORB)orb, 252 CORBALogDomains.RPC_ENCODING ) ; 253 this.omgWrapper = OMGSystemException.get( (ORB)orb, 254 CORBALogDomains.RPC_ENCODING ) ; 255 this.littleEndian = littleEndian; 256 this.bufferManagerRead = bufferManager; 257 this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0); 258 this.bbwi.buflen = size; 259 this.bbwi.byteBuffer.limit(bbwi.buflen); 260 this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler(); 261 262 debug = ((ORB)orb).transportDebugFlag; 263 } 264 265 // See description in CDRInputStream 266 void performORBVersionSpecificInit() { 267 createRepositoryIdHandlers(); 268 } 269 270 private final void createRepositoryIdHandlers() 271 { 272 repIdUtil = RepositoryIdFactory.getRepIdUtility(orb); 273 repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(orb); 274 } 275 276 public GIOPVersion getGIOPVersion() { 277 return GIOPVersion.V1_0; 278 } 279 280 // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only. 281 // Illegal for GIOP versions < 1.2. 282 void setHeaderPadding(boolean headerPadding) { 283 throw wrapper.giopVersionError(); 284 } 285 286 protected final int computeAlignment(int index, int align) { 287 if (align > 1) { 288 int incr = index & (align - 1); 289 if (incr != 0) 290 return align - incr; 291 } 292 293 return 0; 294 } 295 296 public int getSize() 297 { 298 return bbwi.position(); 299 } 300 301 protected void checkBlockLength(int align, int dataSize) { 302 // Since chunks can end at arbitrary points (though not within 303 // primitive CDR types, arrays of primitives, strings, wstrings, 304 // or indirections), 305 // we must check here for termination of the current chunk. 306 if (!isChunked) 307 return; 308 309 // RMI-IIOP stream format version 2 case in which we know 310 // that there is no more optional data available. If the 311 // Serializable's readObject method tries to read anything, 312 // we must throw a MARSHAL exception with the special minor code 313 // so that the ValueHandler can give the correct exception 314 // to readObject. The state is cleared when the ValueHandler 315 // calls end_value after the readObject method exits. 316 if (specialNoOptionalDataState) { 317 throw omgWrapper.rmiiiopOptionalDataIncompatible1() ; 318 } 319 320 boolean checkForEndTag = false; 321 322 // Are we at the end of the current chunk? If so, 323 // try to interpret the next long as a chunk length. 324 // (It has to be either a chunk length, end tag, 325 // or valuetag.) 326 // 327 // If it isn't a chunk length, blockLength will 328 // remain set to maxBlockLength. 329 if (blockLength == get_offset()) { 330 331 blockLength = maxBlockLength; 332 start_block(); 333 334 // What's next is either a valuetag or 335 // an end tag. If it's a valuetag, we're 336 // probably being called as part of the process 337 // to read the valuetag. If it's an end tag, 338 // then there isn't enough data left in 339 // this valuetype to read! 340 if (blockLength == maxBlockLength) 341 checkForEndTag = true; 342 343 } else 344 if (blockLength < get_offset()) { 345 // Are we already past the end of the current chunk? 346 // This is always an error. 347 throw wrapper.chunkOverflow() ; 348 } 349 350 // If what's next on the wire isn't a chunk length or 351 // what we want to read (which can't be split across chunks) 352 // won't fit in the current chunk, throw this exception. 353 // This probably means that we're in an RMI-IIOP 354 // Serializable's readObject method or a custom marshaled 355 // IDL type is reading too much/in an incorrect order 356 int requiredNumBytes = 357 computeAlignment(bbwi.position(), align) + dataSize; 358 359 if (blockLength != maxBlockLength && 360 blockLength < get_offset() + requiredNumBytes) { 361 throw omgWrapper.rmiiiopOptionalDataIncompatible2() ; 362 } 363 364 // REVISIT - We should look at using the built in advancement 365 // of using ByteBuffer.get() rather than explicitly 366 // advancing the ByteBuffer's position. 367 // This is true for anywhere we are incrementing 368 // the ByteBuffer's position. 369 if (checkForEndTag) { 370 int nextLong = read_long(); 371 bbwi.position(bbwi.position() - 4); 372 373 // It was an end tag, so there wasn't enough data 374 // left in the valuetype's encoding on the wire 375 // to read what we wanted 376 if (nextLong < 0) 377 throw omgWrapper.rmiiiopOptionalDataIncompatible3() ; 378 } 379 } 380 381 protected void alignAndCheck(int align, int n) { 382 383 checkBlockLength(align, n); 384 385 // WARNING: Must compute real alignment after calling 386 // checkBlockLength since it may move the position 387 int alignResult = computeAlignment(bbwi.position(), align); 388 bbwi.position(bbwi.position() + alignResult); 389 390 if (bbwi.position() + n > bbwi.buflen) 391 grow(align, n); 392 } 393 394 // 395 // This can be overridden.... 396 // 397 protected void grow(int align, int n) { 398 399 bbwi.needed = n; 400 401 bbwi = bufferManagerRead.underflow(bbwi); 402 403 } 404 405 // 406 // Marshal primitives. 407 // 408 409 public final void consumeEndian() { 410 littleEndian = read_boolean(); 411 } 412 413 // No such type in java 414 public final double read_longdouble() { 415 throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE); 416 } 417 418 public final boolean read_boolean() { 419 return (read_octet() != 0); 420 } 421 422 public final char read_char() { 423 alignAndCheck(1, 1); 424 425 return getConvertedChars(1, getCharConverter())[0]; 426 } 427 428 public char read_wchar() { 429 430 // Don't allow transmission of wchar/wstring data with 431 // foreign ORBs since it's against the spec. 432 if (ORBUtility.isForeignORB((ORB)orb)) { 433 throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE); 434 } 435 436 // If we're talking to one of our legacy ORBs, do what 437 // they did: 438 int b1, b2; 439 440 alignAndCheck(2, 2); 441 442 if (littleEndian) { 443 b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; 444 bbwi.position(bbwi.position() + 1); 445 b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; 446 bbwi.position(bbwi.position() + 1); 447 } else { 448 b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; 449 bbwi.position(bbwi.position() + 1); 450 b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; 451 bbwi.position(bbwi.position() + 1); 452 } 453 454 return (char)((b1 << 8) + (b2 << 0)); 455 } 456 457 public final byte read_octet() { 458 459 alignAndCheck(1, 1); 460 461 byte b = bbwi.byteBuffer.get(bbwi.position()); 462 bbwi.position(bbwi.position() + 1); 463 464 return b; 465 } 466 467 public final short read_short() { 468 int b1, b2; 469 470 alignAndCheck(2, 2); 471 472 if (littleEndian) { 473 b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF; 474 bbwi.position(bbwi.position() + 1); 475 b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00; 476 bbwi.position(bbwi.position() + 1); 477 } else { 478 b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00; 479 bbwi.position(bbwi.position() + 1); 480 b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF; 481 bbwi.position(bbwi.position() + 1); 482 } 483 484 return (short)(b1 | b2); 485 } 486 487 public final short read_ushort() { 488 return read_short(); 489 } 490 491 public final int read_long() { 492 int b1, b2, b3, b4; 493 494 alignAndCheck(4, 4); 495 496 int bufPos = bbwi.position(); 497 if (littleEndian) { 498 b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 499 b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 500 b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 501 b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 502 } else { 503 b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 504 b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 505 b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 506 b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF; 507 } 508 bbwi.position(bufPos); 509 510 return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; 511 } 512 513 public final int read_ulong() { 514 return read_long(); 515 } 516 517 public final long read_longlong() { 518 long i1, i2; 519 520 alignAndCheck(8, 8); 521 522 if (littleEndian) { 523 i2 = read_long() & 0xFFFFFFFFL; 524 i1 = (long)read_long() << 32; 525 } else { 526 i1 = (long)read_long() << 32; 527 i2 = read_long() & 0xFFFFFFFFL; 528 } 529 530 return (i1 | i2); 531 } 532 533 public final long read_ulonglong() { 534 return read_longlong(); 535 } 536 537 public final float read_float() { 538 return Float.intBitsToFloat(read_long()); 539 } 540 541 public final double read_double() { 542 return Double.longBitsToDouble(read_longlong()); 543 } 544 545 protected final void checkForNegativeLength(int length) { 546 if (length < 0) 547 throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE, 548 new Integer(length) ) ; 549 } 550 551 protected final String readStringOrIndirection(boolean allowIndirection) { 552 553 int len = read_long(); 554 555 // 556 // Check for indirection 557 // 558 if (allowIndirection) { 559 if (len == 0xffffffff) 560 return null; 561 else 562 stringIndirection = get_offset() - 4; 563 } 564 565 checkForNegativeLength(len); 566 567 if (orb != null && ORBUtility.isLegacyORB((ORB)orb)) 568 return legacyReadString(len); 569 else 570 return internalReadString(len); 571 } 572 573 private final String internalReadString(int len) { 574 // Workaround for ORBs which send string lengths of 575 // zero to mean empty string. 576 // 577 // IMPORTANT: Do not replace 'new String("")' with "", it may result 578 // in a Serialization bug (See serialization.zerolengthstring) and 579 // bug id: 4728756 for details 580 if (len == 0) 581 return new String(""); 582 583 char[] result = getConvertedChars(len - 1, getCharConverter()); 584 585 // Skip over the 1 byte null 586 read_octet(); 587 588 return new String(result, 0, getCharConverter().getNumChars()); 589 } 590 591 private final String legacyReadString(int len) { 592 593 // 594 // Workaround for ORBs which send string lengths of 595 // zero to mean empty string. 596 // 597 // 598 // IMPORTANT: Do not replace 'new String("")' with "", it may result 599 // in a Serialization bug (See serialization.zerolengthstring) and 600 // bug id: 4728756 for details 601 if (len == 0) 602 return new String(""); 603 604 len--; 605 char[] c = new char[len]; 606 607 int n = 0; 608 while (n < len) { 609 int avail; 610 int bytes; 611 int wanted; 612 613 avail = bbwi.buflen - bbwi.position(); 614 if (avail <= 0) { 615 grow(1, 1); 616 avail = bbwi.buflen - bbwi.position(); 617 } 618 wanted = len - n; 619 bytes = (wanted < avail) ? wanted : avail; 620 // Microbenchmarks are showing a loop of ByteBuffer.get(int) being 621 // faster than ByteBuffer.get(byte[], int, int). 622 for (int i=0; i<bytes; i++) { 623 c[n+i] = (char) (bbwi.byteBuffer.get(bbwi.position()+i) & 0xFF); 624 } 625 bbwi.position(bbwi.position() + bytes); 626 n += bytes; 627 } 628 629 // 630 // Skip past terminating null byte 631 // 632 if (bbwi.position() + 1 > bbwi.buflen) 633 alignAndCheck(1, 1); 634 bbwi.position(bbwi.position() + 1); 635 636 return new String(c); 637 } 638 639 public final String read_string() { 640 return readStringOrIndirection(false); 641 } 642 643 public String read_wstring() { 644 // Don't allow transmission of wchar/wstring data with 645 // foreign ORBs since it's against the spec. 646 if (ORBUtility.isForeignORB((ORB)orb)) { 647 throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE); 648 } 649 650 int len = read_long(); 651 652 // 653 // Workaround for ORBs which send string lengths of 654 // zero to mean empty string. 655 // 656 // 657 // IMPORTANT: Do not replace 'new String("")' with "", it may result 658 // in a Serialization bug (See serialization.zerolengthstring) and 659 // bug id: 4728756 for details 660 if (len == 0) 661 return new String(""); 662 663 checkForNegativeLength(len); 664 665 len--; 666 char[] c = new char[len]; 667 668 for (int i = 0; i < len; i++) 669 c[i] = read_wchar(); 670 671 // skip the two null terminator bytes 672 read_wchar(); 673 // bbwi.position(bbwi.position() + 2); 674 675 return new String(c); 676 } 677 678 public final void read_octet_array(byte[] b, int offset, int length) { 679 if ( b == null ) 680 throw wrapper.nullParam() ; 681 682 // Must call alignAndCheck at least once to ensure 683 // we aren't at the end of a chunk. Of course, we 684 // should only call it if we actually need to read 685 // something, otherwise we might end up with an 686 // exception at the end of the stream. 687 if (length == 0) 688 return; 689 690 alignAndCheck(1, 1); 691 692 int n = offset; 693 while (n < length+offset) { 694 int avail; 695 int bytes; 696 int wanted; 697 698 avail = bbwi.buflen - bbwi.position(); 699 if (avail <= 0) { 700 grow(1, 1); 701 avail = bbwi.buflen - bbwi.position(); 702 } 703 wanted = (length + offset) - n; 704 bytes = (wanted < avail) ? wanted : avail; 705 // Microbenchmarks are showing a loop of ByteBuffer.get(int) being 706 // faster than ByteBuffer.get(byte[], int, int). 707 for (int i = 0; i < bytes; i++) { 708 b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i); 709 } 710 711 bbwi.position(bbwi.position() + bytes); 712 713 n += bytes; 714 } 715 } 716 717 public Principal read_Principal() { 718 int len = read_long(); 719 byte[] pvalue = new byte[len]; 720 read_octet_array(pvalue,0,len); 721 722 Principal p = new PrincipalImpl(); 723 p.name(pvalue); 724 return p; 725 } 726 727 public TypeCode read_TypeCode() { 728 TypeCodeImpl tc = new TypeCodeImpl(orb); 729 tc.read_value(parent); 730 return tc; 731 } 732 733 public Any read_any() { 734 Any any = orb.create_any(); 735 TypeCodeImpl tc = new TypeCodeImpl(orb); 736 737 // read off the typecode 738 739 // REVISIT We could avoid this try-catch if we could peek the typecode 740 // kind off this stream and see if it is a tk_value. Looking at the 741 // code we know that for tk_value the Any.read_value() below 742 // ignores the tc argument anyway (except for the kind field). 743 // But still we would need to make sure that the whole typecode, 744 // including encapsulations, is read off. 745 try { 746 tc.read_value(parent); 747 } catch (MARSHAL ex) { 748 if (tc.kind().value() != TCKind._tk_value) 749 throw ex; 750 // We can be sure that the whole typecode encapsulation has been 751 // read off. 752 dprintThrowable(ex); 753 } 754 // read off the value of the any 755 any.read_value(parent, tc); 756 757 return any; 758 } 759 760 public org.omg.CORBA.Object read_Object() { 761 return read_Object(null); 762 } 763 764 // ------------ RMI related methods -------------------------- 765 766 // IDL to Java ptc-00-01-08 1.21.4.1 767 // 768 // The clz argument to read_Object can be either a stub 769 // Class or the "Class object for the RMI/IDL interface type 770 // that is statically expected." 771 // This functions as follows: 772 // 1. If clz==null, just use the repository ID from the stub 773 // 2. If clz is a stub class, just use it as a static factory. 774 // clz is a stub class iff StubAdapter.isStubClass( clz ). 775 // In addition, clz is a IDL stub class iff 776 // IDLEntity.class.isAssignableFrom( clz ). 777 // 3. If clz is an interface, use it to create the appropriate 778 // stub factory. 779 public org.omg.CORBA.Object read_Object(Class clz) 780 { 781 // In any case, we must first read the IOR. 782 IOR ior = IORFactories.makeIOR(parent) ; 783 if (ior.isNil()) 784 return null ; 785 786 PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ; 787 String codeBase = ior.getProfile().getCodebase() ; 788 PresentationManager.StubFactory stubFactory = null ; 789 790 if (clz == null) { 791 RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ; 792 String className = rid.getClassName() ; 793 boolean isIDLInterface = rid.isIDLType() ; 794 795 if (className == null || className.equals( "" )) 796 stubFactory = null ; 797 else 798 try { 799 stubFactory = sff.createStubFactory( className, 800 isIDLInterface, codeBase, (Class)null, 801 (ClassLoader)null ); 802 } catch (Exception exc) { 803 // Could not create stubFactory, so use null. 804 // XXX stubFactory handling is still too complex: 805 // Can we resolve the stubFactory question once in 806 // a single place? 807 stubFactory = null ; 808 } 809 } else if (StubAdapter.isStubClass( clz )) { 810 stubFactory = PresentationDefaults.makeStaticStubFactory( 811 clz ) ; 812 } else { 813 // clz is an interface class 814 boolean isIDL = IDLEntity.class.isAssignableFrom( clz ) ; 815 816 stubFactory = sff.createStubFactory( clz.getName(), 817 isIDL, codeBase, clz, clz.getClassLoader() ) ; 818 } 819 820 return internalIORToObject( ior, stubFactory, orb ) ; 821 } 822 823 /* 824 * This is used as a general utility (e.g., the PortableInterceptor 825 * implementation uses it. If stubFactory is null, the ior's 826 * IIOPProfile must support getServant. 827 */ 828 public static org.omg.CORBA.Object internalIORToObject( 829 IOR ior, PresentationManager.StubFactory stubFactory, ORB orb) 830 { 831 ORBUtilSystemException wrapper = ORBUtilSystemException.get( 832 (ORB)orb, CORBALogDomains.RPC_ENCODING ) ; 833 834 java.lang.Object servant = ior.getProfile().getServant() ; 835 if (servant != null ) { 836 if (servant instanceof Tie) { 837 String codebase = ior.getProfile().getCodebase(); 838 org.omg.CORBA.Object objref = (org.omg.CORBA.Object) 839 Utility.loadStub( (Tie)servant, stubFactory, codebase, 840 false); 841 842 // If we managed to load a stub, return it, otherwise we 843 // must fail... 844 if (objref != null) { 845 return objref; 846 } else { 847 throw wrapper.readObjectException() ; 848 } 849 } else if (servant instanceof org.omg.CORBA.Object) { 850 if (!(servant instanceof 851 org.omg.CORBA.portable.InvokeHandler)) { 852 return (org.omg.CORBA.Object) servant; 853 } 854 } else 855 throw wrapper.badServantReadObject() ; 856 } 857 858 CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ; 859 org.omg.CORBA.Object objref = null ; 860 try { 861 objref = stubFactory.makeStub() ; 862 } catch (Throwable e) { 863 wrapper.stubCreateError( e ) ; 864 865 if (e instanceof ThreadDeath) { 866 throw (ThreadDeath) e; 867 } 868 869 // Return the "default" stub... 870 objref = new CORBAObjectImpl() ; 871 } 872 873 StubAdapter.setDelegate( objref, del ) ; 874 return objref; 875 } 876 877 public java.lang.Object read_abstract_interface() 878 { 879 return read_abstract_interface(null); 880 } 881 882 public java.lang.Object read_abstract_interface(java.lang.Class clz) 883 { 884 boolean object = read_boolean(); 885 886 if (object) { 887 return read_Object(clz); 888 } else { 889 return read_value(); 890 } 891 } 892 893 public Serializable read_value() 894 { 895 return read_value((Class)null); 896 } 897 898 private Serializable handleIndirection() { 899 int indirection = read_long() + get_offset() - 4; 900 if (valueCache != null && valueCache.containsVal(indirection)) { 901 902 java.io.Serializable cachedValue 903 = (java.io.Serializable)valueCache.getKey(indirection); 904 return cachedValue; 905 } else { 906 // In RMI-IIOP the ValueHandler will recognize this 907 // exception and use the provided indirection value 908 // to lookup a possible indirection to an object 909 // currently on the deserialization stack. 910 throw new IndirectionException(indirection); 911 } 912 } 913 914 private String readRepositoryIds(int valueTag, 915 Class expectedType, 916 String expectedTypeRepId) { 917 return readRepositoryIds(valueTag, expectedType, 918 expectedTypeRepId, null); 919 } 920 921 /** 922 * Examines the valuetag to see how many (if any) repository IDs 923 * are present on the wire. If no repository ID information 924 * is on the wire but the expectedType or expectedTypeRepId 925 * is known, it will return one of those (favoring the 926 * expectedType's repId). Failing that, it uses the supplied 927 * BoxedValueHelper to obtain the repository ID, as a last resort. 928 */ 929 private String readRepositoryIds(int valueTag, 930 Class expectedType, 931 String expectedTypeRepId, 932 BoxedValueHelper factory) { 933 switch(repIdUtil.getTypeInfo(valueTag)) { 934 case RepositoryIdUtility.NO_TYPE_INFO : 935 // Throw an exception if we have no repository ID info and 936 // no expectedType to work with. Otherwise, how would we 937 // know what to unmarshal? 938 if (expectedType == null) { 939 if (expectedTypeRepId != null) { 940 return expectedTypeRepId; 941 } else if (factory != null) { 942 return factory.get_id(); 943 } else { 944 throw wrapper.expectedTypeNullAndNoRepId( 945 CompletionStatus.COMPLETED_MAYBE); 946 } 947 } 948 return repIdStrs.createForAnyType(expectedType); 949 case RepositoryIdUtility.SINGLE_REP_TYPE_INFO : 950 return read_repositoryId(); 951 case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO : 952 return read_repositoryIds(); 953 default: 954 throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE, 955 Integer.toHexString(valueTag) ) ; 956 } 957 } 958 959 public Serializable read_value(Class expectedType) { 960 961 // Read value tag 962 int vType = readValueTag(); 963 964 // Is value null? 965 if (vType == 0) 966 return null; 967 968 // Is this an indirection to a previously 969 // read valuetype? 970 if (vType == 0xffffffff) 971 return handleIndirection(); 972 973 // Save where this valuetype started so we 974 // can put it in the indirection valueCache 975 // later 976 int indirection = get_offset() - 4; 977 978 // Need to save this special marker variable 979 // to restore its value during recursion 980 boolean saveIsChunked = isChunked; 981 982 isChunked = repIdUtil.isChunkedEncoding(vType); 983 984 java.lang.Object value = null; 985 986 String codebase_URL = null; 987 if (repIdUtil.isCodeBasePresent(vType)) { 988 codebase_URL = read_codebase_URL(); 989 } 990 991 // Read repository id(s) 992 String repositoryIDString 993 = readRepositoryIds(vType, expectedType, null); 994 995 // If isChunked was determined to be true based 996 // on the valuetag, this will read a chunk length 997 start_block(); 998 999 // Remember that end_flag keeps track of all nested 1000 // valuetypes and is used for older ORBs 1001 end_flag--; 1002 if (isChunked) 1003 chunkedValueNestingLevel--; 1004 1005 if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) { 1006 value = read_wstring(); 1007 } else 1008 if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) { 1009 // read in the class whether with the old ClassDesc or the 1010 // new one 1011 value = readClass(); 1012 } else { 1013 1014 Class valueClass = expectedType; 1015 1016 // By this point, either the expectedType or repositoryIDString 1017 // is guaranteed to be non-null. 1018 if (expectedType == null || 1019 !repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) { 1020 1021 valueClass = getClassFromString(repositoryIDString, 1022 codebase_URL, 1023 expectedType); 1024 } 1025 1026 if (valueClass == null) { 1027 // No point attempting to use value handler below, since the 1028 // class information is not available. 1029 throw wrapper.couldNotFindClass( 1030 CompletionStatus.COMPLETED_MAYBE, 1031 new ClassNotFoundException()); 1032 } 1033 1034 if (valueClass != null && 1035 org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) { 1036 1037 value = readIDLValue(indirection, 1038 repositoryIDString, 1039 valueClass, 1040 codebase_URL); 1041 1042 } else { 1043 1044 // Must be some form of RMI-IIOP valuetype 1045 1046 try { 1047 if (valueHandler == null) 1048 valueHandler = ORBUtility.createValueHandler(orb); 1049 1050 value = valueHandler.readValue(parent, 1051 indirection, 1052 valueClass, 1053 repositoryIDString, 1054 getCodeBase()); 1055 1056 } catch(SystemException sysEx) { 1057 // Just rethrow any CORBA system exceptions 1058 // that come out of the ValueHandler 1059 throw sysEx; 1060 } catch(Exception ex) { 1061 throw wrapper.valuehandlerReadException( 1062 CompletionStatus.COMPLETED_MAYBE, ex ) ; 1063 } catch(Error e) { 1064 throw wrapper.valuehandlerReadError( 1065 CompletionStatus.COMPLETED_MAYBE, e ) ; 1066 } 1067 } 1068 } 1069 1070 // Skip any remaining chunks until we get to 1071 // an end tag or a valuetag. If we see a valuetag, 1072 // that means there was another valuetype in the sender's 1073 // version of this class that we need to skip over. 1074 handleEndOfValue(); 1075 1076 // Read and process the end tag if we're chunking. 1077 // Assumes that we're at the position of the end tag 1078 // (handleEndOfValue should assure this) 1079 readEndTag(); 1080 1081 // Cache the valuetype that we read 1082 if (valueCache == null) 1083 valueCache = new CacheTable(orb,false); 1084 valueCache.put(value, indirection); 1085 1086 // Allow for possible continuation chunk. 1087 // If we're a nested valuetype inside of a chunked 1088 // valuetype, and that enclosing valuetype has 1089 // more data to write, it will need to have this 1090 // new chunk begin after we wrote our end tag. 1091 isChunked = saveIsChunked; 1092 start_block(); 1093 1094 return (java.io.Serializable)value; 1095 } 1096 1097 public Serializable read_value(BoxedValueHelper factory) { 1098 1099 // Read value tag 1100 int vType = readValueTag(); 1101 1102 if (vType == 0) 1103 return null; // value is null 1104 else if (vType == 0xffffffff) { // Indirection tag 1105 int indirection = read_long() + get_offset() - 4; 1106 if (valueCache != null && valueCache.containsVal(indirection)) 1107 { 1108 java.io.Serializable cachedValue = 1109 (java.io.Serializable)valueCache.getKey(indirection); 1110 return cachedValue; 1111 } 1112 else { 1113 throw new IndirectionException(indirection); 1114 } 1115 } 1116 else { 1117 int indirection = get_offset() - 4; 1118 1119 // end_block(); 1120 1121 boolean saveIsChunked = isChunked; 1122 isChunked = repIdUtil.isChunkedEncoding(vType); 1123 1124 java.lang.Object value = null; 1125 1126 String codebase_URL = null; 1127 if (repIdUtil.isCodeBasePresent(vType)){ 1128 codebase_URL = read_codebase_URL(); 1129 } 1130 1131 // Read repository id 1132 String repositoryIDString 1133 = readRepositoryIds(vType, null, null, factory); 1134 1135 // Compare rep. ids to see if we should use passed helper 1136 if (!repositoryIDString.equals(factory.get_id())) 1137 factory = Utility.getHelper(null, codebase_URL, repositoryIDString); 1138 1139 start_block(); 1140 end_flag--; 1141 if (isChunked) 1142 chunkedValueNestingLevel--; 1143 1144 if (factory instanceof ValueHelper) { 1145 value = readIDLValueWithHelper((ValueHelper)factory, indirection); 1146 } else { 1147 valueIndirection = indirection; // for callback 1148 value = factory.read_value(parent); 1149 } 1150 1151 handleEndOfValue(); 1152 readEndTag(); 1153 1154 // Put into valueCache 1155 if (valueCache == null) 1156 valueCache = new CacheTable(orb,false); 1157 valueCache.put(value, indirection); 1158 1159 // allow for possible continuation chunk 1160 isChunked = saveIsChunked; 1161 start_block(); 1162 1163 return (java.io.Serializable)value; 1164 } 1165 } 1166 1167 private boolean isCustomType(ValueHelper helper) { 1168 try{ 1169 TypeCode tc = helper.get_type(); 1170 int kind = tc.kind().value(); 1171 if (kind == TCKind._tk_value) { 1172 return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value); 1173 } 1174 } catch(BadKind ex) { 1175 throw wrapper.badKind(ex) ; 1176 } 1177 1178 return false; 1179 } 1180 1181 // This method is actually called indirectly by 1182 // read_value(String repositoryId). 1183 // Therefore, it is not a truly independent read call that handles 1184 // header information itself. 1185 public java.io.Serializable read_value(java.io.Serializable value) { 1186 1187 // Put into valueCache using valueIndirection 1188 if (valueCache == null) 1189 valueCache = new CacheTable(orb,false); 1190 valueCache.put(value, valueIndirection); 1191 1192 if (value instanceof StreamableValue) 1193 ((StreamableValue)value)._read(parent); 1194 else if (value instanceof CustomValue) 1195 ((CustomValue)value).unmarshal(parent); 1196 1197 return value; 1198 } 1199 1200 public java.io.Serializable read_value(java.lang.String repositoryId) { 1201 1202 // if (inBlock) 1203 // end_block(); 1204 1205 // Read value tag 1206 int vType = readValueTag(); 1207 1208 if (vType == 0) 1209 return null; // value is null 1210 else if (vType == 0xffffffff) { // Indirection tag 1211 int indirection = read_long() + get_offset() - 4; 1212 if (valueCache != null && valueCache.containsVal(indirection)) 1213 { 1214 java.io.Serializable cachedValue = 1215 (java.io.Serializable)valueCache.getKey(indirection); 1216 return cachedValue; 1217 } 1218 else { 1219 throw new IndirectionException(indirection); 1220 } 1221 } 1222 else { 1223 int indirection = get_offset() - 4; 1224 1225 // end_block(); 1226 1227 boolean saveIsChunked = isChunked; 1228 isChunked = repIdUtil.isChunkedEncoding(vType); 1229 1230 java.lang.Object value = null; 1231 1232 String codebase_URL = null; 1233 if (repIdUtil.isCodeBasePresent(vType)){ 1234 codebase_URL = read_codebase_URL(); 1235 } 1236 1237 // Read repository id 1238 String repositoryIDString 1239 = readRepositoryIds(vType, null, repositoryId); 1240 1241 ValueFactory factory = 1242 Utility.getFactory(null, codebase_URL, orb, repositoryIDString); 1243 1244 start_block(); 1245 end_flag--; 1246 if (isChunked) 1247 chunkedValueNestingLevel--; 1248 1249 valueIndirection = indirection; // for callback 1250 value = factory.read_value(parent); 1251 1252 handleEndOfValue(); 1253 readEndTag(); 1254 1255 // Put into valueCache 1256 if (valueCache == null) 1257 valueCache = new CacheTable(orb,false); 1258 valueCache.put(value, indirection); 1259 1260 // allow for possible continuation chunk 1261 isChunked = saveIsChunked; 1262 start_block(); 1263 1264 return (java.io.Serializable)value; 1265 } 1266 } 1267 1268 private Class readClass() { 1269 1270 String codebases = null, classRepId = null; 1271 1272 if (orb == null || 1273 ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || 1274 ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { 1275 1276 codebases = (String)read_value(java.lang.String.class); 1277 classRepId = (String)read_value(java.lang.String.class); 1278 } else { 1279 // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID 1280 // and codebase strings in the wrong order. 1281 classRepId = (String)read_value(java.lang.String.class); 1282 codebases = (String)read_value(java.lang.String.class); 1283 } 1284 1285 if (debug) { 1286 dprint("readClass codebases: " 1287 + codebases 1288 + " rep Id: " 1289 + classRepId); 1290 } 1291 1292 Class cl = null; 1293 1294 RepositoryIdInterface repositoryID 1295 = repIdStrs.getFromString(classRepId); 1296 1297 try { 1298 cl = repositoryID.getClassFromType(codebases); 1299 } catch(ClassNotFoundException cnfe) { 1300 throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE, 1301 cnfe, repositoryID.getClassName() ) ; 1302 } catch(MalformedURLException me) { 1303 throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, 1304 me, repositoryID.getClassName(), codebases ) ; 1305 } 1306 1307 return cl; 1308 } 1309 1310 private java.lang.Object readIDLValueWithHelper(ValueHelper helper, int indirection) 1311 { 1312 // look for two-argument static read method 1313 Method readMethod; 1314 try { 1315 Class argTypes[] = {org.omg.CORBA.portable.InputStream.class, helper.get_class()}; 1316 readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes); 1317 } 1318 catch(NoSuchMethodException nsme) { // must be boxed value helper 1319 java.lang.Object result = helper.read_value(parent); 1320 return result; 1321 } 1322 1323 // found two-argument read method, so must be non-boxed value... 1324 // ...create a blank instance 1325 java.lang.Object val = null; 1326 try { 1327 val = helper.get_class().newInstance(); 1328 } catch(java.lang.InstantiationException ie) { 1329 throw wrapper.couldNotInstantiateHelper( ie, 1330 helper.get_class() ) ; 1331 } catch(IllegalAccessException iae){ 1332 // Value's constructor is protected or private 1333 // 1334 // So, use the helper to read the value. 1335 // 1336 // NOTE : This means that in this particular case a recursive ref. 1337 // would fail. 1338 return helper.read_value(parent); 1339 } 1340 1341 // add blank instance to cache table 1342 if (valueCache == null) 1343 valueCache = new CacheTable(orb,false); 1344 valueCache.put(val, indirection); 1345 1346 // if custom type, call unmarshal method 1347 if (val instanceof CustomMarshal && isCustomType(helper)) { 1348 ((CustomMarshal)val).unmarshal(parent); 1349 return val; 1350 } 1351 1352 // call two-argument read method using reflection 1353 try { 1354 java.lang.Object args[] = {parent, val}; 1355 readMethod.invoke(helper, args); 1356 return val; 1357 } catch(IllegalAccessException iae2) { 1358 throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ; 1359 } catch(InvocationTargetException ite){ 1360 throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ; 1361 } 1362 } 1363 1364 private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase) 1365 { 1366 Class cls = null ; 1367 1368 try { 1369 ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader()); 1370 1371 cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase, 1372 clazzLoader, clazz, clazzLoader); 1373 final Class helperClass = cls ; 1374 1375 final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class}; 1376 1377 // getDeclaredMethod requires RuntimePermission accessDeclaredMembers 1378 // if a different class loader is used (even though the javadoc says otherwise) 1379 Method readMethod = null; 1380 try { 1381 readMethod = (Method)AccessController.doPrivileged( 1382 new PrivilegedExceptionAction() { 1383 public java.lang.Object run() throws NoSuchMethodException { 1384 return helperClass.getDeclaredMethod(kReadMethod, argTypes); 1385 } 1386 } 1387 ); 1388 } catch (PrivilegedActionException pae) { 1389 // this gets caught below 1390 throw (NoSuchMethodException)pae.getException(); 1391 } 1392 1393 java.lang.Object args[] = {parent}; 1394 return readMethod.invoke(null, args); 1395 1396 } catch (ClassNotFoundException cnfe) { 1397 throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ; 1398 } catch(NoSuchMethodException nsme) { 1399 throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ; 1400 } catch(IllegalAccessException iae) { 1401 throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ; 1402 } catch(InvocationTargetException ite) { 1403 throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ; 1404 } 1405 } 1406 1407 private java.lang.Object readIDLValue(int indirection, String repId, 1408 Class clazz, String codebase) 1409 { 1410 ValueFactory factory ; 1411 1412 // Always try to find a ValueFactory first, as required by the spec. 1413 // There are some complications here in the IDL 3.0 mapping (see 1.13.8), 1414 // but basically we must always be able to override the DefaultFactory 1415 // or Helper mappings that are also used. This appears to be the case 1416 // even in the boxed value cases. The original code only did the lookup 1417 // in the case of class implementing either StreamableValue or CustomValue, 1418 // but abstract valuetypes only implement ValueBase, and really require 1419 // the use of the repId to find a factory (including the DefaultFactory). 1420 try { 1421 // use new-style OBV support (factory object) 1422 factory = Utility.getFactory(clazz, codebase, orb, repId); 1423 } catch (MARSHAL marshal) { 1424 // XXX log marshal at one of the INFO levels 1425 1426 // Could not get a factory, so try alternatives 1427 if (!StreamableValue.class.isAssignableFrom(clazz) && 1428 !CustomValue.class.isAssignableFrom(clazz) && 1429 ValueBase.class.isAssignableFrom(clazz)) { 1430 // use old-style OBV support (helper object) 1431 BoxedValueHelper helper = Utility.getHelper(clazz, codebase, repId); 1432 if (helper instanceof ValueHelper) 1433 return readIDLValueWithHelper((ValueHelper)helper, indirection); 1434 else 1435 return helper.read_value(parent); 1436 } else { 1437 // must be a boxed IDLEntity, so make a reflective call to the 1438 // helper's static read method... 1439 return readBoxedIDLEntity(clazz, codebase); 1440 } 1441 } 1442 1443 // If there was no error in getting the factory, use it. 1444 valueIndirection = indirection; // for callback 1445 return factory.read_value(parent); 1446 } 1447 1448 /** 1449 * End tags are only written for chunked valuetypes. 1450 * 1451 * Before Merlin, our ORBs wrote end tags which took into account 1452 * all enclosing valuetypes. This was changed by an interop resolution 1453 * (see details around chunkedValueNestingLevel) to only include 1454 * enclosing chunked types. 1455 * 1456 * ORB versioning and end tag compaction are handled here. 1457 */ 1458 private void readEndTag() { 1459 if (isChunked) { 1460 1461 // Read the end tag 1462 int anEndTag = read_long(); 1463 1464 // End tags should always be negative, and the outermost 1465 // enclosing chunked valuetype should have a -1 end tag. 1466 // 1467 // handleEndOfValue should have assured that we were 1468 // at the end tag position! 1469 if (anEndTag >= 0) { 1470 throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE, 1471 new Integer(anEndTag), new Integer( get_offset() - 4 ) ) ; 1472 } 1473 1474 // If the ORB is null, or if we're sure we're talking to 1475 // a foreign ORB, Merlin, or something more recent, we 1476 // use the updated end tag computation, and are more strenuous 1477 // about the values. 1478 if (orb == null || 1479 ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || 1480 ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { 1481 1482 // If the end tag we read was less than what we were expecting, 1483 // then the sender must think it's sent more enclosing 1484 // chunked valuetypes than we have. Throw an exception. 1485 if (anEndTag < chunkedValueNestingLevel) 1486 throw wrapper.unexpectedEnclosingValuetype( 1487 CompletionStatus.COMPLETED_MAYBE, new Integer( anEndTag ), 1488 new Integer( chunkedValueNestingLevel ) ) ; 1489 1490 // If the end tag is bigger than what we expected, but 1491 // still negative, then the sender has done some end tag 1492 // compaction. We back up the stream 4 bytes so that the 1493 // next time readEndTag is called, it will get down here 1494 // again. Even with fragmentation, we'll always be able 1495 // to do this. 1496 if (anEndTag != chunkedValueNestingLevel) { 1497 bbwi.position(bbwi.position() - 4); 1498 } 1499 1500 } else { 1501 1502 // When talking to Kestrel or Ladybird, we use our old 1503 // end tag rules and are less strict. If the end tag 1504 // isn't what we expected, we back up, assuming 1505 // compaction. 1506 if (anEndTag != end_flag) { 1507 bbwi.position(bbwi.position() - 4); 1508 } 1509 } 1510 1511 // This only keeps track of the enclosing chunked 1512 // valuetypes 1513 chunkedValueNestingLevel++; 1514 } 1515 1516 // This keeps track of all enclosing valuetypes 1517 end_flag++; 1518 } 1519 1520 protected int get_offset() { 1521 return bbwi.position(); 1522 } 1523 1524 private void start_block() { 1525 1526 // if (outerValueDone) 1527 if (!isChunked) 1528 return; 1529 1530 // if called from alignAndCheck, need to reset blockLength 1531 // to avoid an infinite recursion loop on read_long() call 1532 blockLength = maxBlockLength; 1533 1534 blockLength = read_long(); 1535 1536 // Must remember where we began the chunk to calculate how far 1537 // along we are. See notes above about chunkBeginPos. 1538 1539 if (blockLength > 0 && blockLength < maxBlockLength) { 1540 blockLength += get_offset(); // _REVISIT_ unsafe, should use a Java long 1541 1542 // inBlock = true; 1543 } else { 1544 1545 // System.out.println("start_block snooped a " + Integer.toHexString(blockLength)); 1546 1547 // not a chunk length field 1548 blockLength = maxBlockLength; 1549 1550 bbwi.position(bbwi.position() - 4); 1551 } 1552 } 1553 1554 // Makes sure that if we were reading a chunked value, we end up 1555 // at the right place in the stream, no matter how little the 1556 // unmarshalling code read. 1557 // 1558 // After calling this method, if we are chunking, we should be 1559 // in position to read the end tag. 1560 private void handleEndOfValue() { 1561 1562 // If we're not chunking, we don't have to worry about 1563 // skipping remaining chunks or finding end tags 1564 if (!isChunked) 1565 return; 1566 1567 // Skip any remaining chunks 1568 while (blockLength != maxBlockLength) { 1569 end_block(); 1570 start_block(); 1571 } 1572 1573 // Now look for the end tag 1574 1575 // This is a little wasteful since we're reading 1576 // this long up to 3 times in the worst cases (once 1577 // in start_block, once here, and once in readEndTag 1578 // 1579 // Peek next long 1580 int nextLong = read_long(); 1581 bbwi.position(bbwi.position() - 4); 1582 1583 // We did find an end tag, so we're done. readEndTag 1584 // should take care of making sure it's the correct 1585 // end tag, etc. Remember that since end tags, 1586 // chunk lengths, and valuetags have non overlapping 1587 // ranges, we can tell by the value what the longs are. 1588 if (nextLong < 0) 1589 return; 1590 1591 if (nextLong == 0 || nextLong >= maxBlockLength) { 1592 1593 // A custom marshaled valuetype left extra data 1594 // on the wire, and that data had another 1595 // nested value inside of it. We've just 1596 // read the value tag or null of that nested value. 1597 // 1598 // In an attempt to get by it, we'll try to call 1599 // read_value() to get the nested value off of 1600 // the wire. Afterwards, we must call handleEndOfValue 1601 // recursively to read any further chunks that the containing 1602 // valuetype might still have after the nested 1603 // value. 1604 read_value(); 1605 handleEndOfValue(); 1606 } else { 1607 // This probably means that the code to skip chunks has 1608 // an error, and ended up setting blockLength to something 1609 // other than maxBlockLength even though we weren't 1610 // starting a new chunk. 1611 throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE, 1612 new Integer( nextLong ), new Integer( get_offset() ) ) ; 1613 } 1614 } 1615 1616 private void end_block() { 1617 1618 // if in a chunk, check for underflow or overflow 1619 if (blockLength != maxBlockLength) { 1620 if (blockLength == get_offset()) { 1621 // Chunk ended correctly 1622 blockLength = maxBlockLength; 1623 } else { 1624 // Skip over anything left by bad unmarshaling code (ex: 1625 // a buggy custom unmarshaler). See handleEndOfValue. 1626 if (blockLength > get_offset()) { 1627 skipToOffset(blockLength); 1628 } else { 1629 throw wrapper.badChunkLength( new Integer( blockLength ), 1630 new Integer( get_offset() ) ) ; 1631 } 1632 } 1633 } 1634 } 1635 1636 private int readValueTag(){ 1637 // outerValueDone = false; 1638 return read_long(); 1639 } 1640 1641 public org.omg.CORBA.ORB orb() { 1642 return orb; 1643 } 1644 1645 // ------------ End RMI related methods -------------------------- 1646 1647 public final void read_boolean_array(boolean[] value, int offset, int length) { 1648 for(int i=0; i < length; i++) { 1649 value[i+offset] = read_boolean(); 1650 } 1651 } 1652 1653 public final void read_char_array(char[] value, int offset, int length) { 1654 for(int i=0; i < length; i++) { 1655 value[i+offset] = read_char(); 1656 } 1657 } 1658 1659 public final void read_wchar_array(char[] value, int offset, int length) { 1660 for(int i=0; i < length; i++) { 1661 value[i+offset] = read_wchar(); 1662 } 1663 } 1664 1665 public final void read_short_array(short[] value, int offset, int length) { 1666 for(int i=0; i < length; i++) { 1667 value[i+offset] = read_short(); 1668 } 1669 } 1670 1671 public final void read_ushort_array(short[] value, int offset, int length) { 1672 read_short_array(value, offset, length); 1673 } 1674 1675 public final void read_long_array(int[] value, int offset, int length) { 1676 for(int i=0; i < length; i++) { 1677 value[i+offset] = read_long(); 1678 } 1679 } 1680 1681 public final void read_ulong_array(int[] value, int offset, int length) { 1682 read_long_array(value, offset, length); 1683 } 1684 1685 public final void read_longlong_array(long[] value, int offset, int length) { 1686 for(int i=0; i < length; i++) { 1687 value[i+offset] = read_longlong(); 1688 } 1689 } 1690 1691 public final void read_ulonglong_array(long[] value, int offset, int length) { 1692 read_longlong_array(value, offset, length); 1693 } 1694 1695 public final void read_float_array(float[] value, int offset, int length) { 1696 for(int i=0; i < length; i++) { 1697 value[i+offset] = read_float(); 1698 } 1699 } 1700 1701 public final void read_double_array(double[] value, int offset, int length) { 1702 for(int i=0; i < length; i++) { 1703 value[i+offset] = read_double(); 1704 } 1705 } 1706 1707 public final void read_any_array(org.omg.CORBA.Any[] value, int offset, int length) { 1708 for(int i=0; i < length; i++) { 1709 value[i+offset] = read_any(); 1710 } 1711 } 1712 1713 //--------------------------------------------------------------------// 1714 // CDRInputStream state management. 1715 // 1716 1717 /** 1718 * Are we at the end of the input stream? 1719 */ 1720 // public final boolean isAtEnd() { 1721 // return bbwi.position() == bbwi.buflen; 1722 // } 1723 1724 // public int available() throws IOException { 1725 // return bbwi.buflen - bbwi.position(); 1726 // } 1727 1728 private String read_repositoryIds() { 1729 1730 // Read # of repository ids 1731 int numRepIds = read_long(); 1732 if (numRepIds == 0xffffffff) { 1733 int indirection = read_long() + get_offset() - 4; 1734 if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection)) 1735 return (String)repositoryIdCache.getKey(indirection); 1736 else 1737 throw wrapper.unableToLocateRepIdArray( new Integer( indirection ) ) ; 1738 } else { 1739 1740 // read first array element and store it as an indirection to the whole array 1741 int indirection = get_offset(); 1742 String repID = read_repositoryId(); 1743 if (repositoryIdCache == null) 1744 repositoryIdCache = new CacheTable(orb,false); 1745 repositoryIdCache.put(repID, indirection); 1746 1747 // read and ignore the subsequent array elements, but put them in the 1748 // indirection table in case there are later indirections back to them 1749 for (int i = 1; i < numRepIds; i++) { 1750 read_repositoryId(); 1751 } 1752 1753 return repID; 1754 } 1755 } 1756 1757 private final String read_repositoryId() 1758 { 1759 String result = readStringOrIndirection(true); 1760 1761 if (result == null) { // Indirection 1762 int indirection = read_long() + get_offset() - 4; 1763 1764 if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection)) 1765 return (String)repositoryIdCache.getKey(indirection); 1766 else 1767 throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE, 1768 new Integer(bbwi.position()) ) ; 1769 } else { 1770 if (repositoryIdCache == null) 1771 repositoryIdCache = new CacheTable(orb,false); 1772 repositoryIdCache.put(result, stringIndirection); 1773 } 1774 1775 return result ; 1776 } 1777 1778 private final String read_codebase_URL() 1779 { 1780 String result = readStringOrIndirection(true); 1781 1782 if (result == null) { // Indirection 1783 int indirection = read_long() + get_offset() - 4; 1784 1785 if (codebaseCache != null && codebaseCache.containsVal(indirection)) 1786 return (String)codebaseCache.getKey(indirection); 1787 else 1788 throw wrapper.badCodebaseIndirection( 1789 CompletionStatus.COMPLETED_MAYBE, 1790 new Integer(bbwi.position()) ) ; 1791 } else { 1792 if (codebaseCache == null) 1793 codebaseCache = new CacheTable(orb,false); 1794 codebaseCache.put(result, stringIndirection); 1795 } 1796 1797 return result; 1798 } 1799 1800 /* DataInputStream methods */ 1801 1802 public java.lang.Object read_Abstract () { 1803 return read_abstract_interface(); 1804 } 1805 1806 public java.io.Serializable read_Value () { 1807 return read_value(); 1808 } 1809 1810 public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) { 1811 read_any_array(seq.value, offset, length); 1812 } 1813 1814 public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) { 1815 read_boolean_array(seq.value, offset, length); 1816 } 1817 1818 public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) { 1819 read_char_array(seq.value, offset, length); 1820 } 1821 1822 public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) { 1823 read_wchar_array(seq.value, offset, length); 1824 } 1825 1826 public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) { 1827 read_octet_array(seq.value, offset, length); 1828 } 1829 1830 public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) { 1831 read_short_array(seq.value, offset, length); 1832 } 1833 1834 public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) { 1835 read_ushort_array(seq.value, offset, length); 1836 } 1837 1838 public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) { 1839 read_long_array(seq.value, offset, length); 1840 } 1841 1842 public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) { 1843 read_ulong_array(seq.value, offset, length); 1844 } 1845 1846 public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) { 1847 read_ulonglong_array(seq.value, offset, length); 1848 } 1849 1850 public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) { 1851 read_longlong_array(seq.value, offset, length); 1852 } 1853 1854 public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) { 1855 read_float_array(seq.value, offset, length); 1856 } 1857 1858 public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) { 1859 read_double_array(seq.value, offset, length); 1860 } 1861 1862 public java.math.BigDecimal read_fixed(short digits, short scale) { 1863 // digits isn't really needed here 1864 StringBuffer buffer = read_fixed_buffer(); 1865 if (digits != buffer.length()) 1866 throw wrapper.badFixed( new Integer(digits), 1867 new Integer(buffer.length()) ) ; 1868 buffer.insert(digits - scale, '.'); 1869 return new BigDecimal(buffer.toString()); 1870 } 1871 1872 // This method is unable to yield the correct scale. 1873 public java.math.BigDecimal read_fixed() { 1874 return new BigDecimal(read_fixed_buffer().toString()); 1875 } 1876 1877 // Each octet contains (up to) two decimal digits. 1878 // If the fixed type has an odd number of decimal digits, then the representation 1879 // begins with the first (most significant) digit. 1880 // Otherwise, this first half-octet is all zero, and the first digit 1881 // is in the second half-octet. 1882 // The sign configuration, in the last half-octet of the representation, 1883 // is 0xD for negative numbers and 0xC for positive and zero values. 1884 private StringBuffer read_fixed_buffer() { 1885 StringBuffer buffer = new StringBuffer(64); 1886 byte doubleDigit; 1887 int firstDigit; 1888 int secondDigit; 1889 boolean wroteFirstDigit = false; 1890 boolean more = true; 1891 while (more) { 1892 doubleDigit = this.read_octet(); 1893 firstDigit = (int)((doubleDigit & 0xf0) >> 4); 1894 secondDigit = (int)(doubleDigit & 0x0f); 1895 if (wroteFirstDigit || firstDigit != 0) { 1896 buffer.append(Character.forDigit(firstDigit, 10)); 1897 wroteFirstDigit = true; 1898 } 1899 if (secondDigit == 12) { 1900 // positive number or zero 1901 if ( ! wroteFirstDigit) { 1902 // zero 1903 return new StringBuffer("0.0"); 1904 } else { 1905 // positive number 1906 // done 1907 } 1908 more = false; 1909 } else if (secondDigit == 13) { 1910 // negative number 1911 buffer.insert(0, '-'); 1912 more = false; 1913 } else { 1914 buffer.append(Character.forDigit(secondDigit, 10)); 1915 wroteFirstDigit = true; 1916 } 1917 } 1918 return buffer; 1919 } 1920 1921 private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0"; 1922 private final static String[] _ids = { _id }; 1923 1924 public String[] _truncatable_ids() { 1925 if (_ids == null) 1926 return null; 1927 1928 return (String[])_ids.clone(); 1929 } 1930 1931 /* for debugging */ 1932 1933 public void printBuffer() { 1934 CDRInputStream_1_0.printBuffer(this.bbwi); 1935 } 1936 1937 public static void printBuffer(ByteBufferWithInfo bbwi) { 1938 1939 System.out.println("----- Input Buffer -----"); 1940 System.out.println(); 1941 System.out.println("Current position: " + bbwi.position()); 1942 System.out.println("Total length : " + bbwi.buflen); 1943 System.out.println(); 1944 1945 try { 1946 1947 char[] charBuf = new char[16]; 1948 1949 for (int i = 0; i < bbwi.buflen; i += 16) { 1950 1951 int j = 0; 1952 1953 // For every 16 bytes, there is one line 1954 // of output. First, the hex output of 1955 // the 16 bytes with each byte separated 1956 // by a space. 1957 while (j < 16 && j + i < bbwi.buflen) { 1958 int k = bbwi.byteBuffer.get(i + j); 1959 if (k < 0) 1960 k = 256 + k; 1961 String hex = Integer.toHexString(k); 1962 if (hex.length() == 1) 1963 hex = "0" + hex; 1964 System.out.print(hex + " "); 1965 j++; 1966 } 1967 1968 // Add any extra spaces to align the 1969 // text column in case we didn't end 1970 // at 16 1971 while (j < 16) { 1972 System.out.print(" "); 1973 j++; 1974 } 1975 1976 // Now output the ASCII equivalents. Non-ASCII 1977 // characters are shown as periods. 1978 int x = 0; 1979 while (x < 16 && x + i < bbwi.buflen) { 1980 if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x))) 1981 charBuf[x] = (char)bbwi.byteBuffer.get(i + x); 1982 else 1983 charBuf[x] = '.'; 1984 x++; 1985 } 1986 System.out.println(new String(charBuf, 0, x)); 1987 } 1988 1989 } catch (Throwable t) { 1990 t.printStackTrace(); 1991 } 1992 1993 System.out.println("------------------------"); 1994 } 1995 1996 public ByteBuffer getByteBuffer() { 1997 ByteBuffer result = null; 1998 if (bbwi != null) { 1999 result = bbwi.byteBuffer; 2000 } 2001 return result; 2002 } 2003 2004 public int getBufferLength() { 2005 return bbwi.buflen; 2006 } 2007 2008 public void setBufferLength(int value) { 2009 bbwi.buflen = value; 2010 bbwi.byteBuffer.limit(bbwi.buflen); 2011 } 2012 2013 public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) { 2014 this.bbwi = bbwi; 2015 } 2016 2017 public void setByteBuffer(ByteBuffer byteBuffer) { 2018 bbwi.byteBuffer = byteBuffer; 2019 } 2020 2021 public int getIndex() { 2022 return bbwi.position(); 2023 } 2024 2025 public void setIndex(int value) { 2026 bbwi.position(value); 2027 } 2028 2029 public boolean isLittleEndian() { 2030 return littleEndian; 2031 } 2032 2033 public void orb(org.omg.CORBA.ORB orb) { 2034 this.orb = (ORB)orb; 2035 } 2036 2037 public BufferManagerRead getBufferManager() { 2038 return bufferManagerRead; 2039 } 2040 2041 private void skipToOffset(int offset) { 2042 2043 // Number of bytes to skip 2044 int len = offset - get_offset(); 2045 2046 int n = 0; 2047 2048 while (n < len) { 2049 int avail; 2050 int bytes; 2051 int wanted; 2052 2053 avail = bbwi.buflen - bbwi.position(); 2054 if (avail <= 0) { 2055 grow(1, 1); 2056 avail = bbwi.buflen - bbwi.position(); 2057 } 2058 2059 wanted = len - n; 2060 bytes = (wanted < avail) ? wanted : avail; 2061 bbwi.position(bbwi.position() + bytes); 2062 n += bytes; 2063 } 2064 } 2065 2066 2067 // Mark and reset ------------------------------------------------- 2068 2069 protected MarkAndResetHandler markAndResetHandler = null; 2070 2071 protected class StreamMemento 2072 { 2073 // These are the fields that may change after marking 2074 // the stream position, so we need to save them. 2075 private int blockLength_; 2076 private int end_flag_; 2077 private int chunkedValueNestingLevel_; 2078 private int valueIndirection_; 2079 private int stringIndirection_; 2080 private boolean isChunked_; 2081 private javax.rmi.CORBA.ValueHandler valueHandler_; 2082 private ByteBufferWithInfo bbwi_; 2083 private boolean specialNoOptionalDataState_; 2084 2085 public StreamMemento() 2086 { 2087 blockLength_ = blockLength; 2088 end_flag_ = end_flag; 2089 chunkedValueNestingLevel_ = chunkedValueNestingLevel; 2090 valueIndirection_ = valueIndirection; 2091 stringIndirection_ = stringIndirection; 2092 isChunked_ = isChunked; 2093 valueHandler_ = valueHandler; 2094 specialNoOptionalDataState_ = specialNoOptionalDataState; 2095 bbwi_ = new ByteBufferWithInfo(bbwi); 2096 } 2097 } 2098 2099 public java.lang.Object createStreamMemento() { 2100 return new StreamMemento(); 2101 } 2102 2103 public void restoreInternalState(java.lang.Object streamMemento) { 2104 2105 StreamMemento mem = (StreamMemento)streamMemento; 2106 2107 blockLength = mem.blockLength_; 2108 end_flag = mem.end_flag_; 2109 chunkedValueNestingLevel = mem.chunkedValueNestingLevel_; 2110 valueIndirection = mem.valueIndirection_; 2111 stringIndirection = mem.stringIndirection_; 2112 isChunked = mem.isChunked_; 2113 valueHandler = mem.valueHandler_; 2114 specialNoOptionalDataState = mem.specialNoOptionalDataState_; 2115 bbwi = mem.bbwi_; 2116 } 2117 2118 public int getPosition() { 2119 return get_offset(); 2120 } 2121 2122 public void mark(int readlimit) { 2123 markAndResetHandler.mark(this); 2124 } 2125 2126 public void reset() { 2127 markAndResetHandler.reset(); 2128 } 2129 2130 // ---------------------------------- end Mark and Reset 2131 2132 // Provides a hook so subclasses of CDRInputStream can provide 2133 // a CodeBase. This ultimately allows us to grab a Connection 2134 // instance in IIOPInputStream, the only subclass where this 2135 // is actually used. 2136 CodeBase getCodeBase() { 2137 return parent.getCodeBase(); 2138 } 2139 2140 /** 2141 * Attempts to find the class described by the given 2142 * repository ID string and expected type. The first 2143 * attempt is to find the class locally, falling back 2144 * on the URL that came with the value. The second 2145 * attempt is to use a URL from the remote CodeBase. 2146 */ 2147 private Class getClassFromString(String repositoryIDString, 2148 String codebaseURL, 2149 Class expectedType) 2150 { 2151 RepositoryIdInterface repositoryID 2152 = repIdStrs.getFromString(repositoryIDString); 2153 2154 try { 2155 try { 2156 // First try to load the class locally, then use 2157 // the provided URL (if it isn't null) 2158 return repositoryID.getClassFromType(expectedType, 2159 codebaseURL); 2160 } catch (ClassNotFoundException cnfeOuter) { 2161 2162 try { 2163 2164 if (getCodeBase() == null) { 2165 return null; // class cannot be loaded remotely. 2166 } 2167 2168 // Get a URL from the remote CodeBase and retry 2169 codebaseURL = getCodeBase().implementation(repositoryIDString); 2170 2171 // Don't bother trying to find it locally again if 2172 // we got a null URL 2173 if (codebaseURL == null) 2174 return null; 2175 2176 return repositoryID.getClassFromType(expectedType, 2177 codebaseURL); 2178 } catch (ClassNotFoundException cnfeInner) { 2179 dprintThrowable(cnfeInner); 2180 // Failed to load the class 2181 return null; 2182 } 2183 } 2184 } catch (MalformedURLException mue) { 2185 // Always report a bad URL 2186 throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, 2187 mue, repositoryIDString, codebaseURL ) ; 2188 } 2189 } 2190 2191 /** 2192 * Attempts to find the class described by the given 2193 * repository ID string. At most, three attempts are made: 2194 * Try to find it locally, through the provided URL, and 2195 * finally, via a URL from the remote CodeBase. 2196 */ 2197 private Class getClassFromString(String repositoryIDString, 2198 String codebaseURL) 2199 { 2200 RepositoryIdInterface repositoryID 2201 = repIdStrs.getFromString(repositoryIDString); 2202 2203 for (int i = 0; i < 3; i++) { 2204 2205 try { 2206 2207 switch (i) 2208 { 2209 case 0: 2210 // First try to load the class locally 2211 return repositoryID.getClassFromType(); 2212 case 1: 2213 // Try to load the class using the provided 2214 // codebase URL (falls out below) 2215 break; 2216 case 2: 2217 // Try to load the class using a URL from the 2218 // remote CodeBase 2219 codebaseURL = getCodeBase().implementation(repositoryIDString); 2220 break; 2221 } 2222 2223 // Don't bother if the codebaseURL is null 2224 if (codebaseURL == null) 2225 continue; 2226 2227 return repositoryID.getClassFromType(codebaseURL); 2228 2229 } catch(ClassNotFoundException cnfe) { 2230 // Will ultimately return null if all three 2231 // attempts fail, but don't do anything here. 2232 } catch (MalformedURLException mue) { 2233 throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, 2234 mue, repositoryIDString, codebaseURL ) ; 2235 } 2236 } 2237 2238 // If we get here, we have failed to load the class 2239 dprint("getClassFromString failed with rep id " 2240 + repositoryIDString 2241 + " and codebase " 2242 + codebaseURL); 2243 2244 return null; 2245 } 2246 2247 // Utility method used to get chars from bytes 2248 char[] getConvertedChars(int numBytes, 2249 CodeSetConversion.BTCConverter converter) { 2250 2251 // REVISIT - Look at CodeSetConversion.BTCConverter to see 2252 // if it can work with an NIO ByteBuffer. We should 2253 // avoid getting the bytes into an array if possible. 2254 2255 // To be honest, I doubt this saves much real time 2256 if (bbwi.buflen - bbwi.position() >= numBytes) { 2257 // If the entire string is in this buffer, 2258 // just convert directly from the bbwi rather than 2259 // allocating and copying. 2260 byte[] tmpBuf; 2261 if (bbwi.byteBuffer.hasArray()) 2262 { 2263 tmpBuf = bbwi.byteBuffer.array(); 2264 } 2265 else 2266 { 2267 tmpBuf = new byte[bbwi.buflen]; 2268 // Microbenchmarks are showing a loop of ByteBuffer.get(int) 2269 // being faster than ByteBuffer.get(byte[], int, int). 2270 for (int i = 0; i < bbwi.buflen; i++) 2271 tmpBuf[i] = bbwi.byteBuffer.get(i); 2272 } 2273 char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes); 2274 2275 bbwi.position(bbwi.position() + numBytes); 2276 return result; 2277 } else { 2278 // Stretches across buffers. Unless we provide an 2279 // incremental conversion interface, allocate and 2280 // copy the bytes. 2281 byte[] bytes = new byte[numBytes]; 2282 read_octet_array(bytes, 0, bytes.length); 2283 2284 return converter.getChars(bytes, 0, numBytes); 2285 } 2286 } 2287 2288 protected CodeSetConversion.BTCConverter getCharConverter() { 2289 if (charConverter == null) 2290 charConverter = parent.createCharBTCConverter(); 2291 2292 return charConverter; 2293 } 2294 2295 protected CodeSetConversion.BTCConverter getWCharConverter() { 2296 if (wcharConverter == null) 2297 wcharConverter = parent.createWCharBTCConverter(); 2298 2299 return wcharConverter; 2300 } 2301 2302 protected void dprintThrowable(Throwable t) { 2303 if (debug && t != null) 2304 t.printStackTrace(); 2305 } 2306 2307 protected void dprint(String msg) { 2308 if (debug) { 2309 ORBUtility.dprint(this, msg); 2310 } 2311 } 2312 2313 /** 2314 * Aligns the current position on the given octet boundary 2315 * if there are enough bytes available to do so. Otherwise, 2316 * it just returns. This is used for some (but not all) 2317 * GIOP 1.2 message headers. 2318 */ 2319 2320 void alignOnBoundary(int octetBoundary) { 2321 int needed = computeAlignment(bbwi.position(), octetBoundary); 2322 2323 if (bbwi.position() + needed <= bbwi.buflen) 2324 { 2325 bbwi.position(bbwi.position() + needed); 2326 } 2327 } 2328 2329 public void resetCodeSetConverters() { 2330 charConverter = null; 2331 wcharConverter = null; 2332 } 2333 2334 public void start_value() { 2335 // Read value tag 2336 int vType = readValueTag(); 2337 2338 if (vType == 0) { 2339 // Stream needs to go into a state where it 2340 // throws standard exception until end_value 2341 // is called. This means the sender didn't 2342 // send any custom data. If the reader here 2343 // tries to read more, we need to throw an 2344 // exception before reading beyond where 2345 // we're supposed to 2346 specialNoOptionalDataState = true; 2347 2348 return; 2349 } 2350 2351 if (vType == 0xffffffff) { 2352 // One should never indirect to a custom wrapper 2353 throw wrapper.customWrapperIndirection( 2354 CompletionStatus.COMPLETED_MAYBE); 2355 } 2356 2357 if (repIdUtil.isCodeBasePresent(vType)) { 2358 throw wrapper.customWrapperWithCodebase( 2359 CompletionStatus.COMPLETED_MAYBE); 2360 } 2361 2362 if (repIdUtil.getTypeInfo(vType) 2363 != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) { 2364 throw wrapper.customWrapperNotSingleRepid( 2365 CompletionStatus.COMPLETED_MAYBE); 2366 } 2367 2368 2369 // REVISIT - Could verify repository ID even though 2370 // it isn't used elsewhere 2371 read_repositoryId(); 2372 2373 // Note: isChunked should be true here. Should have 2374 // been set to true in the containing value's read_value 2375 // method. 2376 2377 start_block(); 2378 end_flag--; 2379 chunkedValueNestingLevel--; 2380 } 2381 2382 public void end_value() { 2383 2384 if (specialNoOptionalDataState) { 2385 specialNoOptionalDataState = false; 2386 return; 2387 } 2388 2389 handleEndOfValue(); 2390 readEndTag(); 2391 2392 // Note that isChunked should still be true here. 2393 // If the containing valuetype is the highest 2394 // chunked value, it will get set to false 2395 // at the end of read_value. 2396 2397 // allow for possible continuation chunk 2398 start_block(); 2399 } 2400 2401 public void close() throws IOException 2402 { 2403 2404 // tell BufferManagerRead to release any ByteBuffers 2405 getBufferManager().close(bbwi); 2406 2407 // It's possible bbwi.byteBuffer is shared between 2408 // this InputStream and an OutputStream. Thus, we check 2409 // if the Input/Output streams are using the same ByteBuffer. 2410 // If they sharing the same ByteBuffer we need to ensure only 2411 // one of those ByteBuffers are released to the ByteBufferPool. 2412 2413 if (bbwi != null && getByteBuffer() != null) 2414 { 2415 MessageMediator messageMediator = parent.getMessageMediator(); 2416 if (messageMediator != null) 2417 { 2418 CDROutputObject outputObj = 2419 (CDROutputObject)messageMediator.getOutputObject(); 2420 if (outputObj != null) 2421 { 2422 if (outputObj.isSharing(getByteBuffer())) 2423 { 2424 // Set OutputStream's ByteBuffer and bbwi to null 2425 // so its ByteBuffer cannot be released to the pool 2426 outputObj.setByteBuffer(null); 2427 outputObj.setByteBufferWithInfo(null); 2428 } 2429 } 2430 } 2431 2432 // release this stream's ByteBuffer to the pool 2433 ByteBufferPool byteBufferPool = orb.getByteBufferPool(); 2434 if (debug) 2435 { 2436 // print address of ByteBuffer being released 2437 int bbAddress = System.identityHashCode(bbwi.byteBuffer); 2438 StringBuffer sb = new StringBuffer(80); 2439 sb.append(".close - releasing ByteBuffer id ("); 2440 sb.append(bbAddress).append(") to ByteBufferPool."); 2441 String msg = sb.toString(); 2442 dprint(msg); 2443 } 2444 byteBufferPool.releaseByteBuffer(bbwi.byteBuffer); 2445 bbwi.byteBuffer = null; 2446 bbwi = null; 2447 } 2448 } 2449 }