1:
38:
39:
40: package ;
41:
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50:
51: import ;
52: import ;
53:
54:
125: public class ObjectOutputStream extends OutputStream
126: implements ObjectOutput, ObjectStreamConstants
127: {
128:
139: public ObjectOutputStream (OutputStream out) throws IOException
140: {
141: SecurityManager secMan = System.getSecurityManager();
142: if (secMan != null && overridesMethods(getClass()))
143: secMan.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
144:
145: realOutput = new DataOutputStream(out);
146: blockData = new byte[ BUFFER_SIZE ];
147: blockDataCount = 0;
148: blockDataOutput = new DataOutputStream(this);
149: setBlockDataMode(true);
150: replacementEnabled = false;
151: isSerializing = false;
152: nextOID = baseWireHandle;
153: OIDLookupTable = new ObjectIdentityMap2Int();
154: protocolVersion = defaultProtocolVersion;
155: useSubclassMethod = false;
156: writeStreamHeader();
157:
158: if (DEBUG)
159: {
160: String val = System.getProperty("gcj.dumpobjects");
161: if (val != null && !val.equals(""))
162: dump = true;
163: }
164: }
165:
166:
190: public final void writeObject(Object obj) throws IOException
191: {
192: writeObject(obj, true);
193: }
194:
195:
218: public void writeUnshared(Object obj)
219: throws IOException
220: {
221: writeObject(obj, false);
222: }
223:
224:
250: private final void writeObject(Object obj, boolean shared)
251: throws IOException
252: {
253: if (useSubclassMethod)
254: {
255: if (dump)
256: dumpElementln ("WRITE OVERRIDE: " + obj);
257:
258: writeObjectOverride(obj);
259: return;
260: }
261:
262: if (dump)
263: dumpElementln ("WRITE: ", obj);
264:
265: depth += 2;
266:
267: boolean was_serializing = isSerializing;
268: boolean old_mode = setBlockDataMode(false);
269: try
270: {
271: isSerializing = true;
272: boolean replaceDone = false;
273: Object replacedObject = null;
274:
275: while (true)
276: {
277: if (obj == null)
278: {
279: realOutput.writeByte(TC_NULL);
280: break;
281: }
282:
283: int handle = findHandle(obj);
284: if (handle >= 0 && shared)
285: {
286: realOutput.writeByte(TC_REFERENCE);
287: realOutput.writeInt(handle);
288: break;
289: }
290:
291: if (obj instanceof Class)
292: {
293: Class cl = (Class)obj;
294: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
295: realOutput.writeByte(TC_CLASS);
296: if (!osc.isProxyClass)
297: {
298: writeObject (osc);
299: }
300: else
301: {System.err.println("1");
302: realOutput.writeByte(TC_PROXYCLASSDESC);
303: Class[] intfs = cl.getInterfaces();
304: realOutput.writeInt(intfs.length);
305: for (int i = 0; i < intfs.length; i++)
306: realOutput.writeUTF(intfs[i].getName());
307:
308: boolean oldmode = setBlockDataMode(true);
309: annotateProxyClass(cl);
310: setBlockDataMode(oldmode);
311: realOutput.writeByte(TC_ENDBLOCKDATA);
312:
313: writeObject(osc.getSuper());
314: }
315: if (shared)
316: assignNewHandle(obj);
317: break;
318: }
319:
320: if (obj instanceof ObjectStreamClass)
321: {
322: writeClassDescriptor((ObjectStreamClass) obj);
323: break;
324: }
325:
326: Class clazz = obj.getClass();
327: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz);
328: if (osc == null)
329: throw new NotSerializableException(clazz.getName());
330:
331: if (osc.isEnum())
332: {
333:
334: realOutput.writeByte(TC_ENUM);
335: writeObject(osc);
336: if (shared)
337: assignNewHandle(obj);
338: writeObject(((Enum) obj).name());
339: break;
340: }
341:
342: if ((replacementEnabled || obj instanceof Serializable)
343: && ! replaceDone)
344: {
345: replacedObject = obj;
346:
347: if (obj instanceof Serializable)
348: {
349: try
350: {
351: Method m = osc.writeReplaceMethod;
352: if (m != null)
353: obj = m.invoke(obj, new Object[0]);
354: }
355: catch (IllegalAccessException ignore)
356: {
357: }
358: catch (InvocationTargetException ignore)
359: {
360: }
361: }
362:
363: if (replacementEnabled)
364: obj = replaceObject(obj);
365:
366: replaceDone = true;
367: continue;
368: }
369:
370: if (obj instanceof String)
371: {
372: String s = (String)obj;
373: long l = realOutput.getUTFlength(s, 0, 0);
374: if (l <= 65535)
375: {
376: realOutput.writeByte(TC_STRING);
377: if (shared)
378: assignNewHandle(obj);
379: realOutput.writeUTFShort(s, (int)l);
380: }
381: else
382: {
383: realOutput.writeByte(TC_LONGSTRING);
384: if (shared)
385: assignNewHandle(obj);
386: realOutput.writeUTFLong(s, l);
387: }
388: break;
389: }
390:
391: if (clazz.isArray ())
392: {
393: realOutput.writeByte(TC_ARRAY);
394: writeObject(osc);
395: if (shared)
396: assignNewHandle(obj);
397: writeArraySizeAndElements(obj, clazz.getComponentType());
398: break;
399: }
400:
401: realOutput.writeByte(TC_OBJECT);
402: writeObject(osc);
403:
404: if (shared)
405: if (replaceDone)
406: assignNewHandle(replacedObject);
407: else
408: assignNewHandle(obj);
409:
410: if (obj instanceof Externalizable)
411: {
412: if (protocolVersion == PROTOCOL_VERSION_2)
413: setBlockDataMode(true);
414:
415: ((Externalizable)obj).writeExternal(this);
416:
417: if (protocolVersion == PROTOCOL_VERSION_2)
418: {
419: setBlockDataMode(false);
420: realOutput.writeByte(TC_ENDBLOCKDATA);
421: }
422:
423: break;
424: }
425:
426: if (obj instanceof Serializable)
427: {
428: Object prevObject = this.currentObject;
429: ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
430: currentObject = obj;
431: ObjectStreamClass[] hierarchy = osc.hierarchy();
432:
433: for (int i = 0; i < hierarchy.length; i++)
434: {
435: currentObjectStreamClass = hierarchy[i];
436:
437: fieldsAlreadyWritten = false;
438: if (currentObjectStreamClass.hasWriteMethod())
439: {
440: if (dump)
441: dumpElementln ("WRITE METHOD CALLED FOR: ", obj);
442: setBlockDataMode(true);
443: callWriteMethod(obj, currentObjectStreamClass);
444: setBlockDataMode(false);
445: realOutput.writeByte(TC_ENDBLOCKDATA);
446: if (dump)
447: dumpElementln ("WRITE ENDBLOCKDATA FOR: ", obj);
448: }
449: else
450: {
451: if (dump)
452: dumpElementln ("WRITE FIELDS CALLED FOR: ", obj);
453: writeFields(obj, currentObjectStreamClass);
454: }
455: }
456:
457: this.currentObject = prevObject;
458: this.currentObjectStreamClass = prevObjectStreamClass;
459: currentPutField = null;
460: break;
461: }
462:
463: throw new NotSerializableException(clazz.getName()
464: + " in "
465: + obj.getClass());
466: }
467: }
468: catch (ObjectStreamException ose)
469: {
470:
471: throw ose;
472: }
473: catch (IOException e)
474: {
475: realOutput.writeByte(TC_EXCEPTION);
476: reset(true);
477:
478: setBlockDataMode(false);
479: try
480: {
481: if (DEBUG)
482: {
483: e.printStackTrace(System.out);
484: }
485: writeObject(e);
486: }
487: catch (IOException ioe)
488: {
489: StreamCorruptedException ex =
490: new StreamCorruptedException
491: (ioe + " thrown while exception was being written to stream.");
492: if (DEBUG)
493: {
494: ex.printStackTrace(System.out);
495: }
496: throw ex;
497: }
498:
499: reset (true);
500:
501: }
502: finally
503: {
504: isSerializing = was_serializing;
505: setBlockDataMode(old_mode);
506: depth -= 2;
507:
508: if (dump)
509: dumpElementln ("END: ", obj);
510: }
511: }
512:
513: protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
514: {
515: if (osc.isProxyClass)
516: {
517: realOutput.writeByte(TC_PROXYCLASSDESC);
518: Class[] intfs = osc.forClass().getInterfaces();
519: realOutput.writeInt(intfs.length);
520: for (int i = 0; i < intfs.length; i++)
521: realOutput.writeUTF(intfs[i].getName());
522:
523: assignNewHandle(osc);
524:
525: boolean oldmode = setBlockDataMode(true);
526: annotateProxyClass(osc.forClass());
527: setBlockDataMode(oldmode);
528: realOutput.writeByte(TC_ENDBLOCKDATA);
529: }
530: else
531: {
532: realOutput.writeByte(TC_CLASSDESC);
533: realOutput.writeUTF(osc.getName());
534: if (osc.isEnum())
535: realOutput.writeLong(0L);
536: else
537: realOutput.writeLong(osc.getSerialVersionUID());
538: assignNewHandle(osc);
539:
540: int flags = osc.getFlags();
541:
542: if (protocolVersion == PROTOCOL_VERSION_2
543: && osc.isExternalizable())
544: flags |= SC_BLOCK_DATA;
545:
546: realOutput.writeByte(flags);
547:
548: ObjectStreamField[] fields = osc.fields;
549:
550: if (fields == ObjectStreamClass.INVALID_FIELDS)
551: throw new InvalidClassException
552: (osc.getName(), "serialPersistentFields is invalid");
553:
554: realOutput.writeShort(fields.length);
555:
556: ObjectStreamField field;
557: for (int i = 0; i < fields.length; i++)
558: {
559: field = fields[i];
560: realOutput.writeByte(field.getTypeCode ());
561: realOutput.writeUTF(field.getName ());
562:
563: if (! field.isPrimitive())
564: writeObject(field.getTypeString());
565: }
566:
567: boolean oldmode = setBlockDataMode(true);
568: annotateClass(osc.forClass());
569: setBlockDataMode(oldmode);
570: realOutput.writeByte(TC_ENDBLOCKDATA);
571: }
572:
573: if (osc.isSerializable() || osc.isExternalizable())
574: writeObject(osc.getSuper());
575: else
576: writeObject(null);
577: }
578:
579:
595: public void defaultWriteObject()
596: throws IOException, NotActiveException
597: {
598: markFieldsWritten();
599: writeFields(currentObject, currentObjectStreamClass);
600: }
601:
602:
603: private void markFieldsWritten() throws IOException
604: {
605: if (currentObject == null || currentObjectStreamClass == null)
606: throw new NotActiveException
607: ("defaultWriteObject called by non-active class and/or object");
608:
609: if (fieldsAlreadyWritten)
610: throw new IOException
611: ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
612:
613: fieldsAlreadyWritten = true;
614: }
615:
616:
628: public void reset() throws IOException
629: {
630: reset(false);
631: }
632:
633:
634: private void reset(boolean internal) throws IOException
635: {
636: if (!internal)
637: {
638: if (isSerializing)
639: throw new IOException("Reset called while serialization in progress");
640:
641: realOutput.writeByte(TC_RESET);
642: }
643:
644: clearHandles();
645: }
646:
647:
648:
673: public void useProtocolVersion(int version) throws IOException
674: {
675: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
676: throw new IllegalArgumentException("Invalid protocol version requested.");
677:
678: if (nextOID != baseWireHandle)
679: throw new IllegalStateException("Protocol version cannot be changed "
680: + "after serialization started.");
681:
682: protocolVersion = version;
683: }
684:
685:
696: protected void annotateClass(Class<?> cl) throws IOException
697: {
698: }
699:
700: protected void annotateProxyClass(Class<?> cl) throws IOException
701: {
702: }
703:
704:
718: protected Object replaceObject(Object obj) throws IOException
719: {
720: return obj;
721: }
722:
723:
724:
732: protected boolean enableReplaceObject(boolean enable)
733: throws SecurityException
734: {
735: if (enable)
736: {
737: SecurityManager sm = System.getSecurityManager();
738: if (sm != null)
739: sm.checkPermission(new SerializablePermission("enableSubstitution"));
740: }
741:
742: boolean old_val = replacementEnabled;
743: replacementEnabled = enable;
744: return old_val;
745: }
746:
747:
748:
755: protected void writeStreamHeader() throws IOException
756: {
757: realOutput.writeShort(STREAM_MAGIC);
758: realOutput.writeShort(STREAM_VERSION);
759: }
760:
761:
772: protected ObjectOutputStream() throws IOException, SecurityException
773: {
774: SecurityManager sec_man = System.getSecurityManager ();
775: if (sec_man != null)
776: sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
777: useSubclassMethod = true;
778: }
779:
780:
781:
793: protected void writeObjectOverride(Object obj) throws NotActiveException,
794: IOException
795: {
796: throw new NotActiveException
797: ("Subclass of ObjectOutputStream must implement writeObjectOverride");
798: }
799:
800:
801:
804: public void write (int data) throws IOException
805: {
806: if (writeDataAsBlocks)
807: {
808: if (blockDataCount == BUFFER_SIZE)
809: drain();
810:
811: blockData[ blockDataCount++ ] = (byte)data;
812: }
813: else
814: realOutput.write(data);
815: }
816:
817:
818:
821: public void write(byte[] b) throws IOException
822: {
823: write(b, 0, b.length);
824: }
825:
826:
827:
830: public void write(byte[] b, int off, int len) throws IOException
831: {
832: if (writeDataAsBlocks)
833: {
834: if (len < 0)
835: throw new IndexOutOfBoundsException();
836:
837: if (blockDataCount + len < BUFFER_SIZE)
838: {
839: System.arraycopy(b, off, blockData, blockDataCount, len);
840: blockDataCount += len;
841: }
842: else
843: {
844: drain();
845: writeBlockDataHeader(len);
846: realOutput.write(b, off, len);
847: }
848: }
849: else
850: realOutput.write(b, off, len);
851: }
852:
853:
854:
857: public void flush () throws IOException
858: {
859: drain();
860: realOutput.flush();
861: }
862:
863:
864:
871: protected void drain() throws IOException
872: {
873: if (blockDataCount == 0)
874: return;
875:
876: if (writeDataAsBlocks)
877: writeBlockDataHeader(blockDataCount);
878: realOutput.write(blockData, 0, blockDataCount);
879: blockDataCount = 0;
880: }
881:
882:
883:
886: public void close() throws IOException
887: {
888: flush();
889: realOutput.close();
890: }
891:
892:
893:
896: public void writeBoolean(boolean data) throws IOException
897: {
898: blockDataOutput.writeBoolean(data);
899: }
900:
901:
902:
905: public void writeByte(int data) throws IOException
906: {
907: blockDataOutput.writeByte(data);
908: }
909:
910:
911:
914: public void writeShort (int data) throws IOException
915: {
916: blockDataOutput.writeShort(data);
917: }
918:
919:
920:
923: public void writeChar(int data) throws IOException
924: {
925: blockDataOutput.writeChar(data);
926: }
927:
928:
929:
932: public void writeInt(int data) throws IOException
933: {
934: blockDataOutput.writeInt(data);
935: }
936:
937:
938:
941: public void writeLong(long data) throws IOException
942: {
943: blockDataOutput.writeLong(data);
944: }
945:
946:
947:
950: public void writeFloat(float data) throws IOException
951: {
952: blockDataOutput.writeFloat(data);
953: }
954:
955:
956:
959: public void writeDouble(double data) throws IOException
960: {
961: blockDataOutput.writeDouble(data);
962: }
963:
964:
965:
968: public void writeBytes(String data) throws IOException
969: {
970: blockDataOutput.writeBytes(data);
971: }
972:
973:
974:
977: public void writeChars(String data) throws IOException
978: {
979: dataOutput.writeChars(data);
980: }
981:
982:
983:
986: public void writeUTF(String data) throws IOException
987: {
988: dataOutput.writeUTF(data);
989: }
990:
991:
992:
998: public abstract static class PutField
999: {
1000: public abstract void put (String name, boolean value);
1001: public abstract void put (String name, byte value);
1002: public abstract void put (String name, char value);
1003: public abstract void put (String name, double value);
1004: public abstract void put (String name, float value);
1005: public abstract void put (String name, int value);
1006: public abstract void put (String name, long value);
1007: public abstract void put (String name, short value);
1008: public abstract void put (String name, Object value);
1009:
1010:
1013: public abstract void write (ObjectOutput out) throws IOException;
1014: }
1015:
1016: public PutField putFields() throws IOException
1017: {
1018: if (currentPutField != null)
1019: return currentPutField;
1020:
1021: currentPutField = new PutField()
1022: {
1023: private byte[] prim_field_data
1024: = new byte[currentObjectStreamClass.primFieldSize];
1025: private Object[] objs
1026: = new Object[currentObjectStreamClass.objectFieldCount];
1027:
1028: private ObjectStreamField getField (String name)
1029: {
1030: ObjectStreamField field
1031: = currentObjectStreamClass.getField(name);
1032:
1033: if (field == null)
1034: throw new IllegalArgumentException("no such serializable field " + name);
1035:
1036: return field;
1037: }
1038:
1039: public void put(String name, boolean value)
1040: {
1041: ObjectStreamField field = getField(name);
1042:
1043: checkType(field, 'Z');
1044: prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
1045: }
1046:
1047: public void put(String name, byte value)
1048: {
1049: ObjectStreamField field = getField(name);
1050:
1051: checkType(field, 'B');
1052: prim_field_data[field.getOffset()] = value;
1053: }
1054:
1055: public void put(String name, char value)
1056: {
1057: ObjectStreamField field = getField(name);
1058:
1059: checkType(field, 'C');
1060: int off = field.getOffset();
1061: prim_field_data[off++] = (byte)(value >>> 8);
1062: prim_field_data[off] = (byte)value;
1063: }
1064:
1065: public void put(String name, double value)
1066: {
1067: ObjectStreamField field = getField (name);
1068:
1069: checkType(field, 'D');
1070: int off = field.getOffset();
1071: long l_value = Double.doubleToLongBits (value);
1072: prim_field_data[off++] = (byte)(l_value >>> 52);
1073: prim_field_data[off++] = (byte)(l_value >>> 48);
1074: prim_field_data[off++] = (byte)(l_value >>> 40);
1075: prim_field_data[off++] = (byte)(l_value >>> 32);
1076: prim_field_data[off++] = (byte)(l_value >>> 24);
1077: prim_field_data[off++] = (byte)(l_value >>> 16);
1078: prim_field_data[off++] = (byte)(l_value >>> 8);
1079: prim_field_data[off] = (byte)l_value;
1080: }
1081:
1082: public void put(String name, float value)
1083: {
1084: ObjectStreamField field = getField(name);
1085:
1086: checkType(field, 'F');
1087: int off = field.getOffset();
1088: int i_value = Float.floatToIntBits(value);
1089: prim_field_data[off++] = (byte)(i_value >>> 24);
1090: prim_field_data[off++] = (byte)(i_value >>> 16);
1091: prim_field_data[off++] = (byte)(i_value >>> 8);
1092: prim_field_data[off] = (byte)i_value;
1093: }
1094:
1095: public void put(String name, int value)
1096: {
1097: ObjectStreamField field = getField(name);
1098: checkType(field, 'I');
1099: int off = field.getOffset();
1100: prim_field_data[off++] = (byte)(value >>> 24);
1101: prim_field_data[off++] = (byte)(value >>> 16);
1102: prim_field_data[off++] = (byte)(value >>> 8);
1103: prim_field_data[off] = (byte)value;
1104: }
1105:
1106: public void put(String name, long value)
1107: {
1108: ObjectStreamField field = getField(name);
1109: checkType(field, 'J');
1110: int off = field.getOffset();
1111: prim_field_data[off++] = (byte)(value >>> 52);
1112: prim_field_data[off++] = (byte)(value >>> 48);
1113: prim_field_data[off++] = (byte)(value >>> 40);
1114: prim_field_data[off++] = (byte)(value >>> 32);
1115: prim_field_data[off++] = (byte)(value >>> 24);
1116: prim_field_data[off++] = (byte)(value >>> 16);
1117: prim_field_data[off++] = (byte)(value >>> 8);
1118: prim_field_data[off] = (byte)value;
1119: }
1120:
1121: public void put(String name, short value)
1122: {
1123: ObjectStreamField field = getField(name);
1124: checkType(field, 'S');
1125: int off = field.getOffset();
1126: prim_field_data[off++] = (byte)(value >>> 8);
1127: prim_field_data[off] = (byte)value;
1128: }
1129:
1130: public void put(String name, Object value)
1131: {
1132: ObjectStreamField field = getField(name);
1133:
1134: if (value != null &&
1135: ! field.getType().isAssignableFrom(value.getClass ()))
1136: throw new IllegalArgumentException("Class " + value.getClass() +
1137: " cannot be cast to " + field.getType());
1138: objs[field.getOffset()] = value;
1139: }
1140:
1141: public void write(ObjectOutput out) throws IOException
1142: {
1143:
1144:
1145:
1146: boolean oldmode = setBlockDataMode(false);
1147: out.write(prim_field_data);
1148: for (int i = 0; i < objs.length; ++ i)
1149: out.writeObject(objs[i]);
1150: setBlockDataMode(oldmode);
1151: }
1152:
1153: private void checkType(ObjectStreamField field, char type)
1154: throws IllegalArgumentException
1155: {
1156: if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1157: != type)
1158: throw new IllegalArgumentException();
1159: }
1160: };
1161:
1162:
1163: return currentPutField;
1164: }
1165:
1166:
1167: public void writeFields() throws IOException
1168: {
1169: if (currentPutField == null)
1170: throw new NotActiveException("writeFields can only be called after putFields has been called");
1171:
1172: markFieldsWritten();
1173: currentPutField.write(this);
1174: }
1175:
1176:
1177:
1178:
1179: private void writeBlockDataHeader(int size) throws IOException
1180: {
1181: if (size < 256)
1182: {
1183: realOutput.writeByte(TC_BLOCKDATA);
1184: realOutput.write(size);
1185: }
1186: else
1187: {
1188: realOutput.writeByte(TC_BLOCKDATALONG);
1189: realOutput.writeInt(size);
1190: }
1191: }
1192:
1193:
1194:
1195:
1196: private int findHandle(Object obj)
1197: {
1198: return OIDLookupTable.get(obj);
1199: }
1200:
1201:
1202:
1203: private int assignNewHandle(Object obj)
1204: {
1205: OIDLookupTable.put(obj, nextOID);
1206: return nextOID++;
1207: }
1208:
1209:
1210:
1211: private void clearHandles()
1212: {
1213: nextOID = baseWireHandle;
1214: OIDLookupTable.clear();
1215: }
1216:
1217:
1218:
1219: private void writeArraySizeAndElements(Object array, Class clazz)
1220: throws IOException
1221: {
1222: int length = Array.getLength(array);
1223:
1224: if (clazz.isPrimitive())
1225: {
1226: if (clazz == Boolean.TYPE)
1227: {
1228: boolean[] cast_array = (boolean[])array;
1229: realOutput.writeInt (length);
1230: for (int i = 0; i < length; i++)
1231: realOutput.writeBoolean(cast_array[i]);
1232: return;
1233: }
1234: if (clazz == Byte.TYPE)
1235: {
1236: byte[] cast_array = (byte[])array;
1237: realOutput.writeInt(length);
1238: realOutput.write(cast_array, 0, length);
1239: return;
1240: }
1241: if (clazz == Character.TYPE)
1242: {
1243: char[] cast_array = (char[])array;
1244: realOutput.writeInt(length);
1245: for (int i = 0; i < length; i++)
1246: realOutput.writeChar(cast_array[i]);
1247: return;
1248: }
1249: if (clazz == Double.TYPE)
1250: {
1251: double[] cast_array = (double[])array;
1252: realOutput.writeInt(length);
1253: for (int i = 0; i < length; i++)
1254: realOutput.writeDouble(cast_array[i]);
1255: return;
1256: }
1257: if (clazz == Float.TYPE)
1258: {
1259: float[] cast_array = (float[])array;
1260: realOutput.writeInt(length);
1261: for (int i = 0; i < length; i++)
1262: realOutput.writeFloat(cast_array[i]);
1263: return;
1264: }
1265: if (clazz == Integer.TYPE)
1266: {
1267: int[] cast_array = (int[])array;
1268: realOutput.writeInt(length);
1269: for (int i = 0; i < length; i++)
1270: realOutput.writeInt(cast_array[i]);
1271: return;
1272: }
1273: if (clazz == Long.TYPE)
1274: {
1275: long[] cast_array = (long[])array;
1276: realOutput.writeInt (length);
1277: for (int i = 0; i < length; i++)
1278: realOutput.writeLong(cast_array[i]);
1279: return;
1280: }
1281: if (clazz == Short.TYPE)
1282: {
1283: short[] cast_array = (short[])array;
1284: realOutput.writeInt (length);
1285: for (int i = 0; i < length; i++)
1286: realOutput.writeShort(cast_array[i]);
1287: return;
1288: }
1289: }
1290: else
1291: {
1292: Object[] cast_array = (Object[])array;
1293: realOutput.writeInt(length);
1294: for (int i = 0; i < length; i++)
1295: writeObject(cast_array[i]);
1296: }
1297: }
1298:
1299:
1300:
1301:
1302:
1303:
1304:
1305: private void writeFields(Object obj, ObjectStreamClass osc)
1306: throws IOException
1307: {
1308: osc.ensureFieldsSet(osc.forClass());
1309:
1310:
1311: ObjectStreamField[] fields = osc.fields;
1312: boolean oldmode = setBlockDataMode(false);
1313:
1314: try
1315: {
1316: writeFields(obj,fields);
1317: }
1318: catch (IllegalArgumentException _)
1319: {
1320: InvalidClassException e = new InvalidClassException
1321: ("writing fields of class " + osc.forClass().getName());
1322: e.initCause(_);
1323: throw e;
1324: }
1325: catch (IOException e)
1326: {
1327: throw e;
1328: }
1329: catch (Exception _)
1330: {
1331: IOException e = new IOException("Unexpected exception " + _);
1332: e.initCause(_);
1333: throw(e);
1334: }
1335:
1336: setBlockDataMode(oldmode);
1337: }
1338:
1339:
1340:
1348: private void writeFields(Object obj, ObjectStreamField[] fields)
1349: throws
1350: IllegalArgumentException, IllegalAccessException, IOException
1351: {
1352: for (int i = 0; i < fields.length; i++)
1353: {
1354: ObjectStreamField osf = fields[i];
1355: Field field = osf.field;
1356:
1357: if (DEBUG && dump)
1358: dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());
1359:
1360: switch (osf.getTypeCode())
1361: {
1362: case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
1363: case 'B': realOutput.writeByte (field.getByte (obj)); break;
1364: case 'S': realOutput.writeShort (field.getShort (obj)); break;
1365: case 'C': realOutput.writeChar (field.getChar (obj)); break;
1366: case 'I': realOutput.writeInt (field.getInt (obj)); break;
1367: case 'F': realOutput.writeFloat (field.getFloat (obj)); break;
1368: case 'J': realOutput.writeLong (field.getLong (obj)); break;
1369: case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
1370: case 'L':
1371: case '[': writeObject (field.get (obj)); break;
1372: default:
1373: throw new IOException("Unexpected type code " + osf.getTypeCode());
1374: }
1375: }
1376: }
1377:
1378:
1379:
1380:
1381: boolean setBlockDataMode(boolean on) throws IOException
1382: {
1383: if (on == writeDataAsBlocks)
1384: return on;
1385:
1386: drain();
1387: boolean oldmode = writeDataAsBlocks;
1388: writeDataAsBlocks = on;
1389:
1390: if (on)
1391: dataOutput = blockDataOutput;
1392: else
1393: dataOutput = realOutput;
1394:
1395: return oldmode;
1396: }
1397:
1398:
1399: private void callWriteMethod(Object obj, ObjectStreamClass osc)
1400: throws IOException
1401: {
1402: currentPutField = null;
1403: try
1404: {
1405: Object args[] = {this};
1406: osc.writeObjectMethod.invoke(obj, args);
1407: }
1408: catch (InvocationTargetException x)
1409: {
1410:
1411: Throwable exception = x.getTargetException();
1412: if (exception instanceof RuntimeException)
1413: throw (RuntimeException) exception;
1414: if (exception instanceof IOException)
1415: throw (IOException) exception;
1416:
1417: IOException ioe
1418: = new IOException("Exception thrown from writeObject() on " +
1419: osc.forClass().getName() + ": " +
1420: exception.getClass().getName());
1421: ioe.initCause(exception);
1422: throw ioe;
1423: }
1424: catch (Exception x)
1425: {
1426: IOException ioe
1427: = new IOException("Failure invoking writeObject() on " +
1428: osc.forClass().getName() + ": " +
1429: x.getClass().getName());
1430: ioe.initCause(x);
1431: throw ioe;
1432: }
1433: }
1434:
1435: private void dumpElementln (String msg, Object obj)
1436: {
1437: try
1438: {
1439: for (int i = 0; i < depth; i++)
1440: System.out.print (" ");
1441: System.out.print (Thread.currentThread() + ": ");
1442: System.out.print (msg);
1443: if (java.lang.reflect.Proxy.isProxyClass(obj.getClass()))
1444: System.out.print (obj.getClass());
1445: else
1446: System.out.print (obj);
1447: }
1448: catch (Exception _)
1449: {
1450: }
1451: finally
1452: {
1453: System.out.println ();
1454: }
1455: }
1456:
1457: private void dumpElementln (String msg)
1458: {
1459: for (int i = 0; i < depth; i++)
1460: System.out.print (" ");
1461: System.out.print (Thread.currentThread() + ": ");
1462: System.out.println(msg);
1463: }
1464:
1465:
1466: private static final int BUFFER_SIZE = 1024;
1467:
1468: private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1469:
1470: private DataOutputStream dataOutput;
1471: private boolean writeDataAsBlocks;
1472: private DataOutputStream realOutput;
1473: private DataOutputStream blockDataOutput;
1474: private byte[] blockData;
1475: private int blockDataCount;
1476: private Object currentObject;
1477:
1478: ObjectStreamClass currentObjectStreamClass;
1479: private PutField currentPutField;
1480: private boolean fieldsAlreadyWritten;
1481: private boolean replacementEnabled;
1482: private boolean isSerializing;
1483: private int nextOID;
1484: private ObjectIdentityMap2Int OIDLookupTable;
1485: private int protocolVersion;
1486: private boolean useSubclassMethod;
1487: private SetAccessibleAction setAccessible = new SetAccessibleAction();
1488:
1489:
1490: private int depth = 0;
1491:
1492:
1493: private boolean dump = false;
1494:
1495: private static final boolean DEBUG = false;
1496:
1497:
1504: private static boolean overridesMethods(final Class<?> clazz)
1505: {
1506: if (clazz == ObjectOutputStream.class)
1507: return false;
1508:
1509: return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
1510: public Boolean run()
1511: {
1512: Method[] methods = clazz.getDeclaredMethods();
1513: for (int a = 0; a < methods.length; ++a)
1514: {
1515: String name = methods[a].getName();
1516: if (name.equals("writeUnshared"))
1517: {
1518: Class<?>[] paramTypes = methods[a].getParameterTypes();
1519: if (paramTypes.length == 1 &&
1520: paramTypes[0] == Object.class &&
1521: methods[a].getReturnType() == Void.class)
1522: return true;
1523: }
1524: else if (name.equals("putFields"))
1525: {
1526: if (methods[a].getParameterTypes().length == 0 &&
1527: methods[a].getReturnType() == PutField.class)
1528: return true;
1529: }
1530: }
1531: return false;
1532: }
1533: });
1534: }
1535:
1536: }