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