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