diff options
author | Tom Tromey <tromey@redhat.com> | 2005-07-16 01:27:14 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 01:27:14 +0000 |
commit | b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1 (patch) | |
tree | 8762d1f992e2f725a6bde1ff966ed6f1e5f4f823 /libjava/java/io/ObjectOutputStream.java | |
parent | ea54b29342c8506acb4f858c68340c44b72e3532 (diff) | |
download | gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.zip gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.tar.gz gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.tar.bz2 |
Major merge with Classpath.
Removed many duplicate files.
* HACKING: Updated.x
* classpath: Imported new directory.
* standard.omit: New file.
* Makefile.in, aclocal.m4, configure: Rebuilt.
* sources.am: New file.
* configure.ac: Run Classpath configure script. Moved code around
to support. Disable xlib AWT peers (temporarily).
* Makefile.am (SUBDIRS): Added 'classpath'
(JAVAC): Removed.
(AM_CPPFLAGS): Added more -I options.
(BOOTCLASSPATH): Simplified.
Completely redid how sources are built.
Include sources.am.
* include/Makefile.am (tool_include__HEADERS): Removed jni.h.
* include/jni.h: Removed (in Classpath).
* scripts/classes.pl: Updated to look at built classes.
* scripts/makemake.tcl: New file.
* testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added
-I options.
(gcj_jni_invocation_compile_c_to_binary): Likewise.
From-SVN: r102082
Diffstat (limited to 'libjava/java/io/ObjectOutputStream.java')
-rw-r--r-- | libjava/java/io/ObjectOutputStream.java | 1570 |
1 files changed, 0 insertions, 1570 deletions
diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java deleted file mode 100644 index e7f1fc8..0000000 --- a/libjava/java/io/ObjectOutputStream.java +++ /dev/null @@ -1,1570 +0,0 @@ -/* ObjectOutputStream.java -- Class used to write serialized objects - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.io; - -import gnu.classpath.Configuration; -import gnu.java.io.ObjectIdentityWrapper; -import gnu.java.lang.reflect.TypeSignature; -import gnu.java.security.action.SetAccessibleAction; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.util.Hashtable; - -/** - * An <code>ObjectOutputStream</code> can be used to write objects - * as well as primitive data in a platform-independent manner to an - * <code>OutputStream</code>. - * - * The data produced by an <code>ObjectOutputStream</code> can be read - * and reconstituted by an <code>ObjectInputStream</code>. - * - * <code>writeObject (Object)</code> is used to write Objects, the - * <code>write<type></code> methods are used to write primitive - * data (as in <code>DataOutputStream</code>). Strings can be written - * as objects or as primitive data. - * - * Not all objects can be written out using an - * <code>ObjectOutputStream</code>. Only those objects that are an - * instance of <code>java.io.Serializable</code> can be written. - * - * Using default serialization, information about the class of an - * object is written, all of the non-transient, non-static fields of - * the object are written, if any of these fields are objects, they are - * written out in the same manner. - * - * An object is only written out the first time it is encountered. If - * the object is encountered later, a reference to it is written to - * the underlying stream. Thus writing circular object graphs - * does not present a problem, nor are relationships between objects - * in a graph lost. - * - * Example usage: - * <pre> - * Hashtable map = new Hashtable (); - * map.put ("one", new Integer (1)); - * map.put ("two", new Integer (2)); - * - * ObjectOutputStream oos = - * new ObjectOutputStream (new FileOutputStream ("numbers")); - * oos.writeObject (map); - * oos.close (); - * - * ObjectInputStream ois = - * new ObjectInputStream (new FileInputStream ("numbers")); - * Hashtable newmap = (Hashtable)ois.readObject (); - * - * System.out.println (newmap); - * </pre> - * - * The default serialization can be overriden in two ways. - * - * By defining a method <code>private void - * writeObject (ObjectOutputStream)</code>, a class can dictate exactly - * how information about itself is written. - * <code>defaultWriteObject ()</code> may be called from this method to - * carry out default serialization. This method is not - * responsible for dealing with fields of super-classes or subclasses. - * - * By implementing <code>java.io.Externalizable</code>. This gives - * the class complete control over the way it is written to the - * stream. If this approach is used the burden of writing superclass - * and subclass data is transfered to the class implementing - * <code>java.io.Externalizable</code>. - * - * @see java.io.DataOutputStream - * @see java.io.Externalizable - * @see java.io.ObjectInputStream - * @see java.io.Serializable - */ -public class ObjectOutputStream extends OutputStream - implements ObjectOutput, ObjectStreamConstants -{ - /** - * Creates a new <code>ObjectOutputStream</code> that will do all of - * its writing onto <code>out</code>. This method also initializes - * the stream by writing the header information (stream magic number - * and stream version). - * - * @exception IOException Writing stream header to underlying - * stream cannot be completed. - * - * @see #writeStreamHeader() - */ - public ObjectOutputStream (OutputStream out) throws IOException - { - realOutput = new DataOutputStream(out); - blockData = new byte[ BUFFER_SIZE ]; - blockDataCount = 0; - blockDataOutput = new DataOutputStream(this); - setBlockDataMode(true); - replacementEnabled = false; - isSerializing = false; - nextOID = baseWireHandle; - OIDLookupTable = new Hashtable(); - protocolVersion = defaultProtocolVersion; - useSubclassMethod = false; - writeStreamHeader(); - - if (Configuration.DEBUG) - { - String val = System.getProperty("gcj.dumpobjects"); - if (val != null && !val.equals("")) - dump = true; - } - } - - /** - * Writes a representation of <code>obj</code> to the underlying - * output stream by writing out information about its class, then - * writing out each of the objects non-transient, non-static - * fields. If any of these fields are other objects, - * they are written out in the same manner. - * - * This method can be overriden by a class by implementing - * <code>private void writeObject (ObjectOutputStream)</code>. - * - * If an exception is thrown from this method, the stream is left in - * an undefined state. - * - * @exception NotSerializableException An attempt was made to - * serialize an <code>Object</code> that is not serializable. - * - * @exception InvalidClassException Somebody tried to serialize - * an object which is wrongly formatted. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - */ - public final void writeObject(Object obj) throws IOException - { - if (useSubclassMethod) - { - if (dump) - dumpElementln ("WRITE OVERRIDE: " + obj); - - writeObjectOverride(obj); - return; - } - - if (dump) - dumpElementln ("WRITE: " + obj); - - depth += 2; - - boolean was_serializing = isSerializing; - boolean old_mode = setBlockDataMode(false); - try - { - isSerializing = true; - boolean replaceDone = false; - Object replacedObject = null; - - while (true) - { - if (obj == null) - { - realOutput.writeByte(TC_NULL); - break; - } - - Integer handle = findHandle(obj); - if (handle != null) - { - realOutput.writeByte(TC_REFERENCE); - realOutput.writeInt(handle.intValue()); - break; - } - - if (obj instanceof Class) - { - Class cl = (Class)obj; - ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl); - realOutput.writeByte(TC_CLASS); - if (!osc.isProxyClass) - { - writeObject (osc); - } - else - { - realOutput.writeByte(TC_PROXYCLASSDESC); - Class[] intfs = cl.getInterfaces(); - realOutput.writeInt(intfs.length); - for (int i = 0; i < intfs.length; i++) - realOutput.writeUTF(intfs[i].getName()); - - boolean oldmode = setBlockDataMode(true); - annotateProxyClass(cl); - setBlockDataMode(oldmode); - realOutput.writeByte(TC_ENDBLOCKDATA); - - writeObject(osc.getSuper()); - } - assignNewHandle(obj); - break; - } - - if (obj instanceof ObjectStreamClass) - { - writeClassDescriptor((ObjectStreamClass) obj); - break; - } - - Class clazz = obj.getClass(); - ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz); - if (osc == null) - throw new NotSerializableException(clazz.getName()); - - if ((replacementEnabled || obj instanceof Serializable) - && ! replaceDone) - { - replacedObject = obj; - - if (obj instanceof Serializable) - { - try - { - Method m = osc.writeReplaceMethod; - if (m != null) - obj = m.invoke(obj, new Object[0]); - } - catch (IllegalAccessException ignore) - { - } - catch (InvocationTargetException ignore) - { - } - } - - if (replacementEnabled) - obj = replaceObject(obj); - - replaceDone = true; - continue; - } - - if (obj instanceof String) - { - realOutput.writeByte(TC_STRING); - assignNewHandle(obj); - realOutput.writeUTF((String)obj); - break; - } - - if (clazz.isArray ()) - { - realOutput.writeByte(TC_ARRAY); - writeObject(osc); - assignNewHandle(obj); - writeArraySizeAndElements(obj, clazz.getComponentType()); - break; - } - - realOutput.writeByte(TC_OBJECT); - writeObject(osc); - - if (replaceDone) - assignNewHandle(replacedObject); - else - assignNewHandle(obj); - - if (obj instanceof Externalizable) - { - if (protocolVersion == PROTOCOL_VERSION_2) - setBlockDataMode(true); - - ((Externalizable)obj).writeExternal(this); - - if (protocolVersion == PROTOCOL_VERSION_2) - { - setBlockDataMode(false); - realOutput.writeByte(TC_ENDBLOCKDATA); - } - - break; - } - - if (obj instanceof Serializable) - { - Object prevObject = this.currentObject; - ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass; - currentObject = obj; - ObjectStreamClass[] hierarchy = - ObjectStreamClass.getObjectStreamClasses(clazz); - - for (int i = 0; i < hierarchy.length; i++) - { - currentObjectStreamClass = hierarchy[i]; - - fieldsAlreadyWritten = false; - if (currentObjectStreamClass.hasWriteMethod()) - { - if (dump) - dumpElementln ("WRITE METHOD CALLED FOR: " + obj); - setBlockDataMode(true); - callWriteMethod(obj, currentObjectStreamClass); - setBlockDataMode(false); - realOutput.writeByte(TC_ENDBLOCKDATA); - if (dump) - dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj); - } - else - { - if (dump) - dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); - writeFields(obj, currentObjectStreamClass); - } - } - - this.currentObject = prevObject; - this.currentObjectStreamClass = prevObjectStreamClass; - currentPutField = null; - break; - } - - throw new NotSerializableException(clazz.getName ()); - } // end pseudo-loop - } - catch (ObjectStreamException ose) - { - // Rethrow these are fatal. - throw ose; - } - catch (IOException e) - { - realOutput.writeByte(TC_EXCEPTION); - reset(true); - - setBlockDataMode(false); - try - { - if (Configuration.DEBUG) - { - e.printStackTrace(System.out); - } - writeObject(e); - } - catch (IOException ioe) - { - StreamCorruptedException ex = - new StreamCorruptedException - (ioe + " thrown while exception was being written to stream."); - if (Configuration.DEBUG) - { - ex.printStackTrace(System.out); - } - throw ex; - } - - reset (true); - - } - finally - { - isSerializing = was_serializing; - setBlockDataMode(old_mode); - depth -= 2; - - if (dump) - dumpElementln ("END: " + obj); - } - } - - protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException - { - realOutput.writeByte(TC_CLASSDESC); - realOutput.writeUTF(osc.getName()); - realOutput.writeLong(osc.getSerialVersionUID()); - assignNewHandle(osc); - - int flags = osc.getFlags(); - - if (protocolVersion == PROTOCOL_VERSION_2 - && osc.isExternalizable()) - flags |= SC_BLOCK_DATA; - - realOutput.writeByte(flags); - - ObjectStreamField[] fields = osc.fields; - realOutput.writeShort(fields.length); - - ObjectStreamField field; - for (int i = 0; i < fields.length; i++) - { - field = fields[i]; - realOutput.writeByte(field.getTypeCode ()); - realOutput.writeUTF(field.getName ()); - - if (! field.isPrimitive()) - writeObject(field.getTypeString()); - } - - boolean oldmode = setBlockDataMode(true); - annotateClass(osc.forClass()); - setBlockDataMode(oldmode); - realOutput.writeByte(TC_ENDBLOCKDATA); - - if (osc.isSerializable() || osc.isExternalizable()) - writeObject(osc.getSuper()); - else - writeObject(null); - } - - /** - * Writes the current objects non-transient, non-static fields from - * the current class to the underlying output stream. - * - * This method is intended to be called from within a object's - * <code>private void writeObject (ObjectOutputStream)</code> - * method. - * - * @exception NotActiveException This method was called from a - * context other than from the current object's and current class's - * <code>private void writeObject (ObjectOutputStream)</code> - * method. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - */ - public void defaultWriteObject() - throws IOException, NotActiveException - { - markFieldsWritten(); - writeFields(currentObject, currentObjectStreamClass); - } - - - private void markFieldsWritten() throws IOException - { - if (currentObject == null || currentObjectStreamClass == null) - throw new NotActiveException - ("defaultWriteObject called by non-active class and/or object"); - - if (fieldsAlreadyWritten) - throw new IOException - ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once"); - - fieldsAlreadyWritten = true; - } - - /** - * Resets stream to state equivalent to the state just after it was - * constructed. - * - * Causes all objects previously written to the stream to be - * forgotten. A notification of this reset is also written to the - * underlying stream. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code> or reset called while serialization is - * in progress. - */ - public void reset() throws IOException - { - reset(false); - } - - - private void reset(boolean internal) throws IOException - { - if (!internal) - { - if (isSerializing) - throw new IOException("Reset called while serialization in progress"); - - realOutput.writeByte(TC_RESET); - } - - clearHandles(); - } - - - /** - * Informs this <code>ObjectOutputStream</code> to write data - * according to the specified protocol. There are currently two - * different protocols, specified by <code>PROTOCOL_VERSION_1</code> - * and <code>PROTOCOL_VERSION_2</code>. This implementation writes - * data using <code>PROTOCOL_VERSION_2</code> by default, as is done - * by the JDK 1.2. - * - * A non-portable method, <code>setDefaultProtocolVersion (int - * version)</code> is provided to change the default protocol - * version. - * - * For an explination of the differences beween the two protocols - * see XXX: the Java ObjectSerialization Specification. - * - * @exception IOException if <code>version</code> is not a valid - * protocol - * - * @see #setDefaultProtocolVersion(int) - */ - public void useProtocolVersion(int version) throws IOException - { - if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2) - throw new IOException("Invalid protocol version requested."); - - protocolVersion = version; - } - - - /** - * <em>GNU $classpath specific</em> - * - * Changes the default stream protocol used by all - * <code>ObjectOutputStream</code>s. There are currently two - * different protocols, specified by <code>PROTOCOL_VERSION_1</code> - * and <code>PROTOCOL_VERSION_2</code>. The default default is - * <code>PROTOCOL_VERSION_1</code>. - * - * @exception IOException if <code>version</code> is not a valid - * protocol - * - * @see #useProtocolVersion(int) - */ - public static void setDefaultProtocolVersion(int version) - throws IOException - { - if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2) - throw new IOException("Invalid protocol version requested."); - - defaultProtocolVersion = version; - } - - - /** - * An empty hook that allows subclasses to write extra information - * about classes to the stream. This method is called the first - * time each class is seen, and after all of the standard - * information about the class has been written. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - * - * @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass) - */ - protected void annotateClass(Class cl) throws IOException - { - } - - protected void annotateProxyClass(Class cl) throws IOException - { - } - - /** - * Allows subclasses to replace objects that are written to the - * stream with other objects to be written in their place. This - * method is called the first time each object is encountered - * (modulo reseting of the stream). - * - * This method must be enabled before it will be called in the - * serialization process. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - * - * @see #enableReplaceObject(boolean) - */ - protected Object replaceObject(Object obj) throws IOException - { - return obj; - } - - - /** - * If <code>enable</code> is <code>true</code> and this object is - * trusted, then <code>replaceObject (Object)</code> will be called - * in subsequent calls to <code>writeObject (Object)</code>. - * Otherwise, <code>replaceObject (Object)</code> will not be called. - * - * @exception SecurityException This class is not trusted. - */ - protected boolean enableReplaceObject(boolean enable) - throws SecurityException - { - if (enable) - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(new SerializablePermission("enableSubstitution")); - } - - boolean old_val = replacementEnabled; - replacementEnabled = enable; - return old_val; - } - - - /** - * Writes stream magic and stream version information to the - * underlying stream. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - */ - protected void writeStreamHeader() throws IOException - { - realOutput.writeShort(STREAM_MAGIC); - realOutput.writeShort(STREAM_VERSION); - } - - /** - * Protected constructor that allows subclasses to override - * serialization. This constructor should be called by subclasses - * that wish to override <code>writeObject (Object)</code>. This - * method does a security check <i>NOTE: currently not - * implemented</i>, then sets a flag that informs - * <code>writeObject (Object)</code> to call the subclasses - * <code>writeObjectOverride (Object)</code> method. - * - * @see #writeObjectOverride(Object) - */ - protected ObjectOutputStream() throws IOException, SecurityException - { - SecurityManager sec_man = System.getSecurityManager (); - if (sec_man != null) - sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - useSubclassMethod = true; - } - - - /** - * This method allows subclasses to override the default - * serialization mechanism provided by - * <code>ObjectOutputStream</code>. To make this method be used for - * writing objects, subclasses must invoke the 0-argument - * constructor on this class from there constructor. - * - * @see #ObjectOutputStream() - * - * @exception NotActiveException Subclass has arranged for this - * method to be called, but did not implement this method. - */ - protected void writeObjectOverride(Object obj) throws NotActiveException, - IOException - { - throw new NotActiveException - ("Subclass of ObjectOutputStream must implement writeObjectOverride"); - } - - - /** - * @see DataOutputStream#write(int) - */ - public void write (int data) throws IOException - { - if (writeDataAsBlocks) - { - if (blockDataCount == BUFFER_SIZE) - drain(); - - blockData[ blockDataCount++ ] = (byte)data; - } - else - realOutput.write(data); - } - - - /** - * @see DataOutputStream#write(byte[]) - */ - public void write(byte[] b) throws IOException - { - write(b, 0, b.length); - } - - - /** - * @see DataOutputStream#write(byte[],int,int) - */ - public void write(byte[] b, int off, int len) throws IOException - { - if (writeDataAsBlocks) - { - if (len < 0) - throw new IndexOutOfBoundsException(); - - if (blockDataCount + len < BUFFER_SIZE) - { - System.arraycopy(b, off, blockData, blockDataCount, len); - blockDataCount += len; - } - else - { - drain(); - writeBlockDataHeader(len); - realOutput.write(b, off, len); - } - } - else - realOutput.write(b, off, len); - } - - - /** - * @see DataOutputStream#flush() - */ - public void flush () throws IOException - { - drain(); - realOutput.flush(); - } - - - /** - * Causes the block-data buffer to be written to the underlying - * stream, but does not flush underlying stream. - * - * @exception IOException Exception from underlying - * <code>OutputStream</code>. - */ - protected void drain() throws IOException - { - if (blockDataCount == 0) - return; - - if (writeDataAsBlocks) - writeBlockDataHeader(blockDataCount); - realOutput.write(blockData, 0, blockDataCount); - blockDataCount = 0; - } - - - /** - * @see java.io.DataOutputStream#close () - */ - public void close() throws IOException - { - flush(); - realOutput.close(); - } - - - /** - * @see java.io.DataOutputStream#writeBoolean (boolean) - */ - public void writeBoolean(boolean data) throws IOException - { - blockDataOutput.writeBoolean(data); - } - - - /** - * @see java.io.DataOutputStream#writeByte (int) - */ - public void writeByte(int data) throws IOException - { - blockDataOutput.writeByte(data); - } - - - /** - * @see java.io.DataOutputStream#writeShort (int) - */ - public void writeShort (int data) throws IOException - { - blockDataOutput.writeShort(data); - } - - - /** - * @see java.io.DataOutputStream#writeChar (int) - */ - public void writeChar(int data) throws IOException - { - blockDataOutput.writeChar(data); - } - - - /** - * @see java.io.DataOutputStream#writeInt (int) - */ - public void writeInt(int data) throws IOException - { - blockDataOutput.writeInt(data); - } - - - /** - * @see java.io.DataOutputStream#writeLong (long) - */ - public void writeLong(long data) throws IOException - { - blockDataOutput.writeLong(data); - } - - - /** - * @see java.io.DataOutputStream#writeFloat (float) - */ - public void writeFloat(float data) throws IOException - { - blockDataOutput.writeFloat(data); - } - - - /** - * @see java.io.DataOutputStream#writeDouble (double) - */ - public void writeDouble(double data) throws IOException - { - blockDataOutput.writeDouble(data); - } - - - /** - * @see java.io.DataOutputStream#writeBytes (java.lang.String) - */ - public void writeBytes(String data) throws IOException - { - blockDataOutput.writeBytes(data); - } - - - /** - * @see java.io.DataOutputStream#writeChars (java.lang.String) - */ - public void writeChars(String data) throws IOException - { - dataOutput.writeChars(data); - } - - - /** - * @see java.io.DataOutputStream#writeUTF (java.lang.String) - */ - public void writeUTF(String data) throws IOException - { - dataOutput.writeUTF(data); - } - - - /** - * This class allows a class to specify exactly which fields should - * be written, and what values should be written for these fields. - * - * XXX: finish up comments - */ - public abstract static class PutField - { - public abstract void put (String name, boolean value); - public abstract void put (String name, byte value); - public abstract void put (String name, char value); - public abstract void put (String name, double value); - public abstract void put (String name, float value); - public abstract void put (String name, int value); - public abstract void put (String name, long value); - public abstract void put (String name, short value); - public abstract void put (String name, Object value); - - /** - * @deprecated - */ - public abstract void write (ObjectOutput out) throws IOException; - } - - public PutField putFields() throws IOException - { - if (currentPutField != null) - return currentPutField; - - currentPutField = new PutField() - { - private byte[] prim_field_data - = new byte[currentObjectStreamClass.primFieldSize]; - private Object[] objs - = new Object[currentObjectStreamClass.objectFieldCount]; - - private ObjectStreamField getField (String name) - { - ObjectStreamField field - = currentObjectStreamClass.getField(name); - - if (field == null) - throw new IllegalArgumentException("no such serializable field " + name); - - return field; - } - - public void put(String name, boolean value) - { - ObjectStreamField field = getField(name); - - checkType(field, 'Z'); - prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0); - } - - public void put(String name, byte value) - { - ObjectStreamField field = getField(name); - - checkType(field, 'B'); - prim_field_data[field.getOffset()] = value; - } - - public void put(String name, char value) - { - ObjectStreamField field = getField(name); - - checkType(field, 'C'); - int off = field.getOffset(); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put(String name, double value) - { - ObjectStreamField field = getField (name); - - checkType(field, 'D'); - int off = field.getOffset(); - long l_value = Double.doubleToLongBits (value); - prim_field_data[off++] = (byte)(l_value >>> 52); - prim_field_data[off++] = (byte)(l_value >>> 48); - prim_field_data[off++] = (byte)(l_value >>> 40); - prim_field_data[off++] = (byte)(l_value >>> 32); - prim_field_data[off++] = (byte)(l_value >>> 24); - prim_field_data[off++] = (byte)(l_value >>> 16); - prim_field_data[off++] = (byte)(l_value >>> 8); - prim_field_data[off] = (byte)l_value; - } - - public void put(String name, float value) - { - ObjectStreamField field = getField(name); - - checkType(field, 'F'); - int off = field.getOffset(); - int i_value = Float.floatToIntBits(value); - prim_field_data[off++] = (byte)(i_value >>> 24); - prim_field_data[off++] = (byte)(i_value >>> 16); - prim_field_data[off++] = (byte)(i_value >>> 8); - prim_field_data[off] = (byte)i_value; - } - - public void put(String name, int value) - { - ObjectStreamField field = getField(name); - checkType(field, 'I'); - int off = field.getOffset(); - prim_field_data[off++] = (byte)(value >>> 24); - prim_field_data[off++] = (byte)(value >>> 16); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put(String name, long value) - { - ObjectStreamField field = getField(name); - checkType(field, 'J'); - int off = field.getOffset(); - prim_field_data[off++] = (byte)(value >>> 52); - prim_field_data[off++] = (byte)(value >>> 48); - prim_field_data[off++] = (byte)(value >>> 40); - prim_field_data[off++] = (byte)(value >>> 32); - prim_field_data[off++] = (byte)(value >>> 24); - prim_field_data[off++] = (byte)(value >>> 16); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put(String name, short value) - { - ObjectStreamField field = getField(name); - checkType(field, 'S'); - int off = field.getOffset(); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put(String name, Object value) - { - ObjectStreamField field = getField(name); - - if (value != null && - ! field.getType().isAssignableFrom(value.getClass ())) - throw new IllegalArgumentException("Class " + value.getClass() + - " cannot be cast to " + field.getType()); - objs[field.getOffset()] = value; - } - - public void write(ObjectOutput out) throws IOException - { - // Apparently Block data is not used with PutField as per - // empirical evidence against JDK 1.2. Also see Mauve test - // java.io.ObjectInputOutput.Test.GetPutField. - boolean oldmode = setBlockDataMode(false); - out.write(prim_field_data); - for (int i = 0; i < objs.length; ++ i) - out.writeObject(objs[i]); - setBlockDataMode(oldmode); - } - - private void checkType(ObjectStreamField field, char type) - throws IllegalArgumentException - { - if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0) - != type) - throw new IllegalArgumentException(); - } - }; - // end PutFieldImpl - - return currentPutField; - } - - - public void writeFields() throws IOException - { - if (currentPutField == null) - throw new NotActiveException("writeFields can only be called after putFields has been called"); - - markFieldsWritten(); - currentPutField.write(this); - } - - - // write out the block-data buffer, picking the correct header - // depending on the size of the buffer - private void writeBlockDataHeader(int size) throws IOException - { - if (size < 256) - { - realOutput.writeByte(TC_BLOCKDATA); - realOutput.write(size); - } - else - { - realOutput.writeByte(TC_BLOCKDATALONG); - realOutput.writeInt(size); - } - } - - - // lookup the handle for OBJ, return null if OBJ doesn't have a - // handle yet - private Integer findHandle(Object obj) - { - return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj)); - } - - - // assigns the next availible handle to OBJ - private int assignNewHandle(Object obj) - { - OIDLookupTable.put(new ObjectIdentityWrapper(obj), - new Integer(nextOID)); - return nextOID++; - } - - - // resets mapping from objects to handles - private void clearHandles() - { - nextOID = baseWireHandle; - OIDLookupTable.clear(); - } - - - // write out array size followed by each element of the array - private void writeArraySizeAndElements(Object array, Class clazz) - throws IOException - { - int length = Array.getLength(array); - - if (clazz.isPrimitive()) - { - if (clazz == Boolean.TYPE) - { - boolean[] cast_array = (boolean[])array; - realOutput.writeInt (length); - for (int i = 0; i < length; i++) - realOutput.writeBoolean(cast_array[i]); - return; - } - if (clazz == Byte.TYPE) - { - byte[] cast_array = (byte[])array; - realOutput.writeInt(length); - realOutput.write(cast_array, 0, length); - return; - } - if (clazz == Character.TYPE) - { - char[] cast_array = (char[])array; - realOutput.writeInt(length); - for (int i = 0; i < length; i++) - realOutput.writeChar(cast_array[i]); - return; - } - if (clazz == Double.TYPE) - { - double[] cast_array = (double[])array; - realOutput.writeInt(length); - for (int i = 0; i < length; i++) - realOutput.writeDouble(cast_array[i]); - return; - } - if (clazz == Float.TYPE) - { - float[] cast_array = (float[])array; - realOutput.writeInt(length); - for (int i = 0; i < length; i++) - realOutput.writeFloat(cast_array[i]); - return; - } - if (clazz == Integer.TYPE) - { - int[] cast_array = (int[])array; - realOutput.writeInt(length); - for (int i = 0; i < length; i++) - realOutput.writeInt(cast_array[i]); - return; - } - if (clazz == Long.TYPE) - { - long[] cast_array = (long[])array; - realOutput.writeInt (length); - for (int i = 0; i < length; i++) - realOutput.writeLong(cast_array[i]); - return; - } - if (clazz == Short.TYPE) - { - short[] cast_array = (short[])array; - realOutput.writeInt (length); - for (int i = 0; i < length; i++) - realOutput.writeShort(cast_array[i]); - return; - } - } - else - { - Object[] cast_array = (Object[])array; - realOutput.writeInt(length); - for (int i = 0; i < length; i++) - writeObject(cast_array[i]); - } - } - - - // writes out FIELDS of OBJECT for the specified ObjectStreamClass. - // FIELDS are already in canonical order. - private void writeFields(Object obj, ObjectStreamClass osc) - throws IOException - { - ObjectStreamField[] fields = osc.fields; - boolean oldmode = setBlockDataMode(false); - String field_name; - Class type; - - for (int i = 0; i < fields.length; i++) - { - field_name = fields[i].getName(); - type = fields[i].getType(); - - if (dump) - dumpElementln ("WRITE FIELD: " + field_name + " type=" + type); - - if (type == Boolean.TYPE) - realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name)); - else if (type == Byte.TYPE) - realOutput.writeByte(getByteField(obj, osc.forClass(), field_name)); - else if (type == Character.TYPE) - realOutput.writeChar(getCharField(obj, osc.forClass(), field_name)); - else if (type == Double.TYPE) - realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name)); - else if (type == Float.TYPE) - realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name)); - else if (type == Integer.TYPE) - realOutput.writeInt(getIntField(obj, osc.forClass(), field_name)); - else if (type == Long.TYPE) - realOutput.writeLong(getLongField(obj, osc.forClass(), field_name)); - else if (type == Short.TYPE) - realOutput.writeShort(getShortField(obj, osc.forClass(), field_name)); - else - writeObject(getObjectField(obj, osc.forClass(), field_name, - fields[i].getTypeString ())); - } - setBlockDataMode(oldmode); - } - - - // Toggles writing primitive data to block-data buffer. - // Package-private to avoid a trampoline constructor. - boolean setBlockDataMode(boolean on) throws IOException - { - if (on == writeDataAsBlocks) - return on; - - drain(); - boolean oldmode = writeDataAsBlocks; - writeDataAsBlocks = on; - - if (on) - dataOutput = blockDataOutput; - else - dataOutput = realOutput; - - return oldmode; - } - - - private void callWriteMethod(Object obj, ObjectStreamClass osc) - throws IOException - { - currentPutField = null; - try - { - Object args[] = {this}; - osc.writeObjectMethod.invoke(obj, args); - } - catch (InvocationTargetException x) - { - /* Rethrow if possible. */ - Throwable exception = x.getTargetException(); - if (exception instanceof RuntimeException) - throw (RuntimeException) exception; - if (exception instanceof IOException) - throw (IOException) exception; - - IOException ioe - = new IOException("Exception thrown from writeObject() on " + - osc.forClass().getName() + ": " + - exception.getClass().getName()); - ioe.initCause(exception); - throw ioe; - } - catch (Exception x) - { - IOException ioe - = new IOException("Failure invoking writeObject() on " + - osc.forClass().getName() + ": " + - x.getClass().getName()); - ioe.initCause(x); - throw ioe; - } - } - - private boolean getBooleanField(Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField(klass, field_name); - boolean b = f.getBoolean(obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private byte getByteField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - byte b = f.getByte (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private char getCharField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - char b = f.getChar (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private double getDoubleField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - double b = f.getDouble (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private float getFloatField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - float b = f.getFloat (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private int getIntField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - int b = f.getInt (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private long getLongField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - long b = f.getLong (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private short getShortField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - short b = f.getShort (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private Object getObjectField (Object obj, Class klass, String field_name, - String type_code) throws IOException - { - try - { - Field f = getField (klass, field_name); - ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType()); - - if (of.getTypeString() == null || - !of.getTypeString().equals(type_code)) - throw new InvalidClassException - ("invalid type code for " + field_name + " in class " + klass.getName()); - - Object o = f.get (obj); - // FIXME: We should check the type_code here - return o; - } - catch (IOException e) - { - throw e; - } - catch (Exception e) - { - throw new IOException (); - } - } - - private Field getField (Class klass, String name) - throws java.io.InvalidClassException - { - try - { - final Field f = klass.getDeclaredField(name); - setAccessible.setMember(f); - AccessController.doPrivileged(setAccessible); - return f; - } - catch (java.lang.NoSuchFieldException e) - { - throw new InvalidClassException - ("no field called " + name + " in class " + klass.getName()); - } - } - - private void dumpElementln (String msg) - { - for (int i = 0; i < depth; i++) - System.out.print (" "); - System.out.print (Thread.currentThread() + ": "); - System.out.println(msg); - } - - // this value comes from 1.2 spec, but is used in 1.1 as well - private static final int BUFFER_SIZE = 1024; - - private static int defaultProtocolVersion = PROTOCOL_VERSION_2; - - private DataOutputStream dataOutput; - private boolean writeDataAsBlocks; - private DataOutputStream realOutput; - private DataOutputStream blockDataOutput; - private byte[] blockData; - private int blockDataCount; - private Object currentObject; - // Package-private to avoid a trampoline. - ObjectStreamClass currentObjectStreamClass; - private PutField currentPutField; - private boolean fieldsAlreadyWritten; - private boolean replacementEnabled; - private boolean isSerializing; - private int nextOID; - private Hashtable OIDLookupTable; - private int protocolVersion; - private boolean useSubclassMethod; - private SetAccessibleAction setAccessible = new SetAccessibleAction(); - - // The nesting depth for debugging output - private int depth = 0; - - // Set if we're generating debugging dumps - private boolean dump = false; - - static - { - if (Configuration.INIT_LOAD_LIBRARY) - { - System.loadLibrary("javaio"); - } - } -} |