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