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