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