1 /*
2  * Copyright (c) 2016, 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 package test.java.util.Properties;
25 
26 import java.io.ByteArrayInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.util.Base64;
32 import java.util.Properties;
33 
34 /**
35  * @test
36  * @bug 8029891
37  * @summary tests the compatibility of Properties serial form
38  * @run main PropertiesSerialization read
39  *
40  * To update this test in case the serial form of Properties changes, run this
41  * test with the 'write' flag, and copy the resulting output back into this
42  * file, replacing the existing String declaration(s).
43  */
44 public class PropertiesSerialization {
45     private static final Properties TEST_PROPS;
46     static {
47         TEST_PROPS = new Properties();
48         TEST_PROPS.setProperty("one", "two");
49         TEST_PROPS.setProperty("buckle", "shoe");
50         TEST_PROPS.setProperty("three", "four");
51         TEST_PROPS.setProperty("shut", "door");
52     }
53 
54     /**
55      * Base64 encoded string for Properties object
56      * Java version: 1.8.0
57      **/
58     private static final String TEST_SER_BASE64 =
59          "rO0ABXNyABRqYXZhLnV0aWwuUHJvcGVydGllczkS0HpwNj6YAgABTAAIZGVmYXVs"
60        + "dHN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHIAE2phdmEudXRpbC5IYXNodGFi"
61        + "bGUTuw8lIUrkuAMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAI"
62        + "dwgAAAALAAAABHQAA29uZXQAA3R3b3QABHNodXR0AARkb29ydAAGYnVja2xldAAE"
63        + "c2hvZXQABXRocmVldAAEZm91cnhw";
64 
main(String[] args)65     public static void main(String[] args) throws IOException,
66             ClassNotFoundException {
67         // Android-changed: run both branches.
68         /*
69         if (args.length == 0) {
70             System.err.println("Run with 'read' or 'write'");
71             System.err.println("  read mode:  normal test mode.");
72             System.err.println("              Confirms that serial stream can");
73             System.err.println("              be deserialized as expected.");
74             System.err.println("  write mode: meant for updating the test,");
75             System.err.println("              should the serial form change.");
76             System.err.println("              Test output should be pasted");
77             System.err.println("              back into the test source.");
78             return;
79         }
80         */
81 
82         // Android-changed: run both branches.
83         {
84             Properties deserializedObject;
85             ByteArrayInputStream bais = new
86               ByteArrayInputStream(Base64.getDecoder().decode(TEST_SER_BASE64));
87             try (ObjectInputStream ois = new ObjectInputStream(bais)) {
88                 deserializedObject = (Properties) ois.readObject();
89             }
90             if (!TEST_PROPS.equals(deserializedObject)) {
91                 throw new RuntimeException("deserializedObject not equals()");
92             }
93             System.out.println("Test passed");
94         }
95         {
96             System.out.println("\nTo update the test, paste the following back "
97                     + "into the test code:\n");
98             ByteArrayOutputStream baos = new ByteArrayOutputStream();
99             ObjectOutputStream oos = new ObjectOutputStream(baos);
100             oos.writeObject(TEST_PROPS);
101             oos.flush();
102             oos.close();
103 
104             byte[] byteArray = baos.toByteArray();
105             // Check that the Properties deserializes correctly
106             ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
107             ObjectInputStream ois = new ObjectInputStream(bais);
108             Properties deser = (Properties)ois.readObject();
109             if (!TEST_PROPS.equals(deser)) {
110                 throw new RuntimeException("write: Deserialized != original");
111             }
112 
113             // Now get a Base64 string representation of the serialized bytes.
114             final String base64 = Base64.getEncoder().encodeToString(byteArray);
115             // Check that we can deserialize the Base64 string we just computed.
116             ByteArrayInputStream bais2 =
117               new ByteArrayInputStream(Base64.getDecoder().decode(base64));
118             ObjectInputStream ois2 = new ObjectInputStream(bais2);
119             Properties deser2 = (Properties)ois2.readObject();
120             if (!TEST_PROPS.equals(deser2)) {
121                 throw new RuntimeException("write: Deserialized base64 != "
122                         + "original");
123             }
124             System.out.println(dumpBase64SerialStream(base64));
125         }
126     }
127 
128     private static final String INDENT = "   ";
129     /* Based on:
130      * java/util/logging/HigherResolutionTimeStamps/SerializeLogRecored.java
131      */
dumpBase64SerialStream(String base64)132     private static String dumpBase64SerialStream(String base64) {
133         // Generates the Java Pseudo code that can be cut & pasted into
134         // this test (see Jdk8SerializedLog and Jdk9SerializedLog below)
135         final StringBuilder sb = new StringBuilder();
136         sb.append(INDENT).append(" /**").append('\n');
137         sb.append(INDENT).append("  * Base64 encoded string for Properties object\n");
138         sb.append(INDENT).append("  * Java version: ")
139                 .append(System.getProperty("java.version")).append('\n');
140         sb.append(INDENT).append("  **/").append('\n');
141         sb.append(INDENT).append(" private static final String TEST_SER_BASE64 = ")
142                 .append("\n").append(INDENT).append("      ");
143         final int last = base64.length() - 1;
144         for (int i=0; i<base64.length();i++) {
145             if (i%64 == 0) sb.append("\"");
146             sb.append(base64.charAt(i));
147             if (i%64 == 63 || i == last) {
148                 sb.append("\"");
149                 if (i == last) sb.append(";\n");
150                 else sb.append("\n").append(INDENT).append("    + ");
151             }
152         }
153         return sb.toString();
154     }
155 }
156