1:
38:
39:
40: package ;
41:
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53:
119: public class ObjectOutputStream extends OutputStream
120: implements ObjectOutput, ObjectStreamConstants
121: {
122:
133: public ObjectOutputStream (OutputStream out) throws IOException
134: {
135: realOutput = new DataOutputStream(out);
136: blockData = new byte[ BUFFER_SIZE ];
137: blockDataCount = 0;
138: blockDataOutput = new DataOutputStream(this);
139: setBlockDataMode(true);
140: replacementEnabled = false;
141: isSerializing = false;
142: nextOID = baseWireHandle;
143: OIDLookupTable = new Hashtable();
144: protocolVersion = defaultProtocolVersion;
145: useSubclassMethod = false;
146: writeStreamHeader();
147:
148: if (DEBUG)
149: {
150: String val = System.getProperty("gcj.dumpobjects");
151: if (val != null && !val.equals(""))
152: dump = true;
153: }
154: }
155:
156:
178: public final void writeObject(Object obj) throws IOException
179: {
180: if (useSubclassMethod)
181: {
182: if (dump)
183: dumpElementln ("WRITE OVERRIDE: " + obj);
184:
185: writeObjectOverride(obj);
186: return;
187: }
188:
189: if (dump)
190: dumpElementln ("WRITE: " + obj);
191:
192: depth += 2;
193:
194: boolean was_serializing = isSerializing;
195: boolean old_mode = setBlockDataMode(false);
196: try
197: {
198: isSerializing = true;
199: boolean replaceDone = false;
200: Object replacedObject = null;
201:
202: while (true)
203: {
204: if (obj == null)
205: {
206: realOutput.writeByte(TC_NULL);
207: break;
208: }
209:
210: Integer handle = findHandle(obj);
211: if (handle != null)
212: {
213: realOutput.writeByte(TC_REFERENCE);
214: realOutput.writeInt(handle.intValue());
215: break;
216: }
217:
218: if (obj instanceof Class)
219: {
220: Class cl = (Class)obj;
221: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
222: realOutput.writeByte(TC_CLASS);
223: if (!osc.isProxyClass)
224: {
225: writeObject (osc);
226: }
227: else
228: {
229: realOutput.writeByte(TC_PROXYCLASSDESC);
230: Class[] intfs = cl.getInterfaces();
231: realOutput.writeInt(intfs.length);
232: for (int i = 0; i < intfs.length; i++)
233: realOutput.writeUTF(intfs[i].getName());
234:
235: boolean oldmode = setBlockDataMode(true);
236: annotateProxyClass(cl);
237: setBlockDataMode(oldmode);
238: realOutput.writeByte(TC_ENDBLOCKDATA);
239:
240: writeObject(osc.getSuper());
241: }
242: assignNewHandle(obj);
243: break;
244: }
245:
246: if (obj instanceof ObjectStreamClass)
247: {
248: writeClassDescriptor((ObjectStreamClass) obj);
249: break;
250: }
251:
252: Class clazz = obj.getClass();
253: ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz);
254: if (osc == null)
255: throw new NotSerializableException(clazz.getName());
256:
257: if ((replacementEnabled || obj instanceof Serializable)
258: && ! replaceDone)
259: {
260: replacedObject = obj;
261:
262: if (obj instanceof Serializable)
263: {
264: try
265: {
266: Method m = osc.writeReplaceMethod;
267: if (m != null)
268: obj = m.invoke(obj, new Object[0]);
269: }
270: catch (IllegalAccessException ignore)
271: {
272: }
273: catch (InvocationTargetException ignore)
274: {
275: }
276: }
277:
278: if (replacementEnabled)
279: obj = replaceObject(obj);
280:
281: replaceDone = true;
282: continue;
283: }
284:
285: if (obj instanceof String)
286: {
287: realOutput.writeByte(TC_STRING);
288: assignNewHandle(obj);
289: realOutput.writeUTF((String)obj);
290: break;
291: }
292:
293: if (clazz.isArray ())
294: {
295: realOutput.writeByte(TC_ARRAY);
296: writeObject(osc);
297: assignNewHandle(obj);
298: writeArraySizeAndElements(obj, clazz.getComponentType());
299: break;
300: }
301:
302: realOutput.writeByte(TC_OBJECT);
303: writeObject(osc);
304:
305: if (replaceDone)
306: assignNewHandle(replacedObject);
307: else
308: assignNewHandle(obj);
309:
310: if (obj instanceof Externalizable)
311: {
312: if (protocolVersion == PROTOCOL_VERSION_2)
313: setBlockDataMode(true);
314:
315: ((Externalizable)obj).writeExternal(this);
316:
317: if (protocolVersion == PROTOCOL_VERSION_2)
318: {
319: setBlockDataMode(false);
320: realOutput.writeByte(TC_ENDBLOCKDATA);
321: }
322:
323: break;
324: }
325:
326: if (obj instanceof Serializable)
327: {
328: Object prevObject = this.currentObject;
329: ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
330: currentObject = obj;
331: ObjectStreamClass[] hierarchy =
332: ObjectStreamClass.getObjectStreamClasses(clazz);
333:
334: for (int i = 0; i < hierarchy.length; i++)
335: {
336: currentObjectStreamClass = hierarchy[i];
337:
338: fieldsAlreadyWritten = false;
339: if (currentObjectStreamClass.hasWriteMethod())
340: {
341: if (dump)
342: dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
343: setBlockDataMode(true);
344: callWriteMethod(obj, currentObjectStreamClass);
345: setBlockDataMode(false);
346: realOutput.writeByte(TC_ENDBLOCKDATA);
347: if (dump)
348: dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
349: }
350: else
351: {
352: if (dump)
353: dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
354: writeFields(obj, currentObjectStreamClass);
355: }
356: }
357:
358: this.currentObject = prevObject;
359: this.currentObjectStreamClass = prevObjectStreamClass;
360: currentPutField = null;
361: break;
362: }
363:
364: throw new NotSerializableException(clazz.getName()
365: + " in "
366: + obj.getClass());
367: }
368: }
369: catch (ObjectStreamException ose)
370: {
371:
372: throw ose;
373: }
374: catch (IOException e)
375: {
376: realOutput.writeByte(TC_EXCEPTION);
377: reset(true);
378:
379: setBlockDataMode(false);
380: try
381: {
382: if (DEBUG)
383: {
384: e.printStackTrace(System.out);
385: }
386: writeObject(e);
387: }
388: catch (IOException ioe)
389: {
390: StreamCorruptedException ex =
391: new StreamCorruptedException
392: (ioe + " thrown while exception was being written to stream.");
393: if (DEBUG)
394: {
395: ex.printStackTrace(System.out);
396: }
397: throw ex;
398: }
399:
400: reset (true);
401:
402: }
403: finally
404: {
405: isSerializing = was_serializing;
406: setBlockDataMode(old_mode);
407: depth -= 2;
408:
409: if (dump)
410: dumpElementln ("END: " + obj);
411: }
412: }
413:
414: protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
415: {
416: if (osc.isProxyClass)
417: {
418: realOutput.writeByte(TC_PROXYCLASSDESC);
419: Class[] intfs = osc.forClass().getInterfaces();
420: realOutput.writeInt(intfs.length);
421: for (int i = 0; i < intfs.length; i++)
422: realOutput.writeUTF(intfs[i].getName());
423:
424: assignNewHandle(osc);
425:
426: boolean oldmode = setBlockDataMode(true);
427: annotateProxyClass(osc.forClass());
428: setBlockDataMode(oldmode);
429: realOutput.writeByte(TC_ENDBLOCKDATA);
430: }
431: else
432: {
433: realOutput.writeByte(TC_CLASSDESC);
434: realOutput.writeUTF(osc.getName());
435: realOutput.writeLong(osc.getSerialVersionUID());
436: assignNewHandle(osc);
437:
438: int flags = osc.getFlags();
439:
440: if (protocolVersion == PROTOCOL_VERSION_2
441: && osc.isExternalizable())
442: flags |= SC_BLOCK_DATA;
443:
444: realOutput.writeByte(flags);
445:
446: ObjectStreamField[] fields = osc.fields;
447:
448: if (fields == ObjectStreamClass.INVALID_FIELDS)
449: throw new InvalidClassException
450: (osc.getName(), "serialPersistentFields is invalid");
451:
452: realOutput.writeShort(fields.length);
453:
454: ObjectStreamField field;
455: for (int i = 0; i < fields.length; i++)
456: {
457: field = fields[i];
458: realOutput.writeByte(field.getTypeCode ());
459: realOutput.writeUTF(field.getName ());
460:
461: if (! field.isPrimitive())
462: writeObject(field.getTypeString());
463: }
464:
465: boolean oldmode = setBlockDataMode(true);
466: annotateClass(osc.forClass());
467: setBlockDataMode(oldmode);
468: realOutput.writeByte(TC_ENDBLOCKDATA);
469: }
470:
471: if (osc.isSerializable() || osc.isExternalizable())
472: writeObject(osc.getSuper());
473: else
474: writeObject(null);
475: }
476:
477:
493: public void defaultWriteObject()
494: throws IOException, NotActiveException
495: {
496: markFieldsWritten();
497: writeFields(currentObject, currentObjectStreamClass);
498: }
499:
500:
501: private void markFieldsWritten() throws IOException
502: {
503: if (currentObject == null || currentObjectStreamClass == null)
504: throw new NotActiveException
505: ("defaultWriteObject called by non-active class and/or object");
506:
507: if (fieldsAlreadyWritten)
508: throw new IOException
509: ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
510:
511: fieldsAlreadyWritten = true;
512: }
513:
514:
526: public void reset() throws IOException
527: {
528: reset(false);
529: }
530:
531:
532: private void reset(boolean internal) throws IOException
533: {
534: if (!internal)
535: {
536: if (isSerializing)
537: throw new IOException("Reset called while serialization in progress");
538:
539: realOutput.writeByte(TC_RESET);
540: }
541:
542: clearHandles();
543: }
544:
545:
546:
571: public void useProtocolVersion(int version) throws IOException
572: {
573: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
574: throw new IllegalArgumentException("Invalid protocol version requested.");
575:
576: if (nextOID != baseWireHandle)
577: throw new IllegalStateException("Protocol version cannot be changed "
578: + "after serialization started.");
579:
580: protocolVersion = version;
581: }
582:
583:
594: protected void annotateClass(Class cl) throws IOException
595: {
596: }
597:
598: protected void annotateProxyClass(Class cl) throws IOException
599: {
600: }
601:
602:
616: protected Object replaceObject(Object obj) throws IOException
617: {
618: return obj;
619: }
620:
621:
622:
630: protected boolean enableReplaceObject(boolean enable)
631: throws SecurityException
632: {
633: if (enable)
634: {
635: SecurityManager sm = System.getSecurityManager();
636: if (sm != null)
637: sm.checkPermission(new SerializablePermission("enableSubstitution"));
638: }
639:
640: boolean old_val = replacementEnabled;
641: replacementEnabled = enable;
642: return old_val;
643: }
644:
645:
646:
653: protected void writeStreamHeader() throws IOException
654: {
655: realOutput.writeShort(STREAM_MAGIC);
656: realOutput.writeShort(STREAM_VERSION);
657: }
658:
659:
670: protected ObjectOutputStream() throws IOException, SecurityException
671: {
672: SecurityManager sec_man = System.getSecurityManager ();
673: if (sec_man != null)
674: sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
675: useSubclassMethod = true;
676: }
677:
678:
679:
691: protected void writeObjectOverride(Object obj) throws NotActiveException,
692: IOException
693: {
694: throw new NotActiveException
695: ("Subclass of ObjectOutputStream must implement writeObjectOverride");
696: }
697:
698:
699:
702: public void write (int data) throws IOException
703: {
704: if (writeDataAsBlocks)
705: {
706: if (blockDataCount == BUFFER_SIZE)
707: drain();
708:
709: blockData[ blockDataCount++ ] = (byte)data;
710: }
711: else
712: realOutput.write(data);
713: }
714:
715:
716:
719: public void write(byte[] b) throws IOException
720: {
721: write(b, 0, b.length);
722: }
723:
724:
725:
728: public void write(byte[] b, int off, int len) throws IOException
729: {
730: if (writeDataAsBlocks)
731: {
732: if (len < 0)
733: throw new IndexOutOfBoundsException();
734:
735: if (blockDataCount + len < BUFFER_SIZE)
736: {
737: System.arraycopy(b, off, blockData, blockDataCount, len);
738: blockDataCount += len;
739: }
740: else
741: {
742: drain();
743: writeBlockDataHeader(len);
744: realOutput.write(b, off, len);
745: }
746: }
747: else
748: realOutput.write(b, off, len);
749: }
750:
751:
752:
755: public void flush () throws IOException
756: {
757: drain();
758: realOutput.flush();
759: }
760:
761:
762:
769: protected void drain() throws IOException
770: {
771: if (blockDataCount == 0)
772: return;
773:
774: if (writeDataAsBlocks)
775: writeBlockDataHeader(blockDataCount);
776: realOutput.write(blockData, 0, blockDataCount);
777: blockDataCount = 0;
778: }
779:
780:
781:
784: public void close() throws IOException
785: {
786: flush();
787: realOutput.close();
788: }
789:
790:
791:
794: public void writeBoolean(boolean data) throws IOException
795: {
796: blockDataOutput.writeBoolean(data);
797: }
798:
799:
800:
803: public void writeByte(int data) throws IOException
804: {
805: blockDataOutput.writeByte(data);
806: }
807:
808:
809:
812: public void writeShort (int data) throws IOException
813: {
814: blockDataOutput.writeShort(data);
815: }
816:
817:
818:
821: public void writeChar(int data) throws IOException
822: {
823: blockDataOutput.writeChar(data);
824: }
825:
826:
827:
830: public void writeInt(int data) throws IOException
831: {
832: blockDataOutput.writeInt(data);
833: }
834:
835:
836:
839: public void writeLong(long data) throws IOException
840: {
841: blockDataOutput.writeLong(data);
842: }
843:
844:
845:
848: public void writeFloat(float data) throws IOException
849: {
850: blockDataOutput.writeFloat(data);
851: }
852:
853:
854:
857: public void writeDouble(double data) throws IOException
858: {
859: blockDataOutput.writeDouble(data);
860: }
861:
862:
863:
866: public void writeBytes(String data) throws IOException
867: {
868: blockDataOutput.writeBytes(data);
869: }
870:
871:
872:
875: public void writeChars(String data) throws IOException
876: {
877: dataOutput.writeChars(data);
878: }
879:
880:
881:
884: public void writeUTF(String data) throws IOException
885: {
886: dataOutput.writeUTF(data);
887: }
888:
889:
890:
896: public abstract static class PutField
897: {
898: public abstract void put (String name, boolean value);
899: public abstract void put (String name, byte value);
900: public abstract void put (String name, char value);
901: public abstract void put (String name, double value);
902: public abstract void put (String name, float value);
903: public abstract void put (String name, int value);
904: public abstract void put (String name, long value);
905: public abstract void put (String name, short value);
906: public abstract void put (String name, Object value);
907:
908:
911: public abstract void write (ObjectOutput out) throws IOException;
912: }
913:
914: public PutField putFields() throws IOException
915: {
916: if (currentPutField != null)
917: return currentPutField;
918:
919: currentPutField = new PutField()
920: {
921: private byte[] prim_field_data
922: = new byte[currentObjectStreamClass.primFieldSize];
923: private Object[] objs
924: = new Object[currentObjectStreamClass.objectFieldCount];
925:
926: private ObjectStreamField getField (String name)
927: {
928: ObjectStreamField field
929: = currentObjectStreamClass.getField(name);
930:
931: if (field == null)
932: throw new IllegalArgumentException("no such serializable field " + name);
933:
934: return field;
935: }
936:
937: public void put(String name, boolean value)
938: {
939: ObjectStreamField field = getField(name);
940:
941: checkType(field, 'Z');
942: prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
943: }
944:
945: public void put(String name, byte value)
946: {
947: ObjectStreamField field = getField(name);
948:
949: checkType(field, 'B');
950: prim_field_data[field.getOffset()] = value;
951: }
952:
953: public void put(String name, char value)
954: {
955: ObjectStreamField field = getField(name);
956:
957: checkType(field, 'C');
958: int off = field.getOffset();
959: prim_field_data[off++] = (byte)(value >>> 8);
960: prim_field_data[off] = (byte)value;
961: }
962:
963: public void put(String name, double value)
964: {
965: ObjectStreamField field = getField (name);
966:
967: checkType(field, 'D');
968: int off = field.getOffset();
969: long l_value = Double.doubleToLongBits (value);
970: prim_field_data[off++] = (byte)(l_value >>> 52);
971: prim_field_data[off++] = (byte)(l_value >>> 48);
972: prim_field_data[off++] = (byte)(l_value >>> 40);
973: prim_field_data[off++] = (byte)(l_value >>> 32);
974: prim_field_data[off++] = (byte)(l_value >>> 24);
975: prim_field_data[off++] = (byte)(l_value >>> 16);
976: prim_field_data[off++] = (byte)(l_value >>> 8);
977: prim_field_data[off] = (byte)l_value;
978: }
979:
980: public void put(String name, float value)
981: {
982: ObjectStreamField field = getField(name);
983:
984: checkType(field, 'F');
985: int off = field.getOffset();
986: int i_value = Float.floatToIntBits(value);
987: prim_field_data[off++] = (byte)(i_value >>> 24);
988: prim_field_data[off++] = (byte)(i_value >>> 16);
989: prim_field_data[off++] = (byte)(i_value >>> 8);
990: prim_field_data[off] = (byte)i_value;
991: }
992:
993: public void put(String name, int value)
994: {
995: ObjectStreamField field = getField(name);
996: checkType(field, 'I');
997: int off = field.getOffset();
998: prim_field_data[off++] = (byte)(value >>> 24);
999: prim_field_data[off++] = (byte)(value >>> 16);
1000: prim_field_data[off++] = (byte)(value >>> 8);
1001: prim_field_data[off] = (byte)value;
1002: }
1003:
1004: public void put(String name, long value)
1005: {
1006: ObjectStreamField field = getField(name);
1007: checkType(field, 'J');
1008: int off = field.getOffset();
1009: prim_field_data[off++] = (byte)(value >>> 52);
1010: prim_field_data[off++] = (byte)(value >>> 48);
1011: prim_field_data[off++] = (byte)(value >>> 40);
1012: prim_field_data[off++] = (byte)(value >>> 32);
1013: prim_field_data[off++] = (byte)(value >>> 24);
1014: prim_field_data[off++] = (byte)(value >>> 16);
1015: prim_field_data[off++] = (byte)(value >>> 8);
1016: prim_field_data[off] = (byte)value;
1017: }
1018:
1019: public void put(String name, short value)
1020: {
1021: ObjectStreamField field = getField(name);
1022: checkType(field, 'S');
1023: int off = field.getOffset();
1024: prim_field_data[off++] = (byte)(value >>> 8);
1025: prim_field_data[off] = (byte)value;
1026: }
1027:
1028: public void put(String name, Object value)
1029: {
1030: ObjectStreamField field = getField(name);
1031:
1032: if (value != null &&
1033: ! field.getType().isAssignableFrom(value.getClass ()))
1034: throw new IllegalArgumentException("Class " + value.getClass() +
1035: " cannot be cast to " + field.getType());
1036: objs[field.getOffset()] = value;
1037: }
1038:
1039: public void write(ObjectOutput out) throws IOException
1040: {
1041:
1042:
1043:
1044: boolean oldmode = setBlockDataMode(false);
1045: out.write(prim_field_data);
1046: for (int i = 0; i < objs.length; ++ i)
1047: out.writeObject(objs[i]);
1048: setBlockDataMode(oldmode);
1049: }
1050:
1051: private void checkType(ObjectStreamField field, char type)
1052: throws IllegalArgumentException
1053: {
1054: if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1055: != type)
1056: throw new IllegalArgumentException();
1057: }
1058: };
1059:
1060:
1061: return currentPutField;
1062: }
1063:
1064:
1065: public void writeFields() throws IOException
1066: {
1067: if (currentPutField == null)
1068: throw new NotActiveException("writeFields can only be called after putFields has been called");
1069:
1070: markFieldsWritten();
1071: currentPutField.write(this);
1072: }
1073:
1074:
1075:
1076:
1077: private void writeBlockDataHeader(int size) throws IOException
1078: {
1079: if (size < 256)
1080: {
1081: realOutput.writeByte(TC_BLOCKDATA);
1082: realOutput.write(size);
1083: }
1084: else
1085: {
1086: realOutput.writeByte(TC_BLOCKDATALONG);
1087: realOutput.writeInt(size);
1088: }
1089: }
1090:
1091:
1092:
1093:
1094: private Integer findHandle(Object obj)
1095: {
1096: return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
1097: }
1098:
1099:
1100:
1101: private int assignNewHandle(Object obj)
1102: {
1103: OIDLookupTable.put(new ObjectIdentityWrapper(obj),
1104: new Integer(nextOID));
1105: return nextOID++;
1106: }
1107:
1108:
1109:
1110: private void clearHandles()
1111: {
1112: nextOID = baseWireHandle;
1113: OIDLookupTable.clear();
1114: }
1115:
1116:
1117:
1118: private void writeArraySizeAndElements(Object array, Class clazz)
1119: throws IOException
1120: {
1121: int length = Array.getLength(array);
1122:
1123: if (clazz.isPrimitive())
1124: {
1125: if (clazz == Boolean.TYPE)
1126: {
1127: boolean[] cast_array = (boolean[])array;
1128: realOutput.writeInt (length);
1129: for (int i = 0; i < length; i++)
1130: realOutput.writeBoolean(cast_array[i]);
1131: return;
1132: }
1133: if (clazz == Byte.TYPE)
1134: {
1135: byte[] cast_array = (byte[])array;
1136: realOutput.writeInt(length);
1137: realOutput.write(cast_array, 0, length);
1138: return;
1139: }
1140: if (clazz == Character.TYPE)
1141: {
1142: char[] cast_array = (char[])array;
1143: realOutput.writeInt(length);
1144: for (int i = 0; i < length; i++)
1145: realOutput.writeChar(cast_array[i]);
1146: return;
1147: }
1148: if (clazz == Double.TYPE)
1149: {
1150: double[] cast_array = (double[])array;
1151: realOutput.writeInt(length);
1152: for (int i = 0; i < length; i++)
1153: realOutput.writeDouble(cast_array[i]);
1154: return;
1155: }
1156: if (clazz == Float.TYPE)
1157: {
1158: float[] cast_array = (float[])array;
1159: realOutput.writeInt(length);
1160: for (int i = 0; i < length; i++)
1161: realOutput.writeFloat(cast_array[i]);
1162: return;
1163: }
1164: if (clazz == Integer.TYPE)
1165: {
1166: int[] cast_array = (int[])array;
1167: realOutput.writeInt(length);
1168: for (int i = 0; i < length; i++)
1169: realOutput.writeInt(cast_array[i]);
1170: return;
1171: }
1172: if (clazz == Long.TYPE)
1173: {
1174: long[] cast_array = (long[])array;
1175: realOutput.writeInt (length);
1176: for (int i = 0; i < length; i++)
1177: realOutput.writeLong(cast_array[i]);
1178: return;
1179: }
1180: if (clazz == Short.TYPE)
1181: {
1182: short[] cast_array = (short[])array;
1183: realOutput.writeInt (length);
1184: for (int i = 0; i < length; i++)
1185: realOutput.writeShort(cast_array[i]);
1186: return;
1187: }
1188: }
1189: else
1190: {
1191: Object[] cast_array = (Object[])array;
1192: realOutput.writeInt(length);
1193: for (int i = 0; i < length; i++)
1194: writeObject(cast_array[i]);
1195: }
1196: }
1197:
1198:
1199:
1200:
1201: private void writeFields(Object obj, ObjectStreamClass osc)
1202: throws IOException
1203: {
1204: ObjectStreamField[] fields = osc.fields;
1205: boolean oldmode = setBlockDataMode(false);
1206: String field_name;
1207: Class type;
1208:
1209: for (int i = 0; i < fields.length; i++)
1210: {
1211: field_name = fields[i].getName();
1212: type = fields[i].getType();
1213:
1214: if (dump)
1215: dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
1216:
1217: if (type == Boolean.TYPE)
1218: realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
1219: else if (type == Byte.TYPE)
1220: realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
1221: else if (type == Character.TYPE)
1222: realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
1223: else if (type == Double.TYPE)
1224: realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
1225: else if (type == Float.TYPE)
1226: realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
1227: else if (type == Integer.TYPE)
1228: realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
1229: else if (type == Long.TYPE)
1230: realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
1231: else if (type == Short.TYPE)
1232: realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
1233: else
1234: writeObject(getObjectField(obj, osc.forClass(), field_name,
1235: fields[i].getTypeString ()));
1236: }
1237: setBlockDataMode(oldmode);
1238: }
1239:
1240:
1241:
1242:
1243: boolean setBlockDataMode(boolean on) throws IOException
1244: {
1245: if (on == writeDataAsBlocks)
1246: return on;
1247:
1248: drain();
1249: boolean oldmode = writeDataAsBlocks;
1250: writeDataAsBlocks = on;
1251:
1252: if (on)
1253: dataOutput = blockDataOutput;
1254: else
1255: dataOutput = realOutput;
1256:
1257: return oldmode;
1258: }
1259:
1260:
1261: private void callWriteMethod(Object obj, ObjectStreamClass osc)
1262: throws IOException
1263: {
1264: currentPutField = null;
1265: try
1266: {
1267: Object args[] = {this};
1268: osc.writeObjectMethod.invoke(obj, args);
1269: }
1270: catch (InvocationTargetException x)
1271: {
1272:
1273: Throwable exception = x.getTargetException();
1274: if (exception instanceof RuntimeException)
1275: throw (RuntimeException) exception;
1276: if (exception instanceof IOException)
1277: throw (IOException) exception;
1278:
1279: IOException ioe
1280: = new IOException("Exception thrown from writeObject() on " +
1281: osc.forClass().getName() + ": " +
1282: exception.getClass().getName());
1283: ioe.initCause(exception);
1284: throw ioe;
1285: }
1286: catch (Exception x)
1287: {
1288: IOException ioe
1289: = new IOException("Failure invoking writeObject() on " +
1290: osc.forClass().getName() + ": " +
1291: x.getClass().getName());
1292: ioe.initCause(x);
1293: throw ioe;
1294: }
1295: }
1296:
1297: private boolean getBooleanField(Object obj, Class klass, String field_name)
1298: throws IOException
1299: {
1300: try
1301: {
1302: Field f = getField(klass, field_name);
1303: boolean b = f.getBoolean(obj);
1304: return b;
1305: }
1306: catch (IllegalArgumentException _)
1307: {
1308: throw new InvalidClassException
1309: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1310: }
1311: catch (IOException e)
1312: {
1313: throw e;
1314: }
1315: catch (Exception _)
1316: {
1317: throw new IOException("Unexpected exception " + _);
1318: }
1319: }
1320:
1321: private byte getByteField (Object obj, Class klass, String field_name)
1322: throws IOException
1323: {
1324: try
1325: {
1326: Field f = getField (klass, field_name);
1327: byte b = f.getByte (obj);
1328: return b;
1329: }
1330: catch (IllegalArgumentException _)
1331: {
1332: throw new InvalidClassException
1333: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1334: }
1335: catch (IOException e)
1336: {
1337: throw e;
1338: }
1339: catch (Exception _)
1340: {
1341: throw new IOException("Unexpected exception " + _);
1342: }
1343: }
1344:
1345: private char getCharField (Object obj, Class klass, String field_name)
1346: throws IOException
1347: {
1348: try
1349: {
1350: Field f = getField (klass, field_name);
1351: char b = f.getChar (obj);
1352: return b;
1353: }
1354: catch (IllegalArgumentException _)
1355: {
1356: throw new InvalidClassException
1357: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1358: }
1359: catch (IOException e)
1360: {
1361: throw e;
1362: }
1363: catch (Exception _)
1364: {
1365: throw new IOException("Unexpected exception " + _);
1366: }
1367: }
1368:
1369: private double getDoubleField (Object obj, Class klass, String field_name)
1370: throws IOException
1371: {
1372: try
1373: {
1374: Field f = getField (klass, field_name);
1375: double b = f.getDouble (obj);
1376: return b;
1377: }
1378: catch (IllegalArgumentException _)
1379: {
1380: throw new InvalidClassException
1381: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1382: }
1383: catch (IOException e)
1384: {
1385: throw e;
1386: }
1387: catch (Exception _)
1388: {
1389: throw new IOException("Unexpected exception " + _);
1390: }
1391: }
1392:
1393: private float getFloatField (Object obj, Class klass, String field_name)
1394: throws IOException
1395: {
1396: try
1397: {
1398: Field f = getField (klass, field_name);
1399: float b = f.getFloat (obj);
1400: return b;
1401: }
1402: catch (IllegalArgumentException _)
1403: {
1404: throw new InvalidClassException
1405: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1406: }
1407: catch (IOException e)
1408: {
1409: throw e;
1410: }
1411: catch (Exception _)
1412: {
1413: throw new IOException("Unexpected exception " + _);
1414: }
1415: }
1416:
1417: private int getIntField (Object obj, Class klass, String field_name)
1418: throws IOException
1419: {
1420: try
1421: {
1422: Field f = getField (klass, field_name);
1423: int b = f.getInt (obj);
1424: return b;
1425: }
1426: catch (IllegalArgumentException _)
1427: {
1428: throw new InvalidClassException
1429: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1430: }
1431: catch (IOException e)
1432: {
1433: throw e;
1434: }
1435: catch (Exception _)
1436: {
1437: throw new IOException("Unexpected exception " + _);
1438: }
1439: }
1440:
1441: private long getLongField (Object obj, Class klass, String field_name)
1442: throws IOException
1443: {
1444: try
1445: {
1446: Field f = getField (klass, field_name);
1447: long b = f.getLong (obj);
1448: return b;
1449: }
1450: catch (IllegalArgumentException _)
1451: {
1452: throw new InvalidClassException
1453: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1454: }
1455: catch (IOException e)
1456: {
1457: throw e;
1458: }
1459: catch (Exception _)
1460: {
1461: throw new IOException("Unexpected exception " + _);
1462: }
1463: }
1464:
1465: private short getShortField (Object obj, Class klass, String field_name)
1466: throws IOException
1467: {
1468: try
1469: {
1470: Field f = getField (klass, field_name);
1471: short b = f.getShort (obj);
1472: return b;
1473: }
1474: catch (IllegalArgumentException _)
1475: {
1476: throw new InvalidClassException
1477: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1478: }
1479: catch (IOException e)
1480: {
1481: throw e;
1482: }
1483: catch (Exception _)
1484: {
1485: throw new IOException("Unexpected exception " + _);
1486: }
1487: }
1488:
1489: private Object getObjectField (Object obj, Class klass, String field_name,
1490: String type_code) throws IOException
1491: {
1492: try
1493: {
1494: Field f = getField (klass, field_name);
1495: ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
1496:
1497:
1500: if (of.isPrimitive())
1501: throw new InvalidClassException
1502: ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
1503:
1504: if (!of.getTypeString().equals(type_code))
1505: throw new InvalidClassException
1506: ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
1507:
1508: Object o = f.get (obj);
1509:
1510: return o;
1511: }
1512: catch (IOException e)
1513: {
1514: throw e;
1515: }
1516: catch (Exception e)
1517: {
1518: throw new IOException ();
1519: }
1520: }
1521:
1522: private Field getField (Class klass, String name)
1523: throws java.io.InvalidClassException
1524: {
1525: try
1526: {
1527: final Field f = klass.getDeclaredField(name);
1528: setAccessible.setMember(f);
1529: AccessController.doPrivileged(setAccessible);
1530: return f;
1531: }
1532: catch (java.lang.NoSuchFieldException e)
1533: {
1534: throw new InvalidClassException
1535: ("no field called " + name + " in class " + klass.getName());
1536: }
1537: }
1538:
1539: private void dumpElementln (String msg)
1540: {
1541: for (int i = 0; i < depth; i++)
1542: System.out.print (" ");
1543: System.out.print (Thread.currentThread() + ": ");
1544: System.out.println(msg);
1545: }
1546:
1547:
1548: private static final int BUFFER_SIZE = 1024;
1549:
1550: private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1551:
1552: private DataOutputStream dataOutput;
1553: private boolean writeDataAsBlocks;
1554: private DataOutputStream realOutput;
1555: private DataOutputStream blockDataOutput;
1556: private byte[] blockData;
1557: private int blockDataCount;
1558: private Object currentObject;
1559:
1560: ObjectStreamClass currentObjectStreamClass;
1561: private PutField currentPutField;
1562: private boolean fieldsAlreadyWritten;
1563: private boolean replacementEnabled;
1564: private boolean isSerializing;
1565: private int nextOID;
1566: private Hashtable OIDLookupTable;
1567: private int protocolVersion;
1568: private boolean useSubclassMethod;
1569: private SetAccessibleAction setAccessible = new SetAccessibleAction();
1570:
1571:
1572: private int depth = 0;
1573:
1574:
1575: private boolean dump = false;
1576:
1577: private static final boolean DEBUG = false;
1578: }