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
24import java.lang.module.Configuration;
25import java.lang.module.ResolvedModule;
26import java.io.IOException;
27import java.io.InputStream;
28import java.net.URL;
29import java.nio.file.Files;
30import java.nio.file.Path;
31import java.nio.file.Paths;
32
33/**
34 * Basic test of Class getResource and getResourceAsStream to locate/read
35 * resources in named modules.
36 */
37
38public class Main {
39
40    static final String NAME = "myresource";
41
42    public static void main(String[] args) throws IOException {
43
44        // create resources in m1
45        createResource("m1", Paths.get("."), "m1");
46        createResource("m1", Paths.get("p1"), "m1/p1");
47        createResource("m1", Paths.get("p1", "impl"), "m1/p1.impl");
48        createResource("m1", Paths.get("p1", "resources"), "m1/p1.resources");
49
50        // create resources in m2
51        createResource("m2", Paths.get("."), "m2");
52        createResource("m2", Paths.get("p2"), "m2/p2");
53        createResource("m2", Paths.get("p2", "impl"), "m2/p2.impl");
54        createResource("m2", Paths.get("p2", "resources"), "m2/p2.resources");
55
56
57        // invoke Class getResource from an unnamed module.
58        URL url = Main.class.getResource("/" + NAME);
59        assertNotNull(url);
60
61        url = Main.class.getResource("/p1/" + NAME);
62        assertNull(url);
63
64        url = Main.class.getResource("/p1/impl/" + NAME);
65        assertNull(url);
66
67        url = Main.class.getResource("/p1/resources/" + NAME);
68        assertEquals(readAllAsString(url), "m1/p1.resources");
69
70        url = Main.class.getResource("/p2/" + NAME);
71        assertNull(url);
72
73        url = Main.class.getResource("/p2/impl/" + NAME);
74        assertNull(url);
75
76        // m1: exports private p1.resources
77        url = Main.class.getResource("/p2/resources/" + NAME);
78        assertNull(url);
79
80
81        // invoke Class getResource from module m1
82        url = p1.Main.getResource("/" + NAME);
83        assertEquals(readAllAsString(url), "m1");
84
85        url = p1.Main.getResource("/p1/" + NAME);
86        assertEquals(readAllAsString(url), "m1/p1");
87
88        url = p1.Main.getResource("/p1/impl/" + NAME);
89        assertEquals(readAllAsString(url), "m1/p1.impl");
90
91        url = p1.Main.getResource("/p1/resources/" + NAME);
92        assertEquals(readAllAsString(url), "m1/p1.resources");
93
94        // m2: not a named package
95        url = p1.Main.getResource(p2.Main.class, "/" + NAME);
96        assertEquals(readAllAsString(url), "m2");
97
98        url = p1.Main.getResource(p2.Main.class, "/p2/" + NAME);
99        assertNull(url);
100
101        // m2: exports p2.impl to m1
102        url = p1.Main.getResource(p2.Main.class, "/p2/impl/" + NAME);
103        assertNull(url);
104
105        // m2: exports private p2.resources to m1;
106        url = p1.Main.getResource(p2.Main.class, "/p2/resources/" + NAME);
107        assertEquals(readAllAsString(url), "m2/p2.resources");
108
109
110        // invoke Class getResource from module m2
111        url = p2.Main.getResource("/" + NAME);
112        assertEquals(readAllAsString(url), "m2");
113
114        url = p2.Main.getResource("/p2/" + NAME);
115        assertEquals(readAllAsString(url), "m2/p2");
116
117        url = p2.Main.getResource("/p2/impl/" + NAME);
118        assertEquals(readAllAsString(url), "m2/p2.impl");
119
120        url = p2.Main.getResource("/p2/resources/" + NAME);
121        assertEquals(readAllAsString(url), "m2/p2.resources");
122
123        // m1: not a named package
124        url = p2.Main.getResource(p1.Main.class, "/" + NAME);
125        assertEquals(readAllAsString(url), "m1");
126
127        url = p2.Main.getResource(p1.Main.class, "/p1/" + NAME);
128        assertNull(url);
129
130        url = p2.Main.getResource(p1.Main.class, "/p1/impl/" + NAME);
131        assertNull(url);
132
133        // m1: exports private p1.resources;
134        url = p2.Main.getResource(p1.Main.class, "/p1/resources/" + NAME);
135        assertEquals(readAllAsString(url), "m1/p1.resources");
136
137
138        // invoke Class getResourceAsStream from an unnamed module.
139        InputStream in = Main.class.getResourceAsStream("/" + NAME);
140        assertNotNull(in);
141
142        in = Main.class.getResourceAsStream("/p1/" + NAME);
143        assertNull(in);
144
145        in = Main.class.getResourceAsStream("/p1/impl/" + NAME);
146        assertNull(in);
147
148        in = Main.class.getResourceAsStream("/p1/resources/" + NAME);
149        assertEquals(readAllAsString(in), "m1/p1.resources");
150
151        in = Main.class.getResourceAsStream("/p2/" + NAME);
152        assertNull(in);
153
154        in = Main.class.getResourceAsStream("/p2/impl/" + NAME);
155        assertNull(in);
156
157        in = Main.class.getResourceAsStream("/p2/resources/" + NAME);
158        assertNull(in);
159
160
161        // invoke Class getResourceAsStream from module m1
162        in = p1.Main.getResourceAsStream("/" + NAME);
163        assertEquals(readAllAsString(in), "m1");
164
165        in = p1.Main.getResourceAsStream("/p1/" + NAME);
166        assertEquals(readAllAsString(in), "m1/p1");
167
168        in = p1.Main.getResourceAsStream("/p1/impl/" + NAME);
169        assertEquals(readAllAsString(in), "m1/p1.impl");
170
171        in = p1.Main.getResourceAsStream("/p1/resources/" + NAME);
172        assertEquals(readAllAsString(in), "m1/p1.resources");
173
174        in = p1.Main.getResourceAsStream(p2.Main.class, "/" + NAME);
175        assertEquals(readAllAsString(in), "m2");
176
177        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/" + NAME);
178        assertNull(in);
179
180        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/impl/" + NAME);
181        assertNull(in);
182
183        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/resources/" + NAME);
184        assertEquals(readAllAsString(in), "m2/p2.resources");
185
186
187        // invoke Class getResourceAsStream from module m2
188        in = p2.Main.getResourceAsStream("/" + NAME);
189        assertEquals(readAllAsString(in), "m2");
190
191        in = p2.Main.getResourceAsStream("/p2/" + NAME);
192        assertEquals(readAllAsString(in), "m2/p2");
193
194        in = p2.Main.getResourceAsStream("/p2/impl/" + NAME);
195        assertEquals(readAllAsString(in), "m2/p2.impl");
196
197        in = p2.Main.getResourceAsStream("/p2/resources/" + NAME);
198        assertEquals(readAllAsString(in), "m2/p2.resources");
199
200        in = p2.Main.getResourceAsStream(p1.Main.class, "/" + NAME);
201        assertEquals(readAllAsString(in), "m1");
202
203        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/" + NAME);
204        assertNull(in);
205
206        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/impl/" + NAME);
207        assertNull(in);
208
209        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/resources/" + NAME);
210        assertEquals(readAllAsString(in), "m1/p1.resources");
211
212
213        // Nulls
214        try {
215            Main.class.getResource(null);
216            assertTrue(false);
217        } catch (NullPointerException expected) { }
218        try {
219            Main.class.getResourceAsStream(null);
220            assertTrue(false);
221        } catch (NullPointerException expected) { }
222        try {
223            p1.Main.class.getResource(null);
224            assertTrue(false);
225        } catch (NullPointerException expected) { }
226        try {
227            p1.Main.class.getResourceAsStream(null);
228            assertTrue(false);
229        } catch (NullPointerException expected) { }
230
231        // SecurityManager case
232        System.setSecurityManager(new SecurityManager());
233
234        assertNull(Main.class.getResource("/" + NAME));
235        assertNull(p1.Main.getResource("/" + NAME));
236        assertNull(p2.Main.getResource("/" + NAME));
237
238        assertNull(Main.class.getResourceAsStream("/" + NAME));
239        assertNull(p1.Main.getResourceAsStream("/" + NAME));
240        assertNull(p2.Main.getResourceAsStream("/" + NAME));
241
242        System.out.println("Success!");
243    }
244
245    /**
246     * Create a resource in the sub-directory of the given exploded module
247     */
248    static void createResource(String mn, Path subdir, String msg) throws IOException {
249        Path dir = directoryFor(mn).resolve(subdir);
250        Path file = dir.resolve(NAME);
251        Files.write(file, msg.getBytes("UTF-8"));
252    }
253
254    /**
255     * Returns the directory for the given module (by name).
256     */
257    static Path directoryFor(String name) {
258        Configuration cf = ModuleLayer.boot().configuration();
259        ResolvedModule resolvedModule = cf.findModule(name).orElse(null);
260        if (resolvedModule == null)
261            throw new RuntimeException("not found: " + name);
262        Path dir = Paths.get(resolvedModule.reference().location().get());
263        if (!Files.isDirectory(dir))
264            throw new RuntimeException("not a directory: " + dir);
265        return dir;
266    }
267
268    static String readAllAsString(InputStream in) throws IOException {
269        if (in == null)
270            return null;
271        try (in) {
272            return new String(in.readAllBytes(), "UTF-8");
273        }
274    }
275
276    static String readAllAsString(URL url) throws IOException {
277        if (url == null)
278            return null;
279        InputStream in = url.openStream();
280        return readAllAsString(url.openStream());
281    }
282
283    static void assertTrue(boolean condition) {
284        if (!condition) throw new RuntimeException();
285    }
286
287    static void assertNull(Object o) {
288        assertTrue(o == null);
289    }
290
291    static void assertNotNull(Object o) {
292        assertTrue(o != null);
293    }
294
295    static void assertEquals(Object actual, Object expected) {
296        if (expected == null) {
297            assertNull(actual);
298        } else {
299            assertTrue(expected.equals(actual));
300        }
301    }
302
303    static void assertNotEquals(Object actual, Object expected) {
304        if (expected == null) {
305            assertNotNull(actual);
306        } else {
307            assertTrue(!expected.equals(actual));
308        }
309    }
310}
311
312