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