| /* | |
| * Copyright (c) 1998, 2019, 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. | |
| */ | |
| @SuppressWarnings("deprecation") | |
| 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 constructor. | |
| * 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) { | |
| try { | |
| Class<?>[] args = {ObjectOutputStream.class}; | |
| Method m = cl.getDeclaredMethod("writeObject", args); | |
| int mods = m.getModifiers(); | |
| // Method must be private and non-static | |
| if (!Modifier.isPrivate(mods) || | |
| Modifier.isStatic(mods)) { | |
| return null; | |
| } else { | |
| m.setAccessible(true); | |
| return m; | |
| } | |
| } catch (NoSuchMethodException e) { | |
| return null; | |
| } | |
| } | |
| /*************************************************************/ | |
| /* CODE LIFTED FROM ObjectOutputStream. */ | |
| private static void invokeMethod(final Object obj, final Method m, | |
| final Object[] argList) | |
| throws IOException | |
| { | |
| try { | |
| m.invoke(obj, argList); | |
| } catch (InvocationTargetException ex) { | |
| Throwable t = 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("intenral error"); | |
| } catch (IllegalAccessException iae) { | |
| // IllegalAccessException can not happen | |
| } | |
| } | |
| }; |