KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thoughtworks > acceptance > CustomSerializationTest


1 package com.thoughtworks.acceptance;
2
3 import com.thoughtworks.acceptance.objects.Software;
4 import com.thoughtworks.acceptance.objects.Hardware;
5
6 import java.io.IOException JavaDoc;
7 import java.io.ObjectInputStream JavaDoc;
8 import java.io.ObjectOutputStream JavaDoc;
9 import java.io.Serializable JavaDoc;
10 import java.io.ObjectStreamField JavaDoc;
11 import java.util.Hashtable JavaDoc;
12 import java.util.Vector JavaDoc;
13
14 public class CustomSerializationTest extends AbstractAcceptanceTest {
15
16     public static class ObjectWithCustomSerialization extends StandardObject implements Serializable JavaDoc {
17
18         private int a;
19         private transient int b;
20         private transient String JavaDoc c;
21         private transient Object JavaDoc d;
22         private transient Software e;
23
24         public ObjectWithCustomSerialization() {
25         }
26
27         public ObjectWithCustomSerialization(int a, int b, String JavaDoc c, Software e) {
28             this.a = a;
29             this.b = b;
30             this.c = c;
31             this.e = e;
32         }
33
34         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
35             b = in.readInt();
36             in.defaultReadObject();
37             c = (String JavaDoc) in.readObject();
38             d = in.readObject();
39             e = (Software) in.readObject();
40         }
41
42         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
43             out.writeInt(b);
44             out.defaultWriteObject();
45             out.writeObject(c);
46             out.writeObject(d);
47             out.writeObject(e);
48         }
49
50     }
51
52     public void testWritesCustomFieldsToStream() {
53         ObjectWithCustomSerialization obj = new ObjectWithCustomSerialization(1, 2, "hello", new Software("tw", "xs"));
54         xstream.alias("custom", ObjectWithCustomSerialization.class);
55         xstream.alias("software", Software.class);
56
57         String JavaDoc expectedXml = ""
58                 + "<custom serialization=\"custom\">\n"
59                 + " <custom>\n"
60                 + " <int>2</int>\n"
61                 + " <default>\n"
62                 + " <a>1</a>\n"
63                 + " </default>\n"
64                 + " <string>hello</string>\n"
65                 + " <null/>\n"
66                 + " <software>\n"
67                 + " <vendor>tw</vendor>\n"
68                 + " <name>xs</name>\n"
69                 + " </software>\n"
70                 + " </custom>\n"
71                 + "</custom>";
72
73         assertBothWays(obj, expectedXml);
74     }
75
76     public static class Parent extends StandardObject implements Serializable JavaDoc {
77
78         private transient int parentA;
79         private int parentB;
80         private transient int parentC;
81
82         public Parent() {
83         }
84
85         public Parent(int parentA, int parentB, int parentC) {
86             this.parentA = parentA;
87             this.parentB = parentB;
88             this.parentC = parentC;
89         }
90
91         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
92             parentA = in.readInt();
93             in.defaultReadObject();
94             parentC = in.readInt();
95         }
96
97         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
98             out.writeInt(parentA);
99             out.defaultWriteObject();
100             out.writeInt(parentC);
101         }
102     }
103
104     public static class Child extends Parent {
105
106         private transient int childA;
107         private int childB;
108         private transient int childC;
109
110         public Child() {
111         }
112
113         public Child(int parentA, int parentB, int parentC, int childA, int childB, int childC) {
114             super(parentA, parentB, parentC);
115             this.childA = childA;
116             this.childB = childB;
117             this.childC = childC;
118         }
119
120         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
121             childA = in.readInt();
122             in.defaultReadObject();
123             childC = in.readInt();
124         }
125
126         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
127             out.writeInt(childA);
128             out.defaultWriteObject();
129             out.writeInt(childC);
130         }
131     }
132
133     public void testIncludesCompleteClassHeirarchy() {
134         Child child = new Child(1, 2, 3, 10, 20, 30);
135         xstream.alias("child", Child.class);
136         xstream.alias("parent", Parent.class);
137
138         String JavaDoc expectedXml = ""
139                 + "<child serialization=\"custom\">\n"
140                 + " <parent>\n"
141                 + " <int>1</int>\n"
142                 + " <default>\n"
143                 + " <parentB>2</parentB>\n"
144                 + " </default>\n"
145                 + " <int>3</int>\n"
146                 + " </parent>\n"
147                 + " <child>\n"
148                 + " <int>10</int>\n"
149                 + " <default>\n"
150                 + " <childB>20</childB>\n"
151                 + " </default>\n"
152                 + " <int>30</int>\n"
153                 + " </child>\n"
154                 + "</child>";
155
156         assertBothWays(child, expectedXml);
157     }
158
159     public static class Child2 extends Parent {
160
161         private int childA;
162
163         public Child2(int parentA, int parentB, int parentC, int childA) {
164             super(parentA, parentB, parentC);
165             this.childA = childA;
166         }
167
168     }
169
170     public void testIncludesCompleteClassHeirarchy2() {
171         Child2 child = new Child2(1, 2, 3, 20);
172         xstream.alias("child2", Child2.class);
173         xstream.alias("parent", Parent.class);
174
175         String JavaDoc expectedXml = ""
176                 + "<child2 serialization=\"custom\">\n"
177                 + " <parent>\n"
178                 + " <int>1</int>\n"
179                 + " <default>\n"
180                 + " <parentB>2</parentB>\n"
181                 + " </default>\n"
182                 + " <int>3</int>\n"
183                 + " </parent>\n"
184                 + " <child2>\n"
185                 + " <default>\n"
186                 + " <childA>20</childA>\n"
187                 + " </default>\n"
188                 + " </child2>\n"
189                 + "</child2>";
190
191         assertBothWays(child, expectedXml);
192     }
193
194     static class MyDate extends java.util.Date JavaDoc {
195         public MyDate(int time) {
196             super(time);
197         }
198     }
199
200     static class MyHashtable extends java.util.Hashtable JavaDoc {
201         private String JavaDoc name;
202
203         public MyHashtable(String JavaDoc name) {
204             this.name = name;
205         }
206
207         public synchronized boolean equals(Object JavaDoc o) {
208             return super.equals(o) && ((MyHashtable)o).name.equals(name);
209         }
210     }
211
212     public void testSupportsSubclassesOfClassesThatAlreadyHaveConverters() {
213         MyDate in = new MyDate(1234567890);
214         String JavaDoc xml = xstream.toXML(in);
215         assertObjectsEqual(in, xstream.fromXML(xml));
216
217         MyHashtable in2 = new MyHashtable("hi");
218         in2.put("cheese", "curry");
219         in2.put("apple", new Integer JavaDoc(3));
220         String JavaDoc xml2 = xstream.toXML(in2);
221         assertObjectsEqual(in2, xstream.fromXML(xml2));
222     }
223
224     public static class ObjectWithNamedFields extends StandardObject implements Serializable JavaDoc {
225
226         private String JavaDoc name;
227         private int number;
228         private Software someSoftware;
229         private Object JavaDoc polymorphic;
230         private Object JavaDoc nothing;
231
232         private static final ObjectStreamField JavaDoc[] serialPersistentFields = {
233             new ObjectStreamField JavaDoc("theName", String JavaDoc.class),
234             new ObjectStreamField JavaDoc("theNumber", int.class),
235             new ObjectStreamField JavaDoc("theSoftware", Software.class),
236             new ObjectStreamField JavaDoc("thePolymorphic", Object JavaDoc.class),
237             new ObjectStreamField JavaDoc("theNothing", Object JavaDoc.class)
238         };
239
240         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
241             // don't call defaultWriteObject()
242
ObjectOutputStream.PutField JavaDoc fields = out.putFields();
243             fields.put("theName", name);
244             fields.put("theNumber", number);
245             fields.put("theSoftware", someSoftware);
246             fields.put("thePolymorphic", polymorphic);
247             fields.put("theNothing", nothing);
248             out.writeFields();
249         }
250
251         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
252             // don't call defaultReadObject()
253
ObjectInputStream.GetField JavaDoc fields = in.readFields();
254             name = (String JavaDoc) fields.get("theName", "unknown");
255             number = fields.get("theNumber", -1);
256             someSoftware = (Software) fields.get("theSoftware", null);
257             polymorphic = fields.get("thePolymorphic", null);
258             nothing = fields.get("theNothing", null);
259         }
260
261     }
262
263     public void testAllowsNamedFields() {
264         ObjectWithNamedFields obj = new ObjectWithNamedFields();
265         obj.name = "Joe";
266         obj.number = 99;
267         obj.someSoftware = new Software("tw", "xs");
268         obj.polymorphic = new Hardware("small", "ipod");
269         obj.nothing = null;
270
271         xstream.alias("with-named-fields", ObjectWithNamedFields.class);
272         xstream.alias("software", Software.class);
273
274         String JavaDoc expectedXml = ""
275                 + "<with-named-fields serialization=\"custom\">\n"
276                 + " <with-named-fields>\n"
277                 + " <default>\n"
278                 + " <theName>Joe</theName>\n"
279                 + " <theNumber>99</theNumber>\n"
280                 + " <theSoftware>\n"
281                 + " <vendor>tw</vendor>\n"
282                 + " <name>xs</name>\n"
283                 + " </theSoftware>\n"
284                 + " <thePolymorphic class=\"com.thoughtworks.acceptance.objects.Hardware\">\n"
285                 + " <arch>small</arch>\n"
286                 + " <name>ipod</name>\n"
287                 + " </thePolymorphic>\n"
288                 + " </default>\n"
289                 + " </with-named-fields>\n"
290                 + "</with-named-fields>";
291
292         assertBothWays(obj, expectedXml);
293     }
294
295     public void testUsesDefaultIfNamedFieldNotFound() {
296         xstream.alias("with-named-fields", ObjectWithNamedFields.class);
297         xstream.alias("software", Software.class);
298
299         String JavaDoc inputXml = ""
300                 + "<with-named-fields serialization=\"custom\">\n"
301                 + " <with-named-fields>\n"
302                 + " <default>\n"
303                 + " <theSoftware>\n"
304                 + " <vendor>tw</vendor>\n"
305                 + " <name>xs</name>\n"
306                 + " </theSoftware>\n"
307                 + " <thePolymorphic class=\"com.thoughtworks.acceptance.objects.Hardware\">\n"
308                 + " <arch>small</arch>\n"
309                 + " <name>ipod</name>\n"
310                 + " </thePolymorphic>\n"
311                 + " </default>\n"
312                 + " </with-named-fields>\n"
313                 + "</with-named-fields>";
314
315         ObjectWithNamedFields result = (ObjectWithNamedFields) xstream.fromXML(inputXml);
316         assertEquals(-1, result.number);
317         assertEquals("unknown", result.name);
318         assertEquals(new Software("tw", "xs"), result.someSoftware);
319     }
320
321     public void testCustomStreamWithNestedCustomStream() {
322         ObjectWithNamedFields outer = new ObjectWithNamedFields();
323         outer.name = "Joe";
324         outer.someSoftware = new Software("tw", "xs");
325         outer.nothing = null;
326
327         ObjectWithNamedFields inner = new ObjectWithNamedFields();
328         inner.name = "Thing";
329
330         outer.polymorphic = inner;
331
332         xstream.alias("with-named-fields", ObjectWithNamedFields.class);
333         xstream.alias("software", Software.class);
334
335         String JavaDoc expectedXml = ""
336                 + "<with-named-fields serialization=\"custom\">\n"
337                 + " <with-named-fields>\n"
338                 + " <default>\n"
339                 + " <theName>Joe</theName>\n"
340                 + " <theNumber>0</theNumber>\n"
341                 + " <theSoftware>\n"
342                 + " <vendor>tw</vendor>\n"
343                 + " <name>xs</name>\n"
344                 + " </theSoftware>\n"
345                 + " <thePolymorphic class=\"with-named-fields\" serialization=\"custom\">\n"
346                 + " <with-named-fields>\n"
347                 + " <default>\n"
348                 + " <theName>Thing</theName>\n"
349                 + " <theNumber>0</theNumber>\n"
350                 + " </default>\n"
351                 + " </with-named-fields>\n"
352                 + " </thePolymorphic>\n"
353                 + " </default>\n"
354                 + " </with-named-fields>\n"
355                 + "</with-named-fields>";
356
357         assertBothWays(outer, expectedXml);
358     }
359
360     public static class NoDefaultFields extends StandardObject implements Serializable JavaDoc {
361
362         private transient int something;
363
364         public NoDefaultFields() {
365         }
366
367         public NoDefaultFields(int something) {
368             this.something = something;
369         }
370
371         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
372             in.defaultReadObject();
373             something = in.readInt();
374         }
375
376         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
377             out.defaultWriteObject();
378             out.writeInt(something);
379         }
380
381     }
382
383     public void testObjectWithCallToDefaultWriteButNoDefaultFields() {
384         xstream.alias("x", NoDefaultFields.class);
385
386         String JavaDoc expectedXml = ""
387                 + "<x serialization=\"custom\">\n"
388                 + " <x>\n"
389                 + " <default/>\n"
390                 + " <int>77</int>\n"
391                 + " </x>\n"
392                 + "</x>";
393         assertBothWays(new NoDefaultFields(77), expectedXml);
394     }
395
396     public void testMaintainsBackwardsCompatabilityWithXStream1_1_0FieldFormat() {
397         ObjectWithNamedFields outer = new ObjectWithNamedFields();
398         outer.name = "Joe";
399         outer.someSoftware = new Software("tw", "xs");
400         outer.nothing = null;
401
402         ObjectWithNamedFields inner = new ObjectWithNamedFields();
403         inner.name = "Thing";
404
405         outer.polymorphic = inner;
406
407         xstream.alias("with-named-fields", ObjectWithNamedFields.class);
408         xstream.alias("software", Software.class);
409
410         String JavaDoc oldFormatOfXml = ""
411                 + "<with-named-fields serialization=\"custom\">\n"
412                 + " <with-named-fields>\n"
413                 + " <fields>\n"
414                 + " <field name=\"theName\" class=\"string\">Joe</field>\n"
415                 + " <field name=\"theNumber\" class=\"int\">0</field>\n"
416                 + " <field name=\"theSoftware\" class=\"software\">\n"
417                 + " <vendor>tw</vendor>\n"
418                 + " <name>xs</name>\n"
419                 + " </field>\n"
420                 + " <field name=\"thePolymorphic\" class=\"with-named-fields\" serialization=\"custom\">\n"
421                 + " <with-named-fields>\n"
422                 + " <fields>\n"
423                 + " <field name=\"theName\" class=\"string\">Thing</field>\n"
424                 + " <field name=\"theNumber\" class=\"int\">0</field>\n"
425                 + " </fields>\n"
426                 + " </with-named-fields>\n"
427                 + " </field>\n"
428                 + " </fields>\n"
429                 + " </with-named-fields>\n"
430                 + "</with-named-fields>";
431
432
433         assertEquals(outer, xstream.fromXML(oldFormatOfXml));
434     }
435
436     public static class ObjectWithNamedThatMatchRealFields extends StandardObject implements Serializable JavaDoc {
437
438         private String JavaDoc name;
439         private int number;
440
441         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
442             ObjectOutputStream.PutField JavaDoc fields = out.putFields();
443             fields.put("name", name.toUpperCase());
444             fields.put("number", number * 100);
445             out.writeFields();
446         }
447
448         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
449             ObjectInputStream.GetField JavaDoc fields = in.readFields();
450             name = ((String JavaDoc) fields.get("name", "unknown")).toLowerCase();
451             number = fields.get("number", 10000) / 100;
452         }
453
454     }
455
456     public void testSupportsWritingFieldsForObjectsThatDoNotExplicitlyDefineThem() {
457         xstream.alias("an-object", ObjectWithNamedThatMatchRealFields.class);
458
459         ObjectWithNamedThatMatchRealFields input = new ObjectWithNamedThatMatchRealFields();
460         input.name = "a name";
461         input.number = 5;
462
463         String JavaDoc expectedXml = ""
464                 + "<an-object serialization=\"custom\">\n"
465                 + " <an-object>\n"
466                 + " <default>\n"
467                 + " <name>A NAME</name>\n"
468                 + " <number>500</number>\n"
469                 + " </default>\n"
470                 + " </an-object>\n"
471                 + "</an-object>";
472
473         assertBothWays(input, expectedXml);
474     }
475
476     public static class ObjectThatReadsCustomFieldsButDoesNotWriteThem extends StandardObject implements Serializable JavaDoc {
477
478         private String JavaDoc name;
479         private int number;
480
481         private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
482             out.defaultWriteObject();
483         }
484
485         private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
486             ObjectInputStream.GetField JavaDoc fields = in.readFields();
487             name = ((String JavaDoc) fields.get("name", "unknown"));
488             number = fields.get("number", 10000);
489         }
490
491     }
492
493     public void testSupportsGetFieldsWithoutPutFields() {
494         xstream.alias("an-object", ObjectThatReadsCustomFieldsButDoesNotWriteThem.class);
495
496         ObjectThatReadsCustomFieldsButDoesNotWriteThem input = new ObjectThatReadsCustomFieldsButDoesNotWriteThem();
497         input.name = "a name";
498         input.number = 5;
499
500         String JavaDoc expectedXml = ""
501                 + "<an-object serialization=\"custom\">\n"
502                 + " <an-object>\n"
503                 + " <default>\n"
504                 + " <number>5</number>\n"
505                 + " <name>a name</name>\n"
506                 + " </default>\n"
507                 + " </an-object>\n"
508                 + "</an-object>";
509
510         assertBothWays(input, expectedXml);
511     }
512 }
513
Popular Tags