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