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