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 buildCustomMultiReleaseJar(filename, multiReleaseValue, extraAttributes, false); 113 } 114 115 public void buildCustomMultiReleaseJar(String filename, String multiReleaseValue, 116 Map<String, String> extraAttributes, boolean addEntries) throws IOException { 117 JarBuilder jb = new JarBuilder(filename); 118 extraAttributes.entrySet() 119 .forEach(entry -> jb.addAttribute(entry.getKey(), entry.getValue())); 120 if (addEntries) { 121 addEntries(jb); 122 } 123 jb.addAttribute("Multi-Release", multiReleaseValue); 124 jb.build(); 125 } 126 127 private void addEntries(JarBuilder jb) { 128 jb.addEntry("README", readme8.getBytes()); 129 jb.addEntry("version/Main.java", main.getBytes()); 130 jb.addEntry("version/Main.class", rootClasses.get("version.Main")); 131 jb.addEntry("version/Version.java", java8.getBytes()); 132 jb.addEntry("version/Version.class", rootClasses.get("version.Version")); 133 jb.addEntry("META-INF/versions/9/README", readme9.getBytes()); 134 jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes()); 135 jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes()); 136 jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate")); 137 jb.addEntry("META-INF/versions/10/README", readme10.getBytes()); 138 jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes()); 139 jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version")); 140 } 141 142 public void buildSignedMultiReleaseJar() throws Exception { 143 String testsrc = System.getProperty("test.src","."); 144 String testdir = findTestDir(testsrc); 145 String keystore = testdir + "/sun/security/tools/jarsigner/JarSigning.keystore"; 146 147 // jarsigner -keystore keystore -storepass "bbbbbb" 148 // -signedJar signed-multi-release.jar multi-release.jar b 149 150 char[] password = "bbbbbb".toCharArray(); 151 KeyStore ks = KeyStore.getInstance(new File(keystore), password); 152 PrivateKey pkb = (PrivateKey)ks.getKey("b", password); 153 CertPath cp = CertificateFactory.getInstance("X.509") 154 .generateCertPath(Arrays.asList(ks.getCertificateChain("b"))); 155 JarSigner js = new JarSigner.Builder(pkb, cp).build(); 156 try (ZipFile in = new ZipFile("multi-release.jar"); 157 FileOutputStream os = new FileOutputStream("signed-multi-release.jar")) 158 { 159 js.sign(in, os); 160 } 161 } 162 163 String findTestDir(String dir) throws IOException { 164 Path path = Paths.get(dir).toAbsolutePath(); 165 while (path != null && !path.endsWith("test")) { 166 path = path.getParent(); 167 } 168 if (path == null) { 169 throw new IllegalArgumentException(dir + " is not in a test directory"); 170 } 171 if (!Files.isDirectory(path)) { 172 throw new IOException(path.toString() + " is not a directory"); 173 } 174 return path.toString(); 175 } 176 177 void compileEntries() { 178 Map<String,String> input = new HashMap<>(); 179 input.put("version.Main", main); 180 input.put("version.Version", java8); 181 rootClasses = (new Compiler(input)).setRelease(8).compile(); 182 input.clear(); 183 input.put("version.Version", java9); 184 input.put("version.PackagePrivate", ppjava9); 185 version9Classes = (new Compiler(input)).setRelease(9).compile(); 186 input.clear(); 187 input.put("version.Version", java10); 188 version10Classes = (new Compiler(input)).setRelease(9).compile(); // fixme in JDK 10 189 } 190 }