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