/** * Write a format id for the object provied followed by the object itself to this * FormatIdOutputStream. * * @param ref a reference to the object. * @exception java.io.IOException the exception. */ public void writeObject(Object ref) throws IOException { if (ref == null) { FormatIdUtil.writeFormatIdInteger(this, StoredFormatIds.NULL_FORMAT_ID); return; } if (ref instanceof String) { // String's are special cased to use writeUTF which is more // efficient than the default writeObject(String), but the format // can only store 65535 bytes. The worst case size conversion is // 3 bytes for each unicode character in a String, so limiting // writeUTF optimization to strings smaller than 20000 should // insure that we won't call writeUTF() and produce more than // 65535 bytes. String str = (String) ref; if (str.length() <= 20000) { FormatIdUtil.writeFormatIdInteger(this, StoredFormatIds.STRING_FORMAT_ID); this.writeUTF((String) ref); return; } } // Add debugging code to read-in every formatable that we write // to ensure that it can be read and it's correctly registered. OutputStream oldOut = null; if (SanityManager.DEBUG) { if (ref instanceof Formatable) { oldOut = this.out; this.out = new DebugByteTeeOutputStream(oldOut); } } if (ref instanceof Storable) { Storable s = (Storable) ref; int fmtId = s.getTypeFormatId(); if (fmtId != StoredFormatIds.SERIALIZABLE_FORMAT_ID) { FormatIdUtil.writeFormatIdInteger(this, fmtId); boolean isNull = s.isNull(); writeBoolean(isNull); if (!isNull) { s.writeExternal(this); } if (SanityManager.DEBUG) { ((DebugByteTeeOutputStream) this.out).checkObject(s); this.out = oldOut; } return; } } else if (ref instanceof Formatable) { Formatable f = (Formatable) ref; int fmtId = f.getTypeFormatId(); if (fmtId != StoredFormatIds.SERIALIZABLE_FORMAT_ID) { FormatIdUtil.writeFormatIdInteger(this, fmtId); f.writeExternal(this); if (SanityManager.DEBUG) { ((DebugByteTeeOutputStream) this.out).checkObject(f); this.out = oldOut; } return; } } /* ** Otherwise we assume (ref instanceof Serializable). ** If it isn't we'll get an error, which is what ** we would expect if someone uses something that ** doesn't support Serializable/Externalizable/Formattable ** when it should. */ { /* ** If we are debugging (SerializeTrace), we are ** going to print out every unexpected serialized ** class. We print them out to stdout to help ** in debugging (so they cause diffs in test runs). ** This is only active in a SANE server. */ if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("SerializedTrace")) { String name = ref.getClass().getName(); if (!name.startsWith("java.lang") && !name.startsWith("java.math")) { SanityManager.DEBUG("SerializedTrace", "...writing serialized class: " + name); System.out.println("...writing serialized class: " + name); } } } FormatIdUtil.writeFormatIdInteger(this, StoredFormatIds.SERIALIZABLE_FORMAT_ID); ObjectOutputStream oos = new ObjectOutputStream(this); oos.writeObject(ref); oos.flush(); if (SanityManager.DEBUG && ref instanceof Formatable) { ((DebugByteTeeOutputStream) this.out).checkObject((Formatable) ref); this.out = oldOut; } } }