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