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