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