| GNU Classpath (0.95) | |
| Frames | No Frames |
1: /* ObjectOutputStream.java -- Class used to write serialized objects 2: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.io; 41: 42: import gnu.java.io.ObjectIdentityMap2Int; 43: import gnu.java.lang.reflect.TypeSignature; 44: import gnu.java.security.action.SetAccessibleAction; 45: 46: import java.lang.reflect.Array; 47: import java.lang.reflect.Field; 48: import java.lang.reflect.InvocationTargetException; 49: import java.lang.reflect.Method; 50: 51: 52: /** 53: * An <code>ObjectOutputStream</code> can be used to write objects 54: * as well as primitive data in a platform-independent manner to an 55: * <code>OutputStream</code>. 56: * 57: * The data produced by an <code>ObjectOutputStream</code> can be read 58: * and reconstituted by an <code>ObjectInputStream</code>. 59: * 60: * <code>writeObject (Object)</code> is used to write Objects, the 61: * <code>write<type></code> methods are used to write primitive 62: * data (as in <code>DataOutputStream</code>). Strings can be written 63: * as objects or as primitive data. 64: * 65: * Not all objects can be written out using an 66: * <code>ObjectOutputStream</code>. Only those objects that are an 67: * instance of <code>java.io.Serializable</code> can be written. 68: * 69: * Using default serialization, information about the class of an 70: * object is written, all of the non-transient, non-static fields of 71: * the object are written, if any of these fields are objects, they are 72: * written out in the same manner. 73: * 74: * An object is only written out the first time it is encountered. If 75: * the object is encountered later, a reference to it is written to 76: * the underlying stream. Thus writing circular object graphs 77: * does not present a problem, nor are relationships between objects 78: * in a graph lost. 79: * 80: * Example usage: 81: * <pre> 82: * Hashtable map = new Hashtable (); 83: * map.put ("one", new Integer (1)); 84: * map.put ("two", new Integer (2)); 85: * 86: * ObjectOutputStream oos = 87: * new ObjectOutputStream (new FileOutputStream ("numbers")); 88: * oos.writeObject (map); 89: * oos.close (); 90: * 91: * ObjectInputStream ois = 92: * new ObjectInputStream (new FileInputStream ("numbers")); 93: * Hashtable newmap = (Hashtable)ois.readObject (); 94: * 95: * System.out.println (newmap); 96: * </pre> 97: * 98: * The default serialization can be overriden in two ways. 99: * 100: * By defining a method <code>private void 101: * writeObject (ObjectOutputStream)</code>, a class can dictate exactly 102: * how information about itself is written. 103: * <code>defaultWriteObject ()</code> may be called from this method to 104: * carry out default serialization. This method is not 105: * responsible for dealing with fields of super-classes or subclasses. 106: * 107: * By implementing <code>java.io.Externalizable</code>. This gives 108: * the class complete control over the way it is written to the 109: * stream. If this approach is used the burden of writing superclass 110: * and subclass data is transfered to the class implementing 111: * <code>java.io.Externalizable</code>. 112: * 113: * @see java.io.DataOutputStream 114: * @see java.io.Externalizable 115: * @see java.io.ObjectInputStream 116: * @see java.io.Serializable 117: * @author Tom Tromey (tromey@redhat.com) 118: * @author Jeroen Frijters (jeroen@frijters.net) 119: * @author Guilhem Lavaux (guilhem@kaffe.org) 120: * @author Michael Koch (konqueror@gmx.de) 121: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 122: */ 123: public class ObjectOutputStream extends OutputStream 124: implements ObjectOutput, ObjectStreamConstants 125: { 126: /** 127: * Creates a new <code>ObjectOutputStream</code> that will do all of 128: * its writing onto <code>out</code>. This method also initializes 129: * the stream by writing the header information (stream magic number 130: * and stream version). 131: * 132: * @exception IOException Writing stream header to underlying 133: * stream cannot be completed. 134: * 135: * @see #writeStreamHeader() 136: */ 137: public ObjectOutputStream (OutputStream out) throws IOException 138: { 139: realOutput = new DataOutputStream(out); 140: blockData = new byte[ BUFFER_SIZE ]; 141: blockDataCount = 0; 142: blockDataOutput = new DataOutputStream(this); 143: setBlockDataMode(true); 144: replacementEnabled = false; 145: isSerializing = false; 146: nextOID = baseWireHandle; 147: OIDLookupTable = new ObjectIdentityMap2Int(); 148: protocolVersion = defaultProtocolVersion; 149: useSubclassMethod = false; 150: writeStreamHeader(); 151: 152: if (DEBUG) 153: { 154: String val = System.getProperty("gcj.dumpobjects"); 155: if (val != null && !val.equals("")) 156: dump = true; 157: } 158: } 159: 160: /** 161: * Writes a representation of <code>obj</code> to the underlying 162: * output stream by writing out information about its class, then 163: * writing out each of the objects non-transient, non-static 164: * fields. If any of these fields are other objects, 165: * they are written out in the same manner. 166: * 167: * This method can be overriden by a class by implementing 168: * <code>private void writeObject (ObjectOutputStream)</code>. 169: * 170: * If an exception is thrown from this method, the stream is left in 171: * an undefined state. 172: * 173: * @param obj the object to serialize. 174: * @exception NotSerializableException An attempt was made to 175: * serialize an <code>Object</code> that is not serializable. 176: * 177: * @exception InvalidClassException Somebody tried to serialize 178: * an object which is wrongly formatted. 179: * 180: * @exception IOException Exception from underlying 181: * <code>OutputStream</code>. 182: * @see #writeUnshared(Object) 183: */ 184: public final void writeObject(Object obj) throws IOException 185: { 186: writeObject(obj, true); 187: } 188: 189: /** 190: * Writes an object to the stream in the same manner as 191: * {@link #writeObject(Object)}, but without the use of 192: * references. As a result, the object is always written 193: * to the stream in full. Likewise, if an object is written 194: * by this method and is then later written again by 195: * {@link #writeObject(Object)}, both calls will write out 196: * the object in full, as the later call to 197: * {@link #writeObject(Object)} will know nothing of the 198: * earlier use of {@link #writeUnshared(Object)}. 199: * 200: * @param obj the object to serialize. 201: * @throws NotSerializableException if the object being 202: * serialized does not implement 203: * {@link Serializable}. 204: * @throws InvalidClassException if a problem occurs with 205: * the class of the object being 206: * serialized. 207: * @throws IOException if an I/O error occurs on the underlying 208: * <code>OutputStream</code>. 209: * @since 1.4 210: * @see #writeObject(Object) 211: */ 212: public void writeUnshared(Object obj) 213: throws IOException 214: { 215: writeObject(obj, false); 216: } 217: 218: /** 219: * Writes a representation of <code>obj</code> to the underlying 220: * output stream by writing out information about its class, then 221: * writing out each of the objects non-transient, non-static 222: * fields. If any of these fields are other objects, 223: * they are written out in the same manner. 224: * 225: * This method can be overriden by a class by implementing 226: * <code>private void writeObject (ObjectOutputStream)</code>. 227: * 228: * If an exception is thrown from this method, the stream is left in 229: * an undefined state. 230: * 231: * @param obj the object to serialize. 232: * @param shared true if the serialized object should be 233: * shared with later calls. 234: * @exception NotSerializableException An attempt was made to 235: * serialize an <code>Object</code> that is not serializable. 236: * 237: * @exception InvalidClassException Somebody tried to serialize 238: * an object which is wrongly formatted. 239: * 240: * @exception IOException Exception from underlying 241: * <code>OutputStream</code>. 242: * @see #writeUnshared(Object) 243: */ 244: private final void writeObject(Object obj, boolean shared) 245: throws IOException 246: { 247: if (useSubclassMethod) 248: { 249: if (dump) 250: dumpElementln ("WRITE OVERRIDE: " + obj); 251: 252: writeObjectOverride(obj); 253: return; 254: } 255: 256: if (dump) 257: dumpElementln ("WRITE: " + obj); 258: 259: depth += 2; 260: 261: boolean was_serializing = isSerializing; 262: boolean old_mode = setBlockDataMode(false); 263: try 264: { 265: isSerializing = true; 266: boolean replaceDone = false; 267: Object replacedObject = null; 268: 269: while (true) 270: { 271: if (obj == null) 272: { 273: realOutput.writeByte(TC_NULL); 274: break; 275: } 276: 277: int handle = findHandle(obj); 278: if (handle >= 0 && shared) 279: { 280: realOutput.writeByte(TC_REFERENCE); 281: realOutput.writeInt(handle); 282: break; 283: } 284: 285: if (obj instanceof Class) 286: { 287: Class cl = (Class)obj; 288: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl); 289: realOutput.writeByte(TC_CLASS); 290: if (!osc.isProxyClass) 291: { 292: writeObject (osc); 293: } 294: else 295: {System.err.println("1"); 296: realOutput.writeByte(TC_PROXYCLASSDESC); 297: Class[] intfs = cl.getInterfaces(); 298: realOutput.writeInt(intfs.length); 299: for (int i = 0; i < intfs.length; i++) 300: realOutput.writeUTF(intfs[i].getName()); 301: 302: boolean oldmode = setBlockDataMode(true); 303: annotateProxyClass(cl); 304: setBlockDataMode(oldmode); 305: realOutput.writeByte(TC_ENDBLOCKDATA); 306: 307: writeObject(osc.getSuper()); 308: } 309: if (shared) 310: assignNewHandle(obj); 311: break; 312: } 313: 314: if (obj instanceof ObjectStreamClass) 315: { 316: writeClassDescriptor((ObjectStreamClass) obj); 317: break; 318: } 319: 320: Class clazz = obj.getClass(); 321: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz); 322: if (osc == null) 323: throw new NotSerializableException(clazz.getName()); 324: 325: if (osc.isEnum()) 326: { 327: /* TC_ENUM classDesc newHandle enumConstantName */ 328: realOutput.writeByte(TC_ENUM); 329: writeObject(osc); 330: if (shared) 331: assignNewHandle(obj); 332: writeObject(((Enum) obj).name()); 333: break; 334: } 335: 336: if ((replacementEnabled || obj instanceof Serializable) 337: && ! replaceDone) 338: { 339: replacedObject = obj; 340: 341: if (obj instanceof Serializable) 342: { 343: try 344: { 345: Method m = osc.writeReplaceMethod; 346: if (m != null) 347: obj = m.invoke(obj, new Object[0]); 348: } 349: catch (IllegalAccessException ignore) 350: { 351: } 352: catch (InvocationTargetException ignore) 353: { 354: } 355: } 356: 357: if (replacementEnabled) 358: obj = replaceObject(obj); 359: 360: replaceDone = true; 361: continue; 362: } 363: 364: if (obj instanceof String) 365: { 366: realOutput.writeByte(TC_STRING); 367: if (shared) 368: assignNewHandle(obj); 369: realOutput.writeUTF((String)obj); 370: break; 371: } 372: 373: if (clazz.isArray ()) 374: { 375: realOutput.writeByte(TC_ARRAY); 376: writeObject(osc); 377: if (shared) 378: assignNewHandle(obj); 379: writeArraySizeAndElements(obj, clazz.getComponentType()); 380: break; 381: } 382: 383: realOutput.writeByte(TC_OBJECT); 384: writeObject(osc); 385: 386: if (shared) 387: if (replaceDone) 388: assignNewHandle(replacedObject); 389: else 390: assignNewHandle(obj); 391: 392: if (obj instanceof Externalizable) 393: { 394: if (protocolVersion == PROTOCOL_VERSION_2) 395: setBlockDataMode(true); 396: 397: ((Externalizable)obj).writeExternal(this); 398: 399: if (protocolVersion == PROTOCOL_VERSION_2) 400: { 401: setBlockDataMode(false); 402: realOutput.writeByte(TC_ENDBLOCKDATA); 403: } 404: 405: break; 406: } 407: 408: if (obj instanceof Serializable) 409: { 410: Object prevObject = this.currentObject; 411: ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass; 412: currentObject = obj; 413: ObjectStreamClass[] hierarchy = osc.hierarchy(); 414: 415: for (int i = 0; i < hierarchy.length; i++) 416: { 417: currentObjectStreamClass = hierarchy[i]; 418: 419: fieldsAlreadyWritten = false; 420: if (currentObjectStreamClass.hasWriteMethod()) 421: { 422: if (dump) 423: dumpElementln ("WRITE METHOD CALLED FOR: " + obj); 424: setBlockDataMode(true); 425: callWriteMethod(obj, currentObjectStreamClass); 426: setBlockDataMode(false); 427: realOutput.writeByte(TC_ENDBLOCKDATA); 428: if (dump) 429: dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj); 430: } 431: else 432: { 433: if (dump) 434: dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); 435: writeFields(obj, currentObjectStreamClass); 436: } 437: } 438: 439: this.currentObject = prevObject; 440: this.currentObjectStreamClass = prevObjectStreamClass; 441: currentPutField = null; 442: break; 443: } 444: 445: throw new NotSerializableException(clazz.getName() 446: + " in " 447: + obj.getClass()); 448: } // end pseudo-loop 449: } 450: catch (ObjectStreamException ose) 451: { 452: // Rethrow these are fatal. 453: throw ose; 454: } 455: catch (IOException e) 456: { 457: realOutput.writeByte(TC_EXCEPTION); 458: reset(true); 459: 460: setBlockDataMode(false); 461: try 462: { 463: if (DEBUG) 464: { 465: e.printStackTrace(System.out); 466: } 467: writeObject(e); 468: } 469: catch (IOException ioe) 470: { 471: StreamCorruptedException ex = 472: new StreamCorruptedException 473: (ioe + " thrown while exception was being written to stream."); 474: if (DEBUG) 475: { 476: ex.printStackTrace(System.out); 477: } 478: throw ex; 479: } 480: 481: reset (true); 482: 483: } 484: finally 485: { 486: isSerializing = was_serializing; 487: setBlockDataMode(old_mode); 488: depth -= 2; 489: 490: if (dump) 491: dumpElementln ("END: " + obj); 492: } 493: } 494: 495: protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException 496: { 497: if (osc.isProxyClass) 498: { 499: realOutput.writeByte(TC_PROXYCLASSDESC); 500: Class[] intfs = osc.forClass().getInterfaces(); 501: realOutput.writeInt(intfs.length); 502: for (int i = 0; i < intfs.length; i++) 503: realOutput.writeUTF(intfs[i].getName()); 504: 505: assignNewHandle(osc); 506: 507: boolean oldmode = setBlockDataMode(true); 508: annotateProxyClass(osc.forClass()); 509: setBlockDataMode(oldmode); 510: realOutput.writeByte(TC_ENDBLOCKDATA); 511: } 512: else 513: { 514: realOutput.writeByte(TC_CLASSDESC); 515: realOutput.writeUTF(osc.getName()); 516: if (osc.isEnum()) 517: realOutput.writeLong(0L); 518: else 519: realOutput.writeLong(osc.getSerialVersionUID()); 520: assignNewHandle(osc); 521: 522: int flags = osc.getFlags(); 523: 524: if (protocolVersion == PROTOCOL_VERSION_2 525: && osc.isExternalizable()) 526: flags |= SC_BLOCK_DATA; 527: 528: realOutput.writeByte(flags); 529: 530: ObjectStreamField[] fields = osc.fields; 531: 532: if (fields == ObjectStreamClass.INVALID_FIELDS) 533: throw new InvalidClassException 534: (osc.getName(), "serialPersistentFields is invalid"); 535: 536: realOutput.writeShort(fields.length); 537: 538: ObjectStreamField field; 539: for (int i = 0; i < fields.length; i++) 540: { 541: field = fields[i]; 542: realOutput.writeByte(field.getTypeCode ()); 543: realOutput.writeUTF(field.getName ()); 544: 545: if (! field.isPrimitive()) 546: writeObject(field.getTypeString()); 547: } 548: 549: boolean oldmode = setBlockDataMode(true); 550: annotateClass(osc.forClass()); 551: setBlockDataMode(oldmode); 552: realOutput.writeByte(TC_ENDBLOCKDATA); 553: } 554: 555: if (osc.isSerializable() || osc.isExternalizable()) 556: writeObject(osc.getSuper()); 557: else 558: writeObject(null); 559: } 560: 561: /** 562: * Writes the current objects non-transient, non-static fields from 563: * the current class to the underlying output stream. 564: * 565: * This method is intended to be called from within a object's 566: * <code>private void writeObject (ObjectOutputStream)</code> 567: * method. 568: * 569: * @exception NotActiveException This method was called from a 570: * context other than from the current object's and current class's 571: * <code>private void writeObject (ObjectOutputStream)</code> 572: * method. 573: * 574: * @exception IOException Exception from underlying 575: * <code>OutputStream</code>. 576: */ 577: public void defaultWriteObject() 578: throws IOException, NotActiveException 579: { 580: markFieldsWritten(); 581: writeFields(currentObject, currentObjectStreamClass); 582: } 583: 584: 585: private void markFieldsWritten() throws IOException 586: { 587: if (currentObject == null || currentObjectStreamClass == null) 588: throw new NotActiveException 589: ("defaultWriteObject called by non-active class and/or object"); 590: 591: if (fieldsAlreadyWritten) 592: throw new IOException 593: ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once"); 594: 595: fieldsAlreadyWritten = true; 596: } 597: 598: /** 599: * Resets stream to state equivalent to the state just after it was 600: * constructed. 601: * 602: * Causes all objects previously written to the stream to be 603: * forgotten. A notification of this reset is also written to the 604: * underlying stream. 605: * 606: * @exception IOException Exception from underlying 607: * <code>OutputStream</code> or reset called while serialization is 608: * in progress. 609: */ 610: public void reset() throws IOException 611: { 612: reset(false); 613: } 614: 615: 616: private void reset(boolean internal) throws IOException 617: { 618: if (!internal) 619: { 620: if (isSerializing) 621: throw new IOException("Reset called while serialization in progress"); 622: 623: realOutput.writeByte(TC_RESET); 624: } 625: 626: clearHandles(); 627: } 628: 629: 630: /** 631: * Informs this <code>ObjectOutputStream</code> to write data 632: * according to the specified protocol. There are currently two 633: * different protocols, specified by <code>PROTOCOL_VERSION_1</code> 634: * and <code>PROTOCOL_VERSION_2</code>. This implementation writes 635: * data using <code>PROTOCOL_VERSION_2</code> by default, as is done 636: * since the JDK 1.2. 637: * <p> 638: * For an explanation of the differences between the two protocols 639: * see the Java Object Serialization Specification. 640: * </p> 641: * 642: * @param version the version to use. 643: * 644: * @throws IllegalArgumentException if <code>version</code> is not a valid 645: * protocol. 646: * @throws IllegalStateException if called after the first the first object 647: * was serialized. 648: * @throws IOException if an I/O error occurs. 649: * 650: * @see ObjectStreamConstants#PROTOCOL_VERSION_1 651: * @see ObjectStreamConstants#PROTOCOL_VERSION_2 652: * 653: * @since 1.2 654: */ 655: public void useProtocolVersion(int version) throws IOException 656: { 657: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2) 658: throw new IllegalArgumentException("Invalid protocol version requested."); 659: 660: if (nextOID != baseWireHandle) 661: throw new IllegalStateException("Protocol version cannot be changed " 662: + "after serialization started."); 663: 664: protocolVersion = version; 665: } 666: 667: /** 668: * An empty hook that allows subclasses to write extra information 669: * about classes to the stream. This method is called the first 670: * time each class is seen, and after all of the standard 671: * information about the class has been written. 672: * 673: * @exception IOException Exception from underlying 674: * <code>OutputStream</code>. 675: * 676: * @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass) 677: */ 678: protected void annotateClass(Class<?> cl) throws IOException 679: { 680: } 681: 682: protected void annotateProxyClass(Class<?> cl) throws IOException 683: { 684: } 685: 686: /** 687: * Allows subclasses to replace objects that are written to the 688: * stream with other objects to be written in their place. This 689: * method is called the first time each object is encountered 690: * (modulo reseting of the stream). 691: * 692: * This method must be enabled before it will be called in the 693: * serialization process. 694: * 695: * @exception IOException Exception from underlying 696: * <code>OutputStream</code>. 697: * 698: * @see #enableReplaceObject(boolean) 699: */ 700: protected Object replaceObject(Object obj) throws IOException 701: { 702: return obj; 703: } 704: 705: 706: /** 707: * If <code>enable</code> is <code>true</code> and this object is 708: * trusted, then <code>replaceObject (Object)</code> will be called 709: * in subsequent calls to <code>writeObject (Object)</code>. 710: * Otherwise, <code>replaceObject (Object)</code> will not be called. 711: * 712: * @exception SecurityException This class is not trusted. 713: */ 714: protected boolean enableReplaceObject(boolean enable) 715: throws SecurityException 716: { 717: if (enable) 718: { 719: SecurityManager sm = System.getSecurityManager(); 720: if (sm != null) 721: sm.checkPermission(new SerializablePermission("enableSubstitution")); 722: } 723: 724: boolean old_val = replacementEnabled; 725: replacementEnabled = enable; 726: return old_val; 727: } 728: 729: 730: /** 731: * Writes stream magic and stream version information to the 732: * underlying stream. 733: * 734: * @exception IOException Exception from underlying 735: * <code>OutputStream</code>. 736: */ 737: protected void writeStreamHeader() throws IOException 738: { 739: realOutput.writeShort(STREAM_MAGIC); 740: realOutput.writeShort(STREAM_VERSION); 741: } 742: 743: /** 744: * Protected constructor that allows subclasses to override 745: * serialization. This constructor should be called by subclasses 746: * that wish to override <code>writeObject (Object)</code>. This 747: * method does a security check <i>NOTE: currently not 748: * implemented</i>, then sets a flag that informs 749: * <code>writeObject (Object)</code> to call the subclasses 750: * <code>writeObjectOverride (Object)</code> method. 751: * 752: * @see #writeObjectOverride(Object) 753: */ 754: protected ObjectOutputStream() throws IOException, SecurityException 755: { 756: SecurityManager sec_man = System.getSecurityManager (); 757: if (sec_man != null) 758: sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 759: useSubclassMethod = true; 760: } 761: 762: 763: /** 764: * This method allows subclasses to override the default 765: * serialization mechanism provided by 766: * <code>ObjectOutputStream</code>. To make this method be used for 767: * writing objects, subclasses must invoke the 0-argument 768: * constructor on this class from there constructor. 769: * 770: * @see #ObjectOutputStream() 771: * 772: * @exception NotActiveException Subclass has arranged for this 773: * method to be called, but did not implement this method. 774: */ 775: protected void writeObjectOverride(Object obj) throws NotActiveException, 776: IOException 777: { 778: throw new NotActiveException 779: ("Subclass of ObjectOutputStream must implement writeObjectOverride"); 780: } 781: 782: 783: /** 784: * @see DataOutputStream#write(int) 785: */ 786: public void write (int data) throws IOException 787: { 788: if (writeDataAsBlocks) 789: { 790: if (blockDataCount == BUFFER_SIZE) 791: drain(); 792: 793: blockData[ blockDataCount++ ] = (byte)data; 794: } 795: else 796: realOutput.write(data); 797: } 798: 799: 800: /** 801: * @see DataOutputStream#write(byte[]) 802: */ 803: public void write(byte[] b) throws IOException 804: { 805: write(b, 0, b.length); 806: } 807: 808: 809: /** 810: * @see DataOutputStream#write(byte[],int,int) 811: */ 812: public void write(byte[] b, int off, int len) throws IOException 813: { 814: if (writeDataAsBlocks) 815: { 816: if (len < 0) 817: throw new IndexOutOfBoundsException(); 818: 819: if (blockDataCount + len < BUFFER_SIZE) 820: { 821: System.arraycopy(b, off, blockData, blockDataCount, len); 822: blockDataCount += len; 823: } 824: else 825: { 826: drain(); 827: writeBlockDataHeader(len); 828: realOutput.write(b, off, len); 829: } 830: } 831: else 832: realOutput.write(b, off, len); 833: } 834: 835: 836: /** 837: * @see DataOutputStream#flush() 838: */ 839: public void flush () throws IOException 840: { 841: drain(); 842: realOutput.flush(); 843: } 844: 845: 846: /** 847: * Causes the block-data buffer to be written to the underlying 848: * stream, but does not flush underlying stream. 849: * 850: * @exception IOException Exception from underlying 851: * <code>OutputStream</code>. 852: */ 853: protected void drain() throws IOException 854: { 855: if (blockDataCount == 0) 856: return; 857: 858: if (writeDataAsBlocks) 859: writeBlockDataHeader(blockDataCount); 860: realOutput.write(blockData, 0, blockDataCount); 861: blockDataCount = 0; 862: } 863: 864: 865: /** 866: * @see java.io.DataOutputStream#close () 867: */ 868: public void close() throws IOException 869: { 870: flush(); 871: realOutput.close(); 872: } 873: 874: 875: /** 876: * @see java.io.DataOutputStream#writeBoolean (boolean) 877: */ 878: public void writeBoolean(boolean data) throws IOException 879: { 880: blockDataOutput.writeBoolean(data); 881: } 882: 883: 884: /** 885: * @see java.io.DataOutputStream#writeByte (int) 886: */ 887: public void writeByte(int data) throws IOException 888: { 889: blockDataOutput.writeByte(data); 890: } 891: 892: 893: /** 894: * @see java.io.DataOutputStream#writeShort (int) 895: */ 896: public void writeShort (int data) throws IOException 897: { 898: blockDataOutput.writeShort(data); 899: } 900: 901: 902: /** 903: * @see java.io.DataOutputStream#writeChar (int) 904: */ 905: public void writeChar(int data) throws IOException 906: { 907: blockDataOutput.writeChar(data); 908: } 909: 910: 911: /** 912: * @see java.io.DataOutputStream#writeInt (int) 913: */ 914: public void writeInt(int data) throws IOException 915: { 916: blockDataOutput.writeInt(data); 917: } 918: 919: 920: /** 921: * @see java.io.DataOutputStream#writeLong (long) 922: */ 923: public void writeLong(long data) throws IOException 924: { 925: blockDataOutput.writeLong(data); 926: } 927: 928: 929: /** 930: * @see java.io.DataOutputStream#writeFloat (float) 931: */ 932: public void writeFloat(float data) throws IOException 933: { 934: blockDataOutput.writeFloat(data); 935: } 936: 937: 938: /** 939: * @see java.io.DataOutputStream#writeDouble (double) 940: */ 941: public void writeDouble(