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.ByteArrayInputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.nio.ByteOrder;
30 import java.nio.file.Path;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Set;
36 import java.util.stream.Stream;
37 import jdk.tools.jlink.internal.Archive;
38 import jdk.tools.jlink.internal.ImageFileCreator;
39 import jdk.tools.jlink.internal.ImagePluginStack;
40 import jdk.tools.jlink.internal.ExecutableImage;
41 import jdk.tools.jlink.builder.ImageBuilder;
42 import jdk.tools.jlink.plugin.ResourcePool;
43 
44 
45 /*
46  * @test
47  * @summary ImageFileCreator class test
48  * @author Jean-Francois Denise
49  * @modules jdk.jlink/jdk.tools.jlink.internal
50  *          jdk.jlink/jdk.tools.jlink.builder
51  *          jdk.jlink/jdk.tools.jlink.plugin
52  *          java.base/jdk.internal.jimage
53  * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
54  */
55 public class ImageFileCreatorTest {
56 
57     private static class TestArchive implements Archive {
58 
59         private final String name;
60         private final List<Entry> entries = new ArrayList<>();
61 
TestArchive(String name, List<String> entries)62         private TestArchive(String name, List<String> entries) {
63             this.name = name;
64             for (String p : entries) {
65                 this.entries.add(new TestEntry(p, p));
66             }
67         }
68 
69         @Override
moduleName()70         public String moduleName() {
71             return name;
72         }
73 
74         @Override
entries()75         public Stream<Entry> entries() {
76             return entries.stream();
77         }
78 
79         @Override
getPath()80         public Path getPath() {
81             return null;
82         }
83 
84         @Override
open()85         public void open() throws IOException {
86         }
87 
88         @Override
close()89         public void close() throws IOException {
90         }
91 
92         private class TestEntry extends Entry {
93 
TestEntry(String path, String name)94             TestEntry(String path, String name) {
95                 super(TestArchive.this, path, name, Entry.EntryType.CLASS_OR_RESOURCE);
96             }
97 
98             @Override
size()99             public long size() {
100                 return 0;
101             }
102 
103             @Override
stream()104             public InputStream stream() throws IOException {
105                 return new ByteArrayInputStream(new byte[0]);
106             }
107         }
108     }
109 
main(String[] args)110     public static void main(String[] args) throws Exception {
111 
112         {
113             List<String> entries = new ArrayList<>();
114             entries.add("classes/class");
115             test(entries);
116         }
117 
118         {
119             // Add an entry that is a directory, that is wrong
120             List<String> entries = new ArrayList<>();
121             entries.add("classes");
122             entries.add("classes/class");
123             test(entries);
124         }
125 
126         {
127             // Add an entry that is wrongly prefixed by /
128             // /bad//classes/class is the resource added
129             // /bad/classes/class is the metadata node built.
130             List<String> entries = new ArrayList<>();
131             entries.add("/classes/class");
132             test(entries);
133         }
134 
135         {
136             // Trailing '/' is wrong
137             List<String> entries = new ArrayList<>();
138             entries.add("classes/class/");
139             test(entries);
140         }
141 
142         {
143             // Too much '/' characters
144             List<String> entries = new ArrayList<>();
145             entries.add("classes//class/");
146             test(entries);
147         }
148 
149         {
150             // Too much '/' characters
151             List<String> entries = new ArrayList<>();
152             entries.add("classes/////class/");
153             test(entries);
154         }
155 
156         {
157             // Single '/' character
158             List<String> entries = new ArrayList<>();
159             entries.add("/");
160             test(entries);
161         }
162 
163         {
164             // 2 '/' characters
165             List<String> entries = new ArrayList<>();
166             entries.add("//");
167             test(entries);
168         }
169 
170         {
171             // 3 '/' characters
172             List<String> entries = new ArrayList<>();
173             entries.add("///");
174             test(entries);
175         }
176 
177         {
178             // no character
179             List<String> entries = new ArrayList<>();
180             entries.add("");
181             test(entries);
182         }
183 
184         {
185             // all together
186             List<String> entries = new ArrayList<>();
187             entries.add("");
188             entries.add("///");
189             entries.add("//");
190             entries.add("/");
191             entries.add("classes/////class/");
192             entries.add("classes//class/");
193             entries.add("classes/class/");
194             entries.add("/classes/class");
195             entries.add("classes");
196             entries.add("classes/class");
197             test(entries);
198         }
199 
200     }
201 
test(List<String> entries)202     private static void test(List<String> entries) throws Exception {
203         TestArchive arch = new TestArchive("bad", entries);
204         Set<Archive> archives = new HashSet<>();
205         archives.add(arch);
206         ImageBuilder noopBuilder = new ImageBuilder() {
207 
208             @Override
209             public DataOutputStream getJImageOutputStream() {
210                 return new DataOutputStream(new ByteArrayOutputStream());
211             }
212 
213             @Override
214             public ExecutableImage getExecutableImage() {
215                 return null;
216             }
217 
218             @Override
219             public void storeFiles(ResourcePool content) {
220             }
221         };
222 
223         ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
224                 null, false);
225 
226         ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
227     }
228 }
229