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