IIOPInputStream.java revision 807:408c9c621938
1/* 2 * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25/* 26 * Licensed Materials - Property of IBM 27 * RMI-IIOP v1.0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved 29 * 30 */ 31 32package com.sun.corba.se.impl.io; 33 34import java.io.IOException; 35import java.io.StreamCorruptedException; 36import java.io.ObjectInputValidation; 37import java.io.NotActiveException; 38import java.io.InvalidObjectException; 39import java.io.InvalidClassException; 40import java.io.OptionalDataException; 41import java.io.Externalizable; 42import java.io.EOFException; 43import java.lang.reflect.*; 44import java.util.Vector; 45import java.util.Enumeration; 46 47import sun.corba.Bridge ; 48 49import java.security.AccessController ; 50import java.security.PrivilegedAction ; 51 52import com.sun.corba.se.impl.util.Utility; 53 54import org.omg.CORBA.portable.ValueInputStream; 55 56import org.omg.CORBA.ValueMember; 57import org.omg.CORBA.SystemException; 58import org.omg.CORBA.TCKind; 59import org.omg.CORBA.ORB; 60import org.omg.CORBA.CompletionStatus; 61import org.omg.CORBA.portable.IndirectionException; 62import org.omg.CORBA.MARSHAL; 63import org.omg.CORBA.TypeCode; 64 65import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; 66import com.sun.org.omg.SendingContext.CodeBase; 67 68import javax.rmi.CORBA.Util; 69import javax.rmi.CORBA.ValueHandler; 70 71import java.security.*; 72import java.util.*; 73 74import com.sun.corba.se.impl.logging.OMGSystemException ; 75import com.sun.corba.se.impl.logging.UtilSystemException ; 76 77import com.sun.corba.se.spi.logging.CORBALogDomains ; 78 79/** 80 * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization 81 * input semantics. 82 * 83 * @author Stephen Lewallen 84 * @since JDK1.1.6 85 */ 86 87public class IIOPInputStream 88 extends com.sun.corba.se.impl.io.InputStreamHook 89{ 90 private static Bridge bridge = 91 (Bridge)AccessController.doPrivileged( 92 new PrivilegedAction() { 93 public Object run() { 94 return Bridge.get() ; 95 } 96 } 97 ) ; 98 99 private static OMGSystemException omgWrapper = OMGSystemException.get( 100 CORBALogDomains.RPC_ENCODING ) ; 101 private static UtilSystemException utilWrapper = UtilSystemException.get( 102 CORBALogDomains.RPC_ENCODING ) ; 103 104 // Necessary to pass the appropriate fields into the 105 // defaultReadObjectDelegate method (which takes no 106 // parameters since it's called from 107 // java.io.ObjectInpuStream defaultReadObject() 108 // which we can't change). 109 // 110 // This is only used in the case where the fields had 111 // to be obtained remotely because of a serializable 112 // version difference. Set in inputObjectUsingFVD. 113 // Part of serialization evolution fixes for Ladybird, 114 // bug 4365188. 115 private ValueMember defaultReadObjectFVDMembers[] = null; 116 117 private org.omg.CORBA_2_3.portable.InputStream orbStream; 118 119 private CodeBase cbSender; 120 121 private ValueHandlerImpl vhandler; //d4365188 122 123 private Object currentObject = null; 124 125 private ObjectStreamClass currentClassDesc = null; 126 127 private Class currentClass = null; 128 129 private int recursionDepth = 0; 130 131 private int simpleReadDepth = 0; 132 133 // The ActiveRecursionManager replaces the old RecursionManager which 134 // used to record how many recursions were made, and resolve them after 135 // an object was completely deserialized. 136 // 137 // That created problems (as in bug 4414154) because when custom 138 // unmarshaling in readObject, there can be recursive references 139 // to one of the objects currently being unmarshaled, and the 140 // passive recursion system failed. 141 ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager(); 142 143 private IOException abortIOException = null; 144 145 /* Remember the first exception that stopped this stream. */ 146 private ClassNotFoundException abortClassNotFoundException = null; 147 148 /* Vector of validation callback objects 149 * The vector is created as needed. The vector is maintained in 150 * order of highest (first) priority to lowest 151 */ 152 private Vector callbacks; 153 154 // Serialization machinery fields 155 /* Arrays used to keep track of classes and ObjectStreamClasses 156 * as they are being merged; used in inputObject. 157 * spClass is the stack pointer for both. */ 158 ObjectStreamClass[] classdesc; 159 Class[] classes; 160 int spClass; 161 162 private static final String kEmptyStr = ""; 163 164 // TCKind TypeCodes used in FVD inputClassFields 165 //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref); 166 //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value); 167 // removed TypeCodeImpl dependency 168 public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref); 169 public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value); 170 171 // TESTING CODE - useFVDOnly should be made final before FCS in order to 172 // optimize out the check. 173 private static final boolean useFVDOnly = false; 174 175 private byte streamFormatVersion; 176 177 // Return the stream format version currently being used 178 // to deserialize an object 179 protected byte getStreamFormatVersion() { 180 return streamFormatVersion; 181 } 182 183 // At the beginning of data sent by a writeObject or 184 // writeExternal method there is a byte telling the 185 // reader the stream format version. 186 private void readFormatVersion() throws IOException { 187 188 streamFormatVersion = orbStream.read_octet(); 189 190 if (streamFormatVersion < 1 || 191 streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) { 192 SystemException sysex = omgWrapper.unsupportedFormatVersion( 193 CompletionStatus.COMPLETED_MAYBE); 194 // XXX I18N? Logging for IOException? 195 IOException result = new IOException("Unsupported format version: " 196 + streamFormatVersion); 197 result.initCause( sysex ) ; 198 throw result ; 199 } 200 201 if (streamFormatVersion == 2) { 202 if (!(orbStream instanceof ValueInputStream)) { 203 SystemException sysex = omgWrapper.notAValueinputstream( 204 CompletionStatus.COMPLETED_MAYBE); 205 // XXX I18N? Logging for IOException? 206 IOException result = new IOException("Not a ValueInputStream"); 207 result.initCause( sysex ) ; 208 throw result; 209 } 210 } 211 } 212 213 public static void setTestFVDFlag(boolean val){ 214 // useFVDOnly = val; 215 } 216 217 /** 218 * Dummy constructor; passes upper stream a dummy stream; 219 **/ 220 public IIOPInputStream() 221 throws java.io.IOException { 222 super(); 223 resetStream(); 224 } 225 226 final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) { 227 orbStream = os; 228 } 229 230 final org.omg.CORBA_2_3.portable.InputStream getOrbStream() { 231 return orbStream; 232 } 233 234 //added setSender and getSender 235 public final void setSender(CodeBase cb) { 236 cbSender = cb; 237 } 238 239 public final CodeBase getSender() { 240 return cbSender; 241 } 242 243 // 4365188 this is added to enable backward compatability w/ wrong 244 // rep-ids 245 public final void setValueHandler(ValueHandler vh) { 246 vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh; 247 } 248 249 public final ValueHandler getValueHandler() { 250 return (javax.rmi.CORBA.ValueHandler) vhandler; 251 } 252 253 final void increaseRecursionDepth(){ 254 recursionDepth++; 255 } 256 257 final int decreaseRecursionDepth(){ 258 return --recursionDepth; 259 } 260 261 /** 262 * Override the actions of the final method "readObject()" 263 * in ObjectInputStream. 264 * @since JDK1.1.6 265 * 266 * Read an object from the ObjectInputStream. 267 * The class of the object, the signature of the class, and the values 268 * of the non-transient and non-static fields of the class and all 269 * of its supertypes are read. Default deserializing for a class can be 270 * overriden using the writeObject and readObject methods. 271 * Objects referenced by this object are read transitively so 272 * that a complete equivalent graph of objects is reconstructed by readObject. <p> 273 * 274 * The root object is completly restored when all of its fields 275 * and the objects it references are completely restored. At this 276 * point the object validation callbacks are executed in order 277 * based on their registered priorities. The callbacks are 278 * registered by objects (in the readObject special methods) 279 * as they are individually restored. 280 * 281 * Exceptions are thrown for problems with the InputStream and for classes 282 * that should not be deserialized. All exceptions are fatal to the 283 * InputStream and leave it in an indeterminate state; it is up to the caller 284 * to ignore or recover the stream state. 285 * @exception java.lang.ClassNotFoundException Class of a serialized object 286 * cannot be found. 287 * @exception InvalidClassException Something is wrong with a class used by 288 * serialization. 289 * @exception StreamCorruptedException Control information in the 290 * stream is inconsistent. 291 * @exception OptionalDataException Primitive data was found in the 292 * stream instead of objects. 293 * @exception IOException Any of the usual Input/Output related exceptions. 294 * @since JDK1.1 295 */ 296 public final synchronized Object readObjectDelegate() throws IOException 297 { 298 try { 299 300 readObjectState.readData(this); 301 302 return orbStream.read_abstract_interface(); 303 } catch (MARSHAL marshalException) { 304 handleOptionalDataMarshalException(marshalException, true); 305 throw marshalException; 306 } catch(IndirectionException cdrie) 307 { 308 // The CDR stream had never seen the given offset before, 309 // so check the recursion manager (it will throw an 310 // IOException if it doesn't have a reference, either). 311 return activeRecursionMgr.getObject(cdrie.offset); 312 } 313 } 314 315 final synchronized Object simpleReadObject(Class clz, 316 String repositoryID, 317 com.sun.org.omg.SendingContext.CodeBase sender, 318 int offset) 319 /* throws OptionalDataException, ClassNotFoundException, IOException */ 320 { 321 /* Save the current state and get ready to read an object. */ 322 Object prevObject = currentObject; 323 ObjectStreamClass prevClassDesc = currentClassDesc; 324 Class prevClass = currentClass; 325 byte oldStreamFormatVersion = streamFormatVersion; 326 327 simpleReadDepth++; // Entering 328 Object obj = null; 329 330 /* 331 * Check for reset, handle it before reading an object. 332 */ 333 try { 334 // d4365188: backward compatability 335 if (vhandler.useFullValueDescription(clz, repositoryID)) { 336 obj = inputObjectUsingFVD(clz, repositoryID, sender, offset); 337 } else { 338 obj = inputObject(clz, repositoryID, sender, offset); 339 } 340 341 obj = currentClassDesc.readResolve(obj); 342 } 343 catch(ClassNotFoundException cnfe) 344 { 345 bridge.throwException( cnfe ) ; 346 return null; 347 } 348 catch(IOException ioe) 349 { 350 // System.out.println("CLZ = " + clz + "; " + ioe.toString()); 351 bridge.throwException(ioe) ; 352 return null; 353 } 354 finally { 355 simpleReadDepth --; 356 currentObject = prevObject; 357 currentClassDesc = prevClassDesc; 358 currentClass = prevClass; 359 streamFormatVersion = oldStreamFormatVersion; 360 } 361 362 363 /* Check for thrown exceptions and re-throw them, clearing them if 364 * this is the last recursive call . 365 */ 366 IOException exIOE = abortIOException; 367 if (simpleReadDepth == 0) 368 abortIOException = null; 369 if (exIOE != null){ 370 bridge.throwException( exIOE ) ; 371 return null; 372 } 373 374 375 ClassNotFoundException exCNF = abortClassNotFoundException; 376 if (simpleReadDepth == 0) 377 abortClassNotFoundException = null; 378 if (exCNF != null) { 379 bridge.throwException( exCNF ) ; 380 return null; 381 } 382 383 return obj; 384 } 385 386 public final synchronized void simpleSkipObject(String repositoryID, 387 com.sun.org.omg.SendingContext.CodeBase sender) 388 /* throws OptionalDataException, ClassNotFoundException, IOException */ 389 { 390 391 /* Save the current state and get ready to read an object. */ 392 Object prevObject = currentObject; 393 ObjectStreamClass prevClassDesc = currentClassDesc; 394 Class prevClass = currentClass; 395 byte oldStreamFormatVersion = streamFormatVersion; 396 397 simpleReadDepth++; // Entering 398 Object obj = null; 399 400 /* 401 * Check for reset, handle it before reading an object. 402 */ 403 try { 404 skipObjectUsingFVD(repositoryID, sender); 405 } 406 catch(ClassNotFoundException cnfe) 407 { 408 bridge.throwException( cnfe ) ; 409 return; 410 } 411 catch(IOException ioe) 412 { 413 bridge.throwException( ioe ) ; 414 return; 415 } 416 finally { 417 simpleReadDepth --; 418 streamFormatVersion = oldStreamFormatVersion; 419 currentObject = prevObject; 420 currentClassDesc = prevClassDesc; 421 currentClass = prevClass; 422 } 423 424 425 /* Check for thrown exceptions and re-throw them, clearing them if 426 * this is the last recursive call . 427 */ 428 IOException exIOE = abortIOException; 429 if (simpleReadDepth == 0) 430 abortIOException = null; 431 if (exIOE != null){ 432 bridge.throwException( exIOE ) ; 433 return; 434 } 435 436 437 ClassNotFoundException exCNF = abortClassNotFoundException; 438 if (simpleReadDepth == 0) 439 abortClassNotFoundException = null; 440 if (exCNF != null) { 441 bridge.throwException( exCNF ) ; 442 return; 443 } 444 445 return; 446 } 447 ///////////////// 448 449 /** 450 * This method is called by trusted subclasses of ObjectOutputStream 451 * that constructed ObjectOutputStream using the 452 * protected no-arg constructor. The subclass is expected to provide 453 * an override method with the modifier "final". 454 * 455 * @return the Object read from the stream. 456 * 457 * @see #ObjectInputStream() 458 * @see #readObject 459 * @since JDK 1.2 460 */ 461 protected final Object readObjectOverride() 462 throws OptionalDataException, ClassNotFoundException, IOException 463 { 464 return readObjectDelegate(); 465 } 466 467 /** 468 * Override the actions of the final method "defaultReadObject()" 469 * in ObjectInputStream. 470 * @since JDK1.1.6 471 * 472 * Read the non-static and non-transient fields of the current class 473 * from this stream. This may only be called from the readObject method 474 * of the class being deserialized. It will throw the NotActiveException 475 * if it is called otherwise. 476 * 477 * @exception java.lang.ClassNotFoundException if the class of a serialized 478 * object could not be found. 479 * @exception IOException if an I/O error occurs. 480 * @exception NotActiveException if the stream is not currently reading 481 * objects. 482 * @since JDK1.1 483 */ 484 final synchronized void defaultReadObjectDelegate() 485 /* throws IOException, ClassNotFoundException, NotActiveException */ 486 { 487 try { 488 if (currentObject == null || currentClassDesc == null) 489 // XXX I18N, logging needed. 490 throw new NotActiveException("defaultReadObjectDelegate"); 491 492 if (!currentClassDesc.forClass().isAssignableFrom( 493 currentObject.getClass())) { 494 throw new IOException("Object Type mismatch"); 495 } 496 497 // The array will be null unless fields were retrieved 498 // remotely because of a serializable version difference. 499 // Bug fix for 4365188. See the definition of 500 // defaultReadObjectFVDMembers for more information. 501 if (defaultReadObjectFVDMembers != null && 502 defaultReadObjectFVDMembers.length > 0) { 503 504 // WARNING: Be very careful! What if some of 505 // these fields actually have to do this, too? 506 // This works because the defaultReadObjectFVDMembers 507 // reference is passed to inputClassFields, but 508 // there is no guarantee that 509 // defaultReadObjectFVDMembers will point to the 510 // same array after calling inputClassFields. 511 512 // Use the remote fields to unmarshal. 513 inputClassFields(currentObject, 514 currentClass, 515 currentClassDesc, 516 defaultReadObjectFVDMembers, 517 cbSender); 518 519 } else { 520 521 // Use the local fields to unmarshal. 522 ObjectStreamField[] fields = 523 currentClassDesc.getFieldsNoCopy(); 524 if (fields.length > 0) { 525 inputClassFields(currentObject, currentClass, fields, cbSender); 526 } 527 } 528 } 529 catch(NotActiveException nae) 530 { 531 bridge.throwException( nae ) ; 532 } 533 catch(IOException ioe) 534 { 535 bridge.throwException( ioe ) ; 536 } 537 catch(ClassNotFoundException cnfe) 538 { 539 bridge.throwException( cnfe ) ; 540 } 541 542 } 543 544 /** 545 * Override the actions of the final method "enableResolveObject()" 546 * in ObjectInputStream. 547 * @since JDK1.1.6 548 * 549 * Enable the stream to allow objects read from the stream to be replaced. 550 * If the stream is a trusted class it is allowed to enable replacment. 551 * Trusted classes are those classes with a classLoader equals null. <p> 552 * 553 * When enabled the resolveObject method is called for every object 554 * being deserialized. 555 * 556 * @exception SecurityException The classloader of this stream object is non-null. 557 * @since JDK1.1 558 */ 559 public final boolean enableResolveObjectDelegate(boolean enable) 560 /* throws SecurityException */ 561 { 562 return false; 563 } 564 565 // The following three methods allow the implementing orbStream 566 // to provide mark/reset behavior as defined in java.io.InputStream. 567 568 public final void mark(int readAheadLimit) { 569 orbStream.mark(readAheadLimit); 570 } 571 572 public final boolean markSupported() { 573 return orbStream.markSupported(); 574 } 575 576 public final void reset() throws IOException { 577 try { 578 orbStream.reset(); 579 } catch (Error e) { 580 IOException err = new IOException(e.getMessage()); 581 err.initCause(e) ; 582 throw err ; 583 } 584 } 585 586 public final int available() throws IOException{ 587 return 0; // unreliable 588 } 589 590 public final void close() throws IOException{ 591 // no op 592 } 593 594 public final int read() throws IOException{ 595 try{ 596 readObjectState.readData(this); 597 598 return (orbStream.read_octet() << 0) & 0x000000FF; 599 } catch (MARSHAL marshalException) { 600 if (marshalException.minor 601 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 602 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 603 return -1; 604 } 605 606 throw marshalException; 607 } catch(Error e) { 608 IOException exc = new IOException(e.getMessage()); 609 exc.initCause(e) ; 610 throw exc ; 611 } 612 } 613 614 public final int read(byte data[], int offset, int length) throws IOException{ 615 try{ 616 readObjectState.readData(this); 617 618 orbStream.read_octet_array(data, offset, length); 619 return length; 620 } catch (MARSHAL marshalException) { 621 if (marshalException.minor 622 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 623 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 624 return -1; 625 } 626 627 throw marshalException; 628 } catch(Error e) { 629 IOException exc = new IOException(e.getMessage()); 630 exc.initCause(e) ; 631 throw exc ; 632 } 633 634 } 635 636 public final boolean readBoolean() throws IOException{ 637 try{ 638 readObjectState.readData(this); 639 640 return orbStream.read_boolean(); 641 } catch (MARSHAL marshalException) { 642 handleOptionalDataMarshalException(marshalException, false); 643 throw marshalException; 644 645 } catch(Error e) { 646 IOException exc = new IOException(e.getMessage()); 647 exc.initCause(e); 648 throw exc ; 649 } 650 } 651 652 public final byte readByte() throws IOException{ 653 try{ 654 readObjectState.readData(this); 655 656 return orbStream.read_octet(); 657 } catch (MARSHAL marshalException) { 658 handleOptionalDataMarshalException(marshalException, false); 659 throw marshalException; 660 661 } catch(Error e) { 662 IOException exc = new IOException(e.getMessage()); 663 exc.initCause(e); 664 throw exc ; 665 } 666 } 667 668 public final char readChar() throws IOException{ 669 try{ 670 readObjectState.readData(this); 671 672 return orbStream.read_wchar(); 673 } catch (MARSHAL marshalException) { 674 handleOptionalDataMarshalException(marshalException, false); 675 throw marshalException; 676 677 } catch(Error e) { 678 IOException exc = new IOException(e.getMessage()); 679 exc.initCause(e); 680 throw exc ; 681 } 682 } 683 684 public final double readDouble() throws IOException{ 685 try{ 686 readObjectState.readData(this); 687 688 return orbStream.read_double(); 689 } catch (MARSHAL marshalException) { 690 handleOptionalDataMarshalException(marshalException, false); 691 throw marshalException; 692 } catch(Error e) { 693 IOException exc = new IOException(e.getMessage()); 694 exc.initCause(e); 695 throw exc ; 696 } 697 } 698 699 public final float readFloat() throws IOException{ 700 try{ 701 readObjectState.readData(this); 702 703 return orbStream.read_float(); 704 } catch (MARSHAL marshalException) { 705 handleOptionalDataMarshalException(marshalException, false); 706 throw marshalException; 707 } catch(Error e) { 708 IOException exc = new IOException(e.getMessage()); 709 exc.initCause(e); 710 throw exc ; 711 } 712 } 713 714 public final void readFully(byte data[]) throws IOException{ 715// d11623 : implement readFully, required for serializing some core classes 716 717 readFully(data, 0, data.length); 718 } 719 720 public final void readFully(byte data[], int offset, int size) throws IOException{ 721// d11623 : implement readFully, required for serializing some core classes 722 try{ 723 readObjectState.readData(this); 724 725 orbStream.read_octet_array(data, offset, size); 726 } catch (MARSHAL marshalException) { 727 handleOptionalDataMarshalException(marshalException, false); 728 729 throw marshalException; 730 } catch(Error e) { 731 IOException exc = new IOException(e.getMessage()); 732 exc.initCause(e); 733 throw exc ; 734 } 735 } 736 737 public final int readInt() throws IOException{ 738 try{ 739 readObjectState.readData(this); 740 741 return orbStream.read_long(); 742 } catch (MARSHAL marshalException) { 743 handleOptionalDataMarshalException(marshalException, false); 744 throw marshalException; 745 } catch(Error e) { 746 IOException exc = new IOException(e.getMessage()); 747 exc.initCause(e); 748 throw exc ; 749 } 750 } 751 752 public final String readLine() throws IOException{ 753 // XXX I18N, logging needed. 754 throw new IOException("Method readLine not supported"); 755 } 756 757 public final long readLong() throws IOException{ 758 try{ 759 readObjectState.readData(this); 760 761 return orbStream.read_longlong(); 762 } catch (MARSHAL marshalException) { 763 handleOptionalDataMarshalException(marshalException, false); 764 throw marshalException; 765 } catch(Error e) { 766 IOException exc = new IOException(e.getMessage()); 767 exc.initCause(e); 768 throw exc ; 769 } 770 } 771 772 public final short readShort() throws IOException{ 773 try{ 774 readObjectState.readData(this); 775 776 return orbStream.read_short(); 777 } catch (MARSHAL marshalException) { 778 handleOptionalDataMarshalException(marshalException, false); 779 throw marshalException; 780 } catch(Error e) { 781 IOException exc = new IOException(e.getMessage()); 782 exc.initCause(e); 783 throw exc ; 784 } 785 } 786 787 protected final void readStreamHeader() throws IOException, StreamCorruptedException{ 788 // no op 789 } 790 791 public final int readUnsignedByte() throws IOException{ 792 try{ 793 readObjectState.readData(this); 794 795 return (orbStream.read_octet() << 0) & 0x000000FF; 796 } catch (MARSHAL marshalException) { 797 handleOptionalDataMarshalException(marshalException, false); 798 throw marshalException; 799 } catch(Error e) { 800 IOException exc = new IOException(e.getMessage()); 801 exc.initCause(e); 802 throw exc ; 803 } 804 } 805 806 public final int readUnsignedShort() throws IOException{ 807 try{ 808 readObjectState.readData(this); 809 810 return (orbStream.read_ushort() << 0) & 0x0000FFFF; 811 } catch (MARSHAL marshalException) { 812 handleOptionalDataMarshalException(marshalException, false); 813 throw marshalException; 814 } catch(Error e) { 815 IOException exc = new IOException(e.getMessage()); 816 exc.initCause(e); 817 throw exc ; 818 } 819 } 820 821 /** 822 * Helper method for correcting the Kestrel bug 4367783 (dealing 823 * with larger than 8-bit chars). The old behavior is preserved 824 * in orbutil.IIOPInputStream_1_3 in order to interoperate with 825 * our legacy ORBs. 826 */ 827 protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream) 828 { 829 return stream.read_wstring(); 830 } 831 832 public final String readUTF() throws IOException{ 833 try{ 834 readObjectState.readData(this); 835 836 return internalReadUTF(orbStream); 837 } catch (MARSHAL marshalException) { 838 handleOptionalDataMarshalException(marshalException, false); 839 throw marshalException; 840 } catch(Error e) { 841 IOException exc = new IOException(e.getMessage()); 842 exc.initCause(e); 843 throw exc ; 844 } 845 } 846 847 // If the ORB stream detects an incompatibility between what's 848 // on the wire and what our Serializable's readObject wants, 849 // it throws a MARSHAL exception with a specific minor code. 850 // This is rethrown to the readObject as an OptionalDataException. 851 // So far in RMI-IIOP, this process isn't specific enough to 852 // tell the readObject how much data is available, so we always 853 // set the OptionalDataException's EOF marker to true. 854 private void handleOptionalDataMarshalException(MARSHAL marshalException, 855 boolean objectRead) 856 throws IOException { 857 858 // Java Object Serialization spec 3.4: "If the readObject method 859 // of the class attempts to read more data than is present in the 860 // optional part of the stream for this class, the stream will 861 // return -1 for bytewise reads, throw an EOFException for 862 // primitive data reads, or throw an OptionalDataException 863 // with the eof field set to true for object reads." 864 if (marshalException.minor 865 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 866 867 IOException result; 868 869 if (!objectRead) 870 result = new EOFException("No more optional data"); 871 else 872 result = bridge.newOptionalDataExceptionForSerialization(true); 873 874 result.initCause(marshalException); 875 876 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 877 878 throw result; 879 } 880 } 881 882 public final synchronized void registerValidation(ObjectInputValidation obj, 883 int prio) 884 throws NotActiveException, InvalidObjectException{ 885 // XXX I18N, logging needed. 886 throw new Error("Method registerValidation not supported"); 887 } 888 889 protected final Class resolveClass(ObjectStreamClass v) 890 throws IOException, ClassNotFoundException{ 891 // XXX I18N, logging needed. 892 throw new IOException("Method resolveClass not supported"); 893 } 894 895 protected final Object resolveObject(Object obj) throws IOException{ 896 // XXX I18N, logging needed. 897 throw new IOException("Method resolveObject not supported"); 898 } 899 900 public final int skipBytes(int len) throws IOException{ 901 try{ 902 readObjectState.readData(this); 903 904 byte buf[] = new byte[len]; 905 orbStream.read_octet_array(buf, 0, len); 906 return len; 907 } catch (MARSHAL marshalException) { 908 handleOptionalDataMarshalException(marshalException, false); 909 910 throw marshalException; 911 } catch(Error e) { 912 IOException exc = new IOException(e.getMessage()); 913 exc.initCause(e) ; 914 throw exc ; 915 } 916 } 917 918 private synchronized Object inputObject(Class clz, 919 String repositoryID, 920 com.sun.org.omg.SendingContext.CodeBase sender, 921 int offset) 922 throws IOException, ClassNotFoundException 923 { 924 925 /* 926 * Get the descriptor and then class of the incoming object. 927 */ 928 929 currentClassDesc = ObjectStreamClass.lookup(clz); 930 currentClass = currentClassDesc.forClass(); 931 //currentClassDesc.setClass(currentClass); 932 if (currentClass == null) 933 // XXX I18N, logging needed. 934 throw new ClassNotFoundException(currentClassDesc.getName()); 935 936 try { 937 /* If Externalizable, 938 * Create an instance and tell it to read its data. 939 * else, 940 * Handle it as a serializable class. 941 */ 942 if (Enum.class.isAssignableFrom( clz )) { 943 int ordinal = orbStream.read_long() ; 944 String value = (String)orbStream.read_value( String.class ) ; 945 return Enum.valueOf( clz, value ) ; 946 } else if (currentClassDesc.isExternalizable()) { 947 try { 948 currentObject = (currentClass == null) ? 949 null : currentClassDesc.newInstance(); 950 if (currentObject != null) { 951 952 // Store this object and its beginning position 953 // since there might be indirections to it while 954 // it's been unmarshalled. 955 activeRecursionMgr.addObject(offset, currentObject); 956 957 // Read format version 958 readFormatVersion(); 959 960 Externalizable ext = (Externalizable)currentObject; 961 ext.readExternal(this); 962 } 963 } catch (InvocationTargetException e) { 964 InvalidClassException exc = new InvalidClassException( 965 currentClass.getName(), 966 "InvocationTargetException accessing no-arg constructor"); 967 exc.initCause( e ) ; 968 throw exc ; 969 } catch (UnsupportedOperationException e) { 970 InvalidClassException exc = new InvalidClassException( 971 currentClass.getName(), 972 "UnsupportedOperationException accessing no-arg constructor"); 973 exc.initCause( e ) ; 974 throw exc ; 975 } catch (InstantiationException e) { 976 InvalidClassException exc = new InvalidClassException( 977 currentClass.getName(), 978 "InstantiationException accessing no-arg constructor"); 979 exc.initCause( e ) ; 980 throw exc ; 981 } 982 } // end : if (currentClassDesc.isExternalizable()) 983 else { 984 /* Count number of classes and descriptors we might have 985 * to work on. 986 */ 987 988 ObjectStreamClass currdesc = currentClassDesc; 989 Class currclass = currentClass; 990 991 int spBase = spClass; // current top of stack 992 993 if (currentClass.getName().equals("java.lang.String")) { 994 return this.readUTF(); 995 } 996 /* The object's classes should be processed from supertype to subtype 997 * Push all the clases of the current object onto a stack. 998 * Note that only the serializable classes are represented 999 * in the descriptor list. 1000 * 1001 * Handle versioning where one or more supertypes of 1002 * have been inserted or removed. The stack will 1003 * contain pairs of descriptors and the corresponding 1004 * class. If the object has a class that did not occur in 1005 * the original the descriptor will be null. If the 1006 * original object had a descriptor for a class not 1007 * present in the local hierarchy of the object the class will be 1008 * null. 1009 * 1010 */ 1011 1012 /* 1013 * This is your basic diff pattern, made simpler 1014 * because reordering is not allowed. 1015 */ 1016 // sun.4296963 ibm.11861 1017 // d11861 we should stop when we find the highest serializable class 1018 // We need this so that when we allocate the new object below, we 1019 // can call the constructor of the non-serializable superclass. 1020 // Note that in the JRMP variant of this code the 1021 // ObjectStreamClass.lookup() method handles this, but we've put 1022 // this fix here rather than change lookup because the new behaviour 1023 // is needed in other cases. 1024 1025 for (currdesc = currentClassDesc, currclass = currentClass; 1026 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ 1027 currdesc = currdesc.getSuperclass()) { 1028 1029 /* 1030 * Search the classes to see if the class of this 1031 * descriptor appears further up the hierarchy. Until 1032 * it's found assume its an inserted class. If it's 1033 * not found, its the descriptor's class that has been 1034 * removed. 1035 */ 1036 Class cc = currdesc.forClass(); 1037 Class cl; 1038 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { 1039 if (cc == cl) { 1040 // found a superclass that matches this descriptor 1041 break; 1042 } else { 1043 /* Ignore a class that doesn't match. No 1044 * action is needed since it is already 1045 * initialized. 1046 */ 1047 } 1048 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) 1049 /* Test if there is room for this new entry. 1050 * If not, double the size of the arrays and copy the contents. 1051 */ 1052 spClass++; 1053 if (spClass >= classes.length) { 1054 int newlen = classes.length * 2; 1055 Class[] newclasses = new Class[newlen]; 1056 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; 1057 1058 System.arraycopy(classes, 0, 1059 newclasses, 0, 1060 classes.length); 1061 System.arraycopy(classdesc, 0, 1062 newclassdesc, 0, 1063 classes.length); 1064 1065 classes = newclasses; 1066 classdesc = newclassdesc; 1067 } 1068 1069 if (cl == null) { 1070 /* Class not found corresponding to this descriptor. 1071 * Pop off all the extra classes pushed. 1072 * Push the descriptor and a null class. 1073 */ 1074 classdesc[spClass] = currdesc; 1075 classes[spClass] = null; 1076 } else { 1077 /* Current class descriptor matches current class. 1078 * Some classes may have been inserted. 1079 * Record the match and advance the class, continue 1080 * with the next descriptor. 1081 */ 1082 classdesc[spClass] = currdesc; 1083 classes[spClass] = cl; 1084 currclass = cl.getSuperclass(); 1085 } 1086 } // end : for (currdesc = currentClassDesc, currclass = currentClass; 1087 1088 /* Allocate a new object. The object is only constructed 1089 * above the highest serializable class and is set to 1090 * default values for all more specialized classes. 1091 */ 1092 try { 1093 currentObject = (currentClass == null) ? 1094 null : currentClassDesc.newInstance() ; 1095 1096 // Store this object and its beginning position 1097 // since there might be indirections to it while 1098 // it's been unmarshalled. 1099 activeRecursionMgr.addObject(offset, currentObject); 1100 } catch (InvocationTargetException e) { 1101 InvalidClassException exc = new InvalidClassException( 1102 currentClass.getName(), 1103 "InvocationTargetException accessing no-arg constructor"); 1104 exc.initCause( e ) ; 1105 throw exc ; 1106 } catch (UnsupportedOperationException e) { 1107 InvalidClassException exc = new InvalidClassException( 1108 currentClass.getName(), 1109 "UnsupportedOperationException accessing no-arg constructor"); 1110 exc.initCause( e ) ; 1111 throw exc ; 1112 } catch (InstantiationException e) { 1113 InvalidClassException exc = new InvalidClassException( 1114 currentClass.getName(), 1115 "InstantiationException accessing no-arg constructor"); 1116 exc.initCause( e ) ; 1117 throw exc ; 1118 } 1119 1120 /* 1121 * For all the pushed descriptors and classes. 1122 * if the class has its own writeObject and readObject methods 1123 * call the readObject method 1124 * else 1125 * invoke the defaultReadObject method 1126 */ 1127 try { 1128 for (spClass = spClass; spClass > spBase; spClass--) { 1129 /* 1130 * Set current descriptor and corresponding class 1131 */ 1132 currentClassDesc = classdesc[spClass]; 1133 currentClass = classes[spClass]; 1134 if (classes[spClass] != null) { 1135 /* Read the data from the stream described by the 1136 * descriptor and store into the matching class. 1137 */ 1138 1139 ReadObjectState oldState = readObjectState; 1140 setState(DEFAULT_STATE); 1141 1142 try { 1143 1144 // Changed since invokeObjectReader no longer does this. 1145 if (currentClassDesc.hasWriteObject()) { 1146 1147 // Read format version 1148 readFormatVersion(); 1149 1150 // Read defaultWriteObject indicator 1151 boolean calledDefaultWriteObject = readBoolean(); 1152 1153 readObjectState.beginUnmarshalCustomValue(this, 1154 calledDefaultWriteObject, 1155 currentClassDesc.hasReadObject()); 1156 } else { 1157 if (currentClassDesc.hasReadObject()) 1158 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); 1159 } 1160 1161 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) || 1162 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) { 1163 1164 // Error case of no readObject and didn't call 1165 // defaultWriteObject handled in default state 1166 1167 ObjectStreamField[] fields = 1168 currentClassDesc.getFieldsNoCopy(); 1169 if (fields.length > 0) { 1170 inputClassFields(currentObject, currentClass, fields, sender); 1171 } 1172 } 1173 1174 if (currentClassDesc.hasWriteObject()) 1175 readObjectState.endUnmarshalCustomValue(this); 1176 1177 } finally { 1178 setState(oldState); 1179 } 1180 1181 } else { 1182 1183 // _REVISIT_ : Can we ever get here? 1184 /* No local class for this descriptor, 1185 * Skip over the data for this class. 1186 * like defaultReadObject with a null currentObject. 1187 * The code will read the values but discard them. 1188 */ 1189 ObjectStreamField[] fields = 1190 currentClassDesc.getFieldsNoCopy(); 1191 if (fields.length > 0) { 1192 inputClassFields(null, currentClass, fields, sender); 1193 } 1194 1195 } 1196 1197 } 1198 } finally { 1199 // Make sure we exit at the same stack level as when we started. 1200 spClass = spBase; 1201 } 1202 } 1203 } finally { 1204 // We've completed deserializing this object. Any 1205 // future indirections will be handled correctly at the 1206 // CDR level. The ActiveRecursionManager only deals with 1207 // objects currently being deserialized. 1208 activeRecursionMgr.removeObject(offset); 1209 } 1210 1211 return currentObject; 1212 } 1213 1214 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from 1215 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable 1216 // classes! 1217 private Vector getOrderedDescriptions(String repositoryID, 1218 com.sun.org.omg.SendingContext.CodeBase sender) { 1219 Vector descs = new Vector(); 1220 1221 if (sender == null) { 1222 return descs; 1223 } 1224 1225 FullValueDescription aFVD = sender.meta(repositoryID); 1226 while (aFVD != null) { 1227 descs.insertElementAt(aFVD, 0); 1228 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) { 1229 aFVD = sender.meta(aFVD.base_value); 1230 } 1231 else return descs; 1232 } 1233 1234 return descs; 1235 } 1236 1237 /** 1238 * This input method uses FullValueDescriptions retrieved from the sender's runtime to 1239 * read in the data. This method is capable of throwing out data not applicable to client's fields. 1240 * This method handles instances where the reader has a class not sent by the sender, the sender sent 1241 * a class not present on the reader, and/or the reader's class does not match the sender's class. 1242 * 1243 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also 1244 * indicates custom marsahling than the local type is used to read the data off the wire. However, 1245 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is 1246 * a form of custom marshaling. 1247 * 1248 */ 1249 private synchronized Object inputObjectUsingFVD(Class clz, 1250 String repositoryID, 1251 com.sun.org.omg.SendingContext.CodeBase sender, 1252 int offset) 1253 throws IOException, ClassNotFoundException 1254 { 1255 int spBase = spClass; // current top of stack 1256 try{ 1257 1258 /* 1259 * Get the descriptor and then class of the incoming object. 1260 */ 1261 1262 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz); 1263 Class currclass = currentClass = clz; 1264 1265 /* If Externalizable, 1266 * Create an instance and tell it to read its data. 1267 * else, 1268 * Handle it as a serializable class. 1269 */ 1270 if (currentClassDesc.isExternalizable()) { 1271 try { 1272 currentObject = (currentClass == null) ? 1273 null : currentClassDesc.newInstance(); 1274 if (currentObject != null) { 1275 // Store this object and its beginning position 1276 // since there might be indirections to it while 1277 // it's been unmarshalled. 1278 activeRecursionMgr.addObject(offset, currentObject); 1279 1280 // Read format version 1281 readFormatVersion(); 1282 1283 Externalizable ext = (Externalizable)currentObject; 1284 ext.readExternal(this); 1285 } 1286 } catch (InvocationTargetException e) { 1287 InvalidClassException exc = new InvalidClassException( 1288 currentClass.getName(), 1289 "InvocationTargetException accessing no-arg constructor"); 1290 exc.initCause( e ) ; 1291 throw exc ; 1292 } catch (UnsupportedOperationException e) { 1293 InvalidClassException exc = new InvalidClassException( 1294 currentClass.getName(), 1295 "UnsupportedOperationException accessing no-arg constructor"); 1296 exc.initCause( e ) ; 1297 throw exc ; 1298 } catch (InstantiationException e) { 1299 InvalidClassException exc = new InvalidClassException( 1300 currentClass.getName(), 1301 "InstantiationException accessing no-arg constructor"); 1302 exc.initCause( e ) ; 1303 throw exc ; 1304 } 1305 } else { 1306 /* 1307 * This is your basic diff pattern, made simpler 1308 * because reordering is not allowed. 1309 */ 1310 for (currdesc = currentClassDesc, currclass = currentClass; 1311 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ 1312 1313 currdesc = currdesc.getSuperclass()) { 1314 1315 /* 1316 * Search the classes to see if the class of this 1317 * descriptor appears further up the hierarchy. Until 1318 * it's found assume its an inserted class. If it's 1319 * not found, its the descriptor's class that has been 1320 * removed. 1321 */ 1322 Class cc = currdesc.forClass(); 1323 Class cl; 1324 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { 1325 if (cc == cl) { 1326 // found a superclass that matches this descriptor 1327 break; 1328 } else { 1329 /* Ignore a class that doesn't match. No 1330 * action is needed since it is already 1331 * initialized. 1332 */ 1333 } 1334 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) 1335 /* Test if there is room for this new entry. 1336 * If not, double the size of the arrays and copy the contents. 1337 */ 1338 spClass++; 1339 if (spClass >= classes.length) { 1340 int newlen = classes.length * 2; 1341 Class[] newclasses = new Class[newlen]; 1342 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; 1343 1344 System.arraycopy(classes, 0, 1345 newclasses, 0, 1346 classes.length); 1347 System.arraycopy(classdesc, 0, 1348 newclassdesc, 0, 1349 classes.length); 1350 1351 classes = newclasses; 1352 classdesc = newclassdesc; 1353 } 1354 1355 if (cl == null) { 1356 /* Class not found corresponding to this descriptor. 1357 * Pop off all the extra classes pushed. 1358 * Push the descriptor and a null class. 1359 */ 1360 classdesc[spClass] = currdesc; 1361 classes[spClass] = null; 1362 } else { 1363 /* Current class descriptor matches current class. 1364 * Some classes may have been inserted. 1365 * Record the match and advance the class, continue 1366 * with the next descriptor. 1367 */ 1368 classdesc[spClass] = currdesc; 1369 classes[spClass] = cl; 1370 currclass = cl.getSuperclass(); 1371 } 1372 } // end : for (currdesc = currentClassDesc, currclass = currentClass; 1373 1374 /* Allocate a new object. 1375 */ 1376 try { 1377 currentObject = (currentClass == null) ? 1378 null : currentClassDesc.newInstance(); 1379 1380 // Store this object and its beginning position 1381 // since there might be indirections to it while 1382 // it's been unmarshalled. 1383 activeRecursionMgr.addObject(offset, currentObject); 1384 } catch (InvocationTargetException e) { 1385 InvalidClassException exc = new InvalidClassException( 1386 currentClass.getName(), 1387 "InvocationTargetException accessing no-arg constructor"); 1388 exc.initCause( e ) ; 1389 throw exc ; 1390 } catch (UnsupportedOperationException e) { 1391 InvalidClassException exc = new InvalidClassException( 1392 currentClass.getName(), 1393 "UnsupportedOperationException accessing no-arg constructor"); 1394 exc.initCause( e ) ; 1395 throw exc ; 1396 } catch (InstantiationException e) { 1397 InvalidClassException exc = new InvalidClassException( 1398 currentClass.getName(), 1399 "InstantiationException accessing no-arg constructor"); 1400 exc.initCause( e ) ; 1401 throw exc ; 1402 } 1403 1404 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); 1405 1406 while((fvdsList.hasMoreElements()) && (spClass > spBase)) { 1407 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1408 // d4365188: backward compatability 1409 String repIDForFVD = vhandler.getClassName(fvd.id); 1410 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); 1411 1412 while ((spClass > spBase) && 1413 (!repIDForFVD.equals(repIDForClass))) { 1414 int pos = findNextClass(repIDForFVD, classes, spClass, spBase); 1415 if (pos != -1) { 1416 spClass = pos; 1417 currclass = currentClass = classes[spClass]; 1418 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); 1419 } 1420 else { // Read and throw away one level of the fvdslist 1421 1422 // This seems to mean that the sender had a superclass that 1423 // we don't have 1424 1425 if (fvd.is_custom) { 1426 1427 readFormatVersion(); 1428 boolean calledDefaultWriteObject = readBoolean(); 1429 1430 if (calledDefaultWriteObject) 1431 inputClassFields(null, null, null, fvd.members, sender); 1432 1433 if (getStreamFormatVersion() == 2) { 1434 1435 ((ValueInputStream)getOrbStream()).start_value(); 1436 ((ValueInputStream)getOrbStream()).end_value(); 1437 } 1438 1439 // WARNING: If stream format version is 1 and there's 1440 // optional data, we'll get some form of exception down 1441 // the line or data corruption. 1442 1443 } else { 1444 1445 inputClassFields(null, currentClass, null, fvd.members, sender); 1446 } 1447 1448 if (fvdsList.hasMoreElements()){ 1449 fvd = (FullValueDescription)fvdsList.nextElement(); 1450 repIDForFVD = vhandler.getClassName(fvd.id); 1451 } 1452 else return currentObject; 1453 } 1454 } 1455 1456 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass); 1457 1458 if (!repIDForClass.equals("java.lang.Object")) { 1459 1460 // If the sender used custom marshaling, then it should have put 1461 // the two bytes on the wire indicating stream format version 1462 // and whether or not the writeObject method called 1463 // defaultWriteObject/writeFields. 1464 1465 ReadObjectState oldState = readObjectState; 1466 setState(DEFAULT_STATE); 1467 1468 try { 1469 1470 if (fvd.is_custom) { 1471 1472 // Read format version 1473 readFormatVersion(); 1474 1475 // Read defaultWriteObject indicator 1476 boolean calledDefaultWriteObject = readBoolean(); 1477 1478 readObjectState.beginUnmarshalCustomValue(this, 1479 calledDefaultWriteObject, 1480 currentClassDesc.hasReadObject()); 1481 } 1482 1483 boolean usedReadObject = false; 1484 1485 // Always use readObject if it exists, and fall back to default 1486 // unmarshaling if it doesn't. 1487 try { 1488 1489 if (!fvd.is_custom && currentClassDesc.hasReadObject()) 1490 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); 1491 1492 // See the definition of defaultReadObjectFVDMembers 1493 // for more information. This concerns making sure 1494 // we use the remote FVD's members in defaultReadObject. 1495 defaultReadObjectFVDMembers = fvd.members; 1496 usedReadObject = invokeObjectReader(currentClassDesc, 1497 currentObject, 1498 currentClass); 1499 1500 } finally { 1501 defaultReadObjectFVDMembers = null; 1502 } 1503 1504 // Note that the !usedReadObject !calledDefaultWriteObject 1505 // case is handled by the beginUnmarshalCustomValue method 1506 // of the default state 1507 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) 1508 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender); 1509 1510 if (fvd.is_custom) 1511 readObjectState.endUnmarshalCustomValue(this); 1512 1513 } finally { 1514 setState(oldState); 1515 } 1516 1517 currclass = currentClass = classes[--spClass]; 1518 1519 } else { 1520 1521 // The remaining hierarchy of the local class does not match the sender's FVD. 1522 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate 1523 // custom marshaling, throw MARSHAL error. 1524 inputClassFields(null, currentClass, null, fvd.members, sender); 1525 1526 while (fvdsList.hasMoreElements()){ 1527 fvd = (FullValueDescription)fvdsList.nextElement(); 1528 1529 if (fvd.is_custom) 1530 skipCustomUsingFVD(fvd.members, sender); 1531 else 1532 inputClassFields(null, currentClass, null, fvd.members, sender); 1533 } 1534 1535 } 1536 1537 } // end : while(fvdsList.hasMoreElements()) 1538 while (fvdsList.hasMoreElements()){ 1539 1540 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1541 if (fvd.is_custom) 1542 skipCustomUsingFVD(fvd.members, sender); 1543 else 1544 throwAwayData(fvd.members, sender); 1545 } 1546 } 1547 1548 return currentObject; 1549 } 1550 finally { 1551 // Make sure we exit at the same stack level as when we started. 1552 spClass = spBase; 1553 1554 // We've completed deserializing this object. Any 1555 // future indirections will be handled correctly at the 1556 // CDR level. The ActiveRecursionManager only deals with 1557 // objects currently being deserialized. 1558 activeRecursionMgr.removeObject(offset); 1559 } 1560 1561 } 1562 1563 /** 1564 * This input method uses FullValueDescriptions retrieved from the sender's runtime to 1565 * read in the data. This method is capable of throwing out data not applicable to client's fields. 1566 * 1567 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also 1568 * indicates custom marsahling than the local type is used to read the data off the wire. However, 1569 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is 1570 * a form of custom marshaling. 1571 * 1572 */ 1573 private Object skipObjectUsingFVD(String repositoryID, 1574 com.sun.org.omg.SendingContext.CodeBase sender) 1575 throws IOException, ClassNotFoundException 1576 { 1577 1578 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); 1579 1580 while(fvdsList.hasMoreElements()) { 1581 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1582 String repIDForFVD = vhandler.getClassName(fvd.id); 1583 1584 if (!repIDForFVD.equals("java.lang.Object")) { 1585 if (fvd.is_custom) { 1586 1587 readFormatVersion(); 1588 1589 boolean calledDefaultWriteObject = readBoolean(); 1590 1591 if (calledDefaultWriteObject) 1592 inputClassFields(null, null, null, fvd.members, sender); 1593 1594 if (getStreamFormatVersion() == 2) { 1595 1596 ((ValueInputStream)getOrbStream()).start_value(); 1597 ((ValueInputStream)getOrbStream()).end_value(); 1598 } 1599 1600 // WARNING: If stream format version is 1 and there's 1601 // optional data, we'll get some form of exception down 1602 // the line. 1603 1604 } else { 1605 // Use default marshaling 1606 inputClassFields(null, null, null, fvd.members, sender); 1607 } 1608 } 1609 1610 } // end : while(fvdsList.hasMoreElements()) 1611 return null; 1612 1613 } 1614 1615 /////////////////// 1616 1617 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){ 1618 1619 for (int i = _spClass; i > _spBase; i--){ 1620 if (classname.equals(classes[i].getName())) { 1621 return i; 1622 } 1623 } 1624 1625 return -1; 1626 } 1627 1628 /* 1629 * Invoke the readObject method if present. Assumes that in the case of custom 1630 * marshaling, the format version and defaultWriteObject indicator were already 1631 * removed. 1632 */ 1633 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass) 1634 throws InvalidClassException, StreamCorruptedException, 1635 ClassNotFoundException, IOException 1636 { 1637 try { 1638 return osc.invokeReadObject( obj, this ) ; 1639 } catch (InvocationTargetException e) { 1640 Throwable t = e.getTargetException(); 1641 if (t instanceof ClassNotFoundException) 1642 throw (ClassNotFoundException)t; 1643 else if (t instanceof IOException) 1644 throw (IOException)t; 1645 else if (t instanceof RuntimeException) 1646 throw (RuntimeException) t; 1647 else if (t instanceof Error) 1648 throw (Error) t; 1649 else 1650 // XXX I18N, logging needed. 1651 throw new Error("internal error"); 1652 } 1653 } 1654 1655 /* 1656 * Reset the stream to be just like it was after the constructor. 1657 */ 1658 private void resetStream() throws IOException { 1659 1660 if (classes == null) 1661 classes = new Class[20]; 1662 else { 1663 for (int i = 0; i < classes.length; i++) 1664 classes[i] = null; 1665 } 1666 if (classdesc == null) 1667 classdesc = new ObjectStreamClass[20]; 1668 else { 1669 for (int i = 0; i < classdesc.length; i++) 1670 classdesc[i] = null; 1671 } 1672 spClass = 0; 1673 1674 if (callbacks != null) 1675 callbacks.setSize(0); // discard any pending callbacks 1676 } 1677 1678 /** 1679 * Factored out of inputClassFields This reads a primitive value and sets it 1680 * in the field of o described by the ObjectStreamField field. 1681 * 1682 * Note that reflection cannot be used here, because reflection cannot be used 1683 * to set final fields. 1684 */ 1685 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field) 1686 throws InvalidClassException, IOException { 1687 1688 try { 1689 switch (field.getTypeCode()) { 1690 case 'B': 1691 byte byteValue = orbStream.read_octet(); 1692 if (field.getField() != null) { 1693 bridge.putByte( o, field.getFieldID(), byteValue ) ; 1694 //reflective code: field.getField().setByte( o, byteValue ) ; 1695 } 1696 break; 1697 case 'Z': 1698 boolean booleanValue = orbStream.read_boolean(); 1699 if (field.getField() != null) { 1700 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ; 1701 //reflective code: field.getField().setBoolean( o, booleanValue ) ; 1702 } 1703 break; 1704 case 'C': 1705 char charValue = orbStream.read_wchar(); 1706 if (field.getField() != null) { 1707 bridge.putChar( o, field.getFieldID(), charValue ) ; 1708 //reflective code: field.getField().setChar( o, charValue ) ; 1709 } 1710 break; 1711 case 'S': 1712 short shortValue = orbStream.read_short(); 1713 if (field.getField() != null) { 1714 bridge.putShort( o, field.getFieldID(), shortValue ) ; 1715 //reflective code: field.getField().setShort( o, shortValue ) ; 1716 } 1717 break; 1718 case 'I': 1719 int intValue = orbStream.read_long(); 1720 if (field.getField() != null) { 1721 bridge.putInt( o, field.getFieldID(), intValue ) ; 1722 //reflective code: field.getField().setInt( o, intValue ) ; 1723 } 1724 break; 1725 case 'J': 1726 long longValue = orbStream.read_longlong(); 1727 if (field.getField() != null) { 1728 bridge.putLong( o, field.getFieldID(), longValue ) ; 1729 //reflective code: field.getField().setLong( o, longValue ) ; 1730 } 1731 break; 1732 case 'F' : 1733 float floatValue = orbStream.read_float(); 1734 if (field.getField() != null) { 1735 bridge.putFloat( o, field.getFieldID(), floatValue ) ; 1736 //reflective code: field.getField().setFloat( o, floatValue ) ; 1737 } 1738 break; 1739 case 'D' : 1740 double doubleValue = orbStream.read_double(); 1741 if (field.getField() != null) { 1742 bridge.putDouble( o, field.getFieldID(), doubleValue ) ; 1743 //reflective code: field.getField().setDouble( o, doubleValue ) ; 1744 } 1745 break; 1746 default: 1747 // XXX I18N, logging needed. 1748 throw new InvalidClassException(cl.getName()); 1749 } 1750 } catch (IllegalArgumentException e) { 1751 /* This case should never happen. If the field types 1752 are not the same, InvalidClassException is raised when 1753 matching the local class to the serialized ObjectStreamClass. */ 1754 ClassCastException cce = new ClassCastException("Assigning instance of class " + 1755 field.getType().getName() + 1756 " to field " + 1757 currentClassDesc.getName() + '#' + 1758 field.getField().getName()); 1759 cce.initCause( e ) ; 1760 throw cce ; 1761 } 1762 } 1763 1764 private Object inputObjectField(org.omg.CORBA.ValueMember field, 1765 com.sun.org.omg.SendingContext.CodeBase sender) 1766 throws IndirectionException, ClassNotFoundException, IOException, 1767 StreamCorruptedException { 1768 1769 Object objectValue = null; 1770 Class type = null; 1771 String id = field.id; 1772 1773 try { 1774 type = vhandler.getClassFromType(id); 1775 } catch(ClassNotFoundException cnfe) { 1776 // Make sure type = null 1777 type = null; 1778 } 1779 1780 String signature = null; 1781 if (type != null) 1782 signature = ValueUtility.getSignature(field); 1783 1784 if (signature != null && (signature.equals("Ljava/lang/Object;") || 1785 signature.equals("Ljava/io/Serializable;") || 1786 signature.equals("Ljava/io/Externalizable;"))) { 1787 objectValue = javax.rmi.CORBA.Util.readAny(orbStream); 1788 } else { 1789 // Decide what method call to make based on the type. If 1790 // it is a type for which we need to load a stub, convert 1791 // the type to the correct stub type. 1792 // 1793 // NOTE : Since FullValueDescription does not allow us 1794 // to ask whether something is an interface we do not 1795 // have the ability to optimize this check. 1796 1797 int callType = ValueHandlerImpl.kValueType; 1798 1799 if (!vhandler.isSequence(id)) { 1800 1801 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) { 1802 1803 // RMI Object reference... 1804 callType = ValueHandlerImpl.kRemoteType; 1805 1806 } else { 1807 1808 // REVISIT. If we don't have the local class, 1809 // we should probably verify that it's an RMI type, 1810 // query the remote FVD, and use is_abstract. 1811 // Our FVD seems to get NullPointerExceptions for any 1812 // non-RMI types. 1813 1814 // This uses the local class in the same way as 1815 // inputObjectField(ObjectStreamField) does. REVISIT 1816 // inputObjectField(ObjectStreamField)'s loadStubClass 1817 // logic. Assumption is that the given type cannot 1818 // evolve to become a CORBA abstract interface or 1819 // a RMI abstract interface. 1820 1821 if (type != null && type.isInterface() && 1822 (vhandler.isAbstractBase(type) || 1823 ObjectStreamClassCorbaExt.isAbstractInterface(type))) { 1824 1825 callType = ValueHandlerImpl.kAbstractType; 1826 } 1827 } 1828 } 1829 1830 // Now that we have used the FVD of the field to determine the proper course 1831 // of action, it is ok to use the type (Class) from this point forward since 1832 // the rep. id for this read will also follow on the wire. 1833 1834 switch (callType) { 1835 case ValueHandlerImpl.kRemoteType: 1836 if (type != null) 1837 objectValue = Utility.readObjectAndNarrow(orbStream, type); 1838 else 1839 objectValue = orbStream.read_Object(); 1840 break; 1841 case ValueHandlerImpl.kAbstractType: 1842 if (type != null) 1843 objectValue = Utility.readAbstractAndNarrow(orbStream, type); 1844 else 1845 objectValue = orbStream.read_abstract_interface(); 1846 break; 1847 case ValueHandlerImpl.kValueType: 1848 if (type != null) 1849 objectValue = orbStream.read_value(type); 1850 else 1851 objectValue = orbStream.read_value(); 1852 break; 1853 default: 1854 // XXX I18N, logging needed. 1855 throw new StreamCorruptedException("Unknown callType: " + callType); 1856 } 1857 } 1858 1859 return objectValue; 1860 } 1861 1862 /** 1863 * Factored out of inputClassFields and reused in 1864 * inputCurrentClassFieldsForReadFields. 1865 * 1866 * Reads the field (which of an Object type as opposed to a primitive) 1867 * described by ObjectStreamField field and returns it. 1868 */ 1869 private Object inputObjectField(ObjectStreamField field) 1870 throws InvalidClassException, StreamCorruptedException, 1871 ClassNotFoundException, IndirectionException, IOException { 1872 1873 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) { 1874 return javax.rmi.CORBA.Util.readAny(orbStream); 1875 } 1876 1877 Object objectValue = null; 1878 1879 // fields have an API to provide the actual class 1880 // corresponding to the data type 1881 // Class type = osc.forClass(); 1882 Class fieldType = field.getType(); 1883 Class actualType = fieldType; // This may change if stub loaded. 1884 1885 // Decide what method call to make based on the fieldType. If 1886 // it is a type for which we need to load a stub, convert 1887 // the type to the correct stub type. 1888 1889 int callType = ValueHandlerImpl.kValueType; 1890 boolean narrow = false; 1891 1892 if (fieldType.isInterface()) { 1893 boolean loadStubClass = false; 1894 1895 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) { 1896 1897 // RMI Object reference... 1898 callType = ValueHandlerImpl.kRemoteType; 1899 1900 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){ 1901 1902 // IDL Object reference... 1903 callType = ValueHandlerImpl.kRemoteType; 1904 loadStubClass = true; 1905 1906 } else if (vhandler.isAbstractBase(fieldType)) { 1907 // IDL Abstract Object reference... 1908 1909 callType = ValueHandlerImpl.kAbstractType; 1910 loadStubClass = true; 1911 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) { 1912 // RMI Abstract Object reference... 1913 1914 callType = ValueHandlerImpl.kAbstractType; 1915 } 1916 1917 if (loadStubClass) { 1918 try { 1919 String codebase = Util.getCodebase(fieldType); 1920 String repID = vhandler.createForAnyType(fieldType); 1921 Class stubType = 1922 Utility.loadStubClass(repID, codebase, fieldType); 1923 actualType = stubType; 1924 } catch (ClassNotFoundException e) { 1925 narrow = true; 1926 } 1927 } else { 1928 narrow = true; 1929 } 1930 } 1931 1932 switch (callType) { 1933 case ValueHandlerImpl.kRemoteType: 1934 if (!narrow) 1935 objectValue = (Object)orbStream.read_Object(actualType); 1936 else 1937 objectValue = Utility.readObjectAndNarrow(orbStream, actualType); 1938 break; 1939 case ValueHandlerImpl.kAbstractType: 1940 if (!narrow) 1941 objectValue = (Object)orbStream.read_abstract_interface(actualType); 1942 else 1943 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType); 1944 break; 1945 case ValueHandlerImpl.kValueType: 1946 objectValue = (Object)orbStream.read_value(actualType); 1947 break; 1948 default: 1949 // XXX I18N, logging needed. 1950 throw new StreamCorruptedException("Unknown callType: " + callType); 1951 } 1952 1953 return objectValue; 1954 } 1955 1956 private final boolean mustUseRemoteValueMembers() { 1957 return defaultReadObjectFVDMembers != null; 1958 } 1959 1960 void readFields(java.util.Map fieldToValueMap) 1961 throws InvalidClassException, StreamCorruptedException, 1962 ClassNotFoundException, IOException { 1963 1964 if (mustUseRemoteValueMembers()) { 1965 inputRemoteMembersForReadFields(fieldToValueMap); 1966 } else 1967 inputCurrentClassFieldsForReadFields(fieldToValueMap); 1968 } 1969 1970 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap) 1971 throws InvalidClassException, StreamCorruptedException, 1972 ClassNotFoundException, IOException { 1973 1974 // Must have this local variable since defaultReadObjectFVDMembers 1975 // may get mangled by recursion. 1976 ValueMember fields[] = defaultReadObjectFVDMembers; 1977 1978 try { 1979 1980 for (int i = 0; i < fields.length; i++) { 1981 1982 switch (fields[i].type.kind().value()) { 1983 1984 case TCKind._tk_octet: 1985 byte byteValue = orbStream.read_octet(); 1986 fieldToValueMap.put(fields[i].name, new Byte(byteValue)); 1987 break; 1988 case TCKind._tk_boolean: 1989 boolean booleanValue = orbStream.read_boolean(); 1990 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue)); 1991 break; 1992 case TCKind._tk_char: 1993 // Backwards compatibility. Older Sun ORBs sent 1994 // _tk_char even though they read and wrote wchars 1995 // correctly. 1996 // 1997 // Fall through to the _tk_wchar case. 1998 case TCKind._tk_wchar: 1999 char charValue = orbStream.read_wchar(); 2000 fieldToValueMap.put(fields[i].name, new Character(charValue)); 2001 break; 2002 case TCKind._tk_short: 2003 short shortValue = orbStream.read_short(); 2004 fieldToValueMap.put(fields[i].name, new Short(shortValue)); 2005 break; 2006 case TCKind._tk_long: 2007 int intValue = orbStream.read_long(); 2008 fieldToValueMap.put(fields[i].name, new Integer(intValue)); 2009 break; 2010 case TCKind._tk_longlong: 2011 long longValue = orbStream.read_longlong(); 2012 fieldToValueMap.put(fields[i].name, new Long(longValue)); 2013 break; 2014 case TCKind._tk_float: 2015 float floatValue = orbStream.read_float(); 2016 fieldToValueMap.put(fields[i].name, new Float(floatValue)); 2017 break; 2018 case TCKind._tk_double: 2019 double doubleValue = orbStream.read_double(); 2020 fieldToValueMap.put(fields[i].name, new Double(doubleValue)); 2021 break; 2022 case TCKind._tk_value: 2023 case TCKind._tk_objref: 2024 case TCKind._tk_value_box: 2025 Object objectValue = null; 2026 try { 2027 objectValue = inputObjectField(fields[i], 2028 cbSender); 2029 2030 } catch (IndirectionException cdrie) { 2031 // The CDR stream had never seen the given offset before, 2032 // so check the recursion manager (it will throw an 2033 // IOException if it doesn't have a reference, either). 2034 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2035 } 2036 2037 fieldToValueMap.put(fields[i].name, objectValue); 2038 break; 2039 default: 2040 // XXX I18N, logging needed. 2041 throw new StreamCorruptedException("Unknown kind: " 2042 + fields[i].type.kind().value()); 2043 } 2044 } 2045 } catch (Throwable t) { 2046 StreamCorruptedException result = new StreamCorruptedException(t.getMessage()); 2047 result.initCause(t); 2048 throw result; 2049 } 2050 } 2051 2052 /** 2053 * Called from InputStreamHook. 2054 * 2055 * Reads the fields of the current class (could be the ones 2056 * queried from the remote FVD) and puts them in 2057 * the given Map, name to value. Wraps primitives in the 2058 * corresponding java.lang Objects. 2059 */ 2060 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap) 2061 throws InvalidClassException, StreamCorruptedException, 2062 ClassNotFoundException, IOException { 2063 2064 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy(); 2065 2066 int primFields = fields.length - currentClassDesc.objFields; 2067 2068 // Handle the primitives first 2069 for (int i = 0; i < primFields; ++i) { 2070 2071 switch (fields[i].getTypeCode()) { 2072 case 'B': 2073 byte byteValue = orbStream.read_octet(); 2074 fieldToValueMap.put(fields[i].getName(), 2075 new Byte(byteValue)); 2076 break; 2077 case 'Z': 2078 boolean booleanValue = orbStream.read_boolean(); 2079 fieldToValueMap.put(fields[i].getName(), 2080 new Boolean(booleanValue)); 2081 break; 2082 case 'C': 2083 char charValue = orbStream.read_wchar(); 2084 fieldToValueMap.put(fields[i].getName(), 2085 new Character(charValue)); 2086 break; 2087 case 'S': 2088 short shortValue = orbStream.read_short(); 2089 fieldToValueMap.put(fields[i].getName(), 2090 new Short(shortValue)); 2091 break; 2092 case 'I': 2093 int intValue = orbStream.read_long(); 2094 fieldToValueMap.put(fields[i].getName(), 2095 new Integer(intValue)); 2096 break; 2097 case 'J': 2098 long longValue = orbStream.read_longlong(); 2099 fieldToValueMap.put(fields[i].getName(), 2100 new Long(longValue)); 2101 break; 2102 case 'F' : 2103 float floatValue = orbStream.read_float(); 2104 fieldToValueMap.put(fields[i].getName(), 2105 new Float(floatValue)); 2106 break; 2107 case 'D' : 2108 double doubleValue = orbStream.read_double(); 2109 fieldToValueMap.put(fields[i].getName(), 2110 new Double(doubleValue)); 2111 break; 2112 default: 2113 // XXX I18N, logging needed. 2114 throw new InvalidClassException(currentClassDesc.getName()); 2115 } 2116 } 2117 2118 /* Read and set object fields from the input stream. */ 2119 if (currentClassDesc.objFields > 0) { 2120 for (int i = primFields; i < fields.length; i++) { 2121 Object objectValue = null; 2122 try { 2123 objectValue = inputObjectField(fields[i]); 2124 } catch(IndirectionException cdrie) { 2125 // The CDR stream had never seen the given offset before, 2126 // so check the recursion manager (it will throw an 2127 // IOException if it doesn't have a reference, either). 2128 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2129 } 2130 2131 fieldToValueMap.put(fields[i].getName(), objectValue); 2132 } 2133 } 2134 } 2135 2136 /* 2137 * Read the fields of the specified class from the input stream and set 2138 * the values of the fields in the specified object. If the specified 2139 * object is null, just consume the fields without setting any values. If 2140 * any ObjectStreamField does not have a reflected Field, don't try to set 2141 * that field in the object. 2142 * 2143 * REVISIT -- This code doesn't do what the comment says to when 2144 * getField() is null! 2145 */ 2146 private void inputClassFields(Object o, Class<?> cl, 2147 ObjectStreamField[] fields, 2148 com.sun.org.omg.SendingContext.CodeBase sender) 2149 throws InvalidClassException, StreamCorruptedException, 2150 ClassNotFoundException, IOException 2151 { 2152 2153 int primFields = fields.length - currentClassDesc.objFields; 2154 2155 // this will leave primitives in the inputstream 2156 // should really consume and discard where necessary 2157 if (o != null) { 2158 for (int i = 0; i < primFields; ++i) { 2159 inputPrimitiveField(o, cl, fields[i]); 2160 } 2161 } 2162 2163 /* Read and set object fields from the input stream. */ 2164 if (currentClassDesc.objFields > 0) { 2165 for (int i = primFields; i < fields.length; i++) { 2166 Object objectValue = null; 2167 2168 try { 2169 objectValue = inputObjectField(fields[i]); 2170 } catch(IndirectionException cdrie) { 2171 // The CDR stream had never seen the given offset before, 2172 // so check the recursion manager (it will throw an 2173 // IOException if it doesn't have a reference, either). 2174 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2175 } 2176 2177 if ((o == null) || (fields[i].getField() == null)) { 2178 continue; 2179 } 2180 2181 try { 2182 Class<?> fieldCl = fields[i].getClazz(); 2183 if ((objectValue != null) 2184 && (!fieldCl.isAssignableFrom( 2185 objectValue.getClass()))) { 2186 throw new IllegalArgumentException("Field mismatch"); 2187 } 2188 Field declaredClassField = null; 2189 final String inputStreamFieldName = fields[i].getName(); 2190 try { 2191 declaredClassField = getDeclaredField( cl, inputStreamFieldName); 2192 } catch (PrivilegedActionException paEx) { 2193 throw new IllegalArgumentException( 2194 (NoSuchFieldException) paEx.getException()); 2195 } catch (SecurityException secEx) { 2196 throw new IllegalArgumentException(secEx); 2197 } catch (NullPointerException npEx) { 2198 continue; 2199 } catch (NoSuchFieldException e) { 2200 continue; 2201 } 2202 2203 if (declaredClassField == null) { 2204 continue; 2205 } 2206 2207 Class<?> declaredFieldClass = declaredClassField.getType(); 2208 2209 // check input field type is a declared field type 2210 // input field is a subclass of the declared field 2211 if (!declaredFieldClass.isAssignableFrom(fieldCl)) { 2212 throw new IllegalArgumentException( 2213 "Field Type mismatch"); 2214 } 2215 if (objectValue != null && !fieldCl.isInstance(objectValue)) { 2216 throw new IllegalArgumentException(); 2217 } 2218 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ; 2219 // reflective code: fields[i].getField().set( o, objectValue ) ; 2220 } catch (IllegalArgumentException iaEx) { 2221 String objectValueClassName = "null"; 2222 String currentClassDescClassName = "null"; 2223 String fieldName = "null"; 2224 if (objectValue != null) { 2225 objectValueClassName = objectValue.getClass().getName(); 2226 } 2227 if (currentClassDesc != null) { 2228 currentClassDescClassName = currentClassDesc.getName(); 2229 } 2230 if (fields[i] != null && fields[i].getField() != null) { 2231 fieldName = fields[i].getField().getName(); 2232 } 2233 ClassCastException ccEx = new ClassCastException( 2234 "Assigning instance of class " + objectValueClassName 2235 + " to field " + currentClassDescClassName + '#' + fieldName); 2236 ccEx.initCause( iaEx ) ; 2237 throw ccEx ; 2238 } 2239 } // end : for loop 2240 } 2241 } 2242 2243 /* 2244 * Read the fields of the specified class from the input stream and set 2245 * the values of the fields in the specified object. If the specified 2246 * object is null, just consume the fields without setting any values. If 2247 * any ObjectStreamField does not have a reflected Field, don't try to set 2248 * that field in the object. 2249 */ 2250 private void inputClassFields(Object o, Class cl, 2251 ObjectStreamClass osc, 2252 ValueMember[] fields, 2253 com.sun.org.omg.SendingContext.CodeBase sender) 2254 throws InvalidClassException, StreamCorruptedException, 2255 ClassNotFoundException, IOException 2256 { 2257 try{ 2258 for (int i = 0; i < fields.length; ++i) { 2259 try { 2260 switch (fields[i].type.kind().value()) { 2261 case TCKind._tk_octet: 2262 byte byteValue = orbStream.read_octet(); 2263 if ((o != null) && osc.hasField(fields[i])) 2264 setByteField(o, cl, fields[i].name, byteValue); 2265 break; 2266 case TCKind._tk_boolean: 2267 boolean booleanValue = orbStream.read_boolean(); 2268 if ((o != null) && osc.hasField(fields[i])) 2269 setBooleanField(o, cl, fields[i].name, booleanValue); 2270 break; 2271 case TCKind._tk_char: 2272 // Backwards compatibility. Older Sun ORBs sent 2273 // _tk_char even though they read and wrote wchars 2274 // correctly. 2275 // 2276 // Fall through to the _tk_wchar case. 2277 case TCKind._tk_wchar: 2278 char charValue = orbStream.read_wchar(); 2279 if ((o != null) && osc.hasField(fields[i])) 2280 setCharField(o, cl, fields[i].name, charValue); 2281 break; 2282 case TCKind._tk_short: 2283 short shortValue = orbStream.read_short(); 2284 if ((o != null) && osc.hasField(fields[i])) 2285 setShortField(o, cl, fields[i].name, shortValue); 2286 break; 2287 case TCKind._tk_long: 2288 int intValue = orbStream.read_long(); 2289 if ((o != null) && osc.hasField(fields[i])) 2290 setIntField(o, cl, fields[i].name, intValue); 2291 break; 2292 case TCKind._tk_longlong: 2293 long longValue = orbStream.read_longlong(); 2294 if ((o != null) && osc.hasField(fields[i])) 2295 setLongField(o, cl, fields[i].name, longValue); 2296 break; 2297 case TCKind._tk_float: 2298 float floatValue = orbStream.read_float(); 2299 if ((o != null) && osc.hasField(fields[i])) 2300 setFloatField(o, cl, fields[i].name, floatValue); 2301 break; 2302 case TCKind._tk_double: 2303 double doubleValue = orbStream.read_double(); 2304 if ((o != null) && osc.hasField(fields[i])) 2305 setDoubleField(o, cl, fields[i].name, doubleValue); 2306 break; 2307 case TCKind._tk_value: 2308 case TCKind._tk_objref: 2309 case TCKind._tk_value_box: 2310 Object objectValue = null; 2311 try { 2312 objectValue = inputObjectField(fields[i], sender); 2313 } catch (IndirectionException cdrie) { 2314 // The CDR stream had never seen the given offset before, 2315 // so check the recursion manager (it will throw an 2316 // IOException if it doesn't have a reference, either). 2317 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2318 } 2319 2320 if (o == null) 2321 continue; 2322 try { 2323 if (osc.hasField(fields[i])){ 2324 setObjectField(o, 2325 cl, 2326 fields[i].name, 2327 objectValue); 2328 } else { 2329 // REVISIT. Convert to a log message. 2330 // This is a normal case when fields have 2331 // been added as part of evolution, but 2332 // silently skipping can make it hard to 2333 // debug if there's an error 2334// System.out.println("**** warning, not setting field: " 2335// + fields[i].name 2336// + " since not on class " 2337// + osc.getName()); 2338 2339 } 2340 } catch (IllegalArgumentException e) { 2341 // XXX I18N, logging needed. 2342 ClassCastException cce = new ClassCastException("Assigning instance of class " + 2343 objectValue.getClass().getName() + " to field " + fields[i].name); 2344 cce.initCause(e) ; 2345 throw cce ; 2346 } 2347 break; 2348 default: 2349 // XXX I18N, logging needed. 2350 throw new StreamCorruptedException("Unknown kind: " 2351 + fields[i].type.kind().value()); 2352 } 2353 } catch (IllegalArgumentException e) { 2354 /* This case should never happen. If the field types 2355 are not the same, InvalidClassException is raised when 2356 matching the local class to the serialized ObjectStreamClass. */ 2357 // XXX I18N, logging needed. 2358 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id + 2359 " to field " + currentClassDesc.getName() + '#' + fields[i].name); 2360 cce.initCause( e ) ; 2361 throw cce ; 2362 } 2363 } 2364 } catch(Throwable t){ 2365 // XXX I18N, logging needed. 2366 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage()); 2367 sce.initCause(t) ; 2368 throw sce ; 2369 } 2370 } 2371 2372 private void skipCustomUsingFVD(ValueMember[] fields, 2373 com.sun.org.omg.SendingContext.CodeBase sender) 2374 throws InvalidClassException, StreamCorruptedException, 2375 ClassNotFoundException, IOException 2376 { 2377 readFormatVersion(); 2378 boolean calledDefaultWriteObject = readBoolean(); 2379 2380 if (calledDefaultWriteObject) 2381 throwAwayData(fields, sender); 2382 2383 if (getStreamFormatVersion() == 2) { 2384 2385 ((ValueInputStream)getOrbStream()).start_value(); 2386 ((ValueInputStream)getOrbStream()).end_value(); 2387 } 2388 } 2389 2390 /* 2391 * Read the fields of the specified class from the input stream throw data away. 2392 * This must handle same switch logic as above. 2393 */ 2394 private void throwAwayData(ValueMember[] fields, 2395 com.sun.org.omg.SendingContext.CodeBase sender) 2396 throws InvalidClassException, StreamCorruptedException, 2397 ClassNotFoundException, IOException { 2398 2399 for (int i = 0; i < fields.length; ++i) { 2400 2401 try { 2402 2403 switch (fields[i].type.kind().value()) { 2404 case TCKind._tk_octet: 2405 orbStream.read_octet(); 2406 break; 2407 case TCKind._tk_boolean: 2408 orbStream.read_boolean(); 2409 break; 2410 case TCKind._tk_char: 2411 // Backwards compatibility. Older Sun ORBs sent 2412 // _tk_char even though they read and wrote wchars 2413 // correctly. 2414 // 2415 // Fall through to the _tk_wchar case. 2416 case TCKind._tk_wchar: 2417 orbStream.read_wchar(); 2418 break; 2419 case TCKind._tk_short: 2420 orbStream.read_short(); 2421 break; 2422 case TCKind._tk_long: 2423 orbStream.read_long(); 2424 break; 2425 case TCKind._tk_longlong: 2426 orbStream.read_longlong(); 2427 break; 2428 case TCKind._tk_float: 2429 orbStream.read_float(); 2430 break; 2431 case TCKind._tk_double: 2432 orbStream.read_double(); 2433 break; 2434 case TCKind._tk_value: 2435 case TCKind._tk_objref: 2436 case TCKind._tk_value_box: 2437 Class type = null; 2438 String id = fields[i].id; 2439 2440 try { 2441 type = vhandler.getClassFromType(id); 2442 } 2443 catch(ClassNotFoundException cnfe){ 2444 // Make sure type = null 2445 type = null; 2446 } 2447 String signature = null; 2448 if (type != null) 2449 signature = ValueUtility.getSignature(fields[i]); 2450 2451 // Read value 2452 try { 2453 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") || 2454 signature.equals("Ljava/io/Serializable;") || 2455 signature.equals("Ljava/io/Externalizable;")) ) { 2456 javax.rmi.CORBA.Util.readAny(orbStream); 2457 } 2458 else { 2459 // Decide what method call to make based on the type. 2460 // 2461 // NOTE : Since FullValueDescription does not allow us 2462 // to ask whether something is an interface we do not 2463 // have the ability to optimize this check. 2464 2465 int callType = ValueHandlerImpl.kValueType; 2466 2467 if (!vhandler.isSequence(id)) { 2468 FullValueDescription fieldFVD = sender.meta(fields[i].id); 2469 if (kRemoteTypeCode == fields[i].type) { 2470 2471 // RMI Object reference... 2472 callType = ValueHandlerImpl.kRemoteType; 2473 } else if (fieldFVD.is_abstract) { 2474 // RMI Abstract Object reference... 2475 2476 callType = ValueHandlerImpl.kAbstractType; 2477 } 2478 } 2479 2480 // Now that we have used the FVD of the field to determine the proper course 2481 // of action, it is ok to use the type (Class) from this point forward since 2482 // the rep. id for this read will also follow on the wire. 2483 2484 switch (callType) { 2485 case ValueHandlerImpl.kRemoteType: 2486 orbStream.read_Object(); 2487 break; 2488 case ValueHandlerImpl.kAbstractType: 2489 orbStream.read_abstract_interface(); 2490 break; 2491 case ValueHandlerImpl.kValueType: 2492 if (type != null) { 2493 orbStream.read_value(type); 2494 } else { 2495 orbStream.read_value(); 2496 } 2497 break; 2498 default: 2499 // XXX I18N, logging needed. 2500 throw new StreamCorruptedException("Unknown callType: " 2501 + callType); 2502 } 2503 } 2504 2505 } 2506 catch(IndirectionException cdrie) { 2507 // Since we are throwing this away, don't bother handling recursion. 2508 continue; 2509 } 2510 2511 break; 2512 default: 2513 // XXX I18N, logging needed. 2514 throw new StreamCorruptedException("Unknown kind: " 2515 + fields[i].type.kind().value()); 2516 2517 } 2518 } catch (IllegalArgumentException e) { 2519 /* This case should never happen. If the field types 2520 are not the same, InvalidClassException is raised when 2521 matching the local class to the serialized ObjectStreamClass. */ 2522 // XXX I18N, logging needed. 2523 ClassCastException cce = new ClassCastException("Assigning instance of class " + 2524 fields[i].id + " to field " + currentClassDesc.getName() + 2525 '#' + fields[i].name); 2526 cce.initCause(e) ; 2527 throw cce ; 2528 } 2529 } 2530 } 2531 2532 private static void setObjectField(Object o, Class<?> c, String fieldName, Object v) { 2533 try { 2534 Field fld = getDeclaredField( c, fieldName ) ; 2535 Class fieldCl = fld.getType(); 2536 if(v != null && !fieldCl.isInstance(v)) { 2537 throw new Exception(); 2538 } 2539 long key = bridge.objectFieldOffset( fld ) ; 2540 bridge.putObject( o, key, v ) ; 2541 } catch (Exception e) { 2542 if (o != null) { 2543 throw utilWrapper.errorSetObjectField( e, fieldName, 2544 o.toString(), 2545 v.toString() ) ; 2546 } else { 2547 throw utilWrapper.errorSetObjectField( e, fieldName, 2548 "null " + c.getName() + " object", 2549 v.toString() ) ; 2550 } 2551 } 2552 } 2553 2554 private static void setBooleanField(Object o, Class<?> c, String fieldName, boolean v) 2555 { 2556 try { 2557 Field fld = getDeclaredField( c, fieldName ) ; 2558 if ((fld != null) && (fld.getType() == Boolean.TYPE)) { 2559 long key = bridge.objectFieldOffset( fld ) ; 2560 bridge.putBoolean( o, key, v ) ; 2561 } else { 2562 throw new InvalidObjectException("Field Type mismatch"); 2563 } 2564 } catch (Exception e) { 2565 if (o != null) { 2566 throw utilWrapper.errorSetBooleanField( e, fieldName, 2567 o.toString(), 2568 new Boolean(v) ) ; 2569 } else { 2570 throw utilWrapper.errorSetBooleanField( e, fieldName, 2571 "null " + c.getName() + " object", 2572 new Boolean(v) ) ; 2573 } 2574 } 2575 } 2576 2577 private static void setByteField(Object o, Class<?> c, String fieldName, byte v) 2578 { 2579 try { 2580 Field fld = getDeclaredField( c, fieldName ) ; 2581 if ((fld != null) && (fld.getType() == Byte.TYPE)) { 2582 long key = bridge.objectFieldOffset( fld ) ; 2583 bridge.putByte( o, key, v ) ; 2584 } else { 2585 throw new InvalidObjectException("Field Type mismatch"); 2586 } 2587 } catch (Exception e) { 2588 if (o != null) { 2589 throw utilWrapper.errorSetByteField( e, fieldName, 2590 o.toString(), 2591 new Byte(v) ) ; 2592 } else { 2593 throw utilWrapper.errorSetByteField( e, fieldName, 2594 "null " + c.getName() + " object", 2595 new Byte(v) ) ; 2596 } 2597 } 2598 } 2599 2600 private static void setCharField(Object o, Class<?> c, String fieldName, char v) 2601 { 2602 try { 2603 Field fld = getDeclaredField( c, fieldName ) ; 2604 if ((fld != null) && (fld.getType() == Character.TYPE)) { 2605 long key = bridge.objectFieldOffset( fld ) ; 2606 bridge.putChar( o, key, v ) ; 2607 } else { 2608 throw new InvalidObjectException("Field Type mismatch"); 2609 } 2610 } catch (Exception e) { 2611 if (o != null) { 2612 throw utilWrapper.errorSetCharField( e, fieldName, 2613 o.toString(), 2614 new Character(v) ) ; 2615 } else { 2616 throw utilWrapper.errorSetCharField( e, fieldName, 2617 "null " + c.getName() + " object", 2618 new Character(v) ) ; 2619 } 2620 } 2621 } 2622 2623 private static void setShortField(Object o, Class<?> c, String fieldName, short v) 2624 { 2625 try { 2626 Field fld = getDeclaredField( c, fieldName ) ; 2627 if ((fld != null) && (fld.getType() == Short.TYPE)) { 2628 long key = bridge.objectFieldOffset( fld ) ; 2629 bridge.putShort( o, key, v ) ; 2630 } else { 2631 throw new InvalidObjectException("Field Type mismatch"); 2632 } 2633 } catch (Exception e) { 2634 if (o != null) { 2635 throw utilWrapper.errorSetShortField( e, fieldName, 2636 o.toString(), 2637 new Short(v) ) ; 2638 } else { 2639 throw utilWrapper.errorSetShortField( e, fieldName, 2640 "null " + c.getName() + " object", 2641 new Short(v) ) ; 2642 } 2643 } 2644 } 2645 2646 private static void setIntField(Object o, Class<?> c, String fieldName, int v) 2647 { 2648 try { 2649 Field fld = getDeclaredField( c, fieldName ) ; 2650 if ((fld != null) && (fld.getType() == Integer.TYPE)) { 2651 long key = bridge.objectFieldOffset( fld ) ; 2652 bridge.putInt( o, key, v ) ; 2653 } else { 2654 throw new InvalidObjectException("Field Type mismatch"); 2655 } 2656 } catch (Exception e) { 2657 if (o != null) { 2658 throw utilWrapper.errorSetIntField( e, fieldName, 2659 o.toString(), 2660 new Integer(v) ) ; 2661 } else { 2662 throw utilWrapper.errorSetIntField( e, fieldName, 2663 "null " + c.getName() + " object", 2664 new Integer(v) ) ; 2665 } 2666 } 2667 } 2668 2669 private static void setLongField(Object o, Class<?> c, String fieldName, long v) 2670 { 2671 try { 2672 Field fld = getDeclaredField( c, fieldName ) ; 2673 if ((fld != null) && (fld.getType() == Long.TYPE)) { 2674 long key = bridge.objectFieldOffset( fld ) ; 2675 bridge.putLong( o, key, v ) ; 2676 } else { 2677 throw new InvalidObjectException("Field Type mismatch"); 2678 } 2679 } catch (Exception e) { 2680 if (o != null) { 2681 throw utilWrapper.errorSetLongField( e, fieldName, 2682 o.toString(), 2683 new Long(v) ) ; 2684 } else { 2685 throw utilWrapper.errorSetLongField( e, fieldName, 2686 "null " + c.getName() + " object", 2687 new Long(v) ) ; 2688 } 2689 } 2690 } 2691 2692 private static void setFloatField(Object o, Class<?> c, String fieldName, float v) 2693 { 2694 try { 2695 Field fld = getDeclaredField( c, fieldName ) ; 2696 if ((fld != null) && (fld.getType() == Float.TYPE)) { 2697 long key = bridge.objectFieldOffset( fld ) ; 2698 bridge.putFloat( o, key, v ) ; 2699 } else { 2700 throw new InvalidObjectException("Field Type mismatch"); 2701 } 2702 } catch (Exception e) { 2703 if (o != null) { 2704 throw utilWrapper.errorSetFloatField( e, fieldName, 2705 o.toString(), 2706 new Float(v) ) ; 2707 } else { 2708 throw utilWrapper.errorSetFloatField( e, fieldName, 2709 "null " + c.getName() + " object", 2710 new Float(v) ) ; 2711 } 2712 } 2713 } 2714 2715 private static void setDoubleField(Object o, Class<?> c, String fieldName, double v) 2716 { 2717 try { 2718 Field fld = getDeclaredField( c, fieldName ) ; 2719 if ((fld != null) && (fld.getType() == Double.TYPE)) { 2720 long key = bridge.objectFieldOffset( fld ) ; 2721 bridge.putDouble( o, key, v ) ; 2722 } else { 2723 throw new InvalidObjectException("Field Type mismatch"); 2724 } 2725 } catch (Exception e) { 2726 if (o != null) { 2727 throw utilWrapper.errorSetDoubleField( e, fieldName, 2728 o.toString(), 2729 new Double(v) ) ; 2730 } else { 2731 throw utilWrapper.errorSetDoubleField( e, fieldName, 2732 "null " + c.getName() + " object", 2733 new Double(v) ) ; 2734 } 2735 } 2736 } 2737 2738 2739 private static Field getDeclaredField(final Class<?> c, 2740 final String fieldName) 2741 throws PrivilegedActionException, NoSuchFieldException, SecurityException { 2742 if (System.getSecurityManager() == null) { 2743 return c.getDeclaredField(fieldName); 2744 } else { 2745 return AccessController 2746 .doPrivileged(new PrivilegedExceptionAction<Field>() { 2747 public Field run() throws NoSuchFieldException { 2748 return c.getDeclaredField(fieldName); 2749 } 2750 }); 2751 } 2752 } 2753 2754 /** 2755 * This class maintains a map of stream position to 2756 * an Object currently being deserialized. It is used 2757 * to handle the cases where the are indirections to 2758 * an object on the recursion stack. The CDR level 2759 * handles indirections to objects previously seen 2760 * (and completely deserialized) in the stream. 2761 */ 2762 static class ActiveRecursionManager 2763 { 2764 private Map<Integer, Object> offsetToObjectMap; 2765 2766 public ActiveRecursionManager() { 2767 // A hash map is unsynchronized and allows 2768 // null values 2769 offsetToObjectMap = new HashMap<>(); 2770 } 2771 2772 // Called right after allocating a new object. 2773 // Offset is the starting position in the stream 2774 // of the object. 2775 public void addObject(int offset, Object value) { 2776 offsetToObjectMap.put(new Integer(offset), value); 2777 } 2778 2779 // If the given starting position doesn't refer 2780 // to the beginning of an object currently being 2781 // deserialized, this throws an IOException. 2782 // Otherwise, it returns a reference to the 2783 // object. 2784 public Object getObject(int offset) throws IOException { 2785 Integer position = new Integer(offset); 2786 2787 if (!offsetToObjectMap.containsKey(position)) 2788 // XXX I18N, logging needed. 2789 throw new IOException("Invalid indirection to offset " 2790 + offset); 2791 2792 return offsetToObjectMap.get(position); 2793 } 2794 2795 // Called when an object has been completely 2796 // deserialized, so it should no longer be in 2797 // this mapping. The CDR level can handle 2798 // further indirections. 2799 public void removeObject(int offset) { 2800 offsetToObjectMap.remove(new Integer(offset)); 2801 } 2802 2803 // If the given offset doesn't map to an Object, 2804 // then it isn't an indirection to an object 2805 // currently being deserialized. 2806 public boolean containsObject(int offset) { 2807 return offsetToObjectMap.containsKey(new Integer(offset)); 2808 } 2809 } 2810} 2811