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: boolean oldmode = setBlockDataMode(true);
425: annotateProxyClass(osc.forClass());
426: setBlockDataMode(oldmode);
427: realOutput.writeByte(TC_ENDBLOCKDATA);
428: }
429: else
430: {
431: realOutput.writeByte(TC_CLASSDESC);
432: realOutput.writeUTF(osc.getName());
433: realOutput.writeLong(osc.getSerialVersionUID());
434: assignNewHandle(osc);
435:
436: int flags = osc.getFlags();
437:
438: if (protocolVersion == PROTOCOL_VERSION_2
439: && osc.isExternalizable())
440: flags |= SC_BLOCK_DATA;
441:
442: realOutput.writeByte(flags);
443:
444: ObjectStreamField[] fields = osc.fields;
445: realOutput.writeShort(fields.length);
446:
447: ObjectStreamField field;
448: for (int i = 0; i < fields.length; i++)
449: {
450: field = fields[i];
451: realOutput.writeByte(field.getTypeCode ());
452: realOutput.writeUTF(field.getName ());
453:
454: if (! field.isPrimitive())
455: writeObject(field.getTypeString());
456: }
457:
458: boolean oldmode = setBlockDataMode(true);
459: annotateClass(osc.forClass());
460: setBlockDataMode(oldmode);
461: realOutput.writeByte(TC_ENDBLOCKDATA);
462: }
463:
464: if (osc.isSerializable() || osc.isExternalizable())
465: writeObject(osc.getSuper());
466: else
467: writeObject(null);
468: }
469:
470:
486: public void defaultWriteObject()
487: throws IOException, NotActiveException
488: {
489: markFieldsWritten();
490: writeFields(currentObject, currentObjectStreamClass);
491: }
492:
493:
494: private void markFieldsWritten() throws IOException
495: {
496: if (currentObject == null || currentObjectStreamClass == null)
497: throw new NotActiveException
498: ("defaultWriteObject called by non-active class and/or object");
499:
500: if (fieldsAlreadyWritten)
501: throw new IOException
502: ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
503:
504: fieldsAlreadyWritten = true;
505: }
506:
507:
519: public void reset() throws IOException
520: {
521: reset(false);
522: }
523:
524:
525: private void reset(boolean internal) throws IOException
526: {
527: if (!internal)
528: {
529: if (isSerializing)
530: throw new IOException("Reset called while serialization in progress");
531:
532: realOutput.writeByte(TC_RESET);
533: }
534:
535: clearHandles();
536: }
537:
538:
539:
559: public void useProtocolVersion(int version) throws IOException
560: {
561: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
562: throw new IOException("Invalid protocol version requested.");
563:
564: protocolVersion = version;
565: }
566:
567:
568:
582: public static void setDefaultProtocolVersion(int version)
583: throws IOException
584: {
585: if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
586: throw new IOException("Invalid protocol version requested.");
587:
588: defaultProtocolVersion = version;
589: }
590:
591:
592:
603: protected void annotateClass(Class cl) throws IOException
604: {
605: }
606:
607: protected void annotateProxyClass(Class cl) throws IOException
608: {
609: }
610:
611:
625: protected Object replaceObject(Object obj) throws IOException
626: {
627: return obj;
628: }
629:
630:
631:
639: protected boolean enableReplaceObject(boolean enable)
640: throws SecurityException
641: {
642: if (enable)
643: {
644: SecurityManager sm = System.getSecurityManager();
645: if (sm != null)
646: sm.checkPermission(new SerializablePermission("enableSubstitution"));
647: }
648:
649: boolean old_val = replacementEnabled;
650: replacementEnabled = enable;
651: return old_val;
652: }
653:
654:
655:
662: protected void writeStreamHeader() throws IOException
663: {
664: realOutput.writeShort(STREAM_MAGIC);
665: realOutput.writeShort(STREAM_VERSION);
666: }
667:
668:
679: protected ObjectOutputStream() throws IOException, SecurityException
680: {
681: SecurityManager sec_man = System.getSecurityManager ();
682: if (sec_man != null)
683: sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
684: useSubclassMethod = true;
685: }
686:
687:
688:
700: protected void writeObjectOverride(Object obj) throws NotActiveException,
701: IOException
702: {
703: throw new NotActiveException
704: ("Subclass of ObjectOutputStream must implement writeObjectOverride");
705: }
706:
707:
708:
711: public void write (int data) throws IOException
712: {
713: if (writeDataAsBlocks)
714: {
715: if (blockDataCount == BUFFER_SIZE)
716: drain();
717:
718: blockData[ blockDataCount++ ] = (byte)data;
719: }
720: else
721: realOutput.write(data);
722: }
723:
724:
725:
728: public void write(byte[] b) throws IOException
729: {
730: write(b, 0, b.length);
731: }
732:
733:
734:
737: public void write(byte[] b, int off, int len) throws IOException
738: {
739: if (writeDataAsBlocks)
740: {
741: if (len < 0)
742: throw new IndexOutOfBoundsException();
743:
744: if (blockDataCount + len < BUFFER_SIZE)
745: {
746: System.arraycopy(b, off, blockData, blockDataCount, len);
747: blockDataCount += len;
748: }
749: else
750: {
751: drain();
752: writeBlockDataHeader(len);
753: realOutput.write(b, off, len);
754: }
755: }
756: else
757: realOutput.write(b, off, len);
758: }
759:
760:
761:
764: public void flush () throws IOException
765: {
766: drain();
767: realOutput.flush();
768: }
769:
770:
771:
778: protected void drain() throws IOException
779: {
780: if (blockDataCount == 0)
781: return;
782:
783: if (writeDataAsBlocks)
784: writeBlockDataHeader(blockDataCount);
785: realOutput.write(blockData, 0, blockDataCount);
786: blockDataCount = 0;
787: }
788:
789:
790:
793: public void close() throws IOException
794: {
795: flush();
796: realOutput.close();
797: }
798:
799:
800:
803: public void writeBoolean(boolean data) throws IOException
804: {
805: blockDataOutput.writeBoolean(data);
806: }
807:
808:
809:
812: public void writeByte(int data) throws IOException
813: {
814: blockDataOutput.writeByte(data);
815: }
816:
817:
818:
821: public void writeShort (int data) throws IOException
822: {
823: blockDataOutput.writeShort(data);
824: }
825:
826:
827:
830: public void writeChar(int data) throws IOException
831: {
832: blockDataOutput.writeChar(data);
833: }
834:
835:
836:
839: public void writeInt(int data) throws IOException
840: {
841: blockDataOutput.writeInt(data);
842: }
843:
844:
845:
848: public void writeLong(long data) throws IOException
849: {
850: blockDataOutput.writeLong(data);
851: }
852:
853:
854:
857: public void writeFloat(float data) throws IOException
858: {
859: blockDataOutput.writeFloat(data);
860: }
861:
862:
863:
866: public void writeDouble(double data) throws IOException
867: {
868: blockDataOutput.writeDouble(data);
869: }
870:
871:
872:
875: public void writeBytes(String data) throws IOException
876: {
877: blockDataOutput.writeBytes(data);
878: }
879:
880:
881:
884: public void writeChars(String data) throws IOException
885: {
886: dataOutput.writeChars(data);
887: }
888:
889:
890:
893: public void writeUTF(String data) throws IOException
894: {
895: dataOutput.writeUTF(data);
896: }
897:
898:
899:
905: public abstract static class PutField
906: {
907: public abstract void put (String name, boolean value);
908: public abstract void put (String name, byte value);
909: public abstract void put (String name, char value);
910: public abstract void put (String name, double value);
911: public abstract void put (String name, float value);
912: public abstract void put (String name, int value);
913: public abstract void put (String name, long value);
914: public abstract void put (String name, short value);
915: public abstract void put (String name, Object value);
916:
917:
920: public abstract void write (ObjectOutput out) throws IOException;
921: }
922:
923: public PutField putFields() throws IOException
924: {
925: if (currentPutField != null)
926: return currentPutField;
927:
928: currentPutField = new PutField()
929: {
930: private byte[] prim_field_data
931: = new byte[currentObjectStreamClass.primFieldSize];
932: private Object[] objs
933: = new Object[currentObjectStreamClass.objectFieldCount];
934:
935: private ObjectStreamField getField (String name)
936: {
937: ObjectStreamField field
938: = currentObjectStreamClass.getField(name);
939:
940: if (field == null)
941: throw new IllegalArgumentException("no such serializable field " + name);
942:
943: return field;
944: }
945:
946: public void put(String name, boolean value)
947: {
948: ObjectStreamField field = getField(name);
949:
950: checkType(field, 'Z');
951: prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
952: }
953:
954: public void put(String name, byte value)
955: {
956: ObjectStreamField field = getField(name);
957:
958: checkType(field, 'B');
959: prim_field_data[field.getOffset()] = value;
960: }
961:
962: public void put(String name, char value)
963: {
964: ObjectStreamField field = getField(name);
965:
966: checkType(field, 'C');
967: int off = field.getOffset();
968: prim_field_data[off++] = (byte)(value >>> 8);
969: prim_field_data[off] = (byte)value;
970: }
971:
972: public void put(String name, double value)
973: {
974: ObjectStreamField field = getField (name);
975:
976: checkType(field, 'D');
977: int off = field.getOffset();
978: long l_value = Double.doubleToLongBits (value);
979: prim_field_data[off++] = (byte)(l_value >>> 52);
980: prim_field_data[off++] = (byte)(l_value >>> 48);
981: prim_field_data[off++] = (byte)(l_value >>> 40);
982: prim_field_data[off++] = (byte)(l_value >>> 32);
983: prim_field_data[off++] = (byte)(l_value >>> 24);
984: prim_field_data[off++] = (byte)(l_value >>> 16);
985: prim_field_data[off++] = (byte)(l_value >>> 8);
986: prim_field_data[off] = (byte)l_value;
987: }
988:
989: public void put(String name, float value)
990: {
991: ObjectStreamField field = getField(name);
992:
993: checkType(field, 'F');
994: int off = field.getOffset();
995: int i_value = Float.floatToIntBits(value);
996: prim_field_data[off++] = (byte)(i_value >>> 24);
997: prim_field_data[off++] = (byte)(i_value >>> 16);
998: prim_field_data[off++] = (byte)(i_value >>> 8);
999: prim_field_data[off] = (byte)i_value;
1000: }
1001:
1002: public void put(String name, int value)
1003: {
1004: ObjectStreamField field = getField(name);
1005: checkType(field, 'I');
1006: int off = field.getOffset();
1007: prim_field_data[off++] = (byte)(value >>> 24);
1008: prim_field_data[off++] = (byte)(value >>> 16);
1009: prim_field_data[off++] = (byte)(value >>> 8);
1010: prim_field_data[off] = (byte)value;
1011: }
1012:
1013: public void put(String name, long value)
1014: {
1015: ObjectStreamField field = getField(name);
1016: checkType(field, 'J');
1017: int off = field.getOffset();
1018: prim_field_data[off++] = (byte)(value >>> 52);
1019: prim_field_data[off++] = (byte)(value >>> 48);
1020: prim_field_data[off++] = (byte)(value >>> 40);
1021: prim_field_data[off++] = (byte)(value >>> 32);
1022: prim_field_data[off++] = (byte)(value >>> 24);
1023: prim_field_data[off++] = (byte)(value >>> 16);
1024: prim_field_data[off++] = (byte)(value >>> 8);
1025: prim_field_data[off] = (byte)value;
1026: }
1027:
1028: public void put(String name, short value)
1029: {
1030: ObjectStreamField field = getField(name);
1031: checkType(field, 'S');
1032: int off = field.getOffset();
1033: prim_field_data[off++] = (byte)(value >>> 8);
1034: prim_field_data[off] = (byte)value;
1035: }
1036:
1037: public void put(String name, Object value)
1038: {
1039: ObjectStreamField field = getField(name);
1040:
1041: if (value != null &&
1042: ! field.getType().isAssignableFrom(value.getClass ()))
1043: throw new IllegalArgumentException("Class " + value.getClass() +
1044: " cannot be cast to " + field.getType());
1045: objs[field.getOffset()] = value;
1046: }
1047:
1048: public void write(ObjectOutput out) throws IOException
1049: {
1050:
1051:
1052:
1053: boolean oldmode = setBlockDataMode(false);
1054: out.write(prim_field_data);
1055: for (int i = 0; i < objs.length; ++ i)
1056: out.writeObject(objs[i]);
1057: setBlockDataMode(oldmode);
1058: }
1059:
1060: private void checkType(ObjectStreamField field, char type)
1061: throws IllegalArgumentException
1062: {
1063: if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1064: != type)
1065: throw new IllegalArgumentException();
1066: }
1067: };
1068:
1069:
1070: return currentPutField;
1071: }
1072:
1073:
1074: public void writeFields() throws IOException
1075: {
1076: if (currentPutField == null)
1077: throw new NotActiveException("writeFields can only be called after putFields has been called");
1078:
1079: markFieldsWritten();
1080: currentPutField.write(this);
1081: }
1082:
1083:
1084:
1085:
1086: private void writeBlockDataHeader(int size) throws IOException
1087: {
1088: if (size < 256)
1089: {
1090: realOutput.writeByte(TC_BLOCKDATA);
1091: realOutput.write(size);
1092: }
1093: else
1094: {
1095: realOutput.writeByte(TC_BLOCKDATALONG);
1096: realOutput.writeInt(size);
1097: }
1098: }
1099:
1100:
1101:
1102:
1103: private Integer findHandle(Object obj)
1104: {
1105: return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
1106: }
1107:
1108:
1109:
1110: private int assignNewHandle(Object obj)
1111: {
1112: OIDLookupTable.put(new ObjectIdentityWrapper(obj),
1113: new Integer(nextOID));
1114: return nextOID++;
1115: }
1116:
1117:
1118:
1119: private void clearHandles()
1120: {
1121: nextOID = baseWireHandle;
1122: OIDLookupTable.clear();
1123: }
1124:
1125:
1126:
1127: private void writeArraySizeAndElements(Object array, Class clazz)
1128: throws IOException
1129: {
1130: int length = Array.getLength(array);
1131:
1132: if (clazz.isPrimitive())
1133: {
1134: if (clazz == Boolean.TYPE)
1135: {
1136: boolean[] cast_array = (boolean[])array;
1137: realOutput.writeInt (length);
1138: for (int i = 0; i < length; i++)
1139: realOutput.writeBoolean(cast_array[i]);
1140: return;
1141: }
1142: if (clazz == Byte.TYPE)
1143: {
1144: byte[] cast_array = (byte[])array;
1145: realOutput.writeInt(length);
1146: realOutput.write(cast_array, 0, length);
1147: return;
1148: }
1149: if (clazz == Character.TYPE)
1150: {
1151: char[] cast_array = (char[])array;
1152: realOutput.writeInt(length);
1153: for (int i = 0; i < length; i++)
1154: realOutput.writeChar(cast_array[i]);
1155: return;
1156: }
1157: if (clazz == Double.TYPE)
1158: {
1159: double[] cast_array = (double[])array;
1160: realOutput.writeInt(length);
1161: for (int i = 0; i < length; i++)
1162: realOutput.writeDouble(cast_array[i]);
1163: return;
1164: }
1165: if (clazz == Float.TYPE)
1166: {
1167: float[] cast_array = (float[])array;
1168: realOutput.writeInt(length);
1169: for (int i = 0; i < length; i++)
1170: realOutput.writeFloat(cast_array[i]);
1171: return;
1172: }
1173: if (clazz == Integer.TYPE)
1174: {
1175: int[] cast_array = (int[])array;
1176: realOutput.writeInt(length);
1177: for (int i = 0; i < length; i++)
1178: realOutput.writeInt(cast_array[i]);
1179: return;
1180: }
1181: if (clazz == Long.TYPE)
1182: {
1183: long[] cast_array = (long[])array;
1184: realOutput.writeInt (length);
1185: for (int i = 0; i < length; i++)
1186: realOutput.writeLong(cast_array[i]);
1187: return;
1188: }
1189: if (clazz == Short.TYPE)
1190: {
1191: short[] cast_array = (short[])array;
1192: realOutput.writeInt (length);
1193: for (int i = 0; i < length; i++)
1194: realOutput.writeShort(cast_array[i]);
1195: return;
1196: }
1197: }
1198: else
1199: {
1200: Object[] cast_array = (Object[])array;
1201: realOutput.writeInt(length);
1202: for (int i = 0; i < length; i++)
1203: writeObject(cast_array[i]);
1204: }
1205: }
1206:
1207:
1208:
1209:
1210: private void writeFields(Object obj, ObjectStreamClass osc)
1211: throws IOException
1212: {
1213: ObjectStreamField[] fields = osc.fields;
1214: boolean oldmode = setBlockDataMode(false);
1215: String field_name;
1216: Class type;
1217:
1218: for (int i = 0; i < fields.length; i++)
1219: {
1220: field_name = fields[i].getName();
1221: type = fields[i].getType();
1222:
1223: if (dump)
1224: dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
1225:
1226: if (type == Boolean.TYPE)
1227: realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
1228: else if (type == Byte.TYPE)
1229: realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
1230: else if (type == Character.TYPE)
1231: realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
1232: else if (type == Double.TYPE)
1233: realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
1234: else if (type == Float.TYPE)
1235: realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
1236: else if (type == Integer.TYPE)
1237: realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
1238: else if (type == Long.TYPE)
1239: realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
1240: else if (type == Short.TYPE)
1241: realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
1242: else
1243: writeObject(getObjectField(obj, osc.forClass(), field_name,
1244: fields[i].getTypeString ()));
1245: }
1246: setBlockDataMode(oldmode);
1247: }
1248:
1249:
1250:
1251:
1252: boolean setBlockDataMode(boolean on) throws IOException
1253: {
1254: if (on == writeDataAsBlocks)
1255: return on;
1256:
1257: drain();
1258: boolean oldmode = writeDataAsBlocks;
1259: writeDataAsBlocks = on;
1260:
1261: if (on)
1262: dataOutput = blockDataOutput;
1263: else
1264: dataOutput = realOutput;
1265:
1266: return oldmode;
1267: }
1268:
1269:
1270: private void callWriteMethod(Object obj, ObjectStreamClass osc)
1271: throws IOException
1272: {
1273: currentPutField = null;
1274: try
1275: {
1276: Object args[] = {this};
1277: osc.writeObjectMethod.invoke(obj, args);
1278: }
1279: catch (InvocationTargetException x)
1280: {
1281:
1282: Throwable exception = x.getTargetException();
1283: if (exception instanceof RuntimeException)
1284: throw (RuntimeException) exception;
1285: if (exception instanceof IOException)
1286: throw (IOException) exception;
1287:
1288: IOException ioe
1289: = new IOException("Exception thrown from writeObject() on " +
1290: osc.forClass().getName() + ": " +
1291: exception.getClass().getName());
1292: ioe.initCause(exception);
1293: throw ioe;
1294: }
1295: catch (Exception x)
1296: {
1297: IOException ioe
1298: = new IOException("Failure invoking writeObject() on " +
1299: osc.forClass().getName() + ": " +
1300: x.getClass().getName());
1301: ioe.initCause(x);
1302: throw ioe;
1303: }
1304: }
1305:
1306: private boolean getBooleanField(Object obj, Class klass, String field_name)
1307: throws IOException
1308: {
1309: try
1310: {
1311: Field f = getField(klass, field_name);
1312: boolean b = f.getBoolean(obj);
1313: return b;
1314: }
1315: catch (IllegalArgumentException _)
1316: {
1317: throw new InvalidClassException
1318: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1319: }
1320: catch (IOException e)
1321: {
1322: throw e;
1323: }
1324: catch (Exception _)
1325: {
1326: throw new IOException("Unexpected exception " + _);
1327: }
1328: }
1329:
1330: private byte getByteField (Object obj, Class klass, String field_name)
1331: throws IOException
1332: {
1333: try
1334: {
1335: Field f = getField (klass, field_name);
1336: byte b = f.getByte (obj);
1337: return b;
1338: }
1339: catch (IllegalArgumentException _)
1340: {
1341: throw new InvalidClassException
1342: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1343: }
1344: catch (IOException e)
1345: {
1346: throw e;
1347: }
1348: catch (Exception _)
1349: {
1350: throw new IOException("Unexpected exception " + _);
1351: }
1352: }
1353:
1354: private char getCharField (Object obj, Class klass, String field_name)
1355: throws IOException
1356: {
1357: try
1358: {
1359: Field f = getField (klass, field_name);
1360: char b = f.getChar (obj);
1361: return b;
1362: }
1363: catch (IllegalArgumentException _)
1364: {
1365: throw new InvalidClassException
1366: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1367: }
1368: catch (IOException e)
1369: {
1370: throw e;
1371: }
1372: catch (Exception _)
1373: {
1374: throw new IOException("Unexpected exception " + _);
1375: }
1376: }
1377:
1378: private double getDoubleField (Object obj, Class klass, String field_name)
1379: throws IOException
1380: {
1381: try
1382: {
1383: Field f = getField (klass, field_name);
1384: double b = f.getDouble (obj);
1385: return b;
1386: }
1387: catch (IllegalArgumentException _)
1388: {
1389: throw new InvalidClassException
1390: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1391: }
1392: catch (IOException e)
1393: {
1394: throw e;
1395: }
1396: catch (Exception _)
1397: {
1398: throw new IOException("Unexpected exception " + _);
1399: }
1400: }
1401:
1402: private float getFloatField (Object obj, Class klass, String field_name)
1403: throws IOException
1404: {
1405: try
1406: {
1407: Field f = getField (klass, field_name);
1408: float b = f.getFloat (obj);
1409: return b;
1410: }
1411: catch (IllegalArgumentException _)
1412: {
1413: throw new InvalidClassException
1414: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1415: }
1416: catch (IOException e)
1417: {
1418: throw e;
1419: }
1420: catch (Exception _)
1421: {
1422: throw new IOException("Unexpected exception " + _);
1423: }
1424: }
1425:
1426: private int getIntField (Object obj, Class klass, String field_name)
1427: throws IOException
1428: {
1429: try
1430: {
1431: Field f = getField (klass, field_name);
1432: int b = f.getInt (obj);
1433: return b;
1434: }
1435: catch (IllegalArgumentException _)
1436: {
1437: throw new InvalidClassException
1438: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1439: }
1440: catch (IOException e)
1441: {
1442: throw e;
1443: }
1444: catch (Exception _)
1445: {
1446: throw new IOException("Unexpected exception " + _);
1447: }
1448: }
1449:
1450: private long getLongField (Object obj, Class klass, String field_name)
1451: throws IOException
1452: {
1453: try
1454: {
1455: Field f = getField (klass, field_name);
1456: long b = f.getLong (obj);
1457: return b;
1458: }
1459: catch (IllegalArgumentException _)
1460: {
1461: throw new InvalidClassException
1462: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1463: }
1464: catch (IOException e)
1465: {
1466: throw e;
1467: }
1468: catch (Exception _)
1469: {
1470: throw new IOException("Unexpected exception " + _);
1471: }
1472: }
1473:
1474: private short getShortField (Object obj, Class klass, String field_name)
1475: throws IOException
1476: {
1477: try
1478: {
1479: Field f = getField (klass, field_name);
1480: short b = f.getShort (obj);
1481: return b;
1482: }
1483: catch (IllegalArgumentException _)
1484: {
1485: throw new InvalidClassException
1486: ("invalid requested type for field " + field_name + " in class " + klass.getName());
1487: }
1488: catch (IOException e)
1489: {
1490: throw e;
1491: }
1492: catch (Exception _)
1493: {
1494: throw new IOException("Unexpected exception " + _);
1495: }
1496: }
1497:
1498: private Object getObjectField (Object obj, Class klass, String field_name,
1499: String type_code) throws IOException
1500: {
1501: try
1502: {
1503: Field f = getField (klass, field_name);
1504: ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
1505:
1506:
1509: if (of.isPrimitive())
1510: throw new InvalidClassException
1511: ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
1512:
1513: if (!of.getTypeString().equals(type_code))
1514: throw new InvalidClassException
1515: ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
1516:
1517: Object o = f.get (obj);
1518:
1519: return o;
1520: }
1521: catch (IOException e)
1522: {
1523: throw e;
1524: }
1525: catch (Exception e)
1526: {
1527: throw new IOException ();
1528: }
1529: }
1530:
1531: private Field getField (Class klass, String name)
1532: throws java.io.InvalidClassException
1533: {
1534: try
1535: {
1536: final Field f = klass.getDeclaredField(name);
1537: setAccessible.setMember(f);
1538: AccessController.doPrivileged(setAccessible);
1539: return f;
1540: }
1541: catch (java.lang.NoSuchFieldException e)
1542: {
1543: throw new InvalidClassException
1544: ("no field called " + name + " in class " + klass.getName());
1545: }
1546: }
1547:
1548: private void dumpElementln (String msg)
1549: {
1550: for (int i = 0; i < depth; i++)
1551: System.out.print (" ");
1552: System.out.print (Thread.currentThread() + ": ");
1553: System.out.println(msg);
1554: }
1555:
1556:
1557: private static final int BUFFER_SIZE = 1024;
1558:
1559: private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1560:
1561: private DataOutputStream dataOutput;
1562: private boolean writeDataAsBlocks;
1563: private DataOutputStream realOutput;
1564: private DataOutputStream blockDataOutput;
1565: private byte[] blockData;
1566: private int blockDataCount;
1567: private Object currentObject;
1568:
1569: ObjectStreamClass currentObjectStreamClass;
1570: private PutField currentPutField;
1571: private boolean fieldsAlreadyWritten;
1572: private boolean replacementEnabled;
1573: private boolean isSerializing;
1574: private int nextOID;
1575: private Hashtable OIDLookupTable;
1576: private int protocolVersion;
1577: private boolean useSubclassMethod;
1578: private SetAccessibleAction setAccessible = new SetAccessibleAction();
1579:
1580:
1581: private int depth = 0;
1582:
1583:
1584: private boolean dump = false;
1585:
1586: private static final boolean DEBUG = false;
1587: }