1 /* 2 Copyright (c) 2017, 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 * @bug 8174954 27 * @summary Class p5.c5 in module first_mod cannot access p2.c2 in module 28 * second_mod, because first_mod cannot read second_mod. Test that 29 * p5.c5 still cannot access p2.c2 even after a read edge is added 30 * that enables first_mod to read second_mod. 31 * @compile ModuleLibrary.java 32 * @compile p2/c2.java 33 * @compile p5/c5.java 34 * @run main/othervm MethodAccessReadTwice 35 */ 36 37 import java.lang.module.Configuration; 38 import java.lang.module.ModuleDescriptor; 39 import java.lang.module.ModuleFinder; 40 import java.lang.ModuleLayer; 41 import java.lang.Module; 42 import java.util.HashMap; 43 import java.util.Map; 44 import java.util.Set; 45 46 // defines first_mod --> packages p5 47 // defines second_mod --> package p2, p2 is exported to first_mod 48 49 public class MethodAccessReadTwice { 50 51 // Create a Layer over the boot layer. 52 // Define modules within this layer to test access between 53 // publicly defined classes within packages of those modules. 54 public void createLayerOnBoot() throws Throwable { 55 56 // Define module: first_mod 57 // Can read: java.base 58 // Packages: p5 59 // Packages exported: none 60 // Packages exported: p5 is exported unqualifiedly 61 62 ModuleDescriptor descriptor_first_mod = 63 ModuleDescriptor.newModule("first_mod") 64 .requires("java.base") 65 .exports("p5") 66 .build(); 67 68 // Define module: second_mod 69 // Can read: java.base 70 // Packages: p2 71 // Packages exported: p2 is exported to first_mod 72 ModuleDescriptor descriptor_second_mod = 73 ModuleDescriptor.newModule("second_mod") 74 .requires("java.base") 75 .exports("p2") 76 .build(); 77 78 // Set up a ModuleFinder containing all modules for this layer 79 ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, descriptor_second_mod); 80 81 // Resolves "first_mod" and "second_mod" 82 Configuration cf = ModuleLayer.boot() 83 .configuration() 84 .resolve(finder, ModuleFinder.of(), Set.of("first_mod", "second_mod")); 85 86 // Map each module to this class loader 87 Map<String, ClassLoader> map = new HashMap<>(); 88 ClassLoader loader = MethodAccessReadTwice.class.getClassLoader(); 89 map.put("first_mod", loader); 90 map.put("second_mod", loader); 91 92 // Create Layer that contains first_mod & second_mod 93 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get); 94 95 Class p2_c2_class = loader.loadClass("p2.c2"); 96 Class p5_c5_class = loader.loadClass("p5.c5"); 97 98 Module first_mod = p5_c5_class.getModule(); 99 Module second_mod = p2_c2_class.getModule(); 100 101 p5.c5 c5_obj = new p5.c5(); 102 p2.c2 c2_obj = new p2.c2(); 103 104 // First access check for p5.c5 --> call to method5 --> tries to access p2.c2 105 try { 106 c5_obj.method5(c2_obj); // Should result in IAE 107 throw new RuntimeException("Test Failed, module first_mod should not have access to p2.c2"); 108 } catch (IllegalAccessError e) { 109 String message = e.getMessage(); 110 if (!(message.contains("cannot access") && 111 message.contains("because module first_mod does not read module second_mod"))) { 112 throw new RuntimeException("Wrong message: " + message); 113 } else { 114 System.out.println("Test Succeeded at attempt #1"); 115 } 116 } 117 118 // Add a read edge from p5/c5's module (first_mod) to second_mod 119 c5_obj.methodAddReadEdge(p2_c2_class.getModule()); 120 121 // Second access check for p5.c5, should have same result as first 122 try { 123 c5_obj.method5(c2_obj); // should result in IAE 124 throw new RuntimeException("Test Failed, access should have been cached above"); 125 } catch (IllegalAccessError e) { 126 String message = e.getMessage(); 127 if (!(message.contains("cannot access") && 128 message.contains("because module first_mod does not read module second_mod"))) { 129 throw new RuntimeException("Wrong message: " + message); 130 } else { 131 System.out.println("Test Succeeded at attempt #2"); 132 } 133 } 134 } 135 136 public static void main(String args[]) throws Throwable { 137 MethodAccessReadTwice test = new MethodAccessReadTwice(); 138 test.createLayerOnBoot(); 139 } 140 }