0N/A/*
2362N/A * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Aimport java.io.*;
0N/Aimport java.lang.reflect.Field;
0N/Aimport java.lang.reflect.Method;
0N/Aimport java.lang.reflect.Modifier;
0N/Aimport java.lang.reflect.InvocationTargetException;
0N/Aimport java.security.*;
0N/A
0N/Apublic class XObjectOutputStream extends AbstractObjectOutputStream {
0N/A XObjectOutputStream(OutputStream out) throws IOException {
0N/A super(out);
0N/A }
0N/A
0N/A protected boolean enableReplaceObject(boolean enable)
0N/A {
0N/A throw new Error("not implemented");
0N/A }
0N/A
0N/A protected void annotateClass(Class<?> cl) throws IOException {
0N/A }
0N/A
0N/A public void close() throws IOException{
0N/A out.close();
0N/A }
0N/A
0N/A protected Object replaceObject(Object obj) throws IOException {
0N/A return obj;
0N/A }
0N/A
0N/A protected void writeStreamHeader() throws IOException {
0N/A super.writeStreamHeader();
0N/A }
0N/A
0N/A final protected void writeObjectOverride(Object obj) throws IOException {
0N/A Object prevCurrentObject = currentObject;
0N/A currentObject = obj;
0N/A System.out.println("writeObjectOverride(" + obj.toString() + ")");
0N/A try {
0N/A // ** Preserving reference semantics.
0N/A // if (obj already serialized) {
0N/A // look up streamId for obj and write it into 'this' stream.
0N/A // return;
0N/A // }
0N/A //
0N/A // if (obj instanceof Class) {
0N/A // //Special processing for classes.
0N/A // //Might need to call this.annotateClass(obj.getClass())
0N/A // //someday.
0N/A // return;
0N/A // }
0N/A //
0N/A // **Replacement semantics
0N/A // Object replacement = obj;
0N/A // if (enableReplace)
0N/A // replacement = this.writeReplace(obj);
0N/A // if (replacement instanceof Replaceable)
0N/A // replacement = ((Replaceable)replacement).replaceObject(this);
0N/A // if (obj != replacement) {
0N/A // //record that all future occurances of obj should be replaced
0N/A // //with replacement
0N/A // }
0N/A //
0N/A // if obj is Externalizeable {
0N/A // Object[] argList = {this};
0N/A // invokeMethod(obj, writeExternalMethod, argList);
0N/A // else
0N/A
0N/A Method writeObjectMethod = getWriteObjectMethod(obj.getClass());
0N/A
0N/A if (writeObjectMethod != null) {
0N/A Object[] arglist = {this};
0N/A invokeMethod(obj, writeObjectMethod, arglist);
0N/A } else
0N/A defaultWriteObject();
0N/A } finally {
0N/A currentObject = prevCurrentObject;
0N/A }
0N/A }
0N/A
0N/A /* Since defaultWriteObject() does not take the object to write as a parameter,
0N/A * implementation is required to store currentObject when writeObject is called.
0N/A */
0N/A public void defaultWriteObject() throws IOException {
0N/A Object obj = currentObject;
0N/A System.out.println("XObjectOutputStream.defaultWriteObject(" +
0N/A obj.toString() + ")");
0N/A
0N/A //In order to access package, private and protected fields,
0N/A //one needs to use Priviledged Access and be trusted code.
0N/A //This test will avoid that problem by only serializing public fields.
0N/A Field[] fields = obj.getClass().getFields();
0N/A for (int i= 0; i < fields.length; i++) {
0N/A //Skip non-Serializable fields.
0N/A int mods = fields[i].getModifiers();
0N/A if (Modifier.isStatic(mods) || Modifier.isTransient(mods))
0N/A continue;
0N/A Class FieldType = fields[i].getType();
0N/A if (FieldType.isPrimitive()) {
0N/A System.out.println("Field " + fields[i].getName() +
0N/A " has primitive type " + FieldType.toString());
0N/A } else {
0N/A System.out.println("**Field " + fields[i].getName() +
0N/A " is an Object of type " + FieldType.toString());
0N/A try {
0N/A writeObject(fields[i].get(obj));
0N/A if (FieldType.isArray()) {
0N/A Object[] array = ((Object[]) fields[i].get(obj));
0N/A Class componentType = FieldType.getComponentType();
0N/A if (componentType.isPrimitive())
0N/A System.out.println("Output " + array.length + " primitive elements of" +
0N/A componentType.toString());
0N/A else {
0N/A System.out.println("Output " + array.length + " of Object elements of" +
0N/A componentType.toString());
0N/A for (int k = 0; k < array.length; k++) {
0N/A writeObject(array[k]);
0N/A }
0N/A }
0N/A }
0N/A } catch (IllegalAccessException e) {
0N/A throw new IOException(e.getMessage());
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A public PutField putFields() throws IOException {
0N/A currentPutField = new InternalPutField();
0N/A return currentPutField;
0N/A }
0N/A
0N/A public void writeFields() throws IOException {
0N/A currentPutField.write(this);
0N/A }
0N/A
0N/A static final class InternalPutField extends ObjectOutputStream.PutField {
0N/A String fieldName[];
0N/A int intValue[];
0N/A int next;
0N/A
0N/A InternalPutField() {
0N/A fieldName = new String[10];
0N/A intValue = new int[10];
0N/A next = 0;
0N/A }
0N/A /**
0N/A * Put the value of the named boolean field into the persistent field.
0N/A */
0N/A public void put(String name, boolean value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named char field into the persistent fields.
0N/A */
0N/A public void put(String name, char value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named byte field into the persistent fields.
0N/A */
0N/A public void put(String name, byte value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named short field into the persistent fields.
0N/A */
0N/A public void put(String name, short value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named int field into the persistent fields.
0N/A */
0N/A public void put(String name, int value) {
0N/A if (next < fieldName.length) {
0N/A fieldName[next] = name;
0N/A intValue[next] = value;
0N/A next++;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named long field into the persistent fields.
0N/A */
0N/A public void put(String name, long value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named float field into the persistent fields.
0N/A */
0N/A public void put(String name, float value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named double field into the persistent field.
0N/A */
0N/A public void put(String name, double value) {
0N/A }
0N/A
0N/A /**
0N/A * Put the value of the named Object field into the persistent field.
0N/A */
0N/A public void put(String name, Object value) {
0N/A }
0N/A
0N/A /**
0N/A * Write the data and fields to the specified ObjectOutput stream.
0N/A */
0N/A public void write(ObjectOutput out) throws IOException {
0N/A for (int i = 0; i < next; i++)
0N/A System.out.println(fieldName[i] + "=" + intValue[i]);
0N/A }
0N/A };
0N/A
0N/A
0N/A /**
0N/A * Writes a byte. This method will block until the byte is actually
0N/A * written.
0N/A * @param b the byte
0N/A * @exception IOException If an I/O error has occurred.
0N/A * @since JDK1.1
0N/A */
0N/A public void write(int data) throws IOException {
0N/A }
0N/A
0N/A /**
0N/A * Writes an array of bytes. This method will block until the bytes
0N/A * are actually written.
0N/A * @param b the data to be written
0N/A * @exception IOException If an I/O error has occurred.
0N/A * @since JDK1.1
0N/A */
0N/A public void write(byte b[]) throws IOException {
0N/A }
0N/A
0N/A /**
0N/A * Writes a sub array of bytes.
0N/A * @param b the data to be written
0N/A * @param off the start offset in the data
0N/A * @param len the number of bytes that are written
0N/A * @exception IOException If an I/O error has occurred.
0N/A * @since JDK1.1
0N/A */
0N/A public void write(byte b[], int off, int len) throws IOException {
0N/A }
0N/A
0N/A public void writeBoolean(boolean data) throws IOException {
0N/A }
0N/A
0N/A public void writeByte(int data) throws IOException {
0N/A }
0N/A
0N/A public void writeShort(int data) throws IOException {
0N/A }
0N/A
0N/A public void writeChar(int data) throws IOException {
0N/A }
0N/A public void writeInt(int data) throws IOException{}
0N/A public void writeLong(long data) throws IOException{}
0N/A public void writeFloat(float data) throws IOException{}
0N/A public void writeDouble(double data) throws IOException{}
0N/A public void writeBytes(String data) throws IOException{}
0N/A public void writeChars(String data) throws IOException{}
0N/A public void writeUTF(String data) throws IOException{}
0N/A public void reset() throws IOException {}
0N/A public void available() throws IOException {}
0N/A public void drain() throws IOException {}
0N/A
0N/A private Object currentObject = null;
0N/A private InternalPutField currentPutField;
0N/A
0N/A
0N/A /********************************************************************/
0N/A
0N/A /* CODE LIFTED FROM ObjectStreamClass constuctor.
0N/A * ObjectStreamClass.writeObjectMethod is private.
0N/A *
0N/A * Look for the writeObject method
0N/A * Set the accessible flag on it here.
0N/A * Subclass of AbstractObjectOutputStream will call it as necessary.
0N/A */
0N/A static public Method getWriteObjectMethod(final Class cl) {
0N/A
0N/A Method writeObjectMethod = (Method)
0N/A java.security.AccessController.doPrivileged
0N/A (new java.security.PrivilegedAction() {
0N/A public Object run() {
0N/A Method m = null;
0N/A try {
0N/A Class[] args = {ObjectOutputStream.class};
0N/A m = cl.getDeclaredMethod("writeObject", args);
0N/A int mods = m.getModifiers();
0N/A // Method must be private and non-static
0N/A if (!Modifier.isPrivate(mods) ||
0N/A Modifier.isStatic(mods)) {
0N/A m = null;
0N/A } else {
0N/A m.setAccessible(true);
0N/A }
0N/A } catch (NoSuchMethodException e) {
0N/A m = null;
0N/A }
0N/A return m;
0N/A }
0N/A });
0N/A return writeObjectMethod;
0N/A }
0N/A
0N/A /*************************************************************/
0N/A
0N/A /* CODE LIFTED FROM ObjectOutputStream. */
0N/A static private void invokeMethod(final Object obj, final Method m,
0N/A final Object[] argList)
0N/A throws IOException
0N/A {
0N/A try {
0N/A java.security.AccessController.doPrivileged
0N/A (new java.security.PrivilegedExceptionAction() {
0N/A public Object run() throws InvocationTargetException,
0N/A java.lang.IllegalAccessException {
0N/A m.invoke(obj, argList);
0N/A return null;
0N/A }
0N/A });
0N/A } catch (java.security.PrivilegedActionException e) {
0N/A Exception ex = e.getException();
0N/A if (ex instanceof InvocationTargetException) {
0N/A Throwable t =
0N/A ((InvocationTargetException)ex).getTargetException();
0N/A if (t instanceof IOException)
0N/A throw (IOException)t;
0N/A else if (t instanceof RuntimeException)
0N/A throw (RuntimeException) t;
0N/A else if (t instanceof Error)
0N/A throw (Error) t;
0N/A else
0N/A throw new Error("interal error");
0N/A } else {
0N/A // IllegalAccessException cannot happen
0N/A }
0N/A }
0N/A }
0N/A};