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