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