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