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