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 import java.lang.module.Configuration;
  25 import java.lang.module.ModuleFinder;
  26 import java.lang.reflect.InvocationHandler;
  27 import java.lang.reflect.Layer;
  28 import java.lang.reflect.Proxy;
  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;
  31 import java.util.Arrays;
  32 
  33 import static jdk.testlibrary.ProcessTools.executeTestJava;
  34 
  35 import org.testng.annotations.BeforeTest;
  36 import org.testng.annotations.Test;
  37 import static org.testng.Assert.*;
  38 
  39 /**
  40  * @test
  41  * @library /lib/testlibrary
  42  * @modules jdk.compiler
  43  * @build ProxyTest CompilerUtils jdk.testlibrary.ProcessTools
  44  * @run testng ProxyLayerTest
  45  * @summary Test proxies to implement interfaces in a layer
  46  */
  47 
  48 public class ProxyLayerTest {
  49 
  50     private static final String TEST_SRC = System.getProperty("test.src");
  51     private static final String TEST_CLASSES = System.getProperty("test.classes");
  52 
  53     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
  54     private static final Path MODS_DIR = Paths.get("mods");
  55     private static final Path CPATH_DIR = Paths.get(TEST_CLASSES);
  56 
  57     // the names of the modules in this test
  58     private static String[] modules = new String[] {"m1", "m2", "m3"};
  59 
  60 
  61     /**
  62      * Compiles all modules used by the test
  63      */
  64     @BeforeTest
  65     public void compileAll() throws Exception {
  66         for (String mn : modules) {
  67             Path msrc = SRC_DIR.resolve(mn);
  68             assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
  69         }
  70     }
  71 
  72     /**
  73      * Test proxy implementing interfaces in a Layer defined in
  74      * an unnamed module
  75      */
  76     @Test
  77     public void testProxyInUnnamed() throws Exception {
  78         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
  79         Layer bootLayer = Layer.boot();
  80         Configuration cf = bootLayer
  81                 .configuration()
  82                 .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules));
  83         ClassLoader scl = ClassLoader.getSystemClassLoader();
  84         Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
  85 
  86         ClassLoader loader = layer.findLoader("m1");
  87 
  88         assertTrue(layer.findModule("m1").isPresent());
  89         assertTrue(layer.findModule("m2").isPresent());
  90         assertTrue(layer.findModule("m3").isPresent());
  91 
  92         Class<?>[] interfaces = new Class<?>[] {
  93             Class.forName("p.one.I", false, loader),
  94             Class.forName("p.two.A", false, loader),
  95             Class.forName("p.three.P", false, loader),
  96         };
  97         Object o = Proxy.newProxyInstance(loader, interfaces, handler);
  98 
  99         Class<?> proxyClass = o.getClass();
 100         Package pkg = proxyClass.getPackage();
 101         assertFalse(proxyClass.getModule().isNamed());
 102         assertFalse(pkg.isSealed());
 103         assertEquals(proxyClass.getModule().getLayer(), null);
 104     }
 105 
 106     /**
 107      * Test proxy implementing interfaces in a Layer and defined in a
 108      * dynamic module
 109      */
 110     @Test
 111     public void testProxyInDynamicModule() throws Exception {
 112         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 113         Layer bootLayer = Layer.boot();
 114         Configuration cf = bootLayer
 115                 .configuration()
 116                 .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules));
 117         ClassLoader scl = ClassLoader.getSystemClassLoader();
 118         Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
 119 
 120         ClassLoader loader = layer.findLoader("m1");
 121 
 122         assertTrue(layer.findModule("m1").isPresent());
 123         assertTrue(layer.findModule("m2").isPresent());
 124         assertTrue(layer.findModule("m3").isPresent());
 125 
 126         Class<?>[] interfaces = new Class<?>[] {
 127             Class.forName("p.one.internal.J", false, loader),
 128         };
 129         Object o = Proxy.newProxyInstance(loader, interfaces, handler);
 130         Class<?> proxyClass = o.getClass();
 131         Package pkg = proxyClass.getPackage();
 132         assertTrue(proxyClass.getModule().isNamed());
 133         assertTrue(pkg.isSealed());
 134         assertEquals(proxyClass.getModule().getLayer(), null);
 135     }
 136 
 137     /**
 138      * Test proxy implementing interfaces that the target module has no access
 139      */
 140     @Test
 141     public void testNoReadAccess() throws Exception {
 142         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 143         Layer bootLayer = Layer.boot();
 144         Configuration cf = bootLayer
 145                 .configuration()
 146                 .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules));
 147         ClassLoader scl = ClassLoader.getSystemClassLoader();
 148         Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
 149 
 150         ClassLoader loader = layer.findLoader("m1");
 151 
 152         assertTrue(layer.findModule("m1").isPresent());
 153         assertTrue(layer.findModule("m2").isPresent());
 154         assertTrue(layer.findModule("m3").isPresent());
 155 
 156         Class<?>[] interfaces = new Class<?>[] {
 157                 Class.forName("p.one.I", false, loader),
 158                 Class.forName("p.two.B", false, loader)   // non-public interface but exported package
 159         };
 160         checkIAE(loader, interfaces);
 161     }
 162 
 163     private void checkIAE(ClassLoader loader, Class<?>[] interfaces) {
 164         try {
 165             Proxy.getProxyClass(loader, interfaces);
 166             throw new RuntimeException("Expected IllegalArgumentException thrown");
 167         } catch (IllegalArgumentException e) {}
 168 
 169         try {
 170             Proxy.newProxyInstance(loader, interfaces, handler);
 171             throw new RuntimeException("Expected IllegalArgumentException thrown");
 172         } catch (IllegalArgumentException e) {}
 173     }
 174 
 175     private final static InvocationHandler handler =
 176             (proxy, m, params) -> { throw new RuntimeException(m.toString()); };
 177 
 178 }