151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ObjectStreamClass.WeakClassKey; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.ReferenceQueue; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedAction; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentHashMap; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentMap; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport static java.io.ObjectStreamClass.processQueue; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.SerialCallbackContext; 40ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.reflect.misc.ReflectUtil; 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * An ObjectOutputStream writes primitive data types and graphs of Java objects 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to an OutputStream. The objects can be read (reconstituted) using an 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectInputStream. Persistent storage of objects can be accomplished by 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * using a file for the stream. If the stream is a network socket stream, the 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects can be reconstituted on another host or in another process. 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Only objects that support the java.io.Serializable interface can be 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written to streams. The class of each serializable object is encoded 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * including the class name and signature of the class, the values of the 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object's fields and arrays, and the closure of any other objects referenced 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * from the initial objects. 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The method writeObject is used to write an object to the stream. Any 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object, including Strings and arrays, is written with writeObject. Multiple 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects or primitives can be written to the stream. The objects must be 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * read back from the corresponding ObjectInputstream with the same types and 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the same order as they were written. 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Primitive data types can also be written to the stream using the 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * appropriate methods from DataOutput. Strings can also be written using the 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeUTF method. 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The default serialization mechanism for an object writes the class of the 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object, the class signature, and the values of all non-transient and 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * non-static fields. References to other objects (except in transient or 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * static fields) cause those objects to be written also. Multiple references 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to a single object are encoded using a reference sharing mechanism so that 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * graphs of objects can be restored to the same shape as when the original was 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written. 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>For example to write an object that can be read by the example in 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectInputStream: 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <br> 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FileOutputStream fos = new FileOutputStream("t.tmp"); 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectOutputStream oos = new ObjectOutputStream(fos); 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * oos.writeInt(12345); 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * oos.writeObject("Today"); 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * oos.writeObject(new Date()); 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * oos.close(); 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Classes that require special handling during the serialization and 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * deserialization process must implement special methods with these exact 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * signatures: 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <br> 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void readObject(java.io.ObjectInputStream stream) 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * throws IOException, ClassNotFoundException; 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void writeObject(java.io.ObjectOutputStream stream) 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * throws IOException 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void readObjectNoData() 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * throws ObjectStreamException; 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The writeObject method is responsible for writing the state of the object 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for its particular class so that the corresponding readObject method can 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * restore it. The method does not need to concern itself with the state 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * belonging to the object's superclasses or subclasses. State is saved by 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writing the individual fields to the ObjectOutputStream using the 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeObject method or by using the methods for primitive data types 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * supported by DataOutput. 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Serialization does not write out the fields of any object that does not 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * implement the java.io.Serializable interface. Subclasses of Objects that 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are not serializable can be serializable. In this case the non-serializable 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class must have a no-arg constructor to allow its fields to be initialized. 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In this case it is the responsibility of the subclass to save and restore 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the state of the non-serializable class. It is frequently the case that the 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fields of that class are accessible (public, package, or protected) or that 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * there are get and set methods that can be used to restore the state. 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Serialization of an object can be prevented by implementing writeObject 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and readObject methods that throw the NotSerializableException. The 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exception will be caught by the ObjectOutputStream and abort the 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization process. 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Implementing the Externalizable interface allows the object to assume 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * complete control over the contents and format of the object's serialized 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * form. The methods of the Externalizable interface, writeExternal and 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * readExternal, are called to save and restore the objects state. When 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * implemented by a class they can write and read their own state using all of 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the methods of ObjectOutput and ObjectInput. It is the responsibility of 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the objects to handle any versioning that occurs. 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Enum constants are serialized differently than ordinary serializable or 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * externalizable objects. The serialized form of an enum constant consists 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * solely of its name; field values of the constant are not transmitted. To 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialize an enum constant, ObjectOutputStream writes the string returned by 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the constant's name method. Like other serializable or externalizable 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects, enum constants can function as the targets of back references 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * appearing subsequently in the serialization stream. The process by which 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * enum constants are serialized cannot be customized; any class-specific 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeObject and writeReplace methods defined by enum types are ignored 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * during serialization. Similarly, any serialPersistentFields or 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialVersionUID field declarations are also ignored--all enum types have a 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fixed serialVersionUID of 0L. 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Primitive data, excluding serializable fields and externalizable data, is 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written to the ObjectOutputStream in block-data records. A block data record 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is composed of a header and data. The block data header consists of a marker 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and the number of bytes to follow the header. Consecutive primitive data 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writes are merged into one block-data record. The blocking factor used for 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a block-data record will be 1024 bytes. Each block-data record will be 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * filled up to 1024 bytes, or be written whenever there is a termination of 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * block-data mode. Calls to the ObjectOutputStream methods writeObject, 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * defaultWriteObject and writeFields initially terminate any existing 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * block-data record. 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mike Warres 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Roger Riggs 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.DataOutput 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectInputStream 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.Serializable 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.Externalizable 161d2449bb576ad1e3a3877364e5e1ae28625f69e35Yi Kong * @see <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a> 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since JDK1.1 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class ObjectOutputStream 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski extends OutputStream implements ObjectOutput, ObjectStreamConstants 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{ 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class Caches { 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** cache of subclass security audit results */ 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new ConcurrentHashMap<>(); 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** queue for WeakReferences to audited subclasses */ 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static final ReferenceQueue<Class<?>> subclassAuditsQueue = 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new ReferenceQueue<>(); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** filter stream for handling block data conversion */ 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final BlockDataOutputStream bout; 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** obj -> wire handle map */ 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final HandleTable handles; 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** obj -> replacement obj map */ 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final ReplaceTable subs; 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** stream protocol version */ 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int protocol = PROTOCOL_VERSION_2; 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** recursion depth */ 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int depth; 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** buffer for writing primitive field values */ 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private byte[] primVals; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** if true, invoke writeObjectOverride() instead of writeObject() */ 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final boolean enableOverride; 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** if true, invoke replaceObject() */ 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean enableReplace; 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // values below valid only during upcalls to writeObject()/writeExternal() 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Context during upcalls to class-defined writeObject methods; holds 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object currently being serialized and descriptor for current class. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Null when not during writeObject upcall. 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private SerialCallbackContext curContext; 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** current PutField object */ 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private PutFieldImpl curPut; 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** custom storage for debug trace info */ 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final DebugTraceInfoStack debugInfoStack; 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * value of "sun.io.serialization.extendedDebugInfo" property, 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as true or false for extended information about exception's place 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 214395d3a8746e46bb394c689bcdcac29009c3b8fdbNarayan Kamath private static final boolean extendedDebugInfo = false; 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates an ObjectOutputStream that writes to the specified OutputStream. 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This constructor writes the serialization stream header to the 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * underlying stream; callers may wish to flush the stream immediately to 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ensure that constructors for receiving ObjectInputStreams will not block 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * when reading the header. 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>If a security manager is installed, this constructor will check for 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the "enableSubclassImplementation" SerializablePermission when invoked 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directly or indirectly by the constructor of a subclass which overrides 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods. 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param out output stream to write to 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an I/O error occurs while writing stream header 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws SecurityException if untrusted subclass illegally overrides 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * security-sensitive methods 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException if <code>out</code> is <code>null</code> 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see ObjectOutputStream#ObjectOutputStream() 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see ObjectOutputStream#putFields() 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see ObjectInputStream#ObjectInputStream(InputStream) 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public ObjectOutputStream(OutputStream out) throws IOException { 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski verifySubclass(); 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout = new BlockDataOutputStream(out); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles = new HandleTable(10, (float) 3.00); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski subs = new ReplaceTable(10, (float) 3.00); 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski enableOverride = false; 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeStreamHeader(); 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack = new DebugTraceInfoStack(); 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack = null; 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Provide a way for subclasses that are completely reimplementing 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectOutputStream to not have to allocate private data just used by 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this implementation of ObjectOutputStream. 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>If there is a security manager installed, this method first calls the 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * security manager's <code>checkPermission</code> method with a 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SerializablePermission("enableSubclassImplementation")</code> 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * permission to ensure it's ok to enable subclassing. 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws SecurityException if a security manager exists and its 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>checkPermission</code> method denies enabling 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * subclassing. 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see SecurityManager#checkPermission 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.SerializablePermission 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected ObjectOutputStream() throws IOException, SecurityException { 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SecurityManager sm = System.getSecurityManager(); 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sm != null) { 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout = null; 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles = null; 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski subs = null; 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski enableOverride = true; 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack = null; 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Specify stream protocol version to use when writing the stream. 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This routine provides a hook to enable the current version of 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Serialization to write in a format that is backwards compatible to a 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * previous version of the stream format. 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Every effort will be made to avoid introducing additional 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * backwards incompatibilities; however, sometimes there is no 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * other alternative. 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param version use ProtocolVersion from java.io.ObjectStreamConstants. 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalStateException if called after any objects 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * have been serialized. 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if invalid version is passed in. 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void useProtocolVersion(int version) throws IOException { 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (handles.size() != 0) { 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: implement better check for pristine stream? 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalStateException("stream non-empty"); 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (version) { 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PROTOCOL_VERSION_1: 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PROTOCOL_VERSION_2: 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protocol = version; 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException( 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "unknown version: " + version); 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the specified object to the ObjectOutputStream. The class of the 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object, the signature of the class, and the values of the non-transient 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and non-static fields of the class and all of its supertypes are 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written. Default serialization for a class can be overridden using the 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeObject and the readObject methods. Objects referenced by this 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object are written transitively so that a complete equivalent graph of 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects can be reconstructed by an ObjectInputStream. 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Exceptions are thrown for problems with the OutputStream and for 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * classes that should not be serialized. All exceptions are fatal to the 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OutputStream, which is left in an indeterminate state, and it is up to 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the caller to ignore or recover the stream state. 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws InvalidClassException Something is wrong with a class used by 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization. 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NotSerializableException Some object to be serialized does not 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * implement the java.io.Serializable interface. 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException Any exception thrown by the underlying 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OutputStream. 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public final void writeObject(Object obj) throws IOException { 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (enableOverride) { 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObjectOverride(obj); 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(obj, false); 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException ex) { 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (depth == 0) { 349d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak /* ----- BEGIN android ----- 350d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak writeFatalException(ex);*/ 351d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak try { 352d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak writeFatalException(ex); 353d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak 354d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak } catch (IOException ex2) { 355d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak // If writing the exception to the output stream causes another exception there 356d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak // is no need to propagate the second exception or generate a third exception, 357d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak // both of which might obscure details of the root cause. 358d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak } 359d5ae300ffb7c784dd7006cc87e60cdd329e6cf16Przemyslaw Szczepaniak // ----- END android ----- 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw ex; 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Method used by subclasses to override the default writeObject method. 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method is called by trusted subclasses of ObjectInputStream that 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * constructed ObjectInputStream using the protected no-arg constructor. 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The subclass is expected to provide an override method with the modifier 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "final". 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obj object to be written to the underlying stream 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if there are I/O errors while writing to the 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * underlying stream 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #ObjectOutputStream() 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #writeObject(Object) 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void writeObjectOverride(Object obj) throws IOException { 380c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak /* ----- BEGIN android ----- */ 381c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak if (!enableOverride) { 382c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak // Subclasses must override. 383c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak throw new IOException(); 384c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak } 385c1c9f01cd9d0e1a7f13aaa67f5f8e92e208d67d8Przemyslaw Szczepaniak /* ----- END android ----- */ 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes an "unshared" object to the ObjectOutputStream. This method is 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * identical to writeObject, except that it always writes the given object 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as a new, unique object in the stream (as opposed to a back-reference 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pointing to a previously serialized instance). Specifically: 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>An object written via writeUnshared is always serialized in the 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same manner as a newly appearing object (an object that has not 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * been written to the stream yet), regardless of whether or not the 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object has been written previously. 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>If writeObject is used to write an object that has been previously 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written with writeUnshared, the previous writeUnshared operation 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is treated as if it were a write of a separate object. In other 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * words, ObjectOutputStream will never generate back-references to 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object data written by calls to writeUnshared. 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * While writing an object via writeUnshared does not in itself guarantee a 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unique reference to the object when it is deserialized, it allows a 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * single object to be defined multiple times in a stream, so that multiple 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calls to readUnshared by the receiver will not conflict. Note that the 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * rules described above only apply to the base-level object written with 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeUnshared, and not to any transitively referenced sub-objects in the 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object graph to be serialized. 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>ObjectOutputStream subclasses which override this method can only be 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * constructed in security contexts possessing the 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "enableSubclassImplementation" SerializablePermission; any attempt to 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instantiate such a subclass without this permission will cause a 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * SecurityException to be thrown. 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obj object to write to stream 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NotSerializableException if an object in the graph to be 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialized does not implement the Serializable interface 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws InvalidClassException if a problem exists with the class of an 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object to be serialized 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an I/O error occurs during serialization 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeUnshared(Object obj) throws IOException { 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(obj, true); 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException ex) { 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (depth == 0) { 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeFatalException(ex); 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw ex; 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the non-static and non-transient fields of the current class to 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this stream. This may only be called from the writeObject method of the 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class being serialized. It will throw the NotActiveException if it is 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * called otherwise. 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>OutputStream</code> 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void defaultWriteObject() throws IOException { 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ( curContext == null ) { 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NotActiveException("not in call to writeObject"); 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object curObj = curContext.getObj(); 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass curDesc = curContext.getDesc(); 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultWriteFields(curObj, curDesc); 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Retrieve the object used to buffer persistent fields to be written to 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream. The fields will be written to the stream when writeFields 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method is called. 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return an instance of the class Putfield that holds the serializable 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fields 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public ObjectOutputStream.PutField putFields() throws IOException { 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (curPut == null) { 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (curContext == null) { 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NotActiveException("not in call to writeObject"); 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object curObj = curContext.getObj(); 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass curDesc = curContext.getDesc(); 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut = new PutFieldImpl(curDesc); 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return curPut; 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the buffered fields to the stream. 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NotActiveException Called when a classes writeObject method was 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not called to write the state of the object. 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeFields() throws IOException { 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (curPut == null) { 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NotActiveException("no current PutField object"); 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut.writeFields(); 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reset will disregard the state of any objects already written to the 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. The state is reset to be the same as a new ObjectOutputStream. 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The current point in the stream is marked as reset so the corresponding 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectInputStream will be reset at the same point. Objects previously 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written to the stream will not be refered to as already being in the 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. They will be written to the stream again. 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if reset() is invoked while serializing an object. 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void reset() throws IOException { 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (depth != 0) { 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("stream active"); 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_RESET); 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clear(); 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Subclasses may implement this method to allow class data to be stored in 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream. By default this method does nothing. The corresponding 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method in ObjectInputStream is resolveClass. This method is called 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exactly once for each unique class in the stream. The class name and 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * signature will have already been written to the stream. This method may 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * make free use of the ObjectOutputStream to save any representation of 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the class it deems suitable (for example, the bytes of the class file). 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The resolveClass method in the corresponding subclass of 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectInputStream must read and use any data or objects written by 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * annotateClass. 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cl the class to annotate custom data for 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException Any exception thrown by the underlying 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OutputStream. 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void annotateClass(Class<?> cl) throws IOException { 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Subclasses may implement this method to store custom data in the stream 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * along with descriptors for dynamic proxy classes. 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This method is called exactly once for each unique proxy class 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * descriptor in the stream. The default implementation of this method in 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>ObjectOutputStream</code> does nothing. 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The corresponding method in <code>ObjectInputStream</code> is 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>resolveProxyClass</code>. For a given subclass of 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>ObjectOutputStream</code> that overrides this method, the 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>resolveProxyClass</code> method in the corresponding subclass of 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>ObjectInputStream</code> must read any data or objects written by 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>annotateProxyClass</code>. 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cl the proxy class to annotate custom data for 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException any exception thrown by the underlying 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>OutputStream</code> 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see ObjectInputStream#resolveProxyClass(String[]) 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.3 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void annotateProxyClass(Class<?> cl) throws IOException { 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method will allow trusted subclasses of ObjectOutputStream to 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * substitute one object for another during serialization. Replacing 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects is disabled until enableReplaceObject is called. The 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * enableReplaceObject method checks that the stream requesting to do 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * replacement can be trusted. The first occurrence of each object written 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * into the serialization stream is passed to replaceObject. Subsequent 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * references to the object are replaced by the object returned by the 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * original call to replaceObject. To ensure that the private state of 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects is not unintentionally exposed, only trusted streams may use 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * replaceObject. 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The ObjectOutputStream.writeObject method takes a parameter of type 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Object (as opposed to type Serializable) to allow for cases where 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * non-serializable objects are replaced by serializable ones. 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>When a subclass is replacing objects it must insure that either a 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * complementary substitution must be made during deserialization or that 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the substituted object is compatible with every field where the 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reference will be stored. Objects whose type is not a subclass of the 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * type of the field or array element abort the serialization by raising an 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exception and the object is not be stored. 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This method is called only once when each object is first 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encountered. All subsequent references to the object will be redirected 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the new object. This method should return the object to be 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * substituted or the original object. 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Null can be returned as the object to be substituted, but may cause 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NullReferenceException in classes that contain references to the 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * original object since they may be expecting an object instead of 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * null. 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obj the object to be replaced 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the alternate object that replaced the specified one 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException Any exception thrown by the underlying 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OutputStream. 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected Object replaceObject(Object obj) throws IOException { 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return obj; 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Enable the stream to do replacement of objects in the stream. When 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * enabled, the replaceObject method is called for every object being 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialized. 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>If <code>enable</code> is true, and there is a security manager 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * installed, this method first calls the security manager's 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>checkPermission</code> method with a 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SerializablePermission("enableSubstitution")</code> permission to 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ensure it's ok to enable the stream to do replacement of objects in the 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param enable boolean parameter to enable replacement of objects 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the previous setting before this method was invoked 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws SecurityException if a security manager exists and its 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>checkPermission</code> method denies enabling the stream 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to do replacement of objects in the stream. 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see SecurityManager#checkPermission 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.SerializablePermission 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected boolean enableReplaceObject(boolean enable) 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws SecurityException 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (enable == enableReplace) { 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return enable; 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (enable) { 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SecurityManager sm = System.getSecurityManager(); 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sm != null) { 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sm.checkPermission(SUBSTITUTION_PERMISSION); 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski enableReplace = enable; 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return !enableReplace; 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The writeStreamHeader method is provided so subclasses can append or 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * prepend their own header to the stream. It writes the magic number and 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version to the stream. 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void writeStreamHeader() throws IOException { 64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeShort(STREAM_MAGIC); 64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeShort(STREAM_VERSION); 65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the specified class descriptor to the ObjectOutputStream. Class 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * descriptors are used to identify the classes of objects written to the 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. Subclasses of ObjectOutputStream may override this method to 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * customize the way in which class descriptors are written to the 65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization stream. The corresponding method in ObjectInputStream, 65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>readClassDescriptor</code>, should then be overridden to 65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reconstitute the class descriptor from its custom stream representation. 66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * By default, this method writes class descriptors according to the format 66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * defined in the Object Serialization specification. 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Note that this method will only be called if the ObjectOutputStream 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is not using the old serialization stream format (set by calling 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectOutputStream's <code>useProtocolVersion</code> method). If this 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization stream is using the old format 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * internally in a manner that cannot be overridden or customized. 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param desc class descriptor to write to the stream 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectInputStream#readClassDescriptor() 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #useProtocolVersion(int) 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.3 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void writeClassDescriptor(ObjectStreamClass desc) 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.writeNonProxy(this); 68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a byte. This method will block until the byte is actually 68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written. 68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the byte to be written to the stream 68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(int val) throws IOException { 69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(val); 69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes an array of bytes. This method will block until the bytes are 69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * actually written. 69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param buf the data to be written 69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte[] buf) throws IOException { 70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(buf, 0, buf.length, false); 70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a sub array of bytes. 70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param buf the data to be written 70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param off the start offset in the data 71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes that are written 71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte[] buf, int off, int len) throws IOException { 71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buf == null) { 71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { 71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IndexOutOfBoundsException(); 72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(buf, off, len, false); 72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Flushes the stream. This will write any buffered output bytes and flush 72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * through to the underlying stream. 72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void flush() throws IOException { 73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.flush(); 73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Drain any buffered data in ObjectOutputStream. Similar to flush but 73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * does not propagate the flush to the underlying stream. 73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void drain() throws IOException { 74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.drain(); 74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Closes the stream. This method must be called to release any resources 74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * associated with the stream. 74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException If an I/O error has occurred. 75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws IOException { 75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski flush(); 753ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin // http://b/28159133 754ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin // clear(); 75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.close(); 75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a boolean. 76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the boolean to be written 76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeBoolean(boolean val) throws IOException { 76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeBoolean(val); 76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes an 8 bit byte. 77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the byte value to be written 77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeByte(int val) throws IOException { 77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(val); 77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 16 bit short. 78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the short value to be written 78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeShort(int val) throws IOException { 78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeShort(val); 78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 16 bit char. 79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the char value to be written 79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeChar(int val) throws IOException { 79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeChar(val); 80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 32 bit int. 80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the integer value to be written 80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeInt(int val) throws IOException { 81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(val); 81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 64 bit long. 81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the long value to be written 81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeLong(long val) throws IOException { 82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeLong(val); 82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 32 bit float. 82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the float value to be written 82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeFloat(float val) throws IOException { 83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeFloat(val); 83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a 64 bit double. 83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the double value to be written 83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeDouble(double val) throws IOException { 84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeDouble(val); 84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a String as a sequence of bytes. 84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param str the String of bytes to be written 85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeBytes(String str) throws IOException { 85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeBytes(str); 85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes a String as a sequence of chars. 85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param str the String of chars to be written 86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeChars(String str) throws IOException { 86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeChars(str); 86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Primitive data write of this String in 87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a href="DataInput.html#modified-utf-8">modified UTF-8</a> 87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * format. Note that there is a 87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * significant difference between writing a String into the stream as 87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * primitive data or as an Object. A String instance written by writeObject 87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is written into the stream as a String initially. Future writeObject() 87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calls write references to the string into the stream. 87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param str the String to be written 87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the underlying 87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream 88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeUTF(String str) throws IOException { 88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeUTF(str); 88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Provide programmatic access to the persistent fields to be written 88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to ObjectOutput. 88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static abstract class PutField { 89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named boolean field into the persistent field. 89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>boolean</code> 90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, boolean val); 90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named byte field into the persistent field. 90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>byte</code> 91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, byte val); 91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named char field into the persistent field. 91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>char</code> 92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, char val); 92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named short field into the persistent field. 93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>short</code> 93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, short val); 94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named int field into the persistent field. 94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>int</code> 95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, int val); 95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named long field into the persistent field. 95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>long</code> 96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, long val); 96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named float field into the persistent field. 96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>float</code> 97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, float val); 97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named double field into the persistent field. 97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not 98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>double</code> 98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, double val); 98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the value of the named Object field into the persistent field. 99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the serializable field 99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param val the value to assign to the field 99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (which may be <code>null</code>) 99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if <code>name</code> does not 99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * match the name of a serializable field for the class whose fields 99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are being written, or if the type of the named field is not a 99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reference type 99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void put(String name, Object val); 100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the data and fields to the specified ObjectOutput stream, 100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which must be the same stream that produced this 100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>PutField</code> object. 100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param out the stream to write the data and fields to 100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if I/O errors occur while writing to the 100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * underlying stream 101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if the specified stream is not 101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the same stream that produced this <code>PutField</code> 101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object 101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @deprecated This method does not write the values contained by this 101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>PutField</code> object in a proper format, and may 101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * result in corruption of the serialization stream. The 101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * correct way to write <code>PutField</code> data is by 101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calling the {@link java.io.ObjectOutputStream#writeFields()} 101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method. 101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Deprecated 102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void write(ObjectOutput out) throws IOException; 102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns protocol version in use. 102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getProtocolVersion() { 102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return protocol; 103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes string without allowing it to be replaced in stream. Used by 103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectStreamClass to write class descriptor type strings. 103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeTypeString(String str) throws IOException { 103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int handle; 103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (str == null) { 103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeNull(); 104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if ((handle = handles.lookup(str)) != -1) { 104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeHandle(handle); 104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(str, false); 104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Verifies that this (possibly subclass) instance can be constructed 104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * without violating security constraints: the subclass must not override 105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * security-sensitive non-final methods, or else the 105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "enableSubclassImplementation" SerializablePermission is checked. 105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void verifySubclass() { 105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class cl = getClass(); 105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (cl == ObjectOutputStream.class) { 105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SecurityManager sm = System.getSecurityManager(); 105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sm == null) { 106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); 106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); 106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Boolean result = Caches.subclassAudits.get(key); 106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result == null) { 106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski result = Boolean.valueOf(auditSubclass(cl)); 106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Caches.subclassAudits.putIfAbsent(key, result); 106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result.booleanValue()) { 107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Performs reflective checks on given subclass to verify that it doesn't 107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * override security-sensitive non-final methods. Returns true if subclass 107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is "safe", false otherwise. 107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean auditSubclass(final Class subcl) { 108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Boolean result = AccessController.doPrivileged( 108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<Boolean>() { 108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Boolean run() { 108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (Class cl = subcl; 108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl != ObjectOutputStream.class; 108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl = cl.getSuperclass()) 108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl.getDeclaredMethod( 109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "writeUnshared", new Class[] { Object.class }); 109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Boolean.FALSE; 109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (NoSuchMethodException ex) { 109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl.getDeclaredMethod("putFields", (Class[]) null); 109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Boolean.FALSE; 109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (NoSuchMethodException ex) { 109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Boolean.TRUE; 110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ); 110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return result.booleanValue(); 110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Clears internal data structures. 110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void clear() { 111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski subs.clear(); 111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.clear(); 111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Underlying writeObject/writeUnshared implementation. 111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeObject0(Object obj, boolean unshared) 111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean oldMode = bout.setBlockDataMode(false); 112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski depth++; 112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // handle previously written and non-replaceable objects 112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int h; 112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((obj = subs.lookup(obj)) == null) { 112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeNull(); 112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (!unshared && (h = handles.lookup(obj)) != -1) { 113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeHandle(h); 113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 11321f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak /* ----- BEGIN android ----- 113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof Class) { 113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClass((Class) obj, unshared); 113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof ObjectStreamClass) { 113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc((ObjectStreamClass) obj, unshared); 113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 11391f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak ----- END android ----- */ 114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // check for replacement object 114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object orig = obj; 114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class cl = obj.getClass(); 114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass desc; 11466ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak 11476ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak /* ----- BEGIN android ----- 114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (;;) { 114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: skip this check for strings/arrays? 115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class repCl; 115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc = ObjectStreamClass.lookup(cl, true); 115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!desc.hasWriteReplaceMethod() || 115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (obj = desc.invokeWriteReplace(obj)) == null || 115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (repCl = obj.getClass()) == cl) 115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl = repCl; 11596ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak desc = ObjectStreamClass.lookup(cl, true); 11606ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak break; 11616ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak }*/ 11626ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak // Do only one replace pass 11636ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak 11646ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak Class repCl; 11656ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak desc = ObjectStreamClass.lookup(cl, true); 11666ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak if (desc.hasWriteReplaceMethod() && 11676ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak (obj = desc.invokeWriteReplace(obj)) != null && 11686ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak (repCl = obj.getClass()) != cl) 11696ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak { 11706ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak cl = repCl; 11716ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak desc = ObjectStreamClass.lookup(cl, true); 117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11736ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak // ----- END android ----- 11746ff6e3b4e35f705cfc5f647542460fc933a13bdfPrzemyslaw Szczepaniak 117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (enableReplace) { 117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object rep = replaceObject(obj); 117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rep != obj && rep != null) { 117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl = rep.getClass(); 117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc = ObjectStreamClass.lookup(cl, true); 118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski obj = rep; 118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if object replaced, run through original checks a second time 118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj != orig) { 118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski subs.assign(orig, obj); 118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj == null) { 118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeNull(); 118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (!unshared && (h = handles.lookup(obj)) != -1) { 119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeHandle(h); 119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 11931f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak /* ----- BEGIN android ----- 119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof Class) { 119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClass((Class) obj, unshared); 119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof ObjectStreamClass) { 119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc((ObjectStreamClass) obj, unshared); 119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 12001f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak ----- END android -----*/ 120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // remaining cases 12051f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak // ----- BEGIN android ----- 12061f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak if (obj instanceof Class) { 12071f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak writeClass((Class) obj, unshared); 12081f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak } else if (obj instanceof ObjectStreamClass) { 12091f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak writeClassDesc((ObjectStreamClass) obj, unshared); 12101f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak // ----- END android ----- 12111f114374ca5954429ebde9e244ca88b6b4fb2c94Przemyslaw Szczepaniak } else if (obj instanceof String) { 121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString((String) obj, unshared); 121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (cl.isArray()) { 121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeArray(obj, desc, unshared); 121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof Enum) { 121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeEnum((Enum) obj, desc, unshared); 121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (obj instanceof Serializable) { 121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeOrdinaryObject(obj, desc, unshared); 121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NotSerializableException( 122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cl.getName() + "\n" + debugInfoStack.toString()); 122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NotSerializableException(cl.getName()); 122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski depth--; 122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(oldMode); 123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes null code to stream. 123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeNull() throws IOException { 123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_NULL); 123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given object handle to stream. 124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeHandle(int handle) throws IOException { 124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_REFERENCE); 124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(baseWireHandle + handle); 124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes representation of given class to stream. 125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeClass(Class cl, boolean unshared) throws IOException { 125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_CLASS); 125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc(ObjectStreamClass.lookup(cl, true), false); 125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : cl); 125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes representation of given class descriptor to stream. 125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeClassDesc(ObjectStreamClass desc, boolean unshared) 126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int handle; 126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (desc == null) { 126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeNull(); 126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (!unshared && (handle = handles.lookup(desc)) != -1) { 126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeHandle(handle); 126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (desc.isProxy()) { 126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeProxyDesc(desc, unshared); 127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeNonProxyDesc(desc, unshared); 127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isCustomSubclass() { 127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Return true if this class is a custom subclass of ObjectOutputStream 127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getClass().getClassLoader() 127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski != ObjectOutputStream.class.getClassLoader(); 127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes class descriptor representing a dynamic proxy class to stream. 128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeProxyDesc(ObjectStreamClass desc, boolean unshared) 128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_PROXYCLASSDESC); 128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : desc); 128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class cl = desc.forClass(); 129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class[] ifaces = cl.getInterfaces(); 129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(ifaces.length); 129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < ifaces.length; i++) { 129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeUTF(ifaces[i].getName()); 129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isCustomSubclass()) { 129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ReflectUtil.checkPackageAccess(cl); 130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski annotateProxyClass(cl); 130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ENDBLOCKDATA); 130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc(desc.getSuperDesc(), false); 130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes class descriptor representing a standard (i.e., not a dynamic 131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * proxy) class to stream. 131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared) 131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_CLASSDESC); 131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : desc); 131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (protocol == PROTOCOL_VERSION_1) { 131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // do not invoke class descriptor write hook with old protocol 132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.writeNonProxy(this); 132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDescriptor(desc); 132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class cl = desc.forClass(); 132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isCustomSubclass()) { 132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ReflectUtil.checkPackageAccess(cl); 132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski annotateClass(cl); 133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ENDBLOCKDATA); 133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc(desc.getSuperDesc(), false); 133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given string to stream, using standard or long UTF format 133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * depending on string length. 134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeString(String str, boolean unshared) throws IOException { 134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : str); 134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long utflen = bout.getUTFLength(str); 134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utflen <= 0xFFFF) { 134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_STRING); 134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeUTF(str, utflen); 134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_LONGSTRING); 134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeLongUTF(str, utflen); 135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given array object to stream. 135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeArray(Object array, 135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass desc, 135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean unshared) 135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ARRAY); 136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc(desc, false); 136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : array); 136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Class ccl = desc.forClass().getComponentType(); 136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ccl.isPrimitive()) { 136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ccl == Integer.TYPE) { 136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int[] ia = (int[]) array; 136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(ia.length); 137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInts(ia, 0, ia.length); 137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Byte.TYPE) { 137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] ba = (byte[]) array; 137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(ba.length); 137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(ba, 0, ba.length, true); 137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Long.TYPE) { 137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long[] ja = (long[]) array; 137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(ja.length); 137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeLongs(ja, 0, ja.length); 137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Float.TYPE) { 138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski float[] fa = (float[]) array; 138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(fa.length); 138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeFloats(fa, 0, fa.length); 138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Double.TYPE) { 138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski double[] da = (double[]) array; 138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(da.length); 138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeDoubles(da, 0, da.length); 138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Short.TYPE) { 138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski short[] sa = (short[]) array; 138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(sa.length); 139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeShorts(sa, 0, sa.length); 139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Character.TYPE) { 139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] ca = (char[]) array; 139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(ca.length); 139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeChars(ca, 0, ca.length); 139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (ccl == Boolean.TYPE) { 139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean[] za = (boolean[]) array; 139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(za.length); 139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeBooleans(za, 0, za.length); 139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError(); 140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] objs = (Object[]) array; 140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = objs.length; 140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeInt(len); 140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 140851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "array (class \"" + array.getClass().getName() + 140951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "\", size: " + len + ")"); 141051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 141251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < len; i++) { 141351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 141451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 141551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "element of array (index: " + i + ")"); 141651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 141851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(objs[i], false); 141951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given enum constant to stream. 143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeEnum(Enum en, 143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass desc, 143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean unshared) 143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ENUM); 144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass sdesc = desc.getSuperDesc(); 144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false); 144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : en); 144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(en.name(), false); 144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes representation of a "ordinary" (i.e., not a String, Class, 145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectStreamClass, array, or enum constant) serializable object to the 145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. 145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeOrdinaryObject(Object obj, 145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass desc, 145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean unshared) 145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (depth == 1 ? "root " : "") + "object (class \"" + 146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski obj.getClass().getName() + "\", " + obj.toString() + ")"); 146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.checkSerialize(); 146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_OBJECT); 146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeClassDesc(desc, false); 146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski handles.assign(unshared ? null : obj); 146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (desc.isExternalizable() && !desc.isProxy()) { 147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeExternalData((Externalizable) obj); 147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeSerialData(obj, desc); 147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes externalizable data of given object by invoking its 148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeExternal() method. 148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeExternalData(Externalizable obj) throws IOException { 148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski PutFieldImpl oldPut = curPut; 148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut = null; 148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push("writeExternal data"); 149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SerialCallbackContext oldContext = curContext; 149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curContext = null; 149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (protocol == PROTOCOL_VERSION_1) { 149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski obj.writeExternal(this); 149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski obj.writeExternal(this); 150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ENDBLOCKDATA); 150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curContext = oldContext; 150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut = oldPut; 151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes instance data for each serializable class of given object, from 151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * superclass to subclass. 151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeSerialData(Object obj, ObjectStreamClass desc) 151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); 152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < slots.length; i++) { 152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamClass slotDesc = slots[i].desc; 152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (slotDesc.hasWriteObjectMethod()) { 152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski PutFieldImpl oldPut = curPut; 152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut = null; 152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SerialCallbackContext oldContext = curContext; 152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "custom writeObject data (class \"" + 153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski slotDesc.getName() + "\")"); 153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curContext = new SerialCallbackContext(obj, slotDesc); 153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(true); 153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski slotDesc.invokeWriteObject(obj, this); 153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(false); 153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_ENDBLOCKDATA); 153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curContext.setUsed(); 154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curContext = oldContext; 154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 154351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 154451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 154551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 154651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 154751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski curPut = oldPut; 154851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 154951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultWriteFields(obj, slotDesc); 155051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 155151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 155251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 155351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 155451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 155551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Fetches and writes values of serializable fields of given object to 155651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. The given class descriptor specifies which field values to 155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * write, and in which order they should be written. 155851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void defaultWriteFields(Object obj, ObjectStreamClass desc) 156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: perform conservative isInstance check here? 156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.checkDefaultSerialize(); 156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int primDataSize = desc.getPrimDataSize(); 156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (primVals == null || primVals.length < primDataSize) { 156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski primVals = new byte[primDataSize]; 156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.getPrimFieldValues(obj, primVals); 157051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(primVals, 0, primDataSize, false); 157151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 157251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamField[] fields = desc.getFields(false); 157351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] objVals = new Object[desc.getNumObjFields()]; 157451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numPrimFields = fields.length - objVals.length; 157551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski desc.getObjFieldValues(obj, objVals); 157651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < objVals.length; i++) { 157751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 157851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "field (class \"" + desc.getName() + "\", name: \"" + 158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].getName() + "\", type: \"" + 158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].getType() + "\")"); 158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(objVals[i], 158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].isUnshared()); 158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Attempts to write to stream fatal IOException that has caused 159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization to abort. 159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeFatalException(IOException ex) throws IOException { 159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note: the serialization specification states that if a second 160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IOException occurs while attempting to serialize the original fatal 160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exception to the stream, then a StreamCorruptedException should be 160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * thrown (section 2.1). However, due to a bug in previous 160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * implementations of serialization, StreamCorruptedExceptions were 160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * rarely (if ever) actually thrown--the "root" exceptions from 160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * underlying streams were thrown instead. This historical behavior is 160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * followed here for consistency. 160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clear(); 161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean oldMode = bout.setBlockDataMode(false); 161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.writeByte(TC_EXCEPTION); 161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(ex, false); 161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clear(); 161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.setBlockDataMode(oldMode); 161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts specified span of float values into byte values. 162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: remove once hotspot inlines Float.floatToIntBits 162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static native void floatsToBytes(float[] src, int srcpos, 162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] dst, int dstpos, 162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nfloats); 162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts specified span of double values into byte values. 163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: remove once hotspot inlines Double.doubleToLongBits 163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static native void doublesToBytes(double[] src, int srcpos, 163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] dst, int dstpos, 163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ndoubles); 163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Default PutField implementation. 163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class PutFieldImpl extends PutField { 164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** class descriptor describing serializable fields */ 164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final ObjectStreamClass desc; 164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** primitive field values */ 164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final byte[] primVals; 164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** object field values */ 164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final Object[] objVals; 164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates PutFieldImpl object for writing fields defined in given 165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class descriptor. 165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski PutFieldImpl(ObjectStreamClass desc) { 165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.desc = desc; 165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski primVals = new byte[desc.getPrimDataSize()]; 165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski objVals = new Object[desc.getNumObjFields()]; 165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, boolean val) { 165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val); 166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, byte val) { 166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski primVals[getFieldOffset(name, Byte.TYPE)] = val; 166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, char val) { 166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val); 166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, short val) { 167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val); 167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, int val) { 167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val); 167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, float val) { 167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val); 168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, long val) { 168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val); 168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, double val) { 168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val); 168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 169051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void put(String name, Object val) { 169151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski objVals[getFieldOffset(name, Object.class)] = val; 169251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 169351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // deprecated in ObjectOutputStream.PutField 169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(ObjectOutput out) throws IOException { 169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Applications should *not* use this method to write PutField 169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data, as it will lead to stream corruption if the PutField 169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object writes any primitive data (since block data mode is not 170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unset/set properly, as is done in OOS.writeFields()). This 170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * broken implementation is being retained solely for behavioral 170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * compatibility, in order to support applications which use 170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OOS.PutField.write() for writing only non-primitive data. 170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Serialization of unshared objects is not implemented here since 170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it is not necessary for backwards compatibility; also, unshared 170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * semantics may not be supported by the given ObjectOutput 170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instance. Applications which write unshared objects using the 170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PutField API must use OOS.writeFields(). 171051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 171151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ObjectOutputStream.this != out) { 171251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("wrong stream"); 171351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 171451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(primVals, 0, primVals.length); 171551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 171651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamField[] fields = desc.getFields(false); 171751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numPrimFields = fields.length - objVals.length; 171851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REMIND: warn if numPrimFields > 0? 171951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < objVals.length; i++) { 172051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (fields[numPrimFields + i].isUnshared()) { 172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("cannot write unshared object"); 172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.writeObject(objVals[i]); 172451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes buffered primitive data and object fields to stream. 172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeFields() throws IOException { 173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bout.write(primVals, 0, primVals.length, false); 173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamField[] fields = desc.getFields(false); 173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numPrimFields = fields.length - objVals.length; 173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < objVals.length; i++) { 173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.push( 173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "field (class \"" + desc.getName() + "\", name: \"" + 173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].getName() + "\", type: \"" + 174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].getType() + "\")"); 174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeObject0(objVals[i], 174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fields[numPrimFields + i].isUnshared()); 174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extendedDebugInfo) { 174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debugInfoStack.pop(); 174851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns offset of field with given name and type. A specified type 175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of null matches all types, Object.class matches all non-primitive 175651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * types, and any other non-null type matches assignable types only. 175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Throws IllegalArgumentException if no matching field found. 175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int getFieldOffset(String name, Class type) { 176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ObjectStreamField field = desc.getField(name, type); 176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (field == null) { 176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("no such field " + name + 176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " with type " + type); 176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return field.getOffset(); 176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 177051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Buffered output stream with two modes: in default mode, outputs data in 177151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same format as DataOutputStream; in "block data" mode, outputs data 177251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bracketed by block data markers (see object serialization specification 177351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for details). 177451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 177551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class BlockDataOutputStream 177651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski extends OutputStream implements DataOutput 177751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 177851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** maximum data block length */ 177951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MAX_BLOCK_SIZE = 1024; 178051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** maximum data block header length */ 178151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MAX_HEADER_SIZE = 5; 178251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** (tunable) length of char buffer (for writing strings) */ 178351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int CHAR_BUF_SIZE = 256; 178451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 178551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** buffer for writing general/block data */ 178651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final byte[] buf = new byte[MAX_BLOCK_SIZE]; 178751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** buffer for writing block data headers */ 178851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final byte[] hbuf = new byte[MAX_HEADER_SIZE]; 178951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** char buffer for fast string writes */ 179051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final char[] cbuf = new char[CHAR_BUF_SIZE]; 179151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 179251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** block data mode */ 179351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean blkmode = false; 179451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** current offset into buf */ 179551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int pos = 0; 179651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 179751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** underlying output stream */ 179851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final OutputStream out; 179951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** loopback stream (for data writes that span data blocks) */ 180051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final DataOutputStream dout; 180151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 180251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 1803ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * Indicates that this stream was closed and that a warning must be logged once if an 1804ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * attempt is made to write to it and the underlying stream does not throw an exception. 1805ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * 1806ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * <p>This will be set back to false when a warning is logged to ensure that the log is not 1807ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * flooded with warnings. 1808ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * 1809ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * http://b/28159133 1810ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin */ 1811ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin private boolean warnOnceWhenWriting; 1812ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin 1813ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin /** 181451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates new BlockDataOutputStream on top of given underlying stream. 181551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Block data mode is turned off by default. 181651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 181751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BlockDataOutputStream(OutputStream out) { 181851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.out = out; 181951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout = new DataOutputStream(this); 182051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 182151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 182251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 182351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets block data mode to the given mode (true == on, false == off) 182451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and returns the previous mode value. If the new mode is the same as 182551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the old mode, no action is taken. If the new mode differs from the 182651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * old mode, any buffered data is flushed before switching to the new 182751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mode. 182851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 182951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean setBlockDataMode(boolean mode) throws IOException { 183051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (blkmode == mode) { 183151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return blkmode; 183251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 183351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 183451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski blkmode = mode; 183551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return !blkmode; 183651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 183751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 183851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 183951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns true if the stream is currently in block data mode, false 184051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * otherwise. 184151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 184251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean getBlockDataMode() { 184351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return blkmode; 184451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 184551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1846ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin /** 1847ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * Warns if the stream has been closed. 1848ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * 1849ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * <p>This is called after data has been written to the underlying stream in order to allow 1850ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * the underlying stream to detect and fail if an attempt is made to write to a closed 1851ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * stream. That ensures that this will only log a warning if the underlying stream does not 1852ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin * so it will not log unnecessary warnings. 1853ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin */ 1854ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin private void warnIfClosed() { 1855ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin if (warnOnceWhenWriting) { 1856ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin System.logW("The app is relying on undefined behavior. Attempting to write to a" 1857ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin + " closed ObjectOutputStream could produce corrupt output in a future" 1858ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin + " release of Android.", new IOException("Stream Closed")); 1859ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin // Set back to false so no more messages are logged unless the stream is closed 1860ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin // again. 1861ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnOnceWhenWriting = false; 1862ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin } 1863ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin } 1864ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin 186551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* ----------------- generic output stream methods ----------------- */ 186651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 186751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following methods are equivalent to their counterparts in 186851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OutputStream, except that they partition written data into data 186951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * blocks when in block data mode. 187051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 187151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 187251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(int b) throws IOException { 187351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 187451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 187551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 187651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos++] = (byte) b; 187751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 187851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 187951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte[] b) throws IOException { 188051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(b, 0, b.length, false); 188151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 188251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 188351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte[] b, int off, int len) throws IOException { 188451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(b, off, len, false); 188551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 188651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 188751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void flush() throws IOException { 188851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 188951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.flush(); 189051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws IOException { 189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski flush(); 189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.close(); 1895ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnOnceWhenWriting = true; 189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes specified span of byte values from given array. If copy is 190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * true, copies the values to an intermediate buffer before writing 190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * them to underlying stream (to avoid exposing a reference to the 190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * original byte array). 190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void write(byte[] b, int off, int len, boolean copy) 190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(copy || blkmode)) { // write directly 190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(b, off, len); 1910ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnIfClosed(); 191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 191251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (len > 0) { 191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) { 191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // avoid unnecessary copy 192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeBlockHeader(MAX_BLOCK_SIZE); 192151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(b, off, MAX_BLOCK_SIZE); 192251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += MAX_BLOCK_SIZE; 192351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= MAX_BLOCK_SIZE; 192451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 192551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int wlen = Math.min(len, MAX_BLOCK_SIZE - pos); 192651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(b, off, buf, pos, wlen); 192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += wlen; 192851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += wlen; 192951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= wlen; 193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 1932ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnIfClosed(); 193351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 193551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 193651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes all buffered data from this stream to the underlying stream, 193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * but does not flush underlying stream. 193851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void drain() throws IOException { 194051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos == 0) { 194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (blkmode) { 194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeBlockHeader(pos); 194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(buf, 0, pos); 194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = 0; 1948ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnIfClosed(); 194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes block data header. Data blocks shorter than 256 bytes are 195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * prefixed with a 2-byte header; all others start with a 5-byte 195451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * header. 195551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 195651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeBlockHeader(int len) throws IOException { 195751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len <= 0xFF) { 195851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hbuf[0] = TC_BLOCKDATA; 195951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hbuf[1] = (byte) len; 196051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(hbuf, 0, 2); 196151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 196251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hbuf[0] = TC_BLOCKDATALONG; 196351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putInt(hbuf, 1, len); 196451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(hbuf, 0, 5); 196551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 1966ec949338f804167b669d47ce86ede15cf2258c56Paul Duffin warnIfClosed(); 196751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 196851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 196951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 197051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* ----------------- primitive data output methods ----------------- */ 197151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 197251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following methods are equivalent to their counterparts in 197351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DataOutputStream, except that they partition written data into data 197451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * blocks when in block data mode. 197551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 197651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 197751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeBoolean(boolean v) throws IOException { 197851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 197951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 198051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putBoolean(buf, pos++, v); 198251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 198451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeByte(int v) throws IOException { 198551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 198651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 198751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos++] = (byte) v; 198951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 199151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeChar(int v) throws IOException { 199251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 2 <= MAX_BLOCK_SIZE) { 199351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putChar(buf, pos, (char) v); 199451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 2; 199551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 199651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeChar(v); 199751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 200051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeShort(int v) throws IOException { 200151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 2 <= MAX_BLOCK_SIZE) { 200251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putShort(buf, pos, (short) v); 200351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 2; 200451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 200551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeShort(v); 200651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 200751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 200851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 200951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeInt(int v) throws IOException { 201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 4 <= MAX_BLOCK_SIZE) { 201151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putInt(buf, pos, v); 201251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 4; 201351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 201451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeInt(v); 201551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 201851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeFloat(float v) throws IOException { 201951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 4 <= MAX_BLOCK_SIZE) { 202051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putFloat(buf, pos, v); 202151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 4; 202251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 202351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeFloat(v); 202451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 202751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeLong(long v) throws IOException { 202851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 8 <= MAX_BLOCK_SIZE) { 202951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putLong(buf, pos, v); 203051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 8; 203151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 203251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeLong(v); 203351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 203451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 203551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 203651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeDouble(double v) throws IOException { 203751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos + 8 <= MAX_BLOCK_SIZE) { 203851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putDouble(buf, pos, v); 203951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 8; 204051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 204151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeDouble(v); 204251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 204351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 204451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 204551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeBytes(String s) throws IOException { 204651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = s.length(); 204751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int cpos = 0; 204851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int csize = 0; 204951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int off = 0; off < endoff; ) { 205051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (cpos >= csize) { 205151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cpos = 0; 205251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski csize = Math.min(endoff - off, CHAR_BUF_SIZE); 205351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.getChars(off, off + csize, cbuf, 0); 205451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 205551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 205651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 205751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 205851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos); 205951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = pos + n; 206051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (pos < stop) { 206151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos++] = (byte) cbuf[cpos++]; 206251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += n; 206451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 206751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeChars(String s) throws IOException { 206851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = s.length(); 206951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int off = 0; off < endoff; ) { 207051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int csize = Math.min(endoff - off, CHAR_BUF_SIZE); 207151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.getChars(off, off + csize, cbuf, 0); 207251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeChars(cbuf, 0, csize); 207351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += csize; 207451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 207551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 207651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 207751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeUTF(String s) throws IOException { 207851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeUTF(s, getUTFLength(s)); 207951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 208051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 208151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 208251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -------------- primitive data array output methods -------------- */ 208351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 208451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following methods write out spans of primitive data values. 208551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Though equivalent to calling the corresponding primitive write 208651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods repeatedly, these methods are optimized for writing groups 208751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of primitive data values more efficiently. 208851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 208951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 209051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeBooleans(boolean[] v, int off, int len) throws IOException { 209151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 209251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 209351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= MAX_BLOCK_SIZE) { 209451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski drain(); 209551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 209651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos)); 209751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < stop) { 209851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putBoolean(buf, pos++, v[off++]); 209951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 210351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeChars(char[] v, int off, int len) throws IOException { 210451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 2; 210551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 210651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 210751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 210851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 1; 210951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = Math.min(endoff, off + avail); 211051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < stop) { 211151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putChar(buf, pos, v[off++]); 211251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 2; 211351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 211551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeChar(v[off++]); 211651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 212051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeShorts(short[] v, int off, int len) throws IOException { 212151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 2; 212251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 212351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 212451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 212551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 1; 212651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = Math.min(endoff, off + avail); 212751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < stop) { 212851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putShort(buf, pos, v[off++]); 212951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 2; 213051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 213251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeShort(v[off++]); 213351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 213751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeInts(int[] v, int off, int len) throws IOException { 213851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 4; 213951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 214051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 214151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 214251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 2; 214351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = Math.min(endoff, off + avail); 214451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < stop) { 214551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putInt(buf, pos, v[off++]); 214651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 4; 214751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 214851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 214951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeInt(v[off++]); 215051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 215451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeFloats(float[] v, int off, int len) throws IOException { 215551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 4; 215651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 215751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 215851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 215951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 2; 216051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int chunklen = Math.min(endoff - off, avail); 216151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski floatsToBytes(v, off, buf, pos, chunklen); 216251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += chunklen; 216351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += chunklen << 2; 216451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 216551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeFloat(v[off++]); 216651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 216751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 216851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 216951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 217051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeLongs(long[] v, int off, int len) throws IOException { 217151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 8; 217251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 217351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 217451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 217551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 3; 217651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int stop = Math.min(endoff, off + avail); 217751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < stop) { 217851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Bits.putLong(buf, pos, v[off++]); 217951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 8; 218051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 218151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 218251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeLong(v[off++]); 218351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 218451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 218551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 218651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 218751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeDoubles(double[] v, int off, int len) throws IOException { 218851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 8; 218951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int endoff = off + len; 219051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (off < endoff) { 219151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 219251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = (MAX_BLOCK_SIZE - pos) >> 3; 219351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int chunklen = Math.min(endoff - off, avail); 219451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski doublesToBytes(v, off, buf, pos, chunklen); 219551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += chunklen; 219651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += chunklen << 3; 219751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 219851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dout.writeDouble(v[off++]); 219951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 220051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 220151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 220251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 220351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 220451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the length in bytes of the UTF encoding of the given string. 220551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 220651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long getUTFLength(String s) { 220751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = s.length(); 220851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long utflen = 0; 220951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int off = 0; off < len; ) { 221051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int csize = Math.min(len - off, CHAR_BUF_SIZE); 221151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.getChars(off, off + csize, cbuf, 0); 221251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int cpos = 0; cpos < csize; cpos++) { 221351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = cbuf[cpos]; 221451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c >= 0x0001 && c <= 0x007F) { 221551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski utflen++; 221651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c > 0x07FF) { 221751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski utflen += 3; 221851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 221951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski utflen += 2; 222051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 222151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 222251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += csize; 222351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 222451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return utflen; 222551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 222651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 222751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 222851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes the given string in UTF format. This method is used in 222951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * situations where the UTF encoding length of the string is already 223051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * known; specifying it explicitly avoids a prescan of the string to 223151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * determine its UTF length. 223251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 223351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeUTF(String s, long utflen) throws IOException { 223451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utflen > 0xFFFFL) { 223551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new UTFDataFormatException(); 223651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 223751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeShort((int) utflen); 223851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utflen == (long) s.length()) { 223951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeBytes(s); 224051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 224151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeUTFBody(s); 224251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 224351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 224451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 224551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 224651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given string in "long" UTF format. "Long" UTF format is 224751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * identical to standard UTF, except that it uses an 8 byte header 224851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (instead of the standard 2 bytes) to convey the UTF encoding length. 224951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 225051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeLongUTF(String s) throws IOException { 225151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeLongUTF(s, getUTFLength(s)); 225251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 225351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 225451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 225551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes given string in "long" UTF format, where the UTF encoding 225651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * length of the string is already known. 225751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 225851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void writeLongUTF(String s, long utflen) throws IOException { 225951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeLong(utflen); 226051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utflen == (long) s.length()) { 226151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeBytes(s); 226251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 226351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeUTFBody(s); 226451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 226551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 226651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 226751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 226851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes the "body" (i.e., the UTF representation minus the 2-byte or 226951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8-byte length header) of the UTF encoding for the given string. 227051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 227151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeUTFBody(String s) throws IOException { 227251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int limit = MAX_BLOCK_SIZE - 3; 227351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = s.length(); 227451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int off = 0; off < len; ) { 227551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int csize = Math.min(len - off, CHAR_BUF_SIZE); 227651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.getChars(off, off + csize, cbuf, 0); 227751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int cpos = 0; cpos < csize; cpos++) { 227851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = cbuf[cpos]; 227951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos <= limit) { 228051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c <= 0x007F && c != 0) { 228151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos++] = (byte) c; 228251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c > 0x07FF) { 228351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F)); 228451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F)); 228551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F)); 228651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 3; 228751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 228851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F)); 228951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F)); 229051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += 2; 229151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 229251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { // write one byte at a time to normalize block 229351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c <= 0x007F && c != 0) { 229451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(c); 229551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c > 0x07FF) { 229651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0xE0 | ((c >> 12) & 0x0F)); 229751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0x80 | ((c >> 6) & 0x3F)); 229851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0x80 | ((c >> 0) & 0x3F)); 229951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 230051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0xC0 | ((c >> 6) & 0x1F)); 230151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0x80 | ((c >> 0) & 0x3F)); 230251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski off += csize; 230651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 231051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 231151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Lightweight identity hash table which maps objects to integer handles, 231251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * assigned in ascending order. 231351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 231451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class HandleTable { 231551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 231651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* number of mappings in table/next available handle */ 231751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int size; 231851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* size threshold determining when to expand hash spine */ 231951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int threshold; 232051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* factor for computing size threshold */ 232151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final float loadFactor; 232251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* maps hash value -> candidate handle value */ 232351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int[] spine; 232451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* maps handle value -> next candidate handle value */ 232551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int[] next; 232651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* maps handle value -> associated object */ 232751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Object[] objs; 232851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 232951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 233051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates new HandleTable with given capacity and load factor. 233151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 233251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski HandleTable(int initialCapacity, float loadFactor) { 233351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.loadFactor = loadFactor; 233451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski spine = new int[initialCapacity]; 233551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski next = new int[initialCapacity]; 233651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski objs = new Object[initialCapacity]; 233751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski threshold = (int) (initialCapacity * loadFactor); 233851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clear(); 233951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 234051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 234151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 234251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Assigns next available handle to given object, and returns handle 234351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * value. Handles are assigned in ascending order starting at 0. 234451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 234551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int assign(Object obj) { 234651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size >= next.length) { 234751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski growEntries(); 234851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 234951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size >= threshold) { 235051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski growSpine(); 235151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 235251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski insert(obj, size); 235351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return size++; 235451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 235551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 235651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 235751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Looks up and returns handle associated with given object, or -1 if 235851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * no mapping found. 235951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 236051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int lookup(Object obj) { 236151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size == 0) { 236251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 236351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 236451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = hash(obj) % spine.length; 236551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = spine[index]; i >= 0; i = next[i]) { 236651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (objs[i] == obj) { 236751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 236851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 236951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 237051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 237151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 237251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 237351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 237451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Resets table to its initial (empty) state. 237551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 237651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void clear() { 237751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.fill(spine, -1); 237851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.fill(objs, 0, size, null); 237951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski size = 0; 238051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 238151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 238251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 238351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the number of mappings currently in table. 238451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 238551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int size() { 238651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return size; 238751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 238851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 238951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 239051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inserts mapping object -> handle mapping into table. Assumes table 239151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is large enough to accommodate new mapping. 239251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 239351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void insert(Object obj, int handle) { 239451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = hash(obj) % spine.length; 239551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski objs[handle] = obj; 239651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski next[handle] = spine[index]; 239751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski spine[index] = handle; 239851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 239951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 240051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 240151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Expands the hash "spine" -- equivalent to increasing the number of 240251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buckets in a conventional hash table. 240351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 240451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void growSpine() { 240551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski spine = new int[(spine.length << 1) + 1]; 240651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski threshold = (int) (spine.length * loadFactor); 240751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.fill(spine, -1); 240851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < size; i++) { 240951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski insert(objs[i], i); 241051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 241151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 241251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 241351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 241451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Increases hash table capacity by lengthening entry arrays. 241551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 241651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void growEntries() { 241751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int newLength = (next.length << 1) + 1; 241851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int[] newNext = new int[newLength]; 241951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(next, 0, newNext, 0, size); 242051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski next = newNext; 242151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 242251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] newObjs = new Object[newLength]; 242351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(objs, 0, newObjs, 0, size); 242451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski objs = newObjs; 242551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 242651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 242751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 242851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns hash value for given object. 242951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 243051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int hash(Object obj) { 243151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return System.identityHashCode(obj) & 0x7FFFFFFF; 243251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 243351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 243451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 243551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 243651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Lightweight identity hash table which maps objects to replacement 243751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects. 243851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 243951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class ReplaceTable { 244051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 244151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* maps object -> index */ 244251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final HandleTable htab; 244351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* maps index -> replacement object */ 244451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Object[] reps; 244551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 244651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 244751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates new ReplaceTable with given capacity and load factor. 244851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 244951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ReplaceTable(int initialCapacity, float loadFactor) { 245051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski htab = new HandleTable(initialCapacity, loadFactor); 245151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reps = new Object[initialCapacity]; 245251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 245351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 245451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 245551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Enters mapping from object to replacement object. 245651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 245751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void assign(Object obj, Object rep) { 245851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = htab.assign(obj); 245951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (index >= reps.length) { 246051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski grow(); 246151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 246251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reps[index] = rep; 246351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 246451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 246551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 246651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Looks up and returns replacement for given object. If no 246751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * replacement is found, returns the lookup object itself. 246851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 246951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object lookup(Object obj) { 247051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = htab.lookup(obj); 247151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (index >= 0) ? reps[index] : obj; 247251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 247351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 247451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 247551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Resets table to its initial (empty) state. 247651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 247751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void clear() { 247851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.fill(reps, 0, htab.size(), null); 247951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski htab.clear(); 248051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 248151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 248251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 248351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the number of mappings currently in table. 248451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 248551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int size() { 248651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return htab.size(); 248751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 248851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 248951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 249051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Increases table capacity. 249151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 249251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void grow() { 249351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] newReps = new Object[(reps.length << 1) + 1]; 249451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(reps, 0, newReps, 0, reps.length); 249551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reps = newReps; 249651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 249751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 249851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 249951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 250051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Stack to keep debug information about the state of the 250151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization process, for embedding in exception messages. 250251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 250351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class DebugTraceInfoStack { 250451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final List<String> stack; 250551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 250651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DebugTraceInfoStack() { 250751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stack = new ArrayList<>(); 250851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 250951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 251051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 251151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Removes all of the elements from enclosed list. 251251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 251351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void clear() { 251451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stack.clear(); 251551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 251651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 251751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 251851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Removes the object at the top of enclosed list. 251951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 252051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void pop() { 252151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stack.remove(stack.size()-1); 252251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 252351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 252451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 252551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pushes a String onto the top of enclosed list. 252651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 252751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void push(String entry) { 252851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stack.add("\t- " + entry); 252951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 253051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 253151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 253251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a string representation of this object 253351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 253451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 253551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuilder buffer = new StringBuilder(); 253651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!stack.isEmpty()) { 253751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for(int i = stack.size(); i > 0; i-- ) { 253851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : "")); 253951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 254051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 254151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.toString(); 254251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 254351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 254451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 254551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 2546