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 
  24 /**
  25  * @test
  26  * @library /lib/testlibrary
  27  * @modules java.base/jdk.internal.module
  28  *          jdk.jlink/jdk.tools.jmod
  29  *          jdk.compiler
  30  * @build ModuleReaderTest CompilerUtils JarUtils
  31  * @run testng ModuleReaderTest
  32  * @summary Basic tests for java.lang.module.ModuleReader
  33  */
  34 
  35 import java.io.File;
  36 import java.io.IOException;
  37 import java.io.InputStream;
  38 import java.lang.module.ModuleFinder;
  39 import java.lang.module.ModuleReader;
  40 import java.lang.module.ModuleReference;
  41 import java.lang.reflect.Module;
  42 import java.net.URI;
  43 import java.net.URL;
  44 import java.net.URLConnection;
  45 import java.nio.ByteBuffer;
  46 import java.nio.file.Files;
  47 import java.nio.file.Path;
  48 import java.nio.file.Paths;
  49 import java.util.Arrays;
  50 import java.util.Optional;
  51 
  52 import jdk.internal.module.ConfigurableModuleFinder;
  53 import jdk.internal.module.ConfigurableModuleFinder.Phase;
  54 
  55 import org.testng.annotations.BeforeTest;
  56 import org.testng.annotations.Test;
  57 import static org.testng.Assert.*;
  58 
  59 @Test
  60 public class ModuleReaderTest {
  61 
  62     private static final String TEST_SRC = System.getProperty("test.src");
  63 
  64     private static final Path USER_DIR   = Paths.get(System.getProperty("user.dir"));
  65     private static final Path SRC_DIR    = Paths.get(TEST_SRC, "src");
  66     private static final Path MODS_DIR   = Paths.get("mods");
  67 
  68     // the module name of the base module
  69     private static final String BASE_MODULE = "java.base";
  70 
  71     // the module name of the test module
  72     private static final String TEST_MODULE = "m";
  73 
  74     // resources in the base module
  75     private static final String[] BASE_RESOURCES = {
  76         "java/lang/Object.class"
  77     };
  78 
  79     // resources in test module (can't use module-info.class as a test
  80     // resource as it will be modified by the jmod tool)
  81     private static final String[] TEST_RESOURCES = {
  82         "p/Main.class"
  83     };
  84 
  85     // a resource that is not in the base or test module
  86     private static final String NOT_A_RESOURCE = "NotAResource";
  87 
  88 
  89     @BeforeTest
  90     public void compileTestModule() throws Exception {
  91 
  92         // javac -d mods/$TESTMODULE src/$TESTMODULE/**
  93         boolean compiled
  94             = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
  95                                     MODS_DIR.resolve(TEST_MODULE));
  96         assertTrue(compiled, "test module did not compile");
  97     }
  98 
  99 
 100     /**
 101      * Test ModuleReader to module in runtime image
 102      */
 103     public void testImage() throws Exception {
 104 
 105         ModuleFinder finder = ModuleFinder.ofSystem();
 106         ModuleReference mref = finder.find(BASE_MODULE).get();
 107         ModuleReader reader = mref.open();
 108 
 109         try (reader) {
 110 
 111             for (String name : BASE_RESOURCES) {
 112                 byte[] expectedBytes;
 113                 Module baseModule = Object.class.getModule();
 114                 try (InputStream in = baseModule.getResourceAsStream(name)) {
 115                     expectedBytes = in.readAllBytes();
 116                 }
 117 
 118                 testFind(reader, name, expectedBytes);
 119                 testOpen(reader, name, expectedBytes);
 120                 testRead(reader, name, expectedBytes);
 121 
 122             }
 123 
 124             // test "not found"
 125             assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
 126             assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
 127             assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
 128 
 129 
 130             // test nulls
 131             try {
 132                 reader.find(null);
 133                 assertTrue(false);
 134             } catch (NullPointerException expected) { }
 135 
 136             try {
 137                 reader.open(null);
 138                 assertTrue(false);
 139             } catch (NullPointerException expected) { }
 140 
 141             try {
 142                 reader.read(null);
 143                 assertTrue(false);
 144             } catch (NullPointerException expected) { }
 145 
 146             try {
 147                 reader.release(null);
 148                 assertTrue(false);
 149             } catch (NullPointerException expected) { }
 150 
 151         }
 152 
 153         // test closed ModuleReader
 154         try {
 155             reader.open(BASE_RESOURCES[0]);
 156             assertTrue(false);
 157         } catch (IOException expected) { }
 158 
 159 
 160         try {
 161             reader.read(BASE_RESOURCES[0]);
 162             assertTrue(false);
 163         } catch (IOException expected) { }
 164     }
 165 
 166 
 167     /**
 168      * Test ModuleReader to exploded module
 169      */
 170     public void testExplodedModule() throws Exception {
 171         test(MODS_DIR);
 172     }
 173 
 174 
 175     /**
 176      * Test ModuleReader to modular JAR
 177      */
 178     public void testModularJar() throws Exception {
 179         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 180 
 181         // jar cf mlib/${TESTMODULE}.jar -C mods .
 182         JarUtils.createJarFile(dir.resolve("m.jar"),
 183                                MODS_DIR.resolve(TEST_MODULE));
 184 
 185         test(dir);
 186     }
 187 
 188 
 189     /**
 190      * Test ModuleReader to JMOD
 191      */
 192     public void testJMod() throws Exception {
 193         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 194 
 195         // jmod create --class-path mods/${TESTMODULE}  mlib/${TESTMODULE}.jmod
 196         String cp = MODS_DIR.resolve(TEST_MODULE).toString();
 197         String jmod = dir.resolve("m.jmod").toString();
 198         String[] args = { "create", "--class-path", cp, jmod };
 199         jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask();
 200         assertEquals(task.run(args), 0);
 201 
 202         test(dir);
 203     }
 204 
 205 
 206     /**
 207      * The test module is found on the given module path. Open a ModuleReader
 208      * to the test module and test the reader.
 209      */
 210     void test(Path mp) throws Exception {
 211 
 212         ModuleFinder finder = ModuleFinder.of(mp);
 213         if (finder instanceof ConfigurableModuleFinder) {
 214             // need ModuleFinder to be in the phase to find JMOD files
 215             ((ConfigurableModuleFinder)finder).configurePhase(Phase.LINK_TIME);
 216         }
 217 
 218         ModuleReference mref = finder.find(TEST_MODULE).get();
 219         ModuleReader reader = mref.open();
 220 
 221         try (reader) {
 222 
 223             // test each of the known resources in the module
 224             for (String name : TEST_RESOURCES) {
 225                 byte[] expectedBytes
 226                     = Files.readAllBytes(MODS_DIR
 227                         .resolve(TEST_MODULE)
 228                         .resolve(name.replace('/', File.separatorChar)));
 229 
 230                 testFind(reader, name, expectedBytes);
 231                 testOpen(reader, name, expectedBytes);
 232                 testRead(reader, name, expectedBytes);
 233             }
 234 
 235             // test "not found"
 236             assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
 237             assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
 238             assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
 239 
 240             // test nulls
 241             try {
 242                 reader.find(null);
 243                 assertTrue(false);
 244             } catch (NullPointerException expected) { }
 245 
 246             try {
 247                 reader.open(null);
 248                 assertTrue(false);
 249             } catch (NullPointerException expected) { }
 250 
 251             try {
 252                 reader.read(null);
 253                 assertTrue(false);
 254             } catch (NullPointerException expected) { }
 255 
 256             try {
 257                 reader.release(null);
 258                 throw new RuntimeException();
 259             } catch (NullPointerException expected) { }
 260 
 261         }
 262 
 263         // test closed ModuleReader
 264         try {
 265             reader.open(TEST_RESOURCES[0]);
 266             assertTrue(false);
 267         } catch (IOException expected) { }
 268 
 269 
 270         try {
 271             reader.read(TEST_RESOURCES[0]);
 272             assertTrue(false);
 273         } catch (IOException expected) { }
 274     }
 275 
 276     /**
 277      * Test ModuleReader#find
 278      */
 279     void testFind(ModuleReader reader, String name, byte[] expectedBytes)
 280         throws Exception
 281     {
 282         Optional<URI> ouri = reader.find(name);
 283         assertTrue(ouri.isPresent());
 284 
 285         URL url = ouri.get().toURL();
 286         if (!url.getProtocol().equalsIgnoreCase("jmod")) {
 287             URLConnection uc = url.openConnection();
 288             uc.setUseCaches(false);
 289             try (InputStream in = uc.getInputStream()) {
 290                 byte[] bytes = in.readAllBytes();
 291                 assertTrue(Arrays.equals(bytes, expectedBytes));
 292             }
 293         }
 294     }
 295 
 296     /**
 297      * Test ModuleReader#open
 298      */
 299     void testOpen(ModuleReader reader, String name, byte[] expectedBytes)
 300         throws Exception
 301     {
 302         Optional<InputStream> oin = reader.open(name);
 303         assertTrue(oin.isPresent());
 304 
 305         InputStream in = oin.get();
 306         try (in) {
 307             byte[] bytes = in.readAllBytes();
 308             assertTrue(Arrays.equals(bytes, expectedBytes));
 309         }
 310     }
 311 
 312     /**
 313      * Test ModuleReader#read
 314      */
 315     void testRead(ModuleReader reader, String name, byte[] expectedBytes)
 316         throws Exception
 317     {
 318         Optional<ByteBuffer> obb = reader.read(name);
 319         assertTrue(obb.isPresent());
 320 
 321         ByteBuffer bb = obb.get();
 322         try {
 323             int rem = bb.remaining();
 324             assertTrue(rem == expectedBytes.length);
 325             byte[] bytes = new byte[rem];
 326             bb.get(bytes);
 327             assertTrue(Arrays.equals(bytes, expectedBytes));
 328         } finally {
 329             reader.release(bb);
 330         }
 331     }
 332 
 333 }