1 /* 2 * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4227189 26 * @summary Ensure that class descriptor read, write hooks exist, are backwards 27 * compatible, and work as advertised. 28 */ 29 30 import java.io.*; 31 import java.util.*; 32 33 class Foo implements Serializable { 34 private static final long serialVersionUID = 1L; 35 Short s = new Short((short) 1); 36 Integer i = new Integer(2); 37 Long l = new Long(3); 38 39 public boolean equals(Object obj) { 40 if (obj instanceof Foo) { 41 Foo ofoo = (Foo) obj; 42 return s.equals(ofoo.s) && i.equals(ofoo.i) && l.equals(ofoo.l); 43 } 44 return false; 45 } 46 } 47 48 class CustomOutputStream extends ObjectOutputStream { 49 50 boolean hookCalled = false; 51 52 CustomOutputStream(OutputStream out) throws IOException { 53 super(out); 54 useProtocolVersion(PROTOCOL_VERSION_2); 55 } 56 57 protected void writeClassDescriptor(ObjectStreamClass desc) 58 throws IOException 59 { 60 writeUTF(desc.getName()); 61 hookCalled = true; 62 } 63 } 64 65 class CustomInputStream extends ObjectInputStream { 66 67 boolean hookCalled = false; 68 69 CustomInputStream(InputStream in) throws IOException { 70 super(in); 71 } 72 73 protected ObjectStreamClass readClassDescriptor() 74 throws IOException, ClassNotFoundException 75 { 76 hookCalled = true; 77 return ObjectStreamClass.lookup(Class.forName(readUTF())); 78 } 79 } 80 81 public class ClassDescHooks implements ObjectStreamConstants { 82 public static void main(String[] args) throws Exception { 83 ByteArrayOutputStream bout; 84 ByteArrayInputStream bin; 85 ObjectOutputStream oout; 86 ObjectInputStream oin; 87 FileInputStream fin; 88 File foof; 89 CustomOutputStream cout; 90 CustomInputStream cin; 91 92 // test for backwards compatibility 93 bout = new ByteArrayOutputStream(); 94 foof = new File(System.getProperty("test.src", "."), "Foo.ser"); 95 fin = new FileInputStream(foof); 96 try { 97 while (fin.available() > 0) 98 bout.write(fin.read()); 99 } finally { 100 fin.close(); 101 } 102 byte[] buf1 = bout.toByteArray(); 103 104 bout = new ByteArrayOutputStream(); 105 oout = new ObjectOutputStream(bout); 106 Foo foo = new Foo(); 107 oout.writeObject(foo); 108 oout.flush(); 109 byte[] buf2 = bout.toByteArray(); 110 111 if (! Arrays.equals(buf1, buf2)) 112 throw new Error("Incompatible stream format (write)"); 113 114 Foo foocopy; 115 fin = new FileInputStream(foof); 116 try { 117 oin = new ObjectInputStream(fin); 118 foocopy = (Foo) oin.readObject(); 119 if (! foo.equals(foocopy)) 120 throw new Error("Incompatible stream format (read)"); 121 } finally { 122 fin.close(); 123 } 124 125 // make sure write hook not called when old protocol in use 126 bout = new ByteArrayOutputStream(); 127 cout = new CustomOutputStream(bout); 128 cout.useProtocolVersion(PROTOCOL_VERSION_1); 129 cout.writeObject(foo); 130 if (cout.hookCalled) 131 throw new Error("write descriptor hook should not be called"); 132 133 // write custom class descriptor representations 134 bout = new ByteArrayOutputStream(); 135 cout = new CustomOutputStream(bout); 136 cout.writeObject(foo); 137 cout.flush(); 138 bin = new ByteArrayInputStream(bout.toByteArray()); 139 cin = new CustomInputStream(bin); 140 foocopy = (Foo) cin.readObject(); 141 if (! cout.hookCalled) 142 throw new Error("write descriptor hook never called"); 143 if (! cin.hookCalled) 144 throw new Error("read descriptor hook never called"); 145 if (! foo.equals(foocopy)) 146 throw new Error("serialization failed when hooks active"); 147 } 148 }