1 /*
2  * Copyright (c) 2016, 2020, 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 8164389 8222440
27  * @summary walk entries in a multi-release jar file via jdk.zipfs
28  * @modules jdk.jartool
29  *          jdk.zipfs
30  * @library /test/lib/
31  * @build jdk.test.lib.util.JarBuilder
32  *        jdk.test.lib.compiler.Compiler
33  * @run testng JFSTester
34  */
35 
36 import org.testng.Assert;
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.Test;
39 
40 import java.io.IOException;
41 import java.io.UncheckedIOException;
42 import java.net.URI;
43 import java.nio.file.FileSystem;
44 import java.nio.file.FileSystems;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.nio.file.Paths;
48 import java.util.HashMap;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.stream.Collectors;
52 
53 import jdk.test.lib.util.JarBuilder;
54 
55 public class JFSTester {
56     private URI jarURI;
57 
58     final private String root_dir1_leaf1_txt = "This is leaf 1." + System.lineSeparator();
59     final private String root_dir1_leaf2_txt = "This is leaf 2." + System.lineSeparator();
60     final private String root_dir2_leaf3_txt = "This is leaf 3." + System.lineSeparator();
61     final private String root_dir2_leaf4_txt = "This is leaf 4." + System.lineSeparator();
62     final private String v9_root_dir2_leaf3_txt = "This is version 9 leaf 3." + System.lineSeparator();
63     final private String v9_root_dir2_leaf4_txt = "This is version 9 leaf 4." + System.lineSeparator();
64     final private String v9_root_dir3_leaf5_txt = "This is version 9 leaf 5." + System.lineSeparator();
65     final private String v9_root_dir3_leaf6_txt = "This is version 9 leaf 6." + System.lineSeparator();
66     final private String v10_root_dir3_leaf5_txt = "This is version 10 leaf 5." + System.lineSeparator();
67     final private String v10_root_dir3_leaf6_txt = "This is version 10 leaf 6." + System.lineSeparator();
68 
69     @BeforeClass
initialize()70     public void initialize() throws Exception {
71         Path jarfile = Paths.get("test.jar");
72         JarBuilder jb = new JarBuilder(jarfile.toString());
73         jb.addAttribute("Multi-Release", "true");
74         jb.addEntry("root/dir1/leaf1.txt", root_dir1_leaf1_txt.getBytes());
75         jb.addEntry("root/dir1/leaf2.txt", root_dir1_leaf2_txt.getBytes());
76         jb.addEntry("root/dir2/leaf3.txt", root_dir2_leaf3_txt.getBytes());
77         jb.addEntry("root/dir2/leaf4.txt", root_dir2_leaf4_txt.getBytes());
78         jb.addEntry("META-INF/versions/9/root/dir2/leaf3.txt", v9_root_dir2_leaf3_txt.getBytes());
79         jb.addEntry("META-INF/versions/9/root/dir2/leaf4.txt", v9_root_dir2_leaf4_txt.getBytes());
80         jb.addEntry("META-INF/versions/9/root/dir3/leaf5.txt", v9_root_dir3_leaf5_txt.getBytes());
81         jb.addEntry("META-INF/versions/9/root/dir3/leaf6.txt", v9_root_dir3_leaf6_txt.getBytes());
82         jb.addEntry("META-INF/versions/10/root/dir3/leaf5.txt", v10_root_dir3_leaf5_txt.getBytes());
83         jb.addEntry("META-INF/versions/10/root/dir3/leaf6.txt", v10_root_dir3_leaf6_txt.getBytes());
84         jb.build();
85         System.out.println("Created " + jarfile + ": " + Files.exists(jarfile));
86         jarURI = new URI("jar", jarfile.toUri().toString(), null);
87     }
88 
89     @Test
testWalk()90     public void testWalk() throws IOException {
91         // treat multi-release jar as unversioned
92         Map<String, String> env = new HashMap<>();
93         Set<String> contents = doTest(env);
94         Set<String> expectedContents = Set.of(
95             root_dir1_leaf1_txt,
96             root_dir1_leaf2_txt,
97             root_dir2_leaf3_txt,
98             root_dir2_leaf4_txt
99         );
100         Assert.assertEquals(contents, expectedContents);
101 
102         // open file as multi-release for version 9
103         env.put("multi-release", "9");
104         contents = doTest(env);
105         expectedContents = Set.of(
106             root_dir1_leaf1_txt,
107             root_dir1_leaf2_txt,
108             v9_root_dir2_leaf3_txt,
109             v9_root_dir2_leaf4_txt,
110             v9_root_dir3_leaf5_txt,
111             v9_root_dir3_leaf6_txt
112         );
113         Assert.assertEquals(contents, expectedContents);
114 
115         // open file as multi-release for version 10
116         env.put("multi-release", "10");
117         contents = doTest(env);
118         expectedContents = Set.of(
119             root_dir1_leaf1_txt,
120             root_dir1_leaf2_txt,
121             v9_root_dir2_leaf3_txt,
122             v9_root_dir2_leaf4_txt,
123             v10_root_dir3_leaf5_txt,
124             v10_root_dir3_leaf6_txt
125         );
126         Assert.assertEquals(contents, expectedContents);
127     }
128 
doTest(Map<String,String> env)129     private Set<String> doTest(Map<String,String> env) throws IOException {
130         Set<String> contents;
131         try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) {
132             Path root = fs.getPath("root");
133             contents = Files.walk(root)
134                 .filter(p -> !Files.isDirectory(p))
135                 .map(this::pathToContents)
136                 .sorted()
137                 .collect(Collectors.toSet());
138         }
139         return contents;
140     }
141 
pathToContents(Path path)142     private String pathToContents(Path path) {
143         try {
144             return new String(Files.readAllBytes(path));
145         } catch (IOException x) {
146             throw new UncheckedIOException(x);
147         }
148     }
149 }
150