ObjectInputStream.java revision 6523532145f06d8c208ed7a9374d3ab6d8132e66
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.io; 19 20// BEGIN android-note 21// Harmony uses ObjectAccessors to access fields through JNI. Android has not 22// yet migrated that API. As a consequence, there's a lot of changes here... 23// END android-note 24 25import dalvik.system.VMStack; 26import java.io.EmulatedFields.ObjectSlot; 27import java.lang.reflect.Array; 28import java.lang.reflect.Constructor; 29import java.lang.reflect.Field; 30import java.lang.reflect.InvocationTargetException; 31import java.lang.reflect.Method; 32import java.lang.reflect.Modifier; 33import java.lang.reflect.Proxy; 34import java.security.AccessController; 35import java.security.PrivilegedAction; 36import java.util.ArrayList; 37import java.util.Arrays; 38import java.util.HashMap; 39import java.util.Iterator; 40import libcore.base.EmptyArray; 41import org.apache.harmony.luni.util.PriviAction; 42 43/** 44 * A specialized {@link InputStream} that is able to read (deserialize) Java 45 * objects as well as primitive data types (int, byte, char etc.). The data has 46 * typically been saved using an ObjectOutputStream. 47 * 48 * @see ObjectOutputStream 49 * @see ObjectInput 50 * @see Serializable 51 * @see Externalizable 52 */ 53public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { 54 55 // BEGIN android-note 56 // this is non-static to avoid sync contention. Would static be faster? 57 // END android-note 58 private InputStream emptyStream = new ByteArrayInputStream(EmptyArray.BYTE); 59 60 // To put into objectsRead when reading unsharedObject 61 private static final Object UNSHARED_OBJ = new Object(); // $NON-LOCK-1$ 62 63 // If the receiver has already read & not consumed a TC code 64 private boolean hasPushbackTC; 65 66 // Push back TC code if the variable above is true 67 private byte pushbackTC; 68 69 // How many nested levels to readObject. When we reach 0 we have to validate 70 // the graph then reset it 71 private int nestedLevels; 72 73 // All objects are assigned an ID (integer handle) 74 private int nextHandle; 75 76 // Where we read from 77 private DataInputStream input; 78 79 // Where we read primitive types from 80 private DataInputStream primitiveTypes; 81 82 // Where we keep primitive type data 83 private InputStream primitiveData = emptyStream; 84 85 // Resolve object is a mechanism for replacement 86 private boolean enableResolve; 87 88 /** 89 * All the objects we've read, indexed by their serialization handle (minus the base offset). 90 */ 91 private ArrayList<Object> objectsRead; 92 93 // Used by defaultReadObject 94 private Object currentObject; 95 96 // Used by defaultReadObject 97 private ObjectStreamClass currentClass; 98 99 // All validations to be executed when the complete graph is read. See inner 100 // type below. 101 private InputValidationDesc[] validations; 102 103 // Allows the receiver to decide if it needs to call readObjectOverride 104 private boolean subclassOverridingImplementation; 105 106 // Original caller's class loader, used to perform class lookups 107 private ClassLoader callerClassLoader; 108 109 // false when reading missing fields 110 private boolean mustResolve = true; 111 112 // Handle for the current class descriptor 113 private int descriptorHandle = -1; 114 115 private static final HashMap<String, Class<?>> PRIMITIVE_CLASSES = 116 new HashMap<String, Class<?>>(); 117 118 static { 119 PRIMITIVE_CLASSES.put("byte", byte.class); 120 PRIMITIVE_CLASSES.put("short", short.class); 121 PRIMITIVE_CLASSES.put("int", int.class); 122 PRIMITIVE_CLASSES.put("long", long.class); 123 PRIMITIVE_CLASSES.put("boolean", boolean.class); 124 PRIMITIVE_CLASSES.put("char", char.class); 125 PRIMITIVE_CLASSES.put("float", float.class); 126 PRIMITIVE_CLASSES.put("double", double.class); 127 } 128 129 // BEGIN android-removed 130 // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor(); 131 // END android-removed 132 133 // Internal type used to keep track of validators & corresponding priority 134 static class InputValidationDesc { 135 ObjectInputValidation validator; 136 137 int priority; 138 } 139 140 /** 141 * GetField is an inner class that provides access to the persistent fields 142 * read from the source stream. 143 */ 144 public abstract static class GetField { 145 /** 146 * Gets the ObjectStreamClass that describes a field. 147 * 148 * @return the descriptor class for a serialized field. 149 */ 150 public abstract ObjectStreamClass getObjectStreamClass(); 151 152 /** 153 * Indicates if the field identified by {@code name} is defaulted. This 154 * means that it has no value in this stream. 155 * 156 * @param name 157 * the name of the field to check. 158 * @return {@code true} if the field is defaulted, {@code false} 159 * otherwise. 160 * @throws IllegalArgumentException 161 * if {@code name} does not identify a serializable field. 162 * @throws IOException 163 * if an error occurs while reading from the source input 164 * stream. 165 */ 166 public abstract boolean defaulted(String name) throws IOException, 167 IllegalArgumentException; 168 169 /** 170 * Gets the value of the boolean field identified by {@code name} from 171 * the persistent field. 172 * 173 * @param name 174 * the name of the field to get. 175 * @param defaultValue 176 * the default value that is used if the field does not have 177 * a value when read from the source stream. 178 * @return the value of the field identified by {@code name}. 179 * @throws IOException 180 * if an error occurs while reading from the source input 181 * stream. 182 * @throws IllegalArgumentException 183 * if the type of the field identified by {@code name} is 184 * not {@code boolean}. 185 */ 186 public abstract boolean get(String name, boolean defaultValue) 187 throws IOException, IllegalArgumentException; 188 189 /** 190 * Gets the value of the character field identified by {@code name} from 191 * the persistent field. 192 * 193 * @param name 194 * the name of the field to get. 195 * @param defaultValue 196 * the default value that is used if the field does not have 197 * a value when read from the source stream. 198 * @return the value of the field identified by {@code name}. 199 * @throws IOException 200 * if an error occurs while reading from the source input 201 * stream. 202 * @throws IllegalArgumentException 203 * if the type of the field identified by {@code name} is 204 * not {@code char}. 205 */ 206 public abstract char get(String name, char defaultValue) 207 throws IOException, IllegalArgumentException; 208 209 /** 210 * Gets the value of the byte field identified by {@code name} from the 211 * persistent field. 212 * 213 * @param name 214 * the name of the field to get. 215 * @param defaultValue 216 * the default value that is used if the field does not have 217 * a value when read from the source stream. 218 * @return the value of the field identified by {@code name}. 219 * @throws IOException 220 * if an error occurs while reading from the source input 221 * stream. 222 * @throws IllegalArgumentException 223 * if the type of the field identified by {@code name} is 224 * not {@code byte}. 225 */ 226 public abstract byte get(String name, byte defaultValue) 227 throws IOException, IllegalArgumentException; 228 229 /** 230 * Gets the value of the short field identified by {@code name} from the 231 * persistent field. 232 * 233 * @param name 234 * the name of the field to get. 235 * @param defaultValue 236 * the default value that is used if the field does not have 237 * a value when read from the source stream. 238 * @return the value of the field identified by {@code name}. 239 * @throws IOException 240 * if an error occurs while reading from the source input 241 * stream. 242 * @throws IllegalArgumentException 243 * if the type of the field identified by {@code name} is 244 * not {@code short}. 245 */ 246 public abstract short get(String name, short defaultValue) 247 throws IOException, IllegalArgumentException; 248 249 /** 250 * Gets the value of the integer field identified by {@code name} from 251 * the persistent field. 252 * 253 * @param name 254 * the name of the field to get. 255 * @param defaultValue 256 * the default value that is used if the field does not have 257 * a value when read from the source stream. 258 * @return the value of the field identified by {@code name}. 259 * @throws IOException 260 * if an error occurs while reading from the source input 261 * stream. 262 * @throws IllegalArgumentException 263 * if the type of the field identified by {@code name} is 264 * not {@code int}. 265 */ 266 public abstract int get(String name, int defaultValue) 267 throws IOException, IllegalArgumentException; 268 269 /** 270 * Gets the value of the long field identified by {@code name} from the 271 * persistent field. 272 * 273 * @param name 274 * the name of the field to get. 275 * @param defaultValue 276 * the default value that is used if the field does not have 277 * a value when read from the source stream. 278 * @return the value of the field identified by {@code name}. 279 * @throws IOException 280 * if an error occurs while reading from the source input 281 * stream. 282 * @throws IllegalArgumentException 283 * if the type of the field identified by {@code name} is 284 * not {@code long}. 285 */ 286 public abstract long get(String name, long defaultValue) 287 throws IOException, IllegalArgumentException; 288 289 /** 290 * Gets the value of the float field identified by {@code name} from the 291 * persistent field. 292 * 293 * @param name 294 * the name of the field to get. 295 * @param defaultValue 296 * the default value that is used if the field does not have 297 * a value when read from the source stream. 298 * @return the value of the field identified by {@code name}. 299 * @throws IOException 300 * if an error occurs while reading from the source input 301 * stream. 302 * @throws IllegalArgumentException 303 * if the type of the field identified by {@code float} is 304 * not {@code char}. 305 */ 306 public abstract float get(String name, float defaultValue) 307 throws IOException, IllegalArgumentException; 308 309 /** 310 * Gets the value of the double field identified by {@code name} from 311 * the persistent field. 312 * 313 * @param name 314 * the name of the field to get. 315 * @param defaultValue 316 * the default value that is used if the field does not have 317 * a value when read from the source stream. 318 * @return the value of the field identified by {@code name}. 319 * @throws IOException 320 * if an error occurs while reading from the source input 321 * stream. 322 * @throws IllegalArgumentException 323 * if the type of the field identified by {@code name} is 324 * not {@code double}. 325 */ 326 public abstract double get(String name, double defaultValue) 327 throws IOException, IllegalArgumentException; 328 329 /** 330 * Gets the value of the object field identified by {@code name} from 331 * the persistent field. 332 * 333 * @param name 334 * the name of the field to get. 335 * @param defaultValue 336 * the default value that is used if the field does not have 337 * a value when read from the source stream. 338 * @return the value of the field identified by {@code name}. 339 * @throws IOException 340 * if an error occurs while reading from the source input 341 * stream. 342 * @throws IllegalArgumentException 343 * if the type of the field identified by {@code name} is 344 * not {@code Object}. 345 */ 346 public abstract Object get(String name, Object defaultValue) 347 throws IOException, IllegalArgumentException; 348 } 349 350 /** 351 * Constructs a new ObjectInputStream. This default constructor can be used 352 * by subclasses that do not want to use the public constructor if it 353 * allocates unneeded data. 354 * 355 * @throws IOException 356 * if an error occurs when creating this stream. 357 * @throws SecurityException 358 * if a security manager is installed and it denies subclassing 359 * this class. 360 * @see SecurityManager#checkPermission(java.security.Permission) 361 */ 362 protected ObjectInputStream() throws IOException, SecurityException { 363 super(); 364 SecurityManager currentManager = System.getSecurityManager(); 365 if (currentManager != null) { 366 currentManager.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 367 } 368 // WARNING - we should throw IOException if not called from a subclass 369 // according to the JavaDoc. Add the test. 370 this.subclassOverridingImplementation = true; 371 } 372 373 /** 374 * Constructs a new ObjectInputStream that reads from the InputStream 375 * {@code input}. 376 * 377 * @param input 378 * the non-null source InputStream to filter reads on. 379 * @throws IOException 380 * if an error occurs while reading the stream header. 381 * @throws StreamCorruptedException 382 * if the source stream does not contain serialized objects that 383 * can be read. 384 * @throws SecurityException 385 * if a security manager is installed and it denies subclassing 386 * this class. 387 */ 388 public ObjectInputStream(InputStream input) 389 throws StreamCorruptedException, IOException { 390 final Class<?> implementationClass = getClass(); 391 final Class<?> thisClass = ObjectInputStream.class; 392 SecurityManager sm = System.getSecurityManager(); 393 if (sm != null && implementationClass != thisClass) { 394 boolean mustCheck = AccessController 395 .doPrivileged(new PrivilegedAction<Boolean>() { 396 public Boolean run() { 397 try { 398 Method method = implementationClass.getMethod("readFields", 399 EmptyArray.CLASS); 400 if (method.getDeclaringClass() != thisClass) { 401 return Boolean.TRUE; 402 } 403 } catch (NoSuchMethodException ignored) { 404 } 405 try { 406 Method method = implementationClass.getMethod("readUnshared", 407 EmptyArray.CLASS); 408 if (method.getDeclaringClass() != thisClass) { 409 return Boolean.TRUE; 410 } 411 } catch (NoSuchMethodException ignored) { 412 } 413 return Boolean.FALSE; 414 } 415 }); 416 if (mustCheck) { 417 sm 418 .checkPermission(ObjectStreamConstants.SUBCLASS_IMPLEMENTATION_PERMISSION); 419 } 420 } 421 this.input = (input instanceof DataInputStream) ? (DataInputStream) input 422 : new DataInputStream(input); 423 primitiveTypes = new DataInputStream(this); 424 enableResolve = false; 425 this.subclassOverridingImplementation = false; 426 resetState(); 427 nestedLevels = 0; 428 // So read...() methods can be used by 429 // subclasses during readStreamHeader() 430 primitiveData = this.input; 431 // Has to be done here according to the specification 432 readStreamHeader(); 433 primitiveData = emptyStream; 434 } 435 436 @Override 437 public int available() throws IOException { 438 // returns 0 if next data is an object, or N if reading primitive types 439 checkReadPrimitiveTypes(); 440 return primitiveData.available(); 441 } 442 443 /** 444 * Checks to if it is ok to read primitive types from this stream at 445 * this point. One is not supposed to read primitive types when about to 446 * read an object, for example, so an exception has to be thrown. 447 * 448 * @throws IOException 449 * If any IO problem occurred when trying to read primitive type 450 * or if it is illegal to read primitive types 451 */ 452 private void checkReadPrimitiveTypes() throws IOException { 453 // If we still have primitive data, it is ok to read primitive data 454 if (primitiveData == input || primitiveData.available() > 0) { 455 return; 456 } 457 458 // If we got here either we had no Stream previously created or 459 // we no longer have data in that one, so get more bytes 460 do { 461 int next = 0; 462 if (hasPushbackTC) { 463 hasPushbackTC = false; 464 } else { 465 next = input.read(); 466 pushbackTC = (byte) next; 467 } 468 switch (pushbackTC) { 469 case TC_BLOCKDATA: 470 primitiveData = new ByteArrayInputStream(readBlockData()); 471 return; 472 case TC_BLOCKDATALONG: 473 primitiveData = new ByteArrayInputStream(readBlockDataLong()); 474 return; 475 case TC_RESET: 476 resetState(); 477 break; 478 default: 479 if (next != -1) { 480 pushbackTC(); 481 } 482 return; 483 } 484 // Only TC_RESET falls through 485 } while (true); 486 } 487 488 /** 489 * Closes this stream. This implementation closes the source stream. 490 * 491 * @throws IOException 492 * if an error occurs while closing this stream. 493 */ 494 @Override 495 public void close() throws IOException { 496 input.close(); 497 } 498 499 /** 500 * Default method to read objects from this stream. Serializable fields 501 * defined in the object's class and superclasses are read from the source 502 * stream. 503 * 504 * @throws ClassNotFoundException 505 * if the object's class cannot be found. 506 * @throws IOException 507 * if an I/O error occurs while reading the object data. 508 * @throws NotActiveException 509 * if this method is not called from {@code readObject()}. 510 * @see ObjectOutputStream#defaultWriteObject 511 */ 512 public void defaultReadObject() throws IOException, ClassNotFoundException, 513 NotActiveException { 514 // We can't be called from just anywhere. There are rules. 515 if (currentObject != null || !mustResolve) { 516 readFieldValues(currentObject, currentClass); 517 } else { 518 throw new NotActiveException(); 519 } 520 } 521 522 /** 523 * Enables object replacement for this stream. By default this is not 524 * enabled. Only trusted subclasses (loaded with system class loader) are 525 * allowed to change this status. 526 * 527 * @param enable 528 * {@code true} to enable object replacement; {@code false} to 529 * disable it. 530 * @return the previous setting. 531 * @throws SecurityException 532 * if a security manager is installed and it denies enabling 533 * object replacement for this stream. 534 * @see #resolveObject 535 * @see ObjectOutputStream#enableReplaceObject 536 */ 537 protected boolean enableResolveObject(boolean enable) 538 throws SecurityException { 539 if (enable) { 540 // The Stream has to be trusted for this feature to be enabled. 541 // trusted means the stream's class loader has to be null 542 SecurityManager currentManager = System.getSecurityManager(); 543 if (currentManager != null) { 544 currentManager.checkPermission(SUBSTITUTION_PERMISSION); 545 } 546 } 547 boolean originalValue = enableResolve; 548 enableResolve = enable; 549 return originalValue; 550 } 551 552 /** 553 * Return the next {@code int} handle to be used to indicate cyclic 554 * references being loaded from the stream. 555 * 556 * @return the next handle to represent the next cyclic reference 557 */ 558 private int nextHandle() { 559 return nextHandle++; 560 } 561 562 /** 563 * Return the next token code (TC) from the receiver, which indicates what 564 * kind of object follows 565 * 566 * @return the next TC from the receiver 567 * 568 * @throws IOException 569 * If an IO error occurs 570 * 571 * @see ObjectStreamConstants 572 */ 573 private byte nextTC() throws IOException { 574 if (hasPushbackTC) { 575 hasPushbackTC = false; // We are consuming it 576 } else { 577 // Just in case a later call decides to really push it back, 578 // we don't require the caller to pass it as parameter 579 pushbackTC = input.readByte(); 580 } 581 return pushbackTC; 582 } 583 584 /** 585 * Pushes back the last TC code read 586 */ 587 private void pushbackTC() { 588 hasPushbackTC = true; 589 } 590 591 /** 592 * Reads a single byte from the source stream and returns it as an integer 593 * in the range from 0 to 255. Returns -1 if the end of the source stream 594 * has been reached. Blocks if no input is available. 595 * 596 * @return the byte read or -1 if the end of the source stream has been 597 * reached. 598 * @throws IOException 599 * if an error occurs while reading from this stream. 600 */ 601 @Override 602 public int read() throws IOException { 603 checkReadPrimitiveTypes(); 604 return primitiveData.read(); 605 } 606 607 /** 608 * Reads at most {@code length} bytes from the source stream and stores them 609 * in byte array {@code buffer} starting at offset {@code count}. Blocks 610 * until {@code count} bytes have been read, the end of the source stream is 611 * detected or an exception is thrown. 612 * 613 * @param buffer 614 * the array in which to store the bytes read. 615 * @param offset 616 * the initial position in {@code buffer} to store the bytes 617 * read from the source stream. 618 * @param length 619 * the maximum number of bytes to store in {@code buffer}. 620 * @return the number of bytes read or -1 if the end of the source input 621 * stream has been reached. 622 * @throws IndexOutOfBoundsException 623 * if {@code offset < 0} or {@code length < 0}, or if 624 * {@code offset + length} is greater than the length of 625 * {@code buffer}. 626 * @throws IOException 627 * if an error occurs while reading from this stream. 628 * @throws NullPointerException 629 * if {@code buffer} is {@code null}. 630 */ 631 @Override 632 public int read(byte[] buffer, int offset, int length) throws IOException { 633 Arrays.checkOffsetAndCount(buffer.length, offset, length); 634 if (length == 0) { 635 return 0; 636 } 637 checkReadPrimitiveTypes(); 638 return primitiveData.read(buffer, offset, length); 639 } 640 641 /** 642 * Reads and returns an array of raw bytes with primitive data. The array 643 * will have up to 255 bytes. The primitive data will be in the format 644 * described by {@code DataOutputStream}. 645 * 646 * @return The primitive data read, as raw bytes 647 * 648 * @throws IOException 649 * If an IO exception happened when reading the primitive data. 650 */ 651 private byte[] readBlockData() throws IOException { 652 byte[] result = new byte[input.readByte() & 0xff]; 653 input.readFully(result); 654 return result; 655 } 656 657 /** 658 * Reads and returns an array of raw bytes with primitive data. The array 659 * will have more than 255 bytes. The primitive data will be in the format 660 * described by {@code DataOutputStream}. 661 * 662 * @return The primitive data read, as raw bytes 663 * 664 * @throws IOException 665 * If an IO exception happened when reading the primitive data. 666 */ 667 private byte[] readBlockDataLong() throws IOException { 668 byte[] result = new byte[input.readInt()]; 669 input.readFully(result); 670 return result; 671 } 672 673 /** 674 * Reads a boolean from the source stream. 675 * 676 * @return the boolean value read from the source stream. 677 * @throws EOFException 678 * if the end of the input is reached before the read 679 * request can be satisfied. 680 * @throws IOException 681 * if an error occurs while reading from the source stream. 682 */ 683 public boolean readBoolean() throws IOException { 684 return primitiveTypes.readBoolean(); 685 } 686 687 /** 688 * Reads a byte (8 bit) from the source stream. 689 * 690 * @return the byte value read from the source stream. 691 * @throws EOFException 692 * if the end of the input is reached before the read 693 * request can be satisfied. 694 * @throws IOException 695 * if an error occurs while reading from the source stream. 696 */ 697 public byte readByte() throws IOException { 698 return primitiveTypes.readByte(); 699 } 700 701 /** 702 * Reads a character (16 bit) from the source stream. 703 * 704 * @return the char value read from the source stream. 705 * @throws EOFException 706 * if the end of the input is reached before the read 707 * request can be satisfied. 708 * @throws IOException 709 * if an error occurs while reading from the source stream. 710 */ 711 public char readChar() throws IOException { 712 return primitiveTypes.readChar(); 713 } 714 715 /** 716 * Reads and discards block data and objects until TC_ENDBLOCKDATA is found. 717 * 718 * @throws IOException 719 * If an IO exception happened when reading the optional class 720 * annotation. 721 * @throws ClassNotFoundException 722 * If the class corresponding to the class descriptor could not 723 * be found. 724 */ 725 private void discardData() throws ClassNotFoundException, IOException { 726 primitiveData = emptyStream; 727 boolean resolve = mustResolve; 728 mustResolve = false; 729 do { 730 byte tc = nextTC(); 731 if (tc == TC_ENDBLOCKDATA) { 732 mustResolve = resolve; 733 return; // End of annotation 734 } 735 readContent(tc); 736 } while (true); 737 } 738 739 /** 740 * Reads a class descriptor (an {@code ObjectStreamClass}) from the 741 * stream. 742 * 743 * @return the class descriptor read from the stream 744 * 745 * @throws IOException 746 * If an IO exception happened when reading the class 747 * descriptor. 748 * @throws ClassNotFoundException 749 * If the class corresponding to the class descriptor could not 750 * be found. 751 */ 752 private ObjectStreamClass readClassDesc() throws ClassNotFoundException, IOException { 753 byte tc = nextTC(); 754 switch (tc) { 755 case TC_CLASSDESC: 756 return readNewClassDesc(false); 757 case TC_PROXYCLASSDESC: 758 Class<?> proxyClass = readNewProxyClassDesc(); 759 ObjectStreamClass streamClass = ObjectStreamClass.lookup(proxyClass); 760 streamClass.setLoadFields(ObjectStreamClass.NO_FIELDS); 761 registerObjectRead(streamClass, nextHandle(), false); 762 checkedSetSuperClassDesc(streamClass, readClassDesc()); 763 return streamClass; 764 case TC_REFERENCE: 765 return (ObjectStreamClass) readCyclicReference(); 766 case TC_NULL: 767 return null; 768 default: 769 throw corruptStream(tc); 770 } 771 } 772 773 private StreamCorruptedException corruptStream(byte tc) throws StreamCorruptedException { 774 throw new StreamCorruptedException("Wrong format: " + Integer.toHexString(tc & 0xff)); 775 } 776 777 /** 778 * Reads the content of the receiver based on the previously read token 779 * {@code tc}. 780 * 781 * @param tc 782 * The token code for the next item in the stream 783 * @return the object read from the stream 784 * 785 * @throws IOException 786 * If an IO exception happened when reading the class 787 * descriptor. 788 * @throws ClassNotFoundException 789 * If the class corresponding to the object being read could not 790 * be found. 791 */ 792 private Object readContent(byte tc) throws ClassNotFoundException, 793 IOException { 794 switch (tc) { 795 case TC_BLOCKDATA: 796 return readBlockData(); 797 case TC_BLOCKDATALONG: 798 return readBlockDataLong(); 799 case TC_CLASS: 800 return readNewClass(false); 801 case TC_CLASSDESC: 802 return readNewClassDesc(false); 803 case TC_ARRAY: 804 return readNewArray(false); 805 case TC_OBJECT: 806 return readNewObject(false); 807 case TC_STRING: 808 return readNewString(false); 809 case TC_LONGSTRING: 810 return readNewLongString(false); 811 case TC_REFERENCE: 812 return readCyclicReference(); 813 case TC_NULL: 814 return null; 815 case TC_EXCEPTION: 816 Exception exc = readException(); 817 throw new WriteAbortedException("Read an exception", exc); 818 case TC_RESET: 819 resetState(); 820 return null; 821 default: 822 throw corruptStream(tc); 823 } 824 } 825 826 /** 827 * Reads the content of the receiver based on the previously read token 828 * {@code tc}. Primitive data content is considered an error. 829 * 830 * @param unshared 831 * read the object unshared 832 * @return the object read from the stream 833 * 834 * @throws IOException 835 * If an IO exception happened when reading the class 836 * descriptor. 837 * @throws ClassNotFoundException 838 * If the class corresponding to the object being read could not 839 * be found. 840 */ 841 private Object readNonPrimitiveContent(boolean unshared) 842 throws ClassNotFoundException, IOException { 843 checkReadPrimitiveTypes(); 844 if (primitiveData.available() > 0) { 845 OptionalDataException e = new OptionalDataException(); 846 e.length = primitiveData.available(); 847 throw e; 848 } 849 850 do { 851 byte tc = nextTC(); 852 switch (tc) { 853 case TC_CLASS: 854 return readNewClass(unshared); 855 case TC_CLASSDESC: 856 return readNewClassDesc(unshared); 857 case TC_ARRAY: 858 return readNewArray(unshared); 859 case TC_OBJECT: 860 return readNewObject(unshared); 861 case TC_STRING: 862 return readNewString(unshared); 863 case TC_LONGSTRING: 864 return readNewLongString(unshared); 865 case TC_ENUM: 866 return readEnum(unshared); 867 case TC_REFERENCE: 868 if (unshared) { 869 readNewHandle(); 870 throw new InvalidObjectException("Unshared read of back reference"); 871 } 872 return readCyclicReference(); 873 case TC_NULL: 874 return null; 875 case TC_EXCEPTION: 876 Exception exc = readException(); 877 throw new WriteAbortedException("Read an exception", exc); 878 case TC_RESET: 879 resetState(); 880 break; 881 case TC_ENDBLOCKDATA: // Can occur reading class annotation 882 pushbackTC(); 883 OptionalDataException e = new OptionalDataException(); 884 e.eof = true; 885 throw e; 886 default: 887 throw corruptStream(tc); 888 } 889 // Only TC_RESET falls through 890 } while (true); 891 } 892 893 /** 894 * Reads the next item from the stream assuming it is a cyclic reference to 895 * an object previously read. Return the actual object previously read. 896 * 897 * @return the object previously read from the stream 898 * 899 * @throws IOException 900 * If an IO exception happened when reading the class 901 * descriptor. 902 * @throws InvalidObjectException 903 * If the cyclic reference is not valid. 904 */ 905 private Object readCyclicReference() throws InvalidObjectException, IOException { 906 return registeredObjectRead(readNewHandle()); 907 } 908 909 /** 910 * Reads a double (64 bit) from the source stream. 911 * 912 * @return the double value read from the source stream. 913 * @throws EOFException 914 * if the end of the input is reached before the read 915 * request can be satisfied. 916 * @throws IOException 917 * if an error occurs while reading from the source stream. 918 */ 919 public double readDouble() throws IOException { 920 return primitiveTypes.readDouble(); 921 } 922 923 /** 924 * Read the next item assuming it is an exception. The exception is not a 925 * regular instance in the object graph, but the exception instance that 926 * happened (if any) when dumping the original object graph. The set of seen 927 * objects will be reset just before and just after loading this exception 928 * object. 929 * <p> 930 * When exceptions are found normally in the object graph, they are loaded 931 * as a regular object, and not by this method. In that case, the set of 932 * "known objects" is not reset. 933 * 934 * @return the exception read 935 * 936 * @throws IOException 937 * If an IO exception happened when reading the exception 938 * object. 939 * @throws ClassNotFoundException 940 * If a class could not be found when reading the object graph 941 * for the exception 942 * @throws OptionalDataException 943 * If optional data could not be found when reading the 944 * exception graph 945 * @throws WriteAbortedException 946 * If another exception was caused when dumping this exception 947 */ 948 private Exception readException() throws WriteAbortedException, 949 OptionalDataException, ClassNotFoundException, IOException { 950 951 resetSeenObjects(); 952 953 // Now we read the Throwable object that was saved 954 // WARNING - the grammar says it is a Throwable, but the 955 // WriteAbortedException constructor takes an Exception. So, we read an 956 // Exception from the stream 957 Exception exc = (Exception) readObject(); 958 959 // We reset the receiver's state (the grammar has "reset" in normal 960 // font) 961 resetSeenObjects(); 962 return exc; 963 } 964 965 /** 966 * Reads a collection of field descriptors (name, type name, etc) for the 967 * class descriptor {@code cDesc} (an {@code ObjectStreamClass}) 968 * 969 * @param cDesc 970 * The class descriptor (an {@code ObjectStreamClass}) 971 * for which to write field information 972 * 973 * @throws IOException 974 * If an IO exception happened when reading the field 975 * descriptors. 976 * @throws ClassNotFoundException 977 * If a class for one of the field types could not be found 978 * 979 * @see #readObject() 980 */ 981 private void readFieldDescriptors(ObjectStreamClass cDesc) 982 throws ClassNotFoundException, IOException { 983 short numFields = input.readShort(); 984 ObjectStreamField[] fields = new ObjectStreamField[numFields]; 985 986 // We set it now, but each element will be inserted in the array further 987 // down 988 cDesc.setLoadFields(fields); 989 990 // Check ObjectOutputStream.writeFieldDescriptors 991 for (short i = 0; i < numFields; i++) { 992 char typecode = (char) input.readByte(); 993 String fieldName = input.readUTF(); 994 boolean isPrimType = ObjectStreamClass.isPrimitiveType(typecode); 995 String classSig; 996 if (isPrimType) { 997 classSig = String.valueOf(typecode); 998 } else { 999 // The spec says it is a UTF, but experience shows they dump 1000 // this String using writeObject (unlike the field name, which 1001 // is saved with writeUTF). 1002 // And if resolveObject is enabled, the classSig may be modified 1003 // so that the original class descriptor cannot be read 1004 // properly, so it is disabled. 1005 boolean old = enableResolve; 1006 try { 1007 enableResolve = false; 1008 classSig = (String) readObject(); 1009 } finally { 1010 enableResolve = old; 1011 } 1012 } 1013 1014 classSig = formatClassSig(classSig); 1015 ObjectStreamField f = new ObjectStreamField(classSig, fieldName); 1016 fields[i] = f; 1017 } 1018 } 1019 1020 /* 1021 * Format the class signature for ObjectStreamField, for example, 1022 * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;" 1023 */ 1024 private static String formatClassSig(String classSig) { 1025 int start = 0; 1026 int end = classSig.length(); 1027 1028 if (end <= 0) { 1029 return classSig; 1030 } 1031 1032 while (classSig.startsWith("[L", start) 1033 && classSig.charAt(end - 1) == ';') { 1034 start += 2; 1035 end--; 1036 } 1037 1038 if (start > 0) { 1039 start -= 2; 1040 end++; 1041 return classSig.substring(start, end); 1042 } 1043 return classSig; 1044 } 1045 1046 /** 1047 * Reads the persistent fields of the object that is currently being read 1048 * from the source stream. The values read are stored in a GetField object 1049 * that provides access to the persistent fields. This GetField object is 1050 * then returned. 1051 * 1052 * @return the GetField object from which persistent fields can be accessed 1053 * by name. 1054 * @throws ClassNotFoundException 1055 * if the class of an object being deserialized can not be 1056 * found. 1057 * @throws IOException 1058 * if an error occurs while reading from this stream. 1059 * @throws NotActiveException 1060 * if this stream is currently not reading an object. 1061 */ 1062 public GetField readFields() throws IOException, ClassNotFoundException, NotActiveException { 1063 // We can't be called from just anywhere. There are rules. 1064 if (currentObject == null) { 1065 throw new NotActiveException(); 1066 } 1067 EmulatedFieldsForLoading result = new EmulatedFieldsForLoading( 1068 currentClass); 1069 readFieldValues(result); 1070 return result; 1071 } 1072 1073 /** 1074 * Reads a collection of field values for the emulated fields 1075 * {@code emulatedFields} 1076 * 1077 * @param emulatedFields 1078 * an {@code EmulatedFieldsForLoading}, concrete subclass 1079 * of {@code GetField} 1080 * 1081 * @throws IOException 1082 * If an IO exception happened when reading the field values. 1083 * @throws InvalidClassException 1084 * If an incompatible type is being assigned to an emulated 1085 * field. 1086 * @throws OptionalDataException 1087 * If optional data could not be found when reading the 1088 * exception graph 1089 * 1090 * @see #readFields 1091 * @see #readObject() 1092 */ 1093 private void readFieldValues(EmulatedFieldsForLoading emulatedFields) 1094 throws OptionalDataException, InvalidClassException, IOException { 1095 EmulatedFields.ObjectSlot[] slots = emulatedFields.emulatedFields().slots(); 1096 for (ObjectSlot element : slots) { 1097 element.defaulted = false; 1098 Class<?> type = element.field.getType(); 1099 if (type == Integer.TYPE) { 1100 element.fieldValue = input.readInt(); 1101 } else if (type == Byte.TYPE) { 1102 element.fieldValue = input.readByte(); 1103 } else if (type == Character.TYPE) { 1104 element.fieldValue = input.readChar(); 1105 } else if (type == Short.TYPE) { 1106 element.fieldValue = input.readShort(); 1107 } else if (type == Boolean.TYPE) { 1108 element.fieldValue = input.readBoolean(); 1109 } else if (type == Long.TYPE) { 1110 element.fieldValue = input.readLong(); 1111 } else if (type == Float.TYPE) { 1112 element.fieldValue = input.readFloat(); 1113 } else if (type == Double.TYPE) { 1114 element.fieldValue = input.readDouble(); 1115 } else { 1116 // Either array or Object 1117 try { 1118 element.fieldValue = readObject(); 1119 } catch (ClassNotFoundException cnf) { 1120 // WARNING- Not sure this is the right thing to do. Write 1121 // test case. 1122 throw new InvalidClassException(cnf.toString()); 1123 } 1124 } 1125 } 1126 } 1127 1128 /** 1129 * Reads a collection of field values for the class descriptor 1130 * {@code classDesc} (an {@code ObjectStreamClass}). The 1131 * values will be used to set instance fields in object {@code obj}. 1132 * This is the default mechanism, when emulated fields (an 1133 * {@code GetField}) are not used. Actual values to load are stored 1134 * directly into the object {@code obj}. 1135 * 1136 * @param obj 1137 * Instance in which the fields will be set. 1138 * @param classDesc 1139 * A class descriptor (an {@code ObjectStreamClass}) 1140 * defining which fields should be loaded. 1141 * 1142 * @throws IOException 1143 * If an IO exception happened when reading the field values. 1144 * @throws InvalidClassException 1145 * If an incompatible type is being assigned to an emulated 1146 * field. 1147 * @throws OptionalDataException 1148 * If optional data could not be found when reading the 1149 * exception graph 1150 * @throws ClassNotFoundException 1151 * If a class of an object being de-serialized can not be found 1152 * 1153 * @see #readFields 1154 * @see #readObject() 1155 */ 1156 private void readFieldValues(Object obj, ObjectStreamClass classDesc) throws OptionalDataException, ClassNotFoundException, IOException { 1157 // Now we must read all fields and assign them to the receiver 1158 ObjectStreamField[] fields = classDesc.getLoadFields(); 1159 fields = (fields == null) ? ObjectStreamClass.NO_FIELDS : fields; 1160 Class<?> declaringClass = classDesc.forClass(); 1161 if (declaringClass == null && mustResolve) { 1162 throw new ClassNotFoundException(classDesc.getName()); 1163 } 1164 1165 for (ObjectStreamField fieldDesc : fields) { 1166 Field field = classDesc.getReflectionField(fieldDesc); 1167 // We may not have been able to find the field, but we still need to read the value 1168 // and do the other checking, so there's no null check on 'field' here. 1169 try { 1170 switch (fieldDesc.getTypeCode()) { 1171 case 'B': 1172 byte b = input.readByte(); 1173 if (field != null) { 1174 field.setByte(obj, b); 1175 } 1176 break; 1177 case 'C': 1178 char c = input.readChar(); 1179 if (field != null) { 1180 field.setChar(obj, c); 1181 } 1182 break; 1183 case 'D': 1184 double d = input.readDouble(); 1185 if (field != null) { 1186 field.setDouble(obj, d); 1187 } 1188 break; 1189 case 'F': 1190 float f = input.readFloat(); 1191 if (field != null) { 1192 field.setFloat(obj, f); 1193 } 1194 break; 1195 case 'I': 1196 int i = input.readInt(); 1197 if (field != null) { 1198 field.setInt(obj, i); 1199 } 1200 break; 1201 case 'J': 1202 long j = input.readLong(); 1203 if (field != null) { 1204 field.setLong(obj, j); 1205 } 1206 break; 1207 case 'S': 1208 short s = input.readShort(); 1209 if (field != null) { 1210 field.setShort(obj, s); 1211 } 1212 break; 1213 case 'Z': 1214 boolean z = input.readBoolean(); 1215 if (field != null) { 1216 field.setBoolean(obj, z); 1217 } 1218 break; 1219 case 'L': 1220 case '[': 1221 String fieldName = fieldDesc.getName(); 1222 boolean setBack = false; 1223 ObjectStreamField localFieldDesc = classDesc.getField(fieldName); 1224 if (mustResolve && fieldDesc == null) { 1225 setBack = true; 1226 mustResolve = false; 1227 } 1228 boolean unshared = fieldDesc != null && fieldDesc.isUnshared(); 1229 Object toSet = unshared ? readUnshared() : readObject(); 1230 if (setBack) { 1231 mustResolve = true; 1232 } 1233 if (fieldDesc != null) { 1234 if (toSet != null) { 1235 // BEGIN android-changed 1236 // Get the field type from the local field rather than 1237 // from the stream's supplied data. That's the field 1238 // we'll be setting, so that's the one that needs to be 1239 // validated. 1240 Class<?> fieldType = localFieldDesc.getTypeInternal(); 1241 // END android-added 1242 Class<?> valueType = toSet.getClass(); 1243 if (!fieldType.isAssignableFrom(valueType)) { 1244 throw new ClassCastException(classDesc.getName() + "." + fieldName + " - " + fieldType + " not compatible with " + valueType); 1245 } 1246 if (field != null) { 1247 field.set(obj, toSet); 1248 } 1249 } 1250 } 1251 break; 1252 default: 1253 throw new StreamCorruptedException("Invalid typecode: " + fieldDesc.getTypeCode()); 1254 } 1255 } catch (IllegalAccessException iae) { 1256 // ObjectStreamField should have called setAccessible(true). 1257 throw new AssertionError(iae); 1258 } catch (NoSuchFieldError ignored) { 1259 } 1260 } 1261 } 1262 1263 /** 1264 * Reads a float (32 bit) from the source stream. 1265 * 1266 * @return the float value read from the source stream. 1267 * @throws EOFException 1268 * if the end of the input is reached before the read 1269 * request can be satisfied. 1270 * @throws IOException 1271 * if an error occurs while reading from the source stream. 1272 */ 1273 public float readFloat() throws IOException { 1274 return primitiveTypes.readFloat(); 1275 } 1276 1277 /** 1278 * Reads bytes from the source stream into the byte array {@code dst}. 1279 * This method will block until {@code dst.length} bytes have been read. 1280 * 1281 * @param dst 1282 * the array in which to store the bytes read. 1283 * @throws EOFException 1284 * if the end of the input is reached before the read 1285 * request can be satisfied. 1286 * @throws IOException 1287 * if an error occurs while reading from the source stream. 1288 */ 1289 public void readFully(byte[] dst) throws IOException { 1290 primitiveTypes.readFully(dst); 1291 } 1292 1293 /** 1294 * Reads {@code byteCount} bytes from the source stream into the byte array {@code dst}. 1295 * 1296 * @param dst 1297 * the byte array in which to store the bytes read. 1298 * @param offset 1299 * the initial position in {@code dst} to store the bytes 1300 * read from the source stream. 1301 * @param byteCount 1302 * the number of bytes to read. 1303 * @throws EOFException 1304 * if the end of the input is reached before the read 1305 * request can be satisfied. 1306 * @throws IOException 1307 * if an error occurs while reading from the source stream. 1308 */ 1309 public void readFully(byte[] dst, int offset, int byteCount) throws IOException { 1310 primitiveTypes.readFully(dst, offset, byteCount); 1311 } 1312 1313 /** 1314 * Walks the hierarchy of classes described by class descriptor 1315 * {@code classDesc} and reads the field values corresponding to 1316 * fields declared by the corresponding class descriptor. The instance to 1317 * store field values into is {@code object}. If the class 1318 * (corresponding to class descriptor {@code classDesc}) defines 1319 * private instance method {@code readObject} it will be used to load 1320 * field values. 1321 * 1322 * @param object 1323 * Instance into which stored field values loaded. 1324 * @param classDesc 1325 * A class descriptor (an {@code ObjectStreamClass}) 1326 * defining which fields should be loaded. 1327 * 1328 * @throws IOException 1329 * If an IO exception happened when reading the field values in 1330 * the hierarchy. 1331 * @throws ClassNotFoundException 1332 * If a class for one of the field types could not be found 1333 * @throws NotActiveException 1334 * If {@code defaultReadObject} is called from the wrong 1335 * context. 1336 * 1337 * @see #defaultReadObject 1338 * @see #readObject() 1339 */ 1340 private void readHierarchy(Object object, ObjectStreamClass classDesc) 1341 throws IOException, ClassNotFoundException, NotActiveException { 1342 // We can't be called from just anywhere. There are rules. 1343 if (object == null && mustResolve) { 1344 throw new NotActiveException(); 1345 } 1346 1347 ArrayList<ObjectStreamClass> streamClassList = new ArrayList<ObjectStreamClass>(32); 1348 ObjectStreamClass nextStreamClass = classDesc; 1349 while (nextStreamClass != null) { 1350 streamClassList.add(0, nextStreamClass); 1351 nextStreamClass = nextStreamClass.getSuperclass(); 1352 } 1353 if (object == null) { 1354 for (ObjectStreamClass objectStreamClass : streamClassList) { 1355 readObjectForClass(null, objectStreamClass); 1356 } 1357 } else { 1358 ArrayList<Class<?>> classList = new ArrayList<Class<?>>(32); 1359 Class<?> nextClass = object.getClass(); 1360 while (nextClass != null) { 1361 Class<?> testClass = nextClass.getSuperclass(); 1362 if (testClass != null) { 1363 classList.add(0, nextClass); 1364 } 1365 nextClass = testClass; 1366 } 1367 int lastIndex = 0; 1368 for (Class<?> superclass : classList) { 1369 int index = findStreamSuperclass(superclass, streamClassList, lastIndex); 1370 if (index == -1) { 1371 readObjectNoData(object, superclass, 1372 ObjectStreamClass.lookupStreamClass(superclass)); 1373 } else { 1374 for (int j = lastIndex; j <= index; j++) { 1375 readObjectForClass(object, streamClassList.get(j)); 1376 } 1377 lastIndex = index + 1; 1378 } 1379 } 1380 } 1381 } 1382 1383 private int findStreamSuperclass(Class<?> cl, 1384 ArrayList<ObjectStreamClass> classList, int lastIndex) { 1385 ObjectStreamClass objCl; 1386 String forName; 1387 1388 for (int i = lastIndex; i < classList.size(); i++) { 1389 objCl = classList.get(i); 1390 forName = objCl.forClass().getName(); 1391 1392 if (objCl.getName().equals(forName)) { 1393 if (cl.getName().equals(objCl.getName())) { 1394 return i; 1395 } 1396 } else { 1397 // there was a class replacement 1398 if (cl.getName().equals(forName)) { 1399 return i; 1400 } 1401 } 1402 } 1403 return -1; 1404 } 1405 1406 private void readObjectNoData(Object object, Class<?> cl, ObjectStreamClass classDesc) 1407 throws ObjectStreamException { 1408 if (!classDesc.isSerializable()) { 1409 return; 1410 } 1411 if (classDesc.hasMethodReadObjectNoData()){ 1412 final Method readMethod = classDesc.getMethodReadObjectNoData(); 1413 try { 1414 readMethod.invoke(object); 1415 } catch (InvocationTargetException e) { 1416 Throwable ex = e.getTargetException(); 1417 if (ex instanceof RuntimeException) { 1418 throw (RuntimeException) ex; 1419 } else if (ex instanceof Error) { 1420 throw (Error) ex; 1421 } 1422 throw (ObjectStreamException) ex; 1423 } catch (IllegalAccessException e) { 1424 throw new RuntimeException(e.toString()); 1425 } 1426 } 1427 1428 } 1429 1430 private void readObjectForClass(Object object, ObjectStreamClass classDesc) 1431 throws IOException, ClassNotFoundException, NotActiveException { 1432 // Have to do this before calling defaultReadObject or anything that 1433 // calls defaultReadObject 1434 currentObject = object; 1435 currentClass = classDesc; 1436 1437 boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) != 0; 1438 Class<?> targetClass = classDesc.forClass(); 1439 1440 final Method readMethod; 1441 if (targetClass == null || !mustResolve) { 1442 readMethod = null; 1443 } else { 1444 readMethod = classDesc.getMethodReadObject(); 1445 } 1446 try { 1447 if (readMethod != null) { 1448 // We have to be able to fetch its value, even if it is private 1449 AccessController.doPrivileged(new PriviAction<Object>( 1450 readMethod)); 1451 try { 1452 readMethod.invoke(object, this); 1453 } catch (InvocationTargetException e) { 1454 Throwable ex = e.getTargetException(); 1455 if (ex instanceof ClassNotFoundException) { 1456 throw (ClassNotFoundException) ex; 1457 } else if (ex instanceof RuntimeException) { 1458 throw (RuntimeException) ex; 1459 } else if (ex instanceof Error) { 1460 throw (Error) ex; 1461 } 1462 throw (IOException) ex; 1463 } catch (IllegalAccessException e) { 1464 throw new RuntimeException(e.toString()); 1465 } 1466 } else { 1467 defaultReadObject(); 1468 } 1469 if (hadWriteMethod) { 1470 discardData(); 1471 } 1472 } finally { 1473 // Cleanup, needs to run always so that we can later detect invalid 1474 // calls to defaultReadObject 1475 currentObject = null; // We did not set this, so we do not need to 1476 // clean it 1477 currentClass = null; 1478 } 1479 } 1480 1481 /** 1482 * Reads an integer (32 bit) from the source stream. 1483 * 1484 * @return the integer value read from the source stream. 1485 * @throws EOFException 1486 * if the end of the input is reached before the read 1487 * request can be satisfied. 1488 * @throws IOException 1489 * if an error occurs while reading from the source stream. 1490 */ 1491 public int readInt() throws IOException { 1492 return primitiveTypes.readInt(); 1493 } 1494 1495 /** 1496 * Reads the next line from the source stream. Lines are terminated by 1497 * {@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}. 1498 * 1499 * @return the string read from the source stream. 1500 * @throws IOException 1501 * if an error occurs while reading from the source stream. 1502 * @deprecated Use {@link BufferedReader} 1503 */ 1504 @Deprecated 1505 public String readLine() throws IOException { 1506 return primitiveTypes.readLine(); 1507 } 1508 1509 /** 1510 * Reads a long (64 bit) from the source stream. 1511 * 1512 * @return the long value read from the source stream. 1513 * @throws EOFException 1514 * if the end of the input is reached before the read 1515 * request can be satisfied. 1516 * @throws IOException 1517 * if an error occurs while reading from the source stream. 1518 */ 1519 public long readLong() throws IOException { 1520 return primitiveTypes.readLong(); 1521 } 1522 1523 /** 1524 * Read a new array from the receiver. It is assumed the array has not been 1525 * read yet (not a cyclic reference). Return the array read. 1526 * 1527 * @param unshared 1528 * read the object unshared 1529 * @return the array read 1530 * 1531 * @throws IOException 1532 * If an IO exception happened when reading the array. 1533 * @throws ClassNotFoundException 1534 * If a class for one of the objects could not be found 1535 * @throws OptionalDataException 1536 * If optional data could not be found when reading the array. 1537 */ 1538 private Object readNewArray(boolean unshared) throws OptionalDataException, 1539 ClassNotFoundException, IOException { 1540 ObjectStreamClass classDesc = readClassDesc(); 1541 1542 if (classDesc == null) { 1543 throw missingClassDescriptor(); 1544 } 1545 1546 int newHandle = nextHandle(); 1547 1548 // Array size 1549 int size = input.readInt(); 1550 Class<?> arrayClass = classDesc.forClass(); 1551 Class<?> componentType = arrayClass.getComponentType(); 1552 Object result = Array.newInstance(componentType, size); 1553 1554 registerObjectRead(result, newHandle, unshared); 1555 1556 // Now we have code duplication just because Java is typed. We have to 1557 // read N elements and assign to array positions, but we must typecast 1558 // the array first, and also call different methods depending on the 1559 // elements. 1560 if (componentType.isPrimitive()) { 1561 if (componentType == Integer.TYPE) { 1562 int[] intArray = (int[]) result; 1563 for (int i = 0; i < size; i++) { 1564 intArray[i] = input.readInt(); 1565 } 1566 } else if (componentType == Byte.TYPE) { 1567 byte[] byteArray = (byte[]) result; 1568 input.readFully(byteArray, 0, size); 1569 } else if (componentType == Character.TYPE) { 1570 char[] charArray = (char[]) result; 1571 for (int i = 0; i < size; i++) { 1572 charArray[i] = input.readChar(); 1573 } 1574 } else if (componentType == Short.TYPE) { 1575 short[] shortArray = (short[]) result; 1576 for (int i = 0; i < size; i++) { 1577 shortArray[i] = input.readShort(); 1578 } 1579 } else if (componentType == Boolean.TYPE) { 1580 boolean[] booleanArray = (boolean[]) result; 1581 for (int i = 0; i < size; i++) { 1582 booleanArray[i] = input.readBoolean(); 1583 } 1584 } else if (componentType == Long.TYPE) { 1585 long[] longArray = (long[]) result; 1586 for (int i = 0; i < size; i++) { 1587 longArray[i] = input.readLong(); 1588 } 1589 } else if (componentType == Float.TYPE) { 1590 float[] floatArray = (float[]) result; 1591 for (int i = 0; i < size; i++) { 1592 floatArray[i] = input.readFloat(); 1593 } 1594 } else if (componentType == Double.TYPE) { 1595 double[] doubleArray = (double[]) result; 1596 for (int i = 0; i < size; i++) { 1597 doubleArray[i] = input.readDouble(); 1598 } 1599 } else { 1600 throw new ClassNotFoundException("Wrong base type in " + classDesc.getName()); 1601 } 1602 } else { 1603 // Array of Objects 1604 Object[] objectArray = (Object[]) result; 1605 for (int i = 0; i < size; i++) { 1606 // TODO: This place is the opportunity for enhancement 1607 // We can implement writing elements through fast-path, 1608 // without setting up the context (see readObject()) for 1609 // each element with public API 1610 objectArray[i] = readObject(); 1611 } 1612 } 1613 if (enableResolve) { 1614 result = resolveObject(result); 1615 registerObjectRead(result, newHandle, false); 1616 } 1617 return result; 1618 } 1619 1620 /** 1621 * Reads a new class from the receiver. It is assumed the class has not been 1622 * read yet (not a cyclic reference). Return the class read. 1623 * 1624 * @param unshared 1625 * read the object unshared 1626 * @return The {@code java.lang.Class} read from the stream. 1627 * 1628 * @throws IOException 1629 * If an IO exception happened when reading the class. 1630 * @throws ClassNotFoundException 1631 * If a class for one of the objects could not be found 1632 */ 1633 private Class<?> readNewClass(boolean unshared) throws ClassNotFoundException, IOException { 1634 ObjectStreamClass classDesc = readClassDesc(); 1635 if (classDesc == null) { 1636 throw missingClassDescriptor(); 1637 } 1638 Class<?> localClass = classDesc.forClass(); 1639 if (localClass != null) { 1640 registerObjectRead(localClass, nextHandle(), unshared); 1641 } 1642 return localClass; 1643 } 1644 1645 /* 1646 * read class type for Enum, note there's difference between enum and normal 1647 * classes 1648 */ 1649 private ObjectStreamClass readEnumDesc() throws IOException, 1650 ClassNotFoundException { 1651 byte tc = nextTC(); 1652 switch (tc) { 1653 case TC_CLASSDESC: 1654 return readEnumDescInternal(); 1655 case TC_REFERENCE: 1656 return (ObjectStreamClass) readCyclicReference(); 1657 case TC_NULL: 1658 return null; 1659 default: 1660 throw corruptStream(tc); 1661 } 1662 } 1663 1664 private ObjectStreamClass readEnumDescInternal() throws IOException, ClassNotFoundException { 1665 ObjectStreamClass classDesc; 1666 primitiveData = input; 1667 int oldHandle = descriptorHandle; 1668 descriptorHandle = nextHandle(); 1669 classDesc = readClassDescriptor(); 1670 registerObjectRead(classDesc, descriptorHandle, false); 1671 descriptorHandle = oldHandle; 1672 primitiveData = emptyStream; 1673 classDesc.setClass(resolveClass(classDesc)); 1674 // Consume unread class annotation data and TC_ENDBLOCKDATA 1675 discardData(); 1676 ObjectStreamClass superClass = readClassDesc(); 1677 checkedSetSuperClassDesc(classDesc, superClass); 1678 // Check SUIDs, note all SUID for Enum is 0L 1679 if (0L != classDesc.getSerialVersionUID() || 0L != superClass.getSerialVersionUID()) { 1680 throw new InvalidClassException(superClass.getName(), 1681 "Incompatible class (SUID): " + superClass + " but expected " + superClass); 1682 } 1683 byte tc = nextTC(); 1684 // discard TC_ENDBLOCKDATA after classDesc if any 1685 if (tc == TC_ENDBLOCKDATA) { 1686 // read next parent class. For enum, it may be null 1687 superClass.setSuperclass(readClassDesc()); 1688 } else { 1689 // not TC_ENDBLOCKDATA, push back for next read 1690 pushbackTC(); 1691 } 1692 return classDesc; 1693 } 1694 1695 @SuppressWarnings("unchecked")// For the Enum.valueOf call 1696 private Object readEnum(boolean unshared) throws OptionalDataException, 1697 ClassNotFoundException, IOException { 1698 // read classdesc for Enum first 1699 ObjectStreamClass classDesc = readEnumDesc(); 1700 int newHandle = nextHandle(); 1701 // read name after class desc 1702 String name; 1703 byte tc = nextTC(); 1704 switch (tc) { 1705 case TC_REFERENCE: 1706 if (unshared) { 1707 readNewHandle(); 1708 throw new InvalidObjectException("Unshared read of back reference"); 1709 } 1710 name = (String) readCyclicReference(); 1711 break; 1712 case TC_STRING: 1713 name = (String) readNewString(unshared); 1714 break; 1715 default: 1716 throw corruptStream(tc); 1717 } 1718 1719 Enum<?> result = Enum.valueOf((Class) classDesc.forClass(), name); 1720 registerObjectRead(result, newHandle, unshared); 1721 1722 return result; 1723 } 1724 1725 /** 1726 * Reads a new class descriptor from the receiver. It is assumed the class 1727 * descriptor has not been read yet (not a cyclic reference). Return the 1728 * class descriptor read. 1729 * 1730 * @param unshared 1731 * read the object unshared 1732 * @return The {@code ObjectStreamClass} read from the stream. 1733 * 1734 * @throws IOException 1735 * If an IO exception happened when reading the class 1736 * descriptor. 1737 * @throws ClassNotFoundException 1738 * If a class for one of the objects could not be found 1739 */ 1740 private ObjectStreamClass readNewClassDesc(boolean unshared) 1741 throws ClassNotFoundException, IOException { 1742 // So read...() methods can be used by 1743 // subclasses during readClassDescriptor() 1744 primitiveData = input; 1745 int oldHandle = descriptorHandle; 1746 descriptorHandle = nextHandle(); 1747 ObjectStreamClass newClassDesc = readClassDescriptor(); 1748 registerObjectRead(newClassDesc, descriptorHandle, unshared); 1749 descriptorHandle = oldHandle; 1750 primitiveData = emptyStream; 1751 1752 // We need to map classDesc to class. 1753 try { 1754 newClassDesc.setClass(resolveClass(newClassDesc)); 1755 // Check SUIDs & base name of the class 1756 verifyAndInit(newClassDesc); 1757 } catch (ClassNotFoundException e) { 1758 if (mustResolve) { 1759 throw e; 1760 // Just continue, the class may not be required 1761 } 1762 } 1763 1764 // Resolve the field signatures using the class loader of the 1765 // resolved class 1766 ObjectStreamField[] fields = newClassDesc.getLoadFields(); 1767 fields = (fields == null) ? ObjectStreamClass.NO_FIELDS : fields; 1768 ClassLoader loader = newClassDesc.forClass() == null ? callerClassLoader 1769 : newClassDesc.forClass().getClassLoader(); 1770 for (ObjectStreamField element : fields) { 1771 element.resolve(loader); 1772 } 1773 1774 // Consume unread class annotation data and TC_ENDBLOCKDATA 1775 discardData(); 1776 checkedSetSuperClassDesc(newClassDesc, readClassDesc()); 1777 return newClassDesc; 1778 } 1779 1780 /** 1781 * Reads a new proxy class descriptor from the receiver. It is assumed the 1782 * proxy class descriptor has not been read yet (not a cyclic reference). 1783 * Return the proxy class descriptor read. 1784 * 1785 * @return The {@code Class} read from the stream. 1786 * 1787 * @throws IOException 1788 * If an IO exception happened when reading the class 1789 * descriptor. 1790 * @throws ClassNotFoundException 1791 * If a class for one of the objects could not be found 1792 */ 1793 private Class<?> readNewProxyClassDesc() throws ClassNotFoundException, 1794 IOException { 1795 int count = input.readInt(); 1796 String[] interfaceNames = new String[count]; 1797 for (int i = 0; i < count; i++) { 1798 interfaceNames[i] = input.readUTF(); 1799 } 1800 Class<?> proxy = resolveProxyClass(interfaceNames); 1801 // Consume unread class annotation data and TC_ENDBLOCKDATA 1802 discardData(); 1803 return proxy; 1804 } 1805 1806 /** 1807 * Reads a class descriptor from the source stream. 1808 * 1809 * @return the class descriptor read from the source stream. 1810 * @throws ClassNotFoundException 1811 * if a class for one of the objects cannot be found. 1812 * @throws IOException 1813 * if an error occurs while reading from the source stream. 1814 */ 1815 protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { 1816 ObjectStreamClass newClassDesc = new ObjectStreamClass(); 1817 String name = input.readUTF(); 1818 if (name.length() == 0) { 1819 throw new IOException("The stream is corrupted"); 1820 } 1821 newClassDesc.setName(name); 1822 newClassDesc.setSerialVersionUID(input.readLong()); 1823 newClassDesc.setFlags(input.readByte()); 1824 1825 /* 1826 * We must register the class descriptor before reading field 1827 * descriptors. If called outside of readObject, the descriptorHandle 1828 * might be unset. 1829 */ 1830 if (descriptorHandle == -1) { 1831 descriptorHandle = nextHandle(); 1832 } 1833 registerObjectRead(newClassDesc, descriptorHandle, false); 1834 1835 readFieldDescriptors(newClassDesc); 1836 return newClassDesc; 1837 } 1838 1839 /** 1840 * Creates the proxy class that implements the interfaces specified in 1841 * {@code interfaceNames}. 1842 * 1843 * @param interfaceNames 1844 * the interfaces used to create the proxy class. 1845 * @return the proxy class. 1846 * @throws ClassNotFoundException 1847 * if the proxy class or any of the specified interfaces cannot 1848 * be created. 1849 * @throws IOException 1850 * if an error occurs while reading from the source stream. 1851 * @see ObjectOutputStream#annotateProxyClass(Class) 1852 */ 1853 protected Class<?> resolveProxyClass(String[] interfaceNames) 1854 throws IOException, ClassNotFoundException { 1855 // TODO: This method is opportunity for performance enhancement 1856 // We can cache the classloader and recently used interfaces. 1857 // BEGIN android-changed 1858 // ClassLoader loader = VM.getNonBootstrapClassLoader(); 1859 ClassLoader loader = ClassLoader.getSystemClassLoader(); 1860 // END android-changed 1861 Class<?>[] interfaces = new Class<?>[interfaceNames.length]; 1862 for (int i = 0; i < interfaceNames.length; i++) { 1863 interfaces[i] = Class.forName(interfaceNames[i], false, loader); 1864 } 1865 try { 1866 return Proxy.getProxyClass(loader, interfaces); 1867 } catch (IllegalArgumentException e) { 1868 throw new ClassNotFoundException(e.toString(), e); 1869 } 1870 } 1871 1872 private int readNewHandle() throws IOException { 1873 return input.readInt(); 1874 } 1875 1876 /** 1877 * Read a new object from the stream. It is assumed the object has not been 1878 * loaded yet (not a cyclic reference). Return the object read. 1879 * 1880 * If the object implements <code>Externalizable</code> its 1881 * <code>readExternal</code> is called. Otherwise, all fields described by 1882 * the class hierarchy are loaded. Each class can define how its declared 1883 * instance fields are loaded by defining a private method 1884 * <code>readObject</code> 1885 * 1886 * @param unshared 1887 * read the object unshared 1888 * @return the object read 1889 * 1890 * @throws IOException 1891 * If an IO exception happened when reading the object. 1892 * @throws OptionalDataException 1893 * If optional data could not be found when reading the object 1894 * graph 1895 * @throws ClassNotFoundException 1896 * If a class for one of the objects could not be found 1897 */ 1898 private Object readNewObject(boolean unshared) 1899 throws OptionalDataException, ClassNotFoundException, IOException { 1900 ObjectStreamClass classDesc = readClassDesc(); 1901 1902 if (classDesc == null) { 1903 throw missingClassDescriptor(); 1904 } 1905 1906 int newHandle = nextHandle(); 1907 Class<?> objectClass = classDesc.forClass(); 1908 Object result = null; 1909 Object registeredResult = null; 1910 if (objectClass != null) { 1911 // Now we know which class to instantiate and which constructor to 1912 // run. We are allowed to run the constructor. 1913 result = classDesc.newInstance(objectClass); 1914 registerObjectRead(result, newHandle, unshared); 1915 registeredResult = result; 1916 } else { 1917 result = null; 1918 } 1919 1920 try { 1921 // This is how we know what to do in defaultReadObject. And it is 1922 // also used by defaultReadObject to check if it was called from an 1923 // invalid place. It also allows readExternal to call 1924 // defaultReadObject and have it work. 1925 currentObject = result; 1926 currentClass = classDesc; 1927 1928 // If Externalizable, just let the object read itself 1929 // Note that this value comes from the Stream, and in fact it could be 1930 // that the classes have been changed so that the info below now 1931 // conflicts with the newer class 1932 boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) != 0; 1933 if (wasExternalizable) { 1934 boolean blockData = (classDesc.getFlags() & SC_BLOCK_DATA) != 0; 1935 if (!blockData) { 1936 primitiveData = input; 1937 } 1938 if (mustResolve) { 1939 Externalizable extern = (Externalizable) result; 1940 extern.readExternal(this); 1941 } 1942 if (blockData) { 1943 // Similar to readHierarchy. Anything not read by 1944 // readExternal has to be consumed here 1945 discardData(); 1946 } else { 1947 primitiveData = emptyStream; 1948 } 1949 } else { 1950 // If we got here, it is Serializable but not Externalizable. 1951 // Walk the hierarchy reading each class' slots 1952 readHierarchy(result, classDesc); 1953 } 1954 } finally { 1955 // Cleanup, needs to run always so that we can later detect invalid 1956 // calls to defaultReadObject 1957 currentObject = null; 1958 currentClass = null; 1959 } 1960 1961 if (objectClass != null) { 1962 1963 if (classDesc.hasMethodReadResolve()){ 1964 Method methodReadResolve = classDesc.getMethodReadResolve(); 1965 try { 1966 result = methodReadResolve.invoke(result, (Object[]) null); 1967 } catch (IllegalAccessException ignored) { 1968 } catch (InvocationTargetException ite) { 1969 Throwable target = ite.getTargetException(); 1970 if (target instanceof ObjectStreamException) { 1971 throw (ObjectStreamException) target; 1972 } else if (target instanceof Error) { 1973 throw (Error) target; 1974 } else { 1975 throw (RuntimeException) target; 1976 } 1977 } 1978 1979 } 1980 } 1981 // We get here either if class-based replacement was not needed or if it 1982 // was needed but produced the same object or if it could not be 1983 // computed. 1984 1985 // The object to return is the one we instantiated or a replacement for 1986 // it 1987 if (result != null && enableResolve) { 1988 result = resolveObject(result); 1989 } 1990 if (registeredResult != result) { 1991 registerObjectRead(result, newHandle, unshared); 1992 } 1993 return result; 1994 } 1995 1996 private InvalidClassException missingClassDescriptor() throws InvalidClassException { 1997 throw new InvalidClassException("Read null attempting to read class descriptor for object"); 1998 } 1999 2000 /** 2001 * Read a string encoded in {@link DataInput modified UTF-8} from the 2002 * receiver. Return the string read. 2003 * 2004 * @param unshared 2005 * read the object unshared 2006 * @return the string just read. 2007 * @throws IOException 2008 * If an IO exception happened when reading the String. 2009 */ 2010 private Object readNewString(boolean unshared) throws IOException { 2011 Object result = input.readUTF(); 2012 if (enableResolve) { 2013 result = resolveObject(result); 2014 } 2015 registerObjectRead(result, nextHandle(), unshared); 2016 2017 return result; 2018 } 2019 2020 /** 2021 * Read a new String in UTF format from the receiver. Return the string 2022 * read. 2023 * 2024 * @param unshared 2025 * read the object unshared 2026 * @return the string just read. 2027 * 2028 * @throws IOException 2029 * If an IO exception happened when reading the String. 2030 */ 2031 private Object readNewLongString(boolean unshared) throws IOException { 2032 long length = input.readLong(); 2033 Object result = input.decodeUTF((int) length); 2034 if (enableResolve) { 2035 result = resolveObject(result); 2036 } 2037 registerObjectRead(result, nextHandle(), unshared); 2038 2039 return result; 2040 } 2041 2042 /** 2043 * Reads the next object from the source stream. 2044 * 2045 * @return the object read from the source stream. 2046 * @throws ClassNotFoundException 2047 * if the class of one of the objects in the object graph cannot 2048 * be found. 2049 * @throws IOException 2050 * if an error occurs while reading from the source stream. 2051 * @throws OptionalDataException 2052 * if primitive data types were found instead of an object. 2053 * @see ObjectOutputStream#writeObject(Object) 2054 */ 2055 public final Object readObject() throws OptionalDataException, 2056 ClassNotFoundException, IOException { 2057 return readObject(false); 2058 } 2059 2060 /** 2061 * Reads the next unshared object from the source stream. 2062 * 2063 * @return the new object read. 2064 * @throws ClassNotFoundException 2065 * if the class of one of the objects in the object graph cannot 2066 * be found. 2067 * @throws IOException 2068 * if an error occurs while reading from the source stream. 2069 * @see ObjectOutputStream#writeUnshared 2070 */ 2071 public Object readUnshared() throws IOException, ClassNotFoundException { 2072 return readObject(true); 2073 } 2074 2075 private Object readObject(boolean unshared) throws OptionalDataException, 2076 ClassNotFoundException, IOException { 2077 boolean restoreInput = (primitiveData == input); 2078 if (restoreInput) { 2079 primitiveData = emptyStream; 2080 } 2081 2082 // This is the spec'ed behavior in JDK 1.2. Very bizarre way to allow 2083 // behavior overriding. 2084 if (subclassOverridingImplementation && !unshared) { 2085 return readObjectOverride(); 2086 } 2087 2088 // If we still had primitive types to read, should we discard them 2089 // (reset the primitiveTypes stream) or leave as is, so that attempts to 2090 // read primitive types won't read 'past data' ??? 2091 Object result; 2092 try { 2093 // We need this so we can tell when we are returning to the 2094 // original/outside caller 2095 if (++nestedLevels == 1) { 2096 // Remember the caller's class loader 2097 // BEGIN android-changed 2098 callerClassLoader = getClosestUserClassLoader(); 2099 // END android-changed 2100 } 2101 2102 result = readNonPrimitiveContent(unshared); 2103 if (restoreInput) { 2104 primitiveData = input; 2105 } 2106 } finally { 2107 // We need this so we can tell when we are returning to the 2108 // original/outside caller 2109 if (--nestedLevels == 0) { 2110 // We are going to return to the original caller, perform 2111 // cleanups. 2112 // No more need to remember the caller's class loader 2113 callerClassLoader = null; 2114 } 2115 } 2116 2117 // Done reading this object. Is it time to return to the original 2118 // caller? If so we need to perform validations first. 2119 if (nestedLevels == 0 && validations != null) { 2120 // We are going to return to the original caller. If validation is 2121 // enabled we need to run them now and then cleanup the validation 2122 // collection 2123 try { 2124 for (InputValidationDesc element : validations) { 2125 element.validator.validateObject(); 2126 } 2127 } finally { 2128 // Validations have to be renewed, since they are only called 2129 // from readObject 2130 validations = null; 2131 } 2132 } 2133 return result; 2134 } 2135 2136 // BEGIN android-added 2137 private static final ClassLoader bootstrapLoader 2138 = Object.class.getClassLoader(); 2139 private static final ClassLoader systemLoader 2140 = ClassLoader.getSystemClassLoader(); 2141 2142 /** 2143 * Searches up the call stack to find the closest user-defined class loader. 2144 * 2145 * @return a user-defined class loader or null if one isn't found 2146 */ 2147 private static ClassLoader getClosestUserClassLoader() { 2148 Class<?>[] stackClasses = VMStack.getClasses(-1, false); 2149 for (Class<?> stackClass : stackClasses) { 2150 ClassLoader loader = stackClass.getClassLoader(); 2151 if (loader != null && loader != bootstrapLoader 2152 && loader != systemLoader) { 2153 return loader; 2154 } 2155 } 2156 return null; 2157 } 2158 // END android-added 2159 2160 /** 2161 * Method to be overridden by subclasses to read the next object from the 2162 * source stream. 2163 * 2164 * @return the object read from the source stream. 2165 * @throws ClassNotFoundException 2166 * if the class of one of the objects in the object graph cannot 2167 * be found. 2168 * @throws IOException 2169 * if an error occurs while reading from the source stream. 2170 * @throws OptionalDataException 2171 * if primitive data types were found instead of an object. 2172 * @see ObjectOutputStream#writeObjectOverride 2173 */ 2174 protected Object readObjectOverride() throws OptionalDataException, 2175 ClassNotFoundException, IOException { 2176 if (input == null) { 2177 return null; 2178 } 2179 // Subclasses must override. 2180 throw new IOException(); 2181 } 2182 2183 /** 2184 * Reads a short (16 bit) from the source stream. 2185 * 2186 * @return the short value read from the source stream. 2187 * @throws IOException 2188 * if an error occurs while reading from the source stream. 2189 */ 2190 public short readShort() throws IOException { 2191 return primitiveTypes.readShort(); 2192 } 2193 2194 /** 2195 * Reads and validates the ObjectInputStream header from the source stream. 2196 * 2197 * @throws IOException 2198 * if an error occurs while reading from the source stream. 2199 * @throws StreamCorruptedException 2200 * if the source stream does not contain readable serialized 2201 * objects. 2202 */ 2203 protected void readStreamHeader() throws IOException, 2204 StreamCorruptedException { 2205 if (input.readShort() == STREAM_MAGIC 2206 && input.readShort() == STREAM_VERSION) { 2207 return; 2208 } 2209 throw new StreamCorruptedException(); 2210 } 2211 2212 /** 2213 * Reads an unsigned byte (8 bit) from the source stream. 2214 * 2215 * @return the unsigned byte value read from the source stream packaged in 2216 * an integer. 2217 * @throws EOFException 2218 * if the end of the input is reached before the read 2219 * request can be satisfied. 2220 * @throws IOException 2221 * if an error occurs while reading from the source stream. 2222 */ 2223 public int readUnsignedByte() throws IOException { 2224 return primitiveTypes.readUnsignedByte(); 2225 } 2226 2227 /** 2228 * Reads an unsigned short (16 bit) from the source stream. 2229 * 2230 * @return the unsigned short value read from the source stream packaged in 2231 * an integer. 2232 * @throws EOFException 2233 * if the end of the input is reached before the read 2234 * request can be satisfied. 2235 * @throws IOException 2236 * if an error occurs while reading from the source stream. 2237 */ 2238 public int readUnsignedShort() throws IOException { 2239 return primitiveTypes.readUnsignedShort(); 2240 } 2241 2242 /** 2243 * Reads a string encoded in {@link DataInput modified UTF-8} from the 2244 * source stream. 2245 * 2246 * @return the string encoded in {@link DataInput modified UTF-8} read from 2247 * the source stream. 2248 * @throws EOFException 2249 * if the end of the input is reached before the read 2250 * request can be satisfied. 2251 * @throws IOException 2252 * if an error occurs while reading from the source stream. 2253 */ 2254 public String readUTF() throws IOException { 2255 return primitiveTypes.readUTF(); 2256 } 2257 2258 /** 2259 * Returns the previously-read object corresponding to the given serialization handle. 2260 * @throws InvalidObjectException 2261 * If there is no previously-read object with this handle 2262 */ 2263 private Object registeredObjectRead(int handle) throws InvalidObjectException { 2264 Object res = objectsRead.get(handle - ObjectStreamConstants.baseWireHandle); 2265 if (res == UNSHARED_OBJ) { 2266 throw new InvalidObjectException("Cannot read back reference to unshared object"); 2267 } 2268 return res; 2269 } 2270 2271 /** 2272 * Associates a read object with the its serialization handle. 2273 */ 2274 private void registerObjectRead(Object obj, int handle, boolean unshared) throws IOException { 2275 if (unshared) { 2276 obj = UNSHARED_OBJ; 2277 } 2278 int index = handle - ObjectStreamConstants.baseWireHandle; 2279 if (index < objectsRead.size()) { 2280 objectsRead.set(index, obj); 2281 } else if (index == objectsRead.size()) { 2282 objectsRead.add(obj); 2283 } else { 2284 throw new StreamCorruptedException("non-dense use of serialization handles; " + 2285 "objectsRead.size()=" + objectsRead.size() + " index=" + index); 2286 } 2287 } 2288 2289 /** 2290 * Registers a callback for post-deserialization validation of objects. It 2291 * allows to perform additional consistency checks before the {@code 2292 * readObject()} method of this class returns its result to the caller. This 2293 * method can only be called from within the {@code readObject()} method of 2294 * a class that implements "special" deserialization rules. It can be called 2295 * multiple times. Validation callbacks are then done in order of decreasing 2296 * priority, defined by {@code priority}. 2297 * 2298 * @param object 2299 * an object that can validate itself by receiving a callback. 2300 * @param priority 2301 * the validator's priority. 2302 * @throws InvalidObjectException 2303 * if {@code object} is {@code null}. 2304 * @throws NotActiveException 2305 * if this stream is currently not reading objects. In that 2306 * case, calling this method is not allowed. 2307 * @see ObjectInputValidation#validateObject() 2308 */ 2309 public synchronized void registerValidation(ObjectInputValidation object, 2310 int priority) throws NotActiveException, InvalidObjectException { 2311 // Validation can only be registered when inside readObject calls 2312 Object instanceBeingRead = this.currentObject; 2313 2314 // We can't be called from just anywhere. There are rules. 2315 if (instanceBeingRead == null && nestedLevels == 0) { 2316 throw new NotActiveException(); 2317 } 2318 if (object == null) { 2319 throw new InvalidObjectException("Callback object cannot be null"); 2320 } 2321 // From now on it is just insertion in a SortedCollection. Since 2322 // the Java class libraries don't provide that, we have to 2323 // implement it from scratch here. 2324 InputValidationDesc desc = new InputValidationDesc(); 2325 desc.validator = object; 2326 desc.priority = priority; 2327 // No need for this, validateObject does not take a parameter 2328 // desc.toValidate = instanceBeingRead; 2329 if (validations == null) { 2330 validations = new InputValidationDesc[1]; 2331 validations[0] = desc; 2332 } else { 2333 int i = 0; 2334 for (; i < validations.length; i++) { 2335 InputValidationDesc validation = validations[i]; 2336 // Sorted, higher priority first. 2337 if (priority >= validation.priority) { 2338 break; // Found the index where to insert 2339 } 2340 } 2341 InputValidationDesc[] oldValidations = validations; 2342 int currentSize = oldValidations.length; 2343 validations = new InputValidationDesc[currentSize + 1]; 2344 System.arraycopy(oldValidations, 0, validations, 0, i); 2345 System.arraycopy(oldValidations, i, validations, i + 1, currentSize 2346 - i); 2347 validations[i] = desc; 2348 } 2349 } 2350 2351 /** 2352 * Reset the collection of objects already loaded by the receiver. 2353 */ 2354 private void resetSeenObjects() { 2355 objectsRead = new ArrayList<Object>(); 2356 nextHandle = baseWireHandle; 2357 primitiveData = emptyStream; 2358 } 2359 2360 /** 2361 * Reset the receiver. The collection of objects already read by the 2362 * receiver is reset, and internal structures are also reset so that the 2363 * receiver knows it is in a fresh clean state. 2364 */ 2365 private void resetState() { 2366 resetSeenObjects(); 2367 hasPushbackTC = false; 2368 pushbackTC = 0; 2369 // nestedLevels = 0; 2370 } 2371 2372 /** 2373 * Loads the Java class corresponding to the class descriptor {@code 2374 * osClass} that has just been read from the source stream. 2375 * 2376 * @param osClass 2377 * an ObjectStreamClass read from the source stream. 2378 * @return a Class corresponding to the descriptor {@code osClass}. 2379 * @throws ClassNotFoundException 2380 * if the class for an object cannot be found. 2381 * @throws IOException 2382 * if an I/O error occurs while creating the class. 2383 * @see ObjectOutputStream#annotateClass(Class) 2384 */ 2385 protected Class<?> resolveClass(ObjectStreamClass osClass) 2386 throws IOException, ClassNotFoundException { 2387 // fastpath: obtain cached value 2388 Class<?> cls = osClass.forClass(); 2389 if (cls == null) { 2390 // slowpath: resolve the class 2391 String className = osClass.getName(); 2392 2393 // if it is primitive class, for example, long.class 2394 cls = PRIMITIVE_CLASSES.get(className); 2395 2396 if (cls == null) { 2397 // not primitive class 2398 // Use the first non-null ClassLoader on the stack. If null, use 2399 // the system class loader 2400 cls = Class.forName(className, true, callerClassLoader); 2401 } 2402 } 2403 return cls; 2404 } 2405 2406 /** 2407 * Allows trusted subclasses to substitute the specified original {@code 2408 * object} with a new object. Object substitution has to be activated first 2409 * with calling {@code enableResolveObject(true)}. This implementation just 2410 * returns {@code object}. 2411 * 2412 * @param object 2413 * the original object for which a replacement may be defined. 2414 * @return the replacement object for {@code object}. 2415 * @throws IOException 2416 * if any I/O error occurs while creating the replacement 2417 * object. 2418 * @see #enableResolveObject 2419 * @see ObjectOutputStream#enableReplaceObject 2420 * @see ObjectOutputStream#replaceObject 2421 */ 2422 protected Object resolveObject(Object object) throws IOException { 2423 // By default no object replacement. Subclasses can override 2424 return object; 2425 } 2426 2427 /** 2428 * Skips {@code length} bytes on the source stream. This method should not 2429 * be used to skip bytes at any arbitrary position, just when reading 2430 * primitive data types (int, char etc). 2431 * 2432 * @param length 2433 * the number of bytes to skip. 2434 * @return the number of bytes actually skipped. 2435 * @throws IOException 2436 * if an error occurs while skipping bytes on the source stream. 2437 * @throws NullPointerException 2438 * if the source stream is {@code null}. 2439 */ 2440 public int skipBytes(int length) throws IOException { 2441 // To be used with available. Ok to call if reading primitive buffer 2442 if (input == null) { 2443 throw new NullPointerException(); 2444 } 2445 2446 int offset = 0; 2447 while (offset < length) { 2448 checkReadPrimitiveTypes(); 2449 long skipped = primitiveData.skip(length - offset); 2450 if (skipped == 0) { 2451 return offset; 2452 } 2453 offset += (int) skipped; 2454 } 2455 return length; 2456 } 2457 2458 /** 2459 * Verify if the SUID & the base name for descriptor 2460 * <code>loadedStreamClass</code>matches 2461 * the SUID & the base name of the corresponding loaded class and 2462 * init private fields. 2463 * 2464 * @param loadedStreamClass 2465 * An ObjectStreamClass that was loaded from the stream. 2466 * 2467 * @throws InvalidClassException 2468 * If the SUID of the stream class does not match the VM class 2469 */ 2470 private void verifyAndInit(ObjectStreamClass loadedStreamClass) 2471 throws InvalidClassException { 2472 2473 Class<?> localClass = loadedStreamClass.forClass(); 2474 ObjectStreamClass localStreamClass = ObjectStreamClass 2475 .lookupStreamClass(localClass); 2476 2477 if (loadedStreamClass.getSerialVersionUID() != localStreamClass 2478 .getSerialVersionUID()) { 2479 throw new InvalidClassException(loadedStreamClass.getName(), 2480 "Incompatible class (SUID): " + loadedStreamClass + 2481 " but expected " + localStreamClass); 2482 } 2483 2484 String loadedClassBaseName = getBaseName(loadedStreamClass.getName()); 2485 String localClassBaseName = getBaseName(localStreamClass.getName()); 2486 2487 if (!loadedClassBaseName.equals(localClassBaseName)) { 2488 throw new InvalidClassException(loadedStreamClass.getName(), 2489 String.format("Incompatible class (base name): %s but expected %s", 2490 loadedClassBaseName, localClassBaseName)); 2491 } 2492 2493 loadedStreamClass.initPrivateFields(localStreamClass); 2494 } 2495 2496 private static String getBaseName(String fullName) { 2497 int k = fullName.lastIndexOf('.'); 2498 2499 if (k == -1 || k == (fullName.length() - 1)) { 2500 return fullName; 2501 } 2502 return fullName.substring(k + 1); 2503 } 2504 2505 // Avoid recursive defining. 2506 private static void checkedSetSuperClassDesc(ObjectStreamClass desc, 2507 ObjectStreamClass superDesc) throws StreamCorruptedException { 2508 if (desc.equals(superDesc)) { 2509 throw new StreamCorruptedException(); 2510 } 2511 desc.setSuperclass(superDesc); 2512 } 2513} 2514