1 /*
2  * Copyright (c) 1998, 2017, 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 /*
25  * @test
26  * @bug 4100915
27  * @summary Verify that [write/read]ObjectOverride methods get called.
28  *          Test verifies that ALL methods to write an object can
29  *          be overridden. However, the testing for reading an object
30  *          is incomplete. Only test that readObjectOverride is called.
31  *          An entire protocol would need to be implemented and written
32  *          out before being able to test the input side of the API.
33  *
34  *          Also, would be appropriate that this program verify
35  *          that if SerializablePermission "enableSubclassImplementation"
36  *          is not in the security policy and security is enabled, that
37  *          a security exception is thrown when constructing the
38  *          ObjectOutputStream subclass.
39  *
40  *
41  * @compile AbstractObjectInputStream.java AbstractObjectOutputStream.java
42  * @compile XObjectInputStream.java XObjectOutputStream.java
43  * @compile SubclassTest.java
44  * @run main SubclassTest
45  * @run main/othervm/policy=Allow.policy SubclassTest -expectSecurityException
46  */
47 
48 import java.io.ByteArrayInputStream;
49 import java.io.ByteArrayOutputStream;
50 import java.io.IOException;
51 import java.io.ObjectInputStream;
52 import java.io.ObjectOutputStream;
53 import java.io.ObjectStreamField;
54 import java.io.Serializable;
55 
56 /**
57  * Test if customized readObject and writeObject are called.
58  */
59 class B implements Serializable {
60     public int publicIntField;
61     public static int numWriteObjectCalled = 0;
B(int v)62     B(int v) {
63         publicIntField = v;
64     }
writeObject(ObjectOutputStream os)65     private void writeObject(ObjectOutputStream os) throws IOException {
66         numWriteObjectCalled++;
67         os.defaultWriteObject();
68     }
69 
readObject(ObjectInputStream is)70     private void readObject(ObjectInputStream is)
71         throws IOException, ClassNotFoundException
72     {
73         is.defaultReadObject();
74     }
75 
76 };
77 
78 /**
79  * Test PutFields interface.
80  */
81 
82 class C implements Serializable {
83     public int xx1;
84     public int xx2;
85     static final ObjectStreamField[] serialPersistentFields = {
86         new ObjectStreamField("x1", Integer.TYPE),
87         new ObjectStreamField("x2", Integer.TYPE),
88         new ObjectStreamField("x3", Integer.TYPE),
89         new ObjectStreamField("x4", Integer.TYPE)
90     };
C()91     C() {
92         xx1 = 300;
93         xx2 = 400;
94     }
95 
writeObject(ObjectOutputStream os)96     private void writeObject(ObjectOutputStream os) throws IOException {
97         ObjectOutputStream.PutField putFields = os.putFields();
98         putFields.put("x1", xx1);
99         putFields.put("x2", xx2);
100         putFields.put("x3", xx1 * 2);
101         putFields.put("x4", xx2 * 2);
102         os.writeFields();
103     }
104 
105 };
106 
107 
108 class A implements Serializable {
109     public int  publicIntField;
110     public long publicLongField;
111     public B    publicBField;
112     public B[]  publicBArray = { new B(4), new B(6)};
113     public C    publicCField;
114 
A()115     public A() {
116         publicIntField = 3;
117         publicLongField = 10L;
118         publicBField = new B(5);
119         publicCField = new C();
120     }
121 };
122 
123 public class SubclassTest {
main(String argv[])124     public static void main(String argv[])
125         throws IOException, ClassNotFoundException
126     {
127         boolean expectSecurityException = false;
128 
129         if (argv.length > 0 &&
130             argv[0].compareTo("-expectSecurityException") == 0)
131             expectSecurityException = true;
132 
133         ByteArrayOutputStream baos = new ByteArrayOutputStream(20);
134         XObjectOutputStream os = null;
135         try {
136             os = new XObjectOutputStream(baos);
137             if (expectSecurityException)
138                 throw new Error("Assertion failure. " +
139                                 "Expected a security exception on previous line.");
140         } catch (SecurityException e) {
141             if (expectSecurityException) {
142                 System.err.println("Caught expected security exception.");
143                 return;
144             }
145             throw e;
146         }
147         os.writeObject(new A());
148         os.close();
149         if (B.numWriteObjectCalled != 3)
150             throw new Error("Expected B.writeObject() to be called 3 times;" +
151                             " observed only " + B.numWriteObjectCalled + " times");
152 
153         XObjectInputStream is =
154             new XObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
155         try {
156             A a = (A)is.readObject();
157             throw new Error("Expected readObjectOverride() to be called and throw IOException(not implemented)");
158         } catch (IOException e) {
159         }
160         is.close();
161     }
162 };
163