1 /* 2 * Copyright (c) 2015, 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 import java.io.File; 25 import java.io.FileOutputStream; 26 import java.io.IOException; 27 import java.nio.file.Files; 28 import java.nio.file.Path; 29 import java.nio.file.Paths; 30 import java.security.KeyStore; 31 import java.security.PrivateKey; 32 import java.security.cert.CertPath; 33 import java.security.cert.CertificateFactory; 34 import java.util.Arrays; 35 import java.util.HashMap; 36 import java.util.Map; 37 import java.util.zip.ZipFile; 38 import jdk.security.jarsigner.JarSigner; 39 40 public class CreateMultiReleaseTestJars { 41 final private String main = 42 "package version;\n\n" 43 + "public class Main {\n" 44 + " public static void main(String[] args) {\n" 45 + " Version v = new Version();\n" 46 + " System.out.println(\"I am running on version \" + v.getVersion());\n" 47 + " }\n" 48 + "}\n"; 49 final private String java8 = 50 "package version;\n\n" 51 + "public class Version {\n" 52 + " public int getVersion() {\n" 53 + " return 8;\n" 54 + " }\n" 55 + "}\n"; 56 final private String java9 = 57 "package version;\n\n" 58 + "public class Version {\n" 59 + " public int getVersion() {\n" 60 + " int version = (new PackagePrivate()).getVersion();\n" 61 + " if (version == 9) return 9;\n" // strange I know, but easy to test 62 + " return version;\n" 63 + " }\n" 64 + "}\n"; 65 final private String ppjava9 = 66 "package version;\n\n" 67 + "class PackagePrivate {\n" 68 + " int getVersion() {\n" 69 + " return 9;\n" 70 + " }\n" 71 + "}\n"; 72 final private String java10 = java8.replace("8", "10"); 73 final String readme8 = "This is the root readme file"; 74 final String readme9 = "This is the version nine readme file"; 75 final String readme10 = "This is the version ten readme file"; 76 private Map<String,byte[]> rootClasses; 77 private Map<String,byte[]> version9Classes; 78 private Map<String,byte[]> version10Classes; 79 80 public void buildUnversionedJar() throws IOException { 81 JarBuilder jb = new JarBuilder("unversioned.jar"); 82 jb.addEntry("README", readme8.getBytes()); 83 jb.addEntry("version/Main.java", main.getBytes()); 84 jb.addEntry("version/Main.class", rootClasses.get("version.Main")); 85 jb.addEntry("version/Version.java", java8.getBytes()); 86 jb.addEntry("version/Version.class", rootClasses.get("version.Version")); 87 jb.build(); 88 } 89 90 public void buildMultiReleaseJar() throws IOException { 91 JarBuilder jb = customMultiReleaseJar("multi-release.jar", "true"); 92 addEntries(jb); 93 jb.addEntry("META-INF/versions/9/version/Version.class", version9Classes.get("version.Version")); 94 jb.build(); 95 } 96 97 public void buildShortMultiReleaseJar() throws IOException { 98 JarBuilder jb = customMultiReleaseJar("short-multi-release.jar", "true"); 99 addEntries(jb); 100 jb.build(); 101 } 102 103 private JarBuilder customMultiReleaseJar(String filename, String multiReleaseValue) 104 throws IOException { 105 JarBuilder jb = new JarBuilder(filename); 106 jb.addAttribute("Multi-Release", multiReleaseValue); 107 return jb; 108 } 109 110 public void buildCustomMultiReleaseJar(String filename, String multiReleaseValue, 111 Map<String, String> extraAttributes) throws IOException { 112 JarBuilder jb = new JarBuilder(filename); 113 extraAttributes.entrySet() 114 .forEach(entry -> jb.addAttribute(entry.getKey(), entry.getValue())); 115 jb.addAttribute("Multi-Release", multiReleaseValue); 116 jb.build(); 117 } 118 119 private void addEntries(JarBuilder jb) { 120 jb.addEntry("README", readme8.getBytes()); 121 jb.addEntry("version/Main.java", main.getBytes()); 122 jb.addEntry("version/Main.class", rootClasses.get("version.Main")); 123 jb.addEntry("version/Version.java", java8.getBytes()); 124 jb.addEntry("version/Version.class", rootClasses.get("version.Version")); 125 jb.addEntry("META-INF/versions/9/README", readme9.getBytes()); 126 jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes()); 127 jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes()); 128 jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate")); 129 jb.addEntry("META-INF/versions/10/README", readme10.getBytes()); 130 jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes()); 131 jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version")); 132 } 133 134 public void buildSignedMultiReleaseJar() throws Exception { 135 String testsrc = System.getProperty("test.src","."); 136 String testdir = findTestDir(testsrc); 137 String keystore = testdir + "/sun/security/tools/jarsigner/JarSigning.keystore"; 138 139 // jarsigner -keystore keystore -storepass "bbbbbb" 140 // -signedJar signed-multi-release.jar multi-release.jar b 141 142 char[] password = "bbbbbb".toCharArray(); 143 KeyStore ks = KeyStore.getInstance(new File(keystore), password); 144 PrivateKey pkb = (PrivateKey)ks.getKey("b", password); 145 CertPath cp = CertificateFactory.getInstance("X.509") 146 .generateCertPath(Arrays.asList(ks.getCertificateChain("b"))); 147 JarSigner js = new JarSigner.Builder(pkb, cp).build(); 148 try (ZipFile in = new ZipFile("multi-release.jar"); 149 FileOutputStream os = new FileOutputStream("signed-multi-release.jar")) 150 { 151 js.sign(in, os); 152 } 153 } 154 155 String findTestDir(String dir) throws IOException { 156 Path path = Paths.get(dir).toAbsolutePath(); 157 while (path != null && !path.endsWith("test")) { 158 path = path.getParent(); 159 } 160 if (path == null) { 161 throw new IllegalArgumentException(dir + " is not in a test directory"); 162 } 163 if (!Files.isDirectory(path)) { 164 throw new IOException(path.toString() + " is not a directory"); 165 } 166 return path.toString(); 167 } 168 169 void compileEntries() { 170 Map<String,String> input = new HashMap<>(); 171 input.put("version.Main", main); 172 input.put("version.Version", java8); 173 rootClasses = (new Compiler(input)).setRelease(8).compile(); 174 input.clear(); 175 input.put("version.Version", java9); 176 input.put("version.PackagePrivate", ppjava9); 177 version9Classes = (new Compiler(input)).setRelease(9).compile(); 178 input.clear(); 179 input.put("version.Version", java10); 180 version10Classes = (new Compiler(input)).setRelease(9).compile(); // fixme in JDK 10 181 } 182 }