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