1 package com.thoughtworks.acceptance; 2 3 import com.thoughtworks.xstream.testutil.CallLog; 4 5 import java.io.ByteArrayInputStream ; 6 import java.io.ByteArrayOutputStream ; 7 import java.io.IOException ; 8 import java.io.ObjectInputStream ; 9 import java.io.ObjectInputValidation ; 10 import java.io.ObjectOutputStream ; 11 import java.io.Serializable ; 12 13 public class SerializationCallbackOrderTest extends AbstractAcceptanceTest { 14 15 private static CallLog log = new CallLog(); 17 18 20 public static class Base implements Serializable { 21 22 private void writeObject(ObjectOutputStream out) throws IOException { 23 log.actual("Base.writeObject() start"); 24 out.defaultWriteObject(); 25 log.actual("Base.writeObject() end"); 26 } 27 28 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 29 log.actual("Base.readObject() start"); 30 in.defaultReadObject(); 31 log.actual("Base.readObject() end"); 32 } 33 34 private Object writeReplace() { 35 log.actual("Base.writeReplace()"); 36 return this; 37 } 38 39 private Object readResolve() { 40 log.actual("Base.readResolve()"); 41 return this; 42 } 43 } 44 45 public static class Child extends Base implements Serializable { 46 47 private void writeObject(ObjectOutputStream out) throws IOException { 48 log.actual("Child.writeObject() start"); 49 out.defaultWriteObject(); 50 log.actual("Child.writeObject() end"); 51 } 52 53 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 54 log.actual("Child.readObject() start"); 55 in.defaultReadObject(); 56 log.actual("Child.readObject() end"); 57 } 58 59 private Object writeReplace() { 60 log.actual("Child.writeReplace()"); 61 return this; 62 } 63 64 private Object readResolve() { 65 log.actual("Child.readResolve()"); 66 return this; 67 } 68 } 69 70 72 private byte[] javaSerialize(Object object) throws IOException { 73 ByteArrayOutputStream bytes = new ByteArrayOutputStream (); 74 ObjectOutputStream objectOutputStream = new ObjectOutputStream (bytes); 75 objectOutputStream.writeObject(object); 76 objectOutputStream.close(); 77 return bytes.toByteArray(); 78 } 79 80 private Object javaDeserialize(byte[] data) throws IOException , ClassNotFoundException { 81 ObjectInputStream objectInputStream = new ObjectInputStream (new ByteArrayInputStream (data)); 82 return objectInputStream.readObject(); 83 } 84 85 87 public void testJavaSerialization() throws IOException { 88 log.expect("Child.writeReplace()"); 90 log.expect("Base.writeObject() start"); 91 log.expect("Base.writeObject() end"); 92 log.expect("Child.writeObject() start"); 93 log.expect("Child.writeObject() end"); 94 95 javaSerialize(new Child()); 97 98 log.verify(); 100 } 101 102 public void testXStreamSerialization() throws IOException { 103 log.expect("Child.writeReplace()"); 105 log.expect("Base.writeObject() start"); 106 log.expect("Base.writeObject() end"); 107 log.expect("Child.writeObject() start"); 108 log.expect("Child.writeObject() end"); 109 110 xstream.toXML(new Child()); 112 113 log.verify(); 115 } 116 117 public void testJavaDeserialization() throws IOException , ClassNotFoundException { 118 byte[] data = javaSerialize(new Child()); 120 log.reset(); 121 122 log.expect("Base.readObject() start"); 124 log.expect("Base.readObject() end"); 125 log.expect("Child.readObject() start"); 126 log.expect("Child.readObject() end"); 127 log.expect("Child.readResolve()"); 128 129 javaDeserialize(data); 131 132 log.verify(); 134 } 135 136 public void testXStreamDeserialization() throws IOException , ClassNotFoundException { 137 String data = xstream.toXML(new Child()); 139 log.reset(); 140 141 log.expect("Base.readObject() start"); 143 log.expect("Base.readObject() end"); 144 log.expect("Child.readObject() start"); 145 log.expect("Child.readObject() end"); 146 log.expect("Child.readResolve()"); 147 148 xstream.fromXML(data); 150 151 log.verify(); 153 } 154 155 156 public static class ParentNotTransient implements Serializable { 157 158 public int somethingNotTransient; 159 160 public ParentNotTransient(int somethingNotTransient) { 161 this.somethingNotTransient = somethingNotTransient; 162 } 163 164 } 165 166 public static class ChildWithTransient extends ParentNotTransient implements Serializable { 167 168 public transient int somethingTransient; 169 170 public ChildWithTransient(int somethingNotTransient, int somethingTransient) { 171 super(somethingNotTransient); 172 this.somethingTransient = somethingTransient; 173 } 174 175 private void readObject(ObjectInputStream s) throws IOException , ClassNotFoundException { 176 s.defaultReadObject(); 177 somethingTransient = 99999; 178 } 179 } 180 181 public void testCallsReadObjectEvenWithoutNonTransientFields() { 182 xstream.alias("parent", ParentNotTransient.class); 183 xstream.alias("child", ChildWithTransient.class); 184 185 Object in = new ChildWithTransient(10, 22222); 186 String expectedXml = "" 187 + "<child serialization=\"custom\">\n" 188 + " <parent>\n" 189 + " <default>\n" 190 + " <somethingNotTransient>10</somethingNotTransient>\n" 191 + " </default>\n" 192 + " </parent>\n" 193 + " <child>\n" 194 + " <default/>\n" 195 + " </child>\n" 196 + "</child>"; 197 198 String xml = xstream.toXML(in); 199 assertEquals(expectedXml, xml); 200 201 ChildWithTransient childWithTransient = (ChildWithTransient) xstream.fromXML(xml); 202 203 assertEquals(10, childWithTransient.somethingNotTransient); 204 assertEquals(99999, childWithTransient.somethingTransient); 205 } 206 207 208 public static class SomethingThatValidates implements Serializable { 209 210 private void readObject(ObjectInputStream s) throws IOException { 211 212 final int LOW_PRIORITY = -5; 213 final int MEDIUM_PRIORITY = 0; 214 final int HIGH_PRIORITY = 5; 215 216 s.registerValidation(new ObjectInputValidation () { 217 public void validateObject() { 218 log.actual("validateObject() medium priority 1"); 219 } 220 }, MEDIUM_PRIORITY); 221 222 s.registerValidation(new ObjectInputValidation () { 223 public void validateObject() { 224 log.actual("validateObject() high priority"); 225 } 226 }, HIGH_PRIORITY); 227 228 s.registerValidation(new ObjectInputValidation () { 229 public void validateObject() { 230 log.actual("validateObject() low priority"); 231 } 232 }, LOW_PRIORITY); 233 234 s.registerValidation(new ObjectInputValidation () { 235 public void validateObject() { 236 log.actual("validateObject() medium priority 2"); 237 } 238 }, MEDIUM_PRIORITY); 239 } 240 } 241 242 public void testJavaSerializationValidatesObjectIsCalledInPriorityOrder() throws IOException , ClassNotFoundException { 243 log.expect("validateObject() high priority"); 245 log.expect("validateObject() medium priority 2"); 246 log.expect("validateObject() medium priority 1"); 247 log.expect("validateObject() low priority"); 248 249 javaDeserialize(javaSerialize(new SomethingThatValidates())); 251 252 log.verify(); 254 } 255 256 public void testXStreamSerializationValidatesObjectIsCalledInPriorityOrder() throws IOException , ClassNotFoundException { 257 log.expect("validateObject() high priority"); 259 log.expect("validateObject() medium priority 2"); 260 log.expect("validateObject() medium priority 1"); 261 log.expect("validateObject() low priority"); 262 263 xstream.fromXML(xstream.toXML(new SomethingThatValidates())); 265 266 log.verify(); 268 } 269 270 } 271 | Popular Tags |