1 /* 2 * Copyright (c) 2013, 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 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); 78 // 7 -> 6 79 check(out7(oid), oid); 80 } 81 for (String oid: HUGE) { 82 // 7 -> 6 fails for HUGE oids 83 boolean ok = false; 84 try { 85 check(out7(oid), oid); 86 ok = true; 87 } catch (Exception e) { 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", 226 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 227 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 228 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + 229 "AAACAAAAAgAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAAAVJ4"); 230 dump7.put("1.2.3456", 231 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 232 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 233 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAA3VyAAJbSU26YCZ26rKlAgAAeHAA" + 234 "AAADAAAAAQAAAAIAAA2AdXIAAltCrPMX+AYIVOACAAB4cAAAAAMqmwB4"); 235 dump7.put("1.2.2147483647.4", 236 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 237 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 238 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + 239 "AAAEAAAAAQAAAAJ/////AAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKof///9/" + 240 "BHg="); 241 dump7.put("1.2.268435456.4", 242 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 243 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 244 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + 245 "AAAEAAAAAQAAAAIQAAAAAAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKoGAgIAA" + 246 "BHg="); 247 dump7.put("2.16.764.1.3101555394.1.0.100.2.1", 248 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 249 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 250 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + 251 "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + 252 "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADmCFfAGLxvf1QgEAZAIB" + 253 "eA=="); 254 dump7.put("1.2.2147483648.4", 255 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 256 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 257 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + 258 "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + 259 "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAByqIgICAAAR4"); 260 dump7.put("2.3.4444444444444444444444", 261 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 262 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 263 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + 264 "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + 265 "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADFOD4e+HpNG968eOHHg="); 266 dump7.put("1.2.8888888888888888.33333333333333333.44444444444444", 267 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 268 "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + 269 "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + 270 "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + 271 "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAGCqP5Yzbxa6cOLubj9ek" + 272 "japVio3AusuOHHg="); 273 274 dump6.put("0.0", 275 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 276 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + 277 "W0lNumAmduqypQIAAHhwAAAAAgAAAAAAAAAA"); 278 dump6.put("1.1", 279 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 280 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + 281 "W0lNumAmduqypQIAAHhwAAAAAgAAAAEAAAAB"); 282 dump6.put("2.2", 283 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 284 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + 285 "W0lNumAmduqypQIAAHhwAAAAAgAAAAIAAAAC"); 286 dump6.put("1.2.3456", 287 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 288 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAN1cgAC" + 289 "W0lNumAmduqypQIAAHhwAAAAAwAAAAEAAAACAAANgA=="); 290 dump6.put("1.2.2147483647.4", 291 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 292 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + 293 "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACf////wAAAAQ="); 294 dump6.put("1.2.268435456.4", 295 "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + 296 "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + 297 "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACEAAAAAAAAAQ="); 298 ////////////// PASTE END ////////////// 299 } 300 } --- EOF ---