1:
38:
39:
40: package ;
41:
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50:
51:
52:
123: public class ObjectOutputStream extends OutputStream
124: implements ObjectOutput, ObjectStreamConstants
125: {
126:
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:
184: public final void writeObject(Object obj) throws IOException
185: {
186: writeObject(obj, true);
187: }
188:
189:
212: public void writeUnshared(Object obj)
213: throws IOException
214: {
215: writeObject(obj, false);
216: }
217:
218:
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:
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: }
449: }
450: catch (ObjectStreamException ose)
451: {
452:
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:
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:
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:
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:
678: protected void annotateClass(Class<?> cl) throws IOException
679: {
680: }
681:
682: protected void annotateProxyClass(Class<?> cl) throws IOException
683: {
684: }
685:
686:
700: protected Object replaceObject(Object obj) throws IOException
701: {
702: return obj;
703: }
704:
705:
706:
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:
737: protected void writeStreamHeader() throws IOException
738: {
739: realOutput.writeShort(STREAM_MAGIC);
740: realOutput.writeShort(STREAM_VERSION);
741: }
742:
743:
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:
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:
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:
803: public void write(byte[] b) throws IOException
804: {
805: write(b, 0, b.length);
806: }
807:
808:
809:
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:
839: public void flush () throws IOException
840: {
841: drain();
842: realOutput.flush();
843: }
844:
845:
846:
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:
868: public void close() throws IOException
869: {
870: flush();
871: realOutput.close();
872: }
873:
874:
875:
878: public void writeBoolean(boolean data) throws IOException
879: {
880: blockDataOutput.writeBoolean(data);
881: }
882:
883:
884:
887: public void writeByte(int data) throws IOException
888: {
889: blockDataOutput.writeByte(data);
890: }
891:
892:
893:
896: public void writeShort (int data) throws IOException
897: {
898: blockDataOutput.writeShort(data);
899: }
900:
901:
902:
905: public void writeChar(int data) throws IOException
906: {
907: blockDataOutput.writeChar(data);
908: }
909:
910:
911:
914: public void writeInt(int data) throws IOException
915: {
916: blockDataOutput.writeInt(data);
917: }
918:
919:
920:
923: public void writeLong(long data) throws IOException
924: {
925: blockDataOutput.writeLong(data);
926: }
927:
928:
929:
932: public void writeFloat(float data) throws IOException
933: {
934: blockDataOutput.writeFloat(data);
935: }
936:
937:
938:
941: public void writeDouble(double data) throws IOException
942: {
943: blockDataOutput.writeDouble(data);
944: }
945:
946:
947:
950: public void writeBytes(String data) throws IOException
951: {
952: blockDataOutput.writeBytes(data);
953: }
954:
955:
956:
959: public void writeChars(String data) throws IOException
960: {
961: dataOutput.writeChars(data);
962: }
963:
964:
965:
968: public void writeUTF(String data) throws IOException
969: {
970: dataOutput.writeUTF(data);
971: }
972:
973:
974:
980: public abstract static class PutField
981: {
982: public abstract void put (String name, boolean value);
983: public abstract void put (String name, byte value);
984: public abstract void put (String name, char value);
985: public abstract void put (String name, double value);
986: public abstract void put (String name, float value);
987: public abstract void put (String name, int value);
988: public abstract void put (String name, long value);
989: public abstract void put (String name, short value);
990: public abstract void put (String name, Object value);
991:
992:
995: public abstract void write (ObjectOutput out) throws IOException;
996: }
997:
998: public PutField putFields() throws IOException
999: {
1000: if (currentPutField != null)
1001: return currentPutField;
1002:
1003: currentPutField = new PutField()
1004: {
1005: private byte[] prim_field_data
1006: = new byte[currentObjectStreamClass.primFieldSize];
1007: private Object[] objs
1008: = new Object[currentObjectStreamClass.objectFieldCount];
1009:
1010: private ObjectStreamField getField (String name)
1011: {
1012: ObjectStreamField field
1013: = currentObjectStreamClass.getField(name);
1014:
1015: if (field == null)
1016: throw new IllegalArgumentException("no such serializable field " + name);
1017:
1018: return field;
1019: }
1020:
1021: public void put(String name, boolean value)
1022: {
1023: ObjectStreamField field = getField(name);
1024:
1025: checkType(field, 'Z');
1026: prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
1027: }
1028:
1029: public void put(String name, byte value)
1030: {
1031: ObjectStreamField field = getField(name);
1032:
1033: checkType(field, 'B');
1034: prim_field_data[field.getOffset()] = value;
1035: }
1036:
1037: public void put(String name, char value)
1038: {
1039: ObjectStreamField field = getField(name);
1040:
1041: checkType(field, 'C');
1042: int off = field.getOffset();
1043: prim_field_data[off++] = (byte)(value >>> 8);
1044: prim_field_data[off] = (byte)value;
1045: }
1046:
1047: public void put(String name, double value)
1048: {
1049: ObjectStreamField field = getField (name);
1050:
1051: checkType(field, 'D');
1052: int off = field.getOffset();
1053: long l_value = Double.doubleToLongBits (value);
1054: prim_field_data[off++] = (byte)(l_value >>> 52);
1055: prim_field_data[off++] = (byte)(l_value >>> 48);
1056: prim_field_data[off++] = (byte)(l_value >>> 40);
1057: prim_field_data[off++] = (byte)(l_value >>> 32);
1058: prim_field_data[off++] = (byte)(l_value >>> 24);
1059: prim_field_data[off++] = (byte)(l_value >>> 16);
1060: prim_field_data[off++] = (byte)(l_value >>> 8);
1061: prim_field_data[off] = (byte)l_value;
1062: }
1063:
1064: public void put(String name, float value)
1065: {
1066: ObjectStreamField field = getField(name);
1067:
1068: checkType(field, 'F');
1069: int off = field.getOffset();
1070: int i_value = Float.floatToIntBits(value);
1071: prim_field_data[off++] = (byte)(i_value >>> 24);
1072: prim_field_data[off++] = (byte)(i_value >>> 16);
1073: prim_field_data[off++] = (byte)(i_value >>> 8);
1074: prim_field_data[off] = (byte)i_value;
1075: }
1076:
1077: public void put(String name, int value)
1078: {
1079: ObjectStreamField field = getField(name);
1080: checkType(field, 'I');
1081: int off = field.getOffset();
1082: prim_field_data[off++] = (byte)(value >>> 24);
1083: prim_field_data[off++] = (byte)(value >>> 16);
1084: prim_field_data[off++] = (byte)(value >>> 8);
1085: prim_field_data[off] = (byte)value;
1086: }
1087:
1088: public void put(String name, long value)
1089: {
1090: ObjectStreamField field = getField(name);
1091: checkType(field, 'J');
1092: int off = field.getOffset();
1093: prim_field_data[off++] = (byte)(value >>> 52);
1094: prim_field_data[off++] = (byte)(value >>> 48);
1095: prim_field_data[off++] = (byte)(value >>> 40);
1096: prim_field_data[off++] = (byte)(value >>> 32);
1097: prim_field_data[off++] = (byte)(value >>> 24);
1098: prim_field_data[off++] = (byte)(value >>> 16);
1099: prim_field_data[off++] = (byte)(value >>> 8);
1100: prim_field_data[off] = (byte)value;
1101: }
1102:
1103: public void put(String name, short value)
1104: {
1105: ObjectStreamField field = getField(name);
1106: checkType(field, 'S');
1107: int off = field.getOffset();
1108: prim_field_data[off++] = (byte)(value >>> 8);
1109: prim_field_data[off] = (byte)value;
1110: }
1111:
1112: public void put(String name, Object value)
1113: {
1114: ObjectStreamField field = getField(name);
1115:
1116: if (value != null &&
1117: ! field.getType().isAssignableFrom(value.getClass ()))
1118: throw new IllegalArgumentException("Class " + value.getClass() +
1119: " cannot be cast to " + field.getType());
1120: objs[field.getOffset()] = value;
1121: }
1122:
1123: public void write(ObjectOutput out) throws IOException
1124: {
1125:
1126:
1127:
1128: boolean oldmode = setBlockDataMode(false);
1129: out.write(prim_field_data);
1130: for (int i = 0; i < objs.length; ++ i)
1131: out.writeObject(objs[i]);
1132: setBlockDataMode(oldmode);
1133: }
1134:
1135: private void checkType(ObjectStreamField field, char type)
1136: throws IllegalArgumentException
1137: {
1138: if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1139: != type)
1140: throw new IllegalArgumentException();
1141: }
1142: };
1143:
1144:
1145: return currentPutField;
1146: }
1147:
1148:
1149: public void writeFields() throws IOException
1150: {
1151: if (currentPutField == null)
1152: throw new NotActiveException("writeFields can only be called after putFields has been called");
1153:
1154: markFieldsWritten();
1155: currentPutField.write(this);
1156: }
1157:
1158:
1159:
1160:
1161: private void writeBlockDataHeader(int size) throws IOException
1162: {
1163: if (size < 256)
1164: {
1165: realOutput.writeByte(TC_BLOCKDATA);
1166: realOutput.write(size);
1167: }
1168: else
1169: {
1170: realOutput.writeByte(TC_BLOCKDATALONG);
1171: realOutput.writeInt(size);
1172: }
1173: }
1174:
1175:
1176:
1177:
1178: private int findHandle(Object obj)
1179: {
1180: return OIDLookupTable.get(obj);
1181: }
1182:
1183:
1184:
1185: private int assignNewHandle(Object obj)
1186: {
1187: OIDLookupTable.put(obj, nextOID);
1188: return nextOID++;
1189: }
1190:
1191:
1192:
1193: private void clearHandles()
1194: {
1195: nextOID = baseWireHandle;
1196: OIDLookupTable.clear();
1197: }
1198:
1199:
1200:
1201: private void writeArraySizeAndElements(Object array, Class clazz)
1202: throws IOException
1203: {
1204: int length = Array.getLength(array);
1205:
1206: if (clazz.isPrimitive())
1207: {
1208: if (clazz == Boolean.TYPE)
1209: {
1210: boolean[] cast_array = (boolean[])array;
1211: realOutput.writeInt (length);
1212: for (int i = 0; i < length; i++)
1213: realOutput.writeBoolean(cast_array[i]);
1214: return;
1215: }
1216: if (clazz == Byte.TYPE)
1217: {
1218: byte[] cast_array = (byte[])array;
1219: realOutput.writeInt(length);
1220: realOutput.write(cast_array, 0, length);
1221: return;
1222: }
1223: if (clazz == Character.TYPE)
1224: {
1225: char[] cast_array = (char[])array;
1226: realOutput.writeInt(length);
1227: for (int i = 0; i < length; i++)
1228: realOutput.writeChar(cast_array[i]);
1229: return;
1230: }
1231: if (clazz == Double.TYPE)
1232: {
1233: double[] cast_array = (double[])array;
1234: realOutput.writeInt(length);
1235: for (int i = 0; i < length; i++)
1236: realOutput.writeDouble(cast_array[i]);
1237: return;
1238: }
1239: if (clazz == Float.TYPE)
1240: {
1241: float[] cast_array = (float[])array;
1242: realOutput.writeInt(length);
1243: for (int i = 0; i < length; i++)
1244: realOutput.writeFloat(cast_array[i]);
1245: return;
1246: }
1247: if (clazz == Integer.TYPE)
1248: {
1249: int[] cast_array = (int[])array;
1250: realOutput.writeInt(length);
1251: for (int i = 0; i < length; i++)
1252: realOutput.writeInt(cast_array[i]);
1253: return;
1254: }
1255: if (clazz == Long.TYPE)
1256: {
1257: long[] cast_array = (long[])array;
1258: realOutput.writeInt (length);
1259: for (int i = 0; i < length; i++)
1260: realOutput.writeLong(cast_array[i]);
1261: return;
1262: }
1263: if (clazz == Short.TYPE)
1264: {
1265: short[] cast_array = (short[])array;
1266: realOutput.writeInt (length);
1267: for (int i = 0; i < length; i++)
1268: realOutput.writeShort(cast_array[i]);
1269: return;
1270: }
1271: }
1272: else
1273: {
1274: Object[] cast_array = (Object[])array;
1275: realOutput.writeInt(length);
1276: for (int i = 0; i < length; i++)
1277: writeObject(cast_array[i]);
1278: }
1279: }
1280:
1281:
1282:
1283:
1284: private void writeFields(Object obj, ObjectStreamClass osc)
1285: throws IOException
1286: {
1287: ObjectStreamField[] fields = osc.fields;
1288: boolean oldmode = setBlockDataMode(false);
1289:
1290: try
1291: {
1292: writeFields(obj,fields);
1293: }
1294: catch (IllegalArgumentException _)
1295: {
1296: InvalidClassException e = new InvalidClassException
1297: ("writing fields of class " + osc.forClass().getName());
1298: e.initCause(_);
1299: throw e;
1300: }
1301: catch (IOException e)
1302: {
1303: throw e;
1304: }
1305: catch (Exception _)
1306: {
1307: IOException e = new IOException("Unexpected exception " + _);
1308: e.initCause(_);
1309: throw(e);
1310: }
1311:
1312: setBlockDataMode(oldmode);
1313: }
1314:
1315:
1316:
1324: private void writeFields(Object obj, ObjectStreamField[] fields)
1325: throws
1326: IllegalArgumentException, IllegalAccessException, IOException
1327: {
1328: for (int i = 0; i < fields.length; i++)
1329: {
1330: ObjectStreamField osf = fields[i];
1331: Field field = osf.field;
1332:
1333: if (DEBUG && dump)
1334: dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());
1335:
1336: switch (osf.getTypeCode())
1337: {
1338: case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
1339: case 'B': realOutput.writeByte (field.getByte (obj)); break;
1340: case 'S': realOutput.writeShort (field.getShort (obj)); break;
1341: case 'C': realOutput.writeChar (field.getChar (obj)); break;
1342: case 'I': realOutput.writeInt (field.getInt (obj)); break;
1343: case 'F': realOutput.writeFloat (field.getFloat (obj)); break;
1344: case 'J': realOutput.writeLong (field.getLong (obj)); break;
1345: case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
1346: case 'L':
1347: case '[': writeObject (field.get (obj)); break;
1348: default:
1349: throw new IOException("Unexpected type code " + osf.getTypeCode());
1350: }
1351: }
1352: }
1353:
1354:
1355:
1356:
1357: boolean setBlockDataMode(boolean on) throws IOException
1358: {
1359: if (on == writeDataAsBlocks)
1360: return on;
1361:
1362: drain();
1363: boolean oldmode = writeDataAsBlocks;
1364: writeDataAsBlocks = on;
1365:
1366: if (on)
1367: dataOutput = blockDataOutput;
1368: else
1369: dataOutput = realOutput;
1370:
1371: return oldmode;
1372: }
1373:
1374:
1375: private void callWriteMethod(Object obj, ObjectStreamClass osc)
1376: throws IOException
1377: {
1378: currentPutField = null;
1379: try
1380: {
1381: Object args[] = {this};
1382: osc.writeObjectMethod.invoke(obj, args);
1383: }
1384: catch (InvocationTargetException x)
1385: {
1386:
1387: Throwable exception = x.getTargetException();
1388: if (exception instanceof RuntimeException)
1389: throw (RuntimeException) exception;
1390: if (exception instanceof IOException)
1391: throw (IOException) exception;
1392:
1393: IOException ioe
1394: = new IOException("Exception thrown from writeObject() on " +
1395: osc.forClass().getName() + ": " +
1396: exception.getClass().getName());
1397: ioe.initCause(exception);
1398: throw ioe;
1399: }
1400: catch (Exception x)
1401: {
1402: IOException ioe
1403: = new IOException("Failure invoking writeObject() on " +
1404: osc.forClass().getName() + ": " +
1405: x.getClass().getName());
1406: ioe.initCause(x);
1407: throw ioe;
1408: }
1409: }
1410:
1411: private void dumpElementln (String msg)
1412: {
1413: for (int i = 0; i < depth; i++)
1414: System.out.print (" ");
1415: System.out.print (Thread.currentThread() + ": ");
1416: System.out.println(msg);
1417: }
1418:
1419:
1420: private static final int BUFFER_SIZE = 1024;
1421:
1422: private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1423:
1424: private DataOutputStream dataOutput;
1425: private boolean writeDataAsBlocks;
1426: private DataOutputStream realOutput;
1427: private DataOutputStream blockDataOutput;
1428: private byte[] blockData;
1429: private int blockDataCount;
1430: private Object currentObject;
1431:
1432: ObjectStreamClass currentObjectStreamClass;
1433: private PutField currentPutField;
1434: private boolean fieldsAlreadyWritten;
1435: private boolean replacementEnabled;
1436: private boolean isSerializing;
1437: private int nextOID;
1438: private ObjectIdentityMap2Int OIDLookupTable;
1439: private int protocolVersion;
1440: private boolean useSubclassMethod;
1441: private SetAccessibleAction setAccessible = new SetAccessibleAction();
1442:
1443:
1444: private int depth = 0;
1445:
1446:
1447: private boolean dump = false;
1448:
1449: private static final boolean DEBUG = false;
1450: }