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