1/* 2 * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import java.io.*; 25import java.lang.reflect.Field; 26import java.lang.reflect.Method; 27import java.lang.reflect.Modifier; 28import java.lang.reflect.InvocationTargetException; 29import java.security.*; 30 31public class XObjectOutputStream extends AbstractObjectOutputStream { 32 XObjectOutputStream(OutputStream out) throws IOException { 33 super(out); 34 } 35 36 protected boolean enableReplaceObject(boolean enable) 37 { 38 throw new Error("not implemented"); 39 } 40 41 protected void annotateClass(Class<?> cl) throws IOException { 42 } 43 44 public void close() throws IOException{ 45 out.close(); 46 } 47 48 protected Object replaceObject(Object obj) throws IOException { 49 return obj; 50 } 51 52 protected void writeStreamHeader() throws IOException { 53 super.writeStreamHeader(); 54 } 55 56 protected final void writeObjectOverride(Object obj) throws IOException { 57 Object prevCurrentObject = currentObject; 58 currentObject = obj; 59 System.out.println("writeObjectOverride(" + obj.toString() + ")"); 60 try { 61 // ** Preserving reference semantics. 62 // if (obj already serialized) { 63 // look up streamId for obj and write it into 'this' stream. 64 // return; 65 // } 66 // 67 // if (obj instanceof Class) { 68 // //Special processing for classes. 69 // //Might need to call this.annotateClass(obj.getClass()) 70 // //someday. 71 // return; 72 // } 73 // 74 // **Replacement semantics 75 // Object replacement = obj; 76 // if (enableReplace) 77 // replacement = this.writeReplace(obj); 78 // if (replacement instanceof Replaceable) 79 // replacement = ((Replaceable)replacement).replaceObject(this); 80 // if (obj != replacement) { 81 // //record that all future occurances of obj should be replaced 82 // //with replacement 83 // } 84 // 85 // if obj is Externalizeable { 86 // Object[] argList = {this}; 87 // invokeMethod(obj, writeExternalMethod, argList); 88 // else 89 90 Method writeObjectMethod = getWriteObjectMethod(obj.getClass()); 91 92 if (writeObjectMethod != null) { 93 Object[] arglist = {this}; 94 invokeMethod(obj, writeObjectMethod, arglist); 95 } else 96 defaultWriteObject(); 97 } finally { 98 currentObject = prevCurrentObject; 99 } 100 } 101 102 /* Since defaultWriteObject() does not take the object to write as a parameter, 103 * implementation is required to store currentObject when writeObject is called. 104 */ 105 public void defaultWriteObject() throws IOException { 106 Object obj = currentObject; 107 System.out.println("XObjectOutputStream.defaultWriteObject(" + 108 obj.toString() + ")"); 109 110 //In order to access package, private and protected fields, 111 //one needs to use Priviledged Access and be trusted code. 112 //This test will avoid that problem by only serializing public fields. 113 Field[] fields = obj.getClass().getFields(); 114 for (int i= 0; i < fields.length; i++) { 115 //Skip non-Serializable fields. 116 int mods = fields[i].getModifiers(); 117 if (Modifier.isStatic(mods) || Modifier.isTransient(mods)) 118 continue; 119 Class FieldType = fields[i].getType(); 120 if (FieldType.isPrimitive()) { 121 System.out.println("Field " + fields[i].getName() + 122 " has primitive type " + FieldType.toString()); 123 } else { 124 System.out.println("**Field " + fields[i].getName() + 125 " is an Object of type " + FieldType.toString()); 126 try { 127 writeObject(fields[i].get(obj)); 128 if (FieldType.isArray()) { 129 Object[] array = ((Object[]) fields[i].get(obj)); 130 Class componentType = FieldType.getComponentType(); 131 if (componentType.isPrimitive()) 132 System.out.println("Output " + array.length + " primitive elements of" + 133 componentType.toString()); 134 else { 135 System.out.println("Output " + array.length + " of Object elements of" + 136 componentType.toString()); 137 for (int k = 0; k < array.length; k++) { 138 writeObject(array[k]); 139 } 140 } 141 } 142 } catch (IllegalAccessException e) { 143 throw new IOException(e.getMessage()); 144 } 145 } 146 } 147 } 148 149 public PutField putFields() throws IOException { 150 currentPutField = new InternalPutField(); 151 return currentPutField; 152 } 153 154 public void writeFields() throws IOException { 155 currentPutField.write(this); 156 } 157 158 static final class InternalPutField extends ObjectOutputStream.PutField { 159 String fieldName[]; 160 int intValue[]; 161 int next; 162 163 InternalPutField() { 164 fieldName = new String[10]; 165 intValue = new int[10]; 166 next = 0; 167 } 168 /** 169 * Put the value of the named boolean field into the persistent field. 170 */ 171 public void put(String name, boolean value) { 172 } 173 174 /** 175 * Put the value of the named char field into the persistent fields. 176 */ 177 public void put(String name, char value) { 178 } 179 180 /** 181 * Put the value of the named byte field into the persistent fields. 182 */ 183 public void put(String name, byte value) { 184 } 185 186 /** 187 * Put the value of the named short field into the persistent fields. 188 */ 189 public void put(String name, short value) { 190 } 191 192 /** 193 * Put the value of the named int field into the persistent fields. 194 */ 195 public void put(String name, int value) { 196 if (next < fieldName.length) { 197 fieldName[next] = name; 198 intValue[next] = value; 199 next++; 200 } 201 } 202 203 /** 204 * Put the value of the named long field into the persistent fields. 205 */ 206 public void put(String name, long value) { 207 } 208 209 /** 210 * Put the value of the named float field into the persistent fields. 211 */ 212 public void put(String name, float value) { 213 } 214 215 /** 216 * Put the value of the named double field into the persistent field. 217 */ 218 public void put(String name, double value) { 219 } 220 221 /** 222 * Put the value of the named Object field into the persistent field. 223 */ 224 public void put(String name, Object value) { 225 } 226 227 /** 228 * Write the data and fields to the specified ObjectOutput stream. 229 */ 230 public void write(ObjectOutput out) throws IOException { 231 for (int i = 0; i < next; i++) 232 System.out.println(fieldName[i] + "=" + intValue[i]); 233 } 234 }; 235 236 237 /** 238 * Writes a byte. This method will block until the byte is actually 239 * written. 240 * @param b the byte 241 * @exception IOException If an I/O error has occurred. 242 * @since JDK1.1 243 */ 244 public void write(int data) throws IOException { 245 } 246 247 /** 248 * Writes an array of bytes. This method will block until the bytes 249 * are actually written. 250 * @param b the data to be written 251 * @exception IOException If an I/O error has occurred. 252 * @since JDK1.1 253 */ 254 public void write(byte b[]) throws IOException { 255 } 256 257 /** 258 * Writes a sub array of bytes. 259 * @param b the data to be written 260 * @param off the start offset in the data 261 * @param len the number of bytes that are written 262 * @exception IOException If an I/O error has occurred. 263 * @since JDK1.1 264 */ 265 public void write(byte b[], int off, int len) throws IOException { 266 } 267 268 public void writeBoolean(boolean data) throws IOException { 269 } 270 271 public void writeByte(int data) throws IOException { 272 } 273 274 public void writeShort(int data) throws IOException { 275 } 276 277 public void writeChar(int data) throws IOException { 278 } 279 public void writeInt(int data) throws IOException{} 280 public void writeLong(long data) throws IOException{} 281 public void writeFloat(float data) throws IOException{} 282 public void writeDouble(double data) throws IOException{} 283 public void writeBytes(String data) throws IOException{} 284 public void writeChars(String data) throws IOException{} 285 public void writeUTF(String data) throws IOException{} 286 public void reset() throws IOException {} 287 public void available() throws IOException {} 288 public void drain() throws IOException {} 289 290 private Object currentObject = null; 291 private InternalPutField currentPutField; 292 293 294 /********************************************************************/ 295 296 /* CODE LIFTED FROM ObjectStreamClass constuctor. 297 * ObjectStreamClass.writeObjectMethod is private. 298 * 299 * Look for the writeObject method 300 * Set the accessible flag on it here. 301 * Subclass of AbstractObjectOutputStream will call it as necessary. 302 */ 303 public static Method getWriteObjectMethod(final Class cl) { 304 305 Method writeObjectMethod = (Method) 306 java.security.AccessController.doPrivileged 307 (new java.security.PrivilegedAction() { 308 public Object run() { 309 Method m = null; 310 try { 311 Class[] args = {ObjectOutputStream.class}; 312 m = cl.getDeclaredMethod("writeObject", args); 313 int mods = m.getModifiers(); 314 // Method must be private and non-static 315 if (!Modifier.isPrivate(mods) || 316 Modifier.isStatic(mods)) { 317 m = null; 318 } else { 319 m.setAccessible(true); 320 } 321 } catch (NoSuchMethodException e) { 322 m = null; 323 } 324 return m; 325 } 326 }); 327 return writeObjectMethod; 328 } 329 330 /*************************************************************/ 331 332 /* CODE LIFTED FROM ObjectOutputStream. */ 333 private static void invokeMethod(final Object obj, final Method m, 334 final Object[] argList) 335 throws IOException 336 { 337 try { 338 java.security.AccessController.doPrivileged 339 (new java.security.PrivilegedExceptionAction() { 340 public Object run() throws InvocationTargetException, 341 java.lang.IllegalAccessException { 342 m.invoke(obj, argList); 343 return null; 344 } 345 }); 346 } catch (java.security.PrivilegedActionException e) { 347 Exception ex = e.getException(); 348 if (ex instanceof InvocationTargetException) { 349 Throwable t = 350 ((InvocationTargetException)ex).getTargetException(); 351 if (t instanceof IOException) 352 throw (IOException)t; 353 else if (t instanceof RuntimeException) 354 throw (RuntimeException) t; 355 else if (t instanceof Error) 356 throw (Error) t; 357 else 358 throw new Error("interal error"); 359 } else { 360 // IllegalAccessException cannot happen 361 } 362 } 363 } 364}; 365