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 /* 25 * @test 26 * @bug 8132734 27 * @summary Test the extended API and the aliasing additions in JarFile that 28 * support multi-release jar files 29 * @library /lib/testlibrary/java/util/jar 30 * @build Compiler JarBuilder CreateMultiReleaseTestJars 31 * @run testng MultiReleaseJarIterators 32 */ 33 34 import java.io.File; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.nio.file.Files; 38 import java.util.Enumeration; 39 import java.util.HashMap; 40 import java.util.Map; 41 import java.util.jar.JarEntry; 42 import java.util.jar.JarFile; 43 import java.util.stream.Collectors; 44 import java.util.zip.ZipFile; 45 import jdk.Version; 46 47 import static java.util.jar.JarFile.Release; 48 49 import org.testng.Assert; 50 import org.testng.annotations.AfterClass; 51 import org.testng.annotations.BeforeClass; 52 import org.testng.annotations.Test; 53 54 55 public class MultiReleaseJarIterators { 56 57 static final int MAJOR_VERSION = Version.current().major(); 58 59 String userdir = System.getProperty("user.dir", "."); 60 File unversioned = new File(userdir, "unversioned.jar"); 61 File multirelease = new File(userdir, "multi-release.jar"); 62 Map<String,JarEntry> uvEntries = new HashMap<>(); 63 Map<String,JarEntry> mrEntries = new HashMap<>(); 64 Map<String,JarEntry> baseEntries = new HashMap<>(); 65 Map<String,JarEntry> v9Entries = new HashMap<>(); 66 Map<String, JarEntry> v10Entries = new HashMap<>(); 67 68 @BeforeClass 69 public void initialize() throws Exception { 70 CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); 71 creator.compileEntries(); 72 creator.buildUnversionedJar(); 73 creator.buildMultiReleaseJar(); 74 75 try (JarFile jf = new JarFile(multirelease)) { 76 for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) { 77 JarEntry je = e.nextElement(); 78 String name = je.getName(); 79 mrEntries.put(name, je); 80 if (name.startsWith("META-INF/versions/")) { 81 if (name.startsWith("META-INF/versions/9/")) { 82 v9Entries.put(name.substring(20), je); 83 } else if (name.startsWith("META-INF/versions/10/")) { 84 v10Entries.put(name.substring(21), je); 85 } 86 } else { 87 baseEntries.put(name, je); 88 } 89 } 90 } 91 Assert.assertEquals(mrEntries.size(), 14); 92 Assert.assertEquals(baseEntries.size(), 6); 93 Assert.assertEquals(v9Entries.size(), 5); 94 Assert.assertEquals(v10Entries.size(), 3); 95 96 try (JarFile jf = new JarFile(unversioned)) { 97 jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je)); 98 } 99 Assert.assertEquals(uvEntries.size(), 6); 100 } 101 102 @AfterClass 103 public void close() throws IOException { 104 Files.delete(unversioned.toPath()); 105 Files.delete(multirelease.toPath()); 106 } 107 108 @Test 109 public void testMultiReleaseJar() throws IOException { 110 try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) { 111 testEnumeration(jf, mrEntries); 112 testStream(jf, mrEntries); 113 } 114 115 try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) { 116 testEnumeration(jf, baseEntries); 117 testStream(jf, baseEntries); 118 } 119 120 try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { 121 testEnumeration(jf, v9Entries); 122 testStream(jf, v9Entries); 123 } 124 125 try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) { 126 Map<String,JarEntry> expectedEntries; 127 switch (MAJOR_VERSION) { 128 case 9: 129 expectedEntries = v9Entries; 130 break; 131 case 10: // won't get here until JDK 10 132 expectedEntries = v10Entries; 133 break; 134 default: 135 expectedEntries = baseEntries; 136 break; 137 } 138 139 testEnumeration(jf, expectedEntries); 140 testStream(jf, expectedEntries); 141 } 142 } 143 144 @Test 145 public void testUnversionedJar() throws IOException { 146 try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) { 147 testEnumeration(jf, uvEntries); 148 testStream(jf, uvEntries); 149 } 150 151 try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) { 152 testEnumeration(jf, uvEntries); 153 testStream(jf, uvEntries); 154 } 155 156 try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) { 157 testEnumeration(jf, uvEntries); 158 testStream(jf, uvEntries); 159 } 160 161 try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) { 162 testEnumeration(jf, uvEntries); 163 testStream(jf, uvEntries); 164 } 165 } 166 167 private void testEnumeration(JarFile jf, Map<String,JarEntry> expectedEntries) { 168 Map<String, JarEntry> actualEntries = new HashMap<>(); 169 for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) { 170 JarEntry je = e.nextElement(); 171 actualEntries.put(je.getName(), je); 172 } 173 174 testEntries(jf, actualEntries, expectedEntries); 175 } 176 177 178 private void testStream(JarFile jf, Map<String,JarEntry> expectedEntries) { 179 Map<String,JarEntry> actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je)); 180 181 testEntries(jf, actualEntries, expectedEntries); 182 } 183 184 private void testEntries(JarFile jf, Map<String,JarEntry> actualEntries, Map<String,JarEntry> expectedEntries) { 185 /* For multi-release jar files constructed with a Release object, 186 * actualEntries contain versionedEntries that are considered part of the 187 * public API. They have a 1-1 correspondence with baseEntries, 188 * so entries that are not part of the public API won't be present, 189 * i.e. those entries with a name that starts with version/PackagePrivate 190 * in this particular jar file (multi-release.jar) 191 */ 192 193 Map<String,JarEntry> entries; 194 if (expectedEntries == mrEntries) { 195 Assert.assertEquals(actualEntries.size(), mrEntries.size()); 196 entries = mrEntries; 197 } else if (expectedEntries == uvEntries) { 198 Assert.assertEquals(actualEntries.size(), uvEntries.size()); 199 entries = uvEntries; 200 } else { 201 Assert.assertEquals(actualEntries.size(), baseEntries.size()); // this is correct 202 entries = baseEntries; 203 } 204 205 entries.keySet().forEach(name -> { 206 JarEntry ee = expectedEntries.get(name); 207 if (ee == null) ee = entries.get(name); 208 JarEntry ae = actualEntries.get(name); 209 try { 210 compare(jf, ae, ee); 211 } catch (IOException x) { 212 throw new RuntimeException(x); 213 } 214 }); 215 } 216 217 private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException { 218 byte[] abytes; 219 byte[] ebytes; 220 221 try (InputStream is = jf.getInputStream(actual)) { 222 abytes = is.readAllBytes(); 223 } 224 225 try (InputStream is = jf.getInputStream(expected)) { 226 ebytes = is.readAllBytes(); 227 } 228 229 Assert.assertEquals(abytes, ebytes); 230 } 231 }