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 4811968 6908628 8006564 27 * @modules java.base/sun.misc 28 * java.base/sun.security.util 29 * @run main S11N check 30 * @summary Serialization compatibility with old versions (and fixes) 31 */ 32 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.ObjectInputStream; 36 import java.io.ObjectOutputStream; 37 import java.util.HashMap; 38 import java.util.Map; 39 import sun.misc.BASE64Encoder; 40 import sun.security.util.ObjectIdentifier; 41 42 public class S11N { 43 static String[] SMALL= { 44 "0.0", 45 "1.1", 46 "2.2", 47 "1.2.3456", 48 "1.2.2147483647.4", 49 "1.2.268435456.4", 50 }; 51 52 static String[] HUGE = { 53 "2.16.764.1.3101555394.1.0.100.2.1", 54 "1.2.2147483648.4", 55 "2.3.4444444444444444444444", 56 "1.2.8888888888888888.33333333333333333.44444444444444", 57 }; 58 59 // Do not use j.u.Base64, the test needs to run in jdk6 60 static BASE64Encoder encoder = new BASE64Encoder() { 61 @Override 62 protected int bytesPerLine() { 63 return 48; 64 } 65 }; 66 67 public static void main(String[] args) throws Exception { 68 if (args[0].equals("check")) { 69 int version = Integer.valueOf(System.getProperty("java.version") 70 .split("\\.")[1]); 71 System.out.println("version is " + version); 72 if (version >= 7) { 73 for (String oid: SMALL) { 74 // 7 -> 7 75 check(out(oid), oid); 76 // 6 -> 7 77 check(out6(oid), oid); 78 } 79 for (String oid: HUGE) { 80 // 7 -> 7 81 check(out(oid), oid); 82 } 83 } else { 84 for (String oid: SMALL) { 85 // 6 -> 6 86 check(out(oid), oid); 97 System.out.println(e); 98 } 99 if (ok) { 100 throw new Exception(); 101 } 102 } 103 } 104 } else { 105 // Generates the JDK6 serialized string inside this test, call 106 // $JDK7/bin/java S11N dump7 107 // $JDK6/bin/java S11N dump6 108 // and paste the output at the end of this test. 109 dump(args[0], SMALL); 110 // For jdk6, the following line will throw an exception, ignore it 111 dump(args[0], HUGE); 112 } 113 } 114 115 // Gets the serialized form for jdk6 116 private static byte[] out6(String oid) throws Exception { 117 return new sun.misc.BASE64Decoder().decodeBuffer(dump6.get(oid)); 118 } 119 120 // Gets the serialized form for jdk7 121 private static byte[] out7(String oid) throws Exception { 122 return new sun.misc.BASE64Decoder().decodeBuffer(dump7.get(oid)); 123 } 124 125 // Gets the serialized form for this java 126 private static byte[] out(String oid) throws Exception { 127 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 128 new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); 129 return bout.toByteArray(); 130 } 131 132 // Makes sure serialized form can be deserialized 133 private static void check(byte[] in, String oid) throws Exception { 134 ObjectIdentifier o = (ObjectIdentifier) ( 135 new ObjectInputStream(new ByteArrayInputStream(in)).readObject()); 136 if (!o.toString().equals(oid)) { 137 throw new Exception("Read Fail " + o + ", not " + oid); 138 } 139 } 140 141 // dump serialized form to java code style text 142 private static void dump(String title, String[] oids) throws Exception { 143 for (String oid: oids) { 144 String[] base64 = encoder.encodeBuffer(out(oid)).split("\n"); 145 System.out.println(" " + title + ".put(\"" + oid + "\","); 146 for (int i = 0; i<base64.length; i++) { 147 System.out.print(" \"" + base64[i] + "\""); 148 if (i == base64.length - 1) { 149 System.out.println(");"); 150 } else { 151 System.out.println(" +"); 152 } 153 } 154 } 155 } 156 157 // Do not use diamond operator, this test is also meant to run in jdk6 158 private static Map<String,String> dump7 = new HashMap<String,String>(); 159 private static Map<String,String> dump6 = new HashMap<String,String>(); 160 161 static { 162 ////////////// PASTE BEGIN ////////////// 163 dump7.put("0.0", 164 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 165 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 166 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + 167 "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4"); 168 dump7.put("1.1", 169 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 170 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 171 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + 172 "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4"); 173 dump7.put("2.2", | 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 4811968 6908628 8006564 27 * @modules java.base/sun.security.util 28 * @run main S11N check 29 * @summary Serialization compatibility with old versions (and fixes) 30 */ 31 32 import java.io.ByteArrayInputStream; 33 import java.io.ByteArrayOutputStream; 34 import java.io.ObjectInputStream; 35 import java.io.ObjectOutputStream; 36 import java.lang.reflect.Method; 37 import java.util.HashMap; 38 import java.util.Map; 39 import sun.security.util.ObjectIdentifier; 40 41 public class S11N { 42 static String[] SMALL= { 43 "0.0", 44 "1.1", 45 "2.2", 46 "1.2.3456", 47 "1.2.2147483647.4", 48 "1.2.268435456.4", 49 }; 50 51 static String[] HUGE = { 52 "2.16.764.1.3101555394.1.0.100.2.1", 53 "1.2.2147483648.4", 54 "2.3.4444444444444444444444", 55 "1.2.8888888888888888.33333333333333333.44444444444444", 56 }; 57 58 public static void main(String[] args) throws Exception { 59 if (args[0].equals("check")) { 60 int version = Integer.valueOf(System.getProperty("java.version") 61 .split("\\.")[1]); 62 System.out.println("version is " + version); 63 if (version >= 7) { 64 for (String oid: SMALL) { 65 // 7 -> 7 66 check(out(oid), oid); 67 // 6 -> 7 68 check(out6(oid), oid); 69 } 70 for (String oid: HUGE) { 71 // 7 -> 7 72 check(out(oid), oid); 73 } 74 } else { 75 for (String oid: SMALL) { 76 // 6 -> 6 77 check(out(oid), oid); 88 System.out.println(e); 89 } 90 if (ok) { 91 throw new Exception(); 92 } 93 } 94 } 95 } else { 96 // Generates the JDK6 serialized string inside this test, call 97 // $JDK7/bin/java S11N dump7 98 // $JDK6/bin/java S11N dump6 99 // and paste the output at the end of this test. 100 dump(args[0], SMALL); 101 // For jdk6, the following line will throw an exception, ignore it 102 dump(args[0], HUGE); 103 } 104 } 105 106 // Gets the serialized form for jdk6 107 private static byte[] out6(String oid) throws Exception { 108 return getCoder().decode(dump6.get(oid)); 109 } 110 111 // Gets the serialized form for jdk7 112 private static byte[] out7(String oid) throws Exception { 113 return getCoder().decode(dump7.get(oid)); 114 } 115 116 // Gets the serialized form for this java 117 private static byte[] out(String oid) throws Exception { 118 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 119 new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); 120 return bout.toByteArray(); 121 } 122 123 // Makes sure serialized form can be deserialized 124 private static void check(byte[] in, String oid) throws Exception { 125 ObjectIdentifier o = (ObjectIdentifier) ( 126 new ObjectInputStream(new ByteArrayInputStream(in)).readObject()); 127 if (!o.toString().equals(oid)) { 128 throw new Exception("Read Fail " + o + ", not " + oid); 129 } 130 } 131 132 // dump serialized form to java code style text 133 private static void dump(String title, String[] oids) throws Exception { 134 for (String oid: oids) { 135 String base64 = getCoder().encode(out(oid)).replaceAll("\n", ""); 136 137 System.out.format(" %s.put(\"%s\",%n \"", title, oid); 138 for (int i=0; i<base64.length(); i++) { 139 System.out.format("%s", base64.charAt(i)); 140 if (i == base64.length() - 1) 141 System.out.format("\");%n"); 142 else if (i != 0 && (i+1) % 64 == 0) 143 System.out.format("\" +%n \""); 144 } 145 } 146 } 147 148 // Reflective use of Base64 coders so the test can compile/run on older JDKs 149 interface Coder { 150 String encode(byte bytes[]) throws Exception; 151 byte[] decode(String src) throws Exception; 152 } 153 154 static Coder getCoder() { 155 try { 156 return new JavaUtilBase64Coder(); 157 } catch (ClassNotFoundException x) { 158 return new SunMiscBase64Coder(); 159 } 160 } 161 162 static class JavaUtilBase64Coder implements Coder { 163 final Object encoder, decoder; 164 final Method encodeMethod, decodeMethod; 165 166 JavaUtilBase64Coder() throws ClassNotFoundException { 167 Class<?> c = Class.forName("java.util.Base64"); 168 try { 169 encoder = c.getDeclaredMethod("getEncoder").invoke(null); 170 decoder = c.getDeclaredMethod("getDecoder").invoke(null); 171 encodeMethod = Class.forName("java.util.Base64$Encoder") 172 .getDeclaredMethod("encode", byte[].class); 173 decodeMethod = Class.forName("java.util.Base64$Decoder") 174 .getDeclaredMethod("decode", String.class); 175 } catch (Exception x) { 176 throw new AssertionError(x); 177 } 178 } 179 public String encode(byte aBuffer[]) throws Exception { 180 return new String((byte[]) encodeMethod.invoke(encoder, aBuffer)); 181 } 182 public byte[] decode(String src) throws Exception{ 183 return (byte[]) decodeMethod.invoke(decoder, src); 184 } 185 } 186 187 static class SunMiscBase64Coder implements Coder { 188 final Object encoder, decoder; 189 final Method encodeMethod, decodeMethod; 190 191 SunMiscBase64Coder() { 192 try { 193 encoder = Class.forName("sun.misc.BASE64Encoder").newInstance(); 194 decoder = Class.forName("sun.misc.BASE64Decoder").newInstance(); 195 encodeMethod = encoder.getClass().getMethod("encodeBuffer", byte[].class); 196 decodeMethod = decoder.getClass().getMethod("decodeBuffer", String.class); 197 } catch (Exception x) { 198 throw new AssertionError(x); 199 } 200 } 201 public String encode(byte aBuffer[]) throws Exception { 202 return (String) encodeMethod.invoke(encoder, aBuffer); 203 } 204 public byte[] decode(String src) throws Exception { 205 return (byte[]) decodeMethod.invoke(decoder, src); 206 } 207 } 208 209 // Do not use diamond operator, this test is also meant to run in jdk6 210 private static Map<String,String> dump7 = new HashMap<String,String>(); 211 private static Map<String,String> dump6 = new HashMap<String,String>(); 212 213 static { 214 ////////////// PASTE BEGIN ////////////// 215 dump7.put("0.0", 216 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 217 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 218 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + 219 "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4"); 220 dump7.put("1.1", 221 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 222 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 223 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + 224 "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4"); 225 dump7.put("2.2", |