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: String s = (String)obj;
367: long l = realOutput.getUTFlength(s, 0, 0);
368: if (l <= 65535)
369: {
370: realOutput.writeByte(TC_STRING);
371: if (shared)
372: assignNewHandle(obj);
373: realOutput.writeUTFShort(s, (int)l);
374: }
375: else
376: {
377: realOutput.writeByte(TC_LONGSTRING);
378: if (shared)
379: assignNewHandle(obj);
380: realOutput.writeUTFLong(s, l);
381: }
382: break;
383: }
384:
385: if (clazz.isArray ())
386: {
387: realOutput.writeByte(TC_ARRAY);
388: writeObject(osc);
389: if (shared)
390: assignNewHandle(obj);
391: writeArraySizeAndElements(obj, clazz.getComponentType());
392: break;
393: }
394:
395: realOutput.writeByte(TC_OBJECT);
396: writeObject(osc);
397:
398: if (shared)
399: if (replaceDone)
400: assignNewHandle(replacedObject);
401: else
402: assignNewHandle(obj);
403:
404: if (obj instanceof Externalizable)
405: {
406: if (protocolVersion == PROTOCOL_VERSION_2)
407: setBlockDataMode(true);
408:
409: ((Externalizable)obj).writeExternal(this);
410:
411: if (protocolVersion == PROTOCOL_VERSION_2)
412: {
413: setBlockDataMode(false);
414: realOutput.writeByte(TC_ENDBLOCKDATA);
415: }
416:
417: break;
418: }
419:
420: if (obj instanceof Serializable)
421: {
422: Object prevObject = this.currentObject;
423: ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
424: currentObject = obj;
425: ObjectStreamClass[] hierarchy = osc.hierarchy();
426:
427: for (int i = 0; i < hierarchy.length; i++)
428: {
429: currentObjectStreamClass = hierarchy[i];
430:
431: fieldsAlreadyWritten = false;
432: if (currentObjectStreamClass.hasWriteMethod())
433: {
434: if (dump)
435: dumpElementln ("WRITE METHOD CALLED FOR: ", obj);
436: setBlockDataMode(true);
437: callWriteMethod(obj, currentObjectStreamClass);
438: setBlockDataMode(false);
439: realOutput.writeByte(TC_ENDBLOCKDATA);
440: if (dump)
441: dumpElementln ("WRITE ENDBLOCKDATA FOR: ", obj);
442: }
443: else
444: {
445: if (dump)
446: dumpElementln ("WRITE FIELDS CALLED FOR: ", obj);
447: writeFields(obj, currentObjectStreamClass);
448: }
449: }
450:
451: this.currentObject = prevObject;
452: this.currentObjectStreamClass = prevObjectStreamClass;
453: currentPutField = null;
454: break;
455: }
456:
457: throw new NotSerializableException(clazz.getName()
458: + " in "
459: + obj.getClass());
460: }
461: }
462: catch (ObjectStreamException ose)
463: {
464:
465: throw ose;
466: }
467: catch (IOException e)
468: {
469: realOutput.writeByte(TC_EXCEPTION);
470: reset(true);
471:
472: setBlockDataMode(false);
473: try
474: {
475: if (DEBUG)
476: {
477: e.printStackTrace(System.out);
478: }
479: writeObject(e);
480: }
481: catch (IOException ioe)
482: {
483: StreamCorruptedException ex =
484: new StreamCorruptedException
485: (ioe + " thrown while exception was being written to stream.");
486: if (DEBUG)
487: {
488: ex.printStackTrace(System.out);
489: }
490: throw ex;
491: }
492:
493: reset (true);
494:
495: }
496: finally
497: {
498: isSerializing = was_serializing;
499: setBlockDataMode(old_mode);
500: depth -= 2;
501:
502: if (dump)
503: dumpElementln ("END: ", obj);
504: }
505: }
506:
507: protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
508: {
509: if (osc.isProxyClass)
510: {
511: realOutput.writeByte(TC_PROXYCLASSDESC);
512: Class[] intfs = osc.forClass().getInterfaces();
513: realOutput.writeInt(intfs.length);
514: for (int i = 0; i < intfs.length; i++)
515: realOutput.writeUTF(intfs[i].getName());
516:
517: assignNewHandle(osc);
518:
519: boolean oldmode = setBlockDataMode(true);
520: annotateProxyClass(osc.forClass());
521: setBlockDataMode(oldmode);
522: realOutput.writeByte(TC_ENDBLOCKDATA);
523: }
524: else
525: {
526: realOutput.writeByte(TC_CLASSDESC);
527: realOutput.writeUTF(osc.getName());
528: if (osc.isEnum())
529: realOutput.writeLong(0L);
530: else
531: realOutput.writeLong(osc.getSerialVersionUID());
532: assignNewHandle(osc);
533:
534: int flags = osc.getFlags();
535:
536: if (protocolVersion == PROTOCOL_VERSION_2
537: && osc.isExternalizable())
538: flags |= SC_BLOCK_DATA;
539:
540: realOutput.writeByte(flags);
541:
542: ObjectStreamField[] fields = osc.fields;
543:
544: if (fields == ObjectStreamClass.INVALID_FIELDS)
545: throw new InvalidClassException
546: (osc.getName(), "serialPersistentFields is invalid");
547:
548: realOutput.writeShort(fields.length);
549:
550: ObjectStreamField field;
551: for (int i = 0; i < fields.length; i++)
552: {
553: field = fields[i];
554: realOutput.writeByte(field.getTypeCode ());
555: realOutput.writeUTF(field.getName ());
556:
557: if (! field.isPrimitive())
558: writeObject(field.getTypeString());
559: }
560:
561: boolean oldmode = setBlockDataMode(true);
562: annotateClass(osc.forClass());
563: setBlockDataMode(oldmode);
564: realOutput.writeByte(TC_ENDBLOCKDATA);
565: }
566:
567: if (osc.isSerializable() || osc.isExternalizable())
568: writeObject(osc.getSuper());
569: else
570: writeObject(null);
571: }
572:
573:
589: public void defaultWriteObject()
590: throws IOException, NotActiveException
591: {
592: markFieldsWritten();
593: writeFields(currentObject, currentObjectStreamClass);
594: }
595:
596:
597: private void markFieldsWritten() throws IOException
598: {
599: if (currentObject == null || currentObjectStreamClass == null)
600: throw new NotActiveException
601: ("defaultWriteObject called by non-active class and/or object");
602:
603: if (fieldsAlreadyWritten)
604: throw new IOException
605: ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
606:
607: fieldsAlreadyWritten = true;
608: }
609:
610:
622: public void reset() throws IOException
623: {
624: reset(false);
625: }
626:
627:
628: private void reset(boolean internal) throws IOException
629: {
630: if (!internal)
631: {
632: if (isSerializing)
633: throw new IOException("Reset called while serialization in progress");
634:
635: realOutput.writeByte(TC_RESET);
636: }
637:
638: clearHandles();
639: }
640:
641:
642:
667: public void useProtocolVersion(int version) throws IOException
668: {
669: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
670: throw new IllegalArgumentException("Invalid protocol version requested.");
671:
672: if (nextOID != baseWireHandle)
673: throw new IllegalStateException("Protocol version cannot be changed "
674: + "after serialization started.");
675:
676: protocolVersion = version;
677: }
678:
679:
690: protected void annotateClass(Class<?> cl) throws IOException
691: {
692: }
693:
694: protected void annotateProxyClass(Class<?> cl) throws IOException
695: {
696: }
697:
698:
712: protected Object replaceObject(Object obj) throws IOException
713: {
714: return obj;
715: }
716:
717:
718:
726: protected boolean enableReplaceObject(boolean enable)
727: throws SecurityException
728: {
729: if (enable)
730: {
731: SecurityManager sm = System.getSecurityManager();
732: if (sm != null)
733: sm.checkPermission(new SerializablePermission("enableSubstitution"));
734: }
735:
736: boolean old_val = replacementEnabled;
737: replacementEnabled = enable;
738: return old_val;
739: }
740:
741:
742:
749: protected void writeStreamHeader() throws IOException
750: {
751: realOutput.writeShort(STREAM_MAGIC);
752: realOutput.writeShort(STREAM_VERSION);
753: }
754:
755:
766: protected ObjectOutputStream() throws IOException, SecurityException
767: {
768: SecurityManager sec_man = System.getSecurityManager ();
769: if (sec_man != null)
770: sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
771: useSubclassMethod = true;
772: }
773:
774:
775:
787: protected void writeObjectOverride(Object obj) throws NotActiveException,
788: IOException
789: {
790: throw new NotActiveException
791: ("Subclass of ObjectOutputStream must implement writeObjectOverride");
792: }
793:
794:
795:
798: public void write (int data) throws IOException
799: {
800: if (writeDataAsBlocks)
801: {
802: if (blockDataCount == BUFFER_SIZE)
803: drain();
804:
805: blockData[ blockDataCount++ ] = (byte)data;
806: }
807: else
808: realOutput.write(data);
809: }
810:
811:
812:
815: public void write(byte[] b) throws IOException
816: {
817: write(b, 0, b.length);
818: }
819:
820:
821:
824: public void write(byte[] b, int off, int len) throws IOException
825: {
826: if (writeDataAsBlocks)
827: {
828: if (len < 0)
829: throw new IndexOutOfBoundsException();
830:
831: if (blockDataCount + len < BUFFER_SIZE)
832: {
833: System.arraycopy(b, off, blockData, blockDataCount, len);
834: blockDataCount += len;
835: }
836: else
837: {
838: drain();
839: writeBlockDataHeader(len);
840: realOutput.write(b, off, len);
841: }
842: }
843: else
844: realOutput.write(b, off, len);
845: }
846:
847:
848:
851: public void flush () throws IOException
852: {
853: drain();
854: realOutput.flush();
855: }
856:
857:
858:
865: protected void drain() throws IOException
866: {
867: if (blockDataCount == 0)
868: return;
869:
870: if (writeDataAsBlocks)
871: writeBlockDataHeader(blockDataCount);
872: realOutput.write(blockData, 0, blockDataCount);
873: blockDataCount = 0;
874: }
875:
876:
877:
880: public void close() throws IOException
881: {
882: flush();
883: realOutput.close();
884: }
885:
886:
887:
890: public void writeBoolean(boolean data) throws IOException
891: {
892: blockDataOutput.writeBoolean(data);
893: }
894:
895:
896:
899: public void writeByte(int data) throws IOException
900: {
901: blockDataOutput.writeByte(data);
902: }
903:
904:
905:
908: public void writeShort (int data) throws IOException
909: {
910: blockDataOutput.writeShort(data);
911: }
912:
913:
914:
917: public void writeChar(int data) throws IOException
918: {
919: blockDataOutput.writeChar(data);
920: }
921:
922:
923:
926: public void writeInt(int data) throws IOException
927: {
928: blockDataOutput.writeInt(data);
929: }
930:
931:
932:
935: public void writeLong(long data) throws IOException
936: {
937: blockDataOutput.writeLong(data);
938: }
939:
940:
941:
944: public void writeFloat(float data) throws IOException
945: {
946: blockDataOutput.writeFloat(data);
947: }
948:
949:
950:
953: public void writeDouble(double data) throws IOException
954: {
955: blockDataOutput.writeDouble(data);
956: }
957:
958:
959:
962: public void writeBytes(String data) throws IOException
963: {
964: blockDataOutput.writeBytes(data);
965: }
966:
967:
968:
971: public void writeChars(String data) throws IOException
972: {
973: dataOutput.writeChars(data);
974: }
975:
976:
977:
980: public void writeUTF(String data) throws IOException
981: {
982: dataOutput.writeUTF(data);
983: }
984:
985:
986:
992: public abstract static class PutField
993: {
994: public abstract void put (String name, boolean value);
995: public abstract void put (String name, byte value);
996: public abstract void put (String name, char value);
997: public abstract void put (String name, double value);
998: public abstract void put (String name, float value);
999: public abstract void put (String name, int value);
1000: public abstract void put (String name, long value);
1001: public abstract void put (String name, short value);
1002: public abstract void put (String name, Object value);
1003:
1004:
1007: public abstract void write (ObjectOutput out) throws IOException;
1008: }
1009:
1010: public PutField putFields() throws IOException
1011: {
1012: if (currentPutField != null)
1013: return currentPutField;
1014:
1015: currentPutField = new PutField()
1016: {
1017: private byte[] prim_field_data
1018: = new byte[currentObjectStreamClass.primFieldSize];
1019: private Object[] objs
1020: = new Object[currentObjectStreamClass.objectFieldCount];
1021:
1022: private ObjectStreamField getField (String name)
1023: {
1024: ObjectStreamField field
1025: = currentObjectStreamClass.getField(name);
1026:
1027: if (field == null)
1028: throw new IllegalArgumentException("no such serializable field " + name);
1029:
1030: return field;
1031: }
1032:
1033: public void put(String name, boolean value)
1034: {
1035: ObjectStreamField field = getField(name);
1036:
1037: checkType(field, 'Z');
1038: prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
1039: }
1040:
1041: public void put(String name, byte value)
1042: {
1043: ObjectStreamField field = getField(name);
1044:
1045: checkType(field, 'B');
1046: prim_field_data[field.getOffset()] = value;
1047: }
1048:
1049: public void put(String name, char value)
1050: {
1051: ObjectStreamField field = getField(name);
1052:
1053: checkType(field, 'C');
1054: int off = field.getOffset();
1055: prim_field_data[off++] = (byte)(value >>> 8);
1056: prim_field_data[off] = (byte)value;
1057: }
1058:
1059: public void put(String name, double value)
1060: {
1061: ObjectStreamField field = getField (name);
1062:
1063: checkType(field, 'D');
1064: int off = field.getOffset();
1065: long l_value = Double.doubleToLongBits (value);
1066: prim_field_data[off++] = (byte)(l_value >>> 52);
1067: prim_field_data[off++] = (byte)(l_value >>> 48);
1068: prim_field_data[off++] = (byte)(l_value >>> 40);
1069: prim_field_data[off++] = (byte)(l_value >>> 32);
1070: prim_field_data[off++] = (byte)(l_value >>> 24);
1071: prim_field_data[off++] = (byte)(l_value >>> 16);
1072: prim_field_data[off++] = (byte)(l_value >>> 8);
1073: prim_field_data[off] = (byte)l_value;
1074: }
1075:
1076: public void put(String name, float value)
1077: {
1078: ObjectStreamField field = getField(name);
1079:
1080: checkType(field, 'F');
1081: int off = field.getOffset();
1082: int i_value = Float.floatToIntBits(value);
1083: prim_field_data[off++] = (byte)(i_value >>> 24);
1084: prim_field_data[off++] = (byte)(i_value >>> 16);
1085: prim_field_data[off++] = (byte)(i_value >>> 8);
1086: prim_field_data[off] = (byte)i_value;
1087: }
1088:
1089: public void put(String name, int value)
1090: {
1091: ObjectStreamField field = getField(name);
1092: checkType(field, 'I');
1093: int off = field.getOffset();
1094: prim_field_data[off++] = (byte)(value >>> 24);
1095: prim_field_data[off++] = (byte)(value >>> 16);
1096: prim_field_data[off++] = (byte)(value >>> 8);
1097: prim_field_data[off] = (byte)value;
1098: }
1099:
1100: public void put(String name, long value)
1101: {
1102: ObjectStreamField field = getField(name);
1103: checkType(field, 'J');
1104: int off = field.getOffset();
1105: prim_field_data[off++] = (byte)(value >>> 52);
1106: prim_field_data[off++] = (byte)(value >>> 48);
1107: prim_field_data[off++] = (byte)(value >>> 40);
1108: prim_field_data[off++] = (byte)(value >>> 32);
1109: prim_field_data[off++] = (byte)(value >>> 24);
1110: prim_field_data[off++] = (byte)(value >>> 16);
1111: prim_field_data[off++] = (byte)(value >>> 8);
1112: prim_field_data[off] = (byte)value;
1113: }
1114:
1115: public void put(String name, short value)
1116: {
1117: ObjectStreamField field = getField(name);
1118: checkType(field, 'S');
1119: int off = field.getOffset();
1120: prim_field_data[off++] = (byte)(value >>> 8);
1121: prim_field_data[off] = (byte)value;
1122: }
1123:
1124: public void put(String name, Object value)
1125: {
1126: ObjectStreamField field = getField(name);
1127:
1128: if (value != null &&
1129: ! field.getType().isAssignableFrom(value.getClass ()))
1130: throw new IllegalArgumentException("Class " + value.getClass() +
1131: " cannot be cast to " + field.getType());
1132: objs[field.getOffset()] = value;
1133: }
1134:
1135: public void write(ObjectOutput out) throws IOException
1136: {
1137:
1138:
1139:
1140: boolean oldmode = setBlockDataMode(false);
1141: out.write(prim_field_data);
1142: for (int i = 0; i < objs.length; ++ i)
1143: out.writeObject(objs[i]);
1144: setBlockDataMode(oldmode);
1145: }
1146:
1147: private void checkType(ObjectStreamField field, char type)
1148: throws IllegalArgumentException
1149: {
1150: if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1151: != type)
1152: throw new IllegalArgumentException();
1153: }
1154: };
1155:
1156:
1157: return currentPutField;
1158: }
1159:
1160:
1161: public void writeFields() throws IOException
1162: {
1163: if (currentPutField == null)
1164: throw new NotActiveException("writeFields can only be called after putFields has been called");
1165:
1166: markFieldsWritten();
1167: currentPutField.write(this);
1168: }
1169:
1170:
1171:
1172:
1173: private void writeBlockDataHeader(int size) throws IOException
1174: {
1175: if (size < 256)
1176: {
1177: realOutput.writeByte(TC_BLOCKDATA);
1178: realOutput.write(size);
1179: }
1180: else
1181: {
1182: realOutput.writeByte(TC_BLOCKDATALONG);
1183: realOutput.writeInt(size);
1184: }
1185: }
1186:
1187:
1188:
1189:
1190: private int findHandle(Object obj)
1191: {
1192: return OIDLookupTable.get(obj);
1193: }
1194:
1195:
1196:
1197: private int assignNewHandle(Object obj)
1198: {
1199: OIDLookupTable.put(obj, nextOID);
1200: return nextOID++;
1201: }
1202:
1203:
1204:
1205: private void clearHandles()
1206: {
1207: nextOID = baseWireHandle;
1208: OIDLookupTable.clear();
1209: }
1210:
1211:
1212:
1213: private void writeArraySizeAndElements(Object array, Class clazz)
1214: throws IOException
1215: {
1216: int length = Array.getLength(array);
1217:
1218: if (clazz.isPrimitive())
1219: {
1220: if (clazz == Boolean.TYPE)
1221: {
1222: boolean[] cast_array = (boolean[])array;
1223: realOutput.writeInt (length);
1224: for (int i = 0; i < length; i++)
1225: realOutput.writeBoolean(cast_array[i]);
1226: return;
1227: }
1228: if (clazz == Byte.TYPE)
1229: {
1230: byte[] cast_array = (byte[])array;
1231: realOutput.writeInt(length);
1232: realOutput.write(cast_array, 0, length);
1233: return;
1234: }
1235: if (clazz == Character.TYPE)
1236: {
1237: char[] cast_array = (char[])array;
1238: realOutput.writeInt(length);
1239: for (int i = 0; i < length; i++)
1240: realOutput.writeChar(cast_array[i]);
1241: return;
1242: }
1243: if (clazz == Double.TYPE)
1244: {
1245: double[] cast_array = (double[])array;
1246: realOutput.writeInt(length);
1247: for (int i = 0; i < length; i++)
1248: realOutput.writeDouble(cast_array[i]);
1249: return;
1250: }
1251: if (clazz == Float.TYPE)
1252: {
1253: float[] cast_array = (float[])array;
1254: realOutput.writeInt(length);
1255: for (int i = 0; i < length; i++)
1256: realOutput.writeFloat(cast_array[i]);
1257: return;
1258: }
1259: if (clazz == Integer.TYPE)
1260: {
1261: int[] cast_array = (int[])array;
1262: realOutput.writeInt(length);
1263: for (int i = 0; i < length; i++)
1264: realOutput.writeInt(cast_array[i]);
1265: return;
1266: }
1267: if (clazz == Long.TYPE)
1268: {
1269: long[] cast_array = (long[])array;
1270: realOutput.writeInt (length);
1271: for (int i = 0; i < length; i++)
1272: realOutput.writeLong(cast_array[i]);
1273: return;
1274: }
1275: if (clazz == Short.TYPE)
1276: {
1277: short[] cast_array = (short[])array;
1278: realOutput.writeInt (length);
1279: for (int i = 0; i < length; i++)
1280: realOutput.writeShort(cast_array[i]);
1281: return;
1282: }
1283: }
1284: else
1285: {
1286: Object[] cast_array = (Object[])array;
1287: realOutput.writeInt(length);
1288: for (int i = 0; i < length; i++)
1289: writeObject(cast_array[i]);
1290: }
1291: }
1292:
1293:
1294:
1295:
1296: private void writeFields(Object obj, ObjectStreamClass osc)
1297: throws IOException
1298: {
1299: ObjectStreamField[] fields = osc.fields;
1300: boolean oldmode = setBlockDataMode(false);
1301:
1302: try
1303: {
1304: writeFields(obj,fields);
1305: }
1306: catch (IllegalArgumentException _)
1307: {
1308: InvalidClassException e = new InvalidClassException
1309: ("writing fields of class " + osc.forClass().getName());
1310: e.initCause(_);
1311: throw e;
1312: }
1313: catch (IOException e)
1314: {
1315: throw e;
1316: }
1317: catch (Exception _)
1318: {
1319: IOException e = new IOException("Unexpected exception " + _);
1320: e.initCause(_);
1321: throw(e);
1322: }
1323:
1324: setBlockDataMode(oldmode);
1325: }
1326:
1327:
1328:
1336: private void writeFields(Object obj, ObjectStreamField[] fields)
1337: throws
1338: IllegalArgumentException, IllegalAccessException, IOException
1339: {
1340: for (int i = 0; i < fields.length; i++)
1341: {
1342: ObjectStreamField osf = fields[i];
1343: Field field = osf.field;
1344:
1345: if (DEBUG && dump)
1346: dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());
1347:
1348: switch (osf.getTypeCode())
1349: {
1350: case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
1351: case 'B': realOutput.writeByte (field.getByte (obj)); break;
1352: case 'S': realOutput.writeShort (field.getShort (obj)); break;
1353: case 'C': realOutput.writeChar (field.getChar (obj)); break;
1354: case 'I': realOutput.writeInt (field.getInt (obj)); break;
1355: case 'F': realOutput.writeFloat (field.getFloat (obj)); break;
1356: case 'J': realOutput.writeLong (field.getLong (obj)); break;
1357: case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
1358: case 'L':
1359: case '[': writeObject (field.get (obj)); break;
1360: default:
1361: throw new IOException("Unexpected type code " + osf.getTypeCode());
1362: }
1363: }
1364: }
1365:
1366:
1367:
1368:
1369: boolean setBlockDataMode(boolean on) throws IOException
1370: {
1371: if (on == writeDataAsBlocks)
1372: return on;
1373:
1374: drain();
1375: boolean oldmode = writeDataAsBlocks;
1376: writeDataAsBlocks = on;
1377:
1378: if (on)
1379: dataOutput = blockDataOutput;
1380: else
1381: dataOutput = realOutput;
1382:
1383: return oldmode;
1384: }
1385:
1386:
1387: private void callWriteMethod(Object obj, ObjectStreamClass osc)
1388: throws IOException
1389: {
1390: currentPutField = null;
1391: try
1392: {
1393: Object args[] = {this};
1394: osc.writeObjectMethod.invoke(obj, args);
1395: }
1396: catch (InvocationTargetException x)
1397: {
1398:
1399: Throwable exception = x.getTargetException();
1400: if (exception instanceof RuntimeException)
1401: throw (RuntimeException) exception;
1402: if (exception instanceof IOException)
1403: throw (IOException) exception;
1404:
1405: IOException ioe
1406: = new IOException("Exception thrown from writeObject() on " +
1407: osc.forClass().getName() + ": " +
1408: exception.getClass().getName());
1409: ioe.initCause(exception);
1410: throw ioe;
1411: }
1412: catch (Exception x)
1413: {
1414: IOException ioe
1415: = new IOException("Failure invoking writeObject() on " +
1416: osc.forClass().getName() + ": " +
1417: x.getClass().getName());
1418: ioe.initCause(x);
1419: throw ioe;
1420: }
1421: }
1422:
1423: private void dumpElementln (String msg, Object obj)
1424: {
1425: try
1426: {
1427: for (int i = 0; i < depth; i++)
1428: System.out.print (" ");
1429: System.out.print (Thread.currentThread() + ": ");
1430: System.out.print (msg);
1431: if (java.lang.reflect.Proxy.isProxyClass(obj.getClass()))
1432: System.out.print (obj.getClass());
1433: else
1434: System.out.print (obj);
1435: }
1436: catch (Exception _)
1437: {
1438: }
1439: finally
1440: {
1441: System.out.println ();
1442: }
1443: }
1444:
1445: private void dumpElementln (String msg)
1446: {
1447: for (int i = 0; i < depth; i++)
1448: System.out.print (" ");
1449: System.out.print (Thread.currentThread() + ": ");
1450: System.out.println(msg);
1451: }
1452:
1453:
1454: private static final int BUFFER_SIZE = 1024;
1455:
1456: private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1457:
1458: private DataOutputStream dataOutput;
1459: private boolean writeDataAsBlocks;
1460: private DataOutputStream realOutput;
1461: private DataOutputStream blockDataOutput;
1462: private byte[] blockData;
1463: private int blockDataCount;
1464: private Object currentObject;
1465:
1466: ObjectStreamClass currentObjectStreamClass;
1467: private PutField currentPutField;
1468: private boolean fieldsAlreadyWritten;
1469: private boolean replacementEnabled;
1470: private boolean isSerializing;
1471: private int nextOID;
1472: private ObjectIdentityMap2Int OIDLookupTable;
1473: private int protocolVersion;
1474: private boolean useSubclassMethod;
1475: private SetAccessibleAction setAccessible = new SetAccessibleAction();
1476:
1477:
1478: private int depth = 0;
1479:
1480:
1481: private boolean dump = false;
1482:
1483: private static final boolean DEBUG = false;
1484: }