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