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