1 /* 2 * Copyright (c) 2015, 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 package p1; 25 26 import java.lang.invoke.MethodHandle; 27 import java.lang.invoke.MethodHandles; 28 import java.lang.invoke.MethodHandles.Lookup; 29 import java.lang.invoke.MethodType; 30 31 import static java.lang.invoke.MethodHandles.Lookup.*; 32 33 import org.testng.annotations.BeforeTest; 34 import org.testng.annotations.Test; 35 import static org.testng.Assert.*; 36 37 /** 38 * Basic test case for module access checks and Lookup.in. 39 */ 40 41 @Test 42 public class Main { 43 44 private Class<?> p1_Type1; // m1, exported 45 private Class<?> p2_Type2; // m1, not exported 46 private Class<?> q1_Type1; // m2, exported 47 private Class<?> q2_Type2; // m2, not exported 48 private Class<?> x500NameClass; // java.base, not exported 49 private Class<?> unnamedClass; // class in unnamed module 50 51 @BeforeTest 52 public void setup() throws Exception { 53 try { 54 p1_Type1 = Class.forName("p1.Type1"); 55 p2_Type2 = Class.forName("p2.Type2"); 56 q1_Type1 = Class.forName("q1.Type1"); 57 q2_Type2 = Class.forName("q2.Type2"); 58 x500NameClass = Class.forName("sun.security.x509.X500Name"); 59 unnamedClass = Class.forName("Unnamed"); 60 } catch (ClassNotFoundException e) { 61 throw new AssertionError(e); 62 } 63 64 // check setup 65 Module m1 = ModuleLayer.boot().findModule("m1").orElse(null); 66 assertNotNull(m1); 67 assertTrue(p1_Type1.getModule() == m1); 68 assertTrue(p2_Type2.getModule() == m1); 69 assertTrue(m1.isExported("p1")); 70 assertFalse(m1.isExported("p2")); 71 72 Module m2 = ModuleLayer.boot().findModule("m2").orElse(null); 73 assertNotNull(m2); 74 assertTrue(q1_Type1.getModule() == m2); 75 assertTrue(q2_Type2.getModule() == m2); 76 assertTrue(m2.isExported("q1")); 77 assertFalse(m2.isExported("q2")); 78 79 Module unnamedModule = unnamedClass.getModule(); 80 assertFalse(unnamedModule.isNamed()); 81 82 // m1 needs to read unnamed module 83 Main.class.getModule().addReads(unnamedModule); 84 } 85 86 /** 87 * MethodHandles.lookup() 88 * 89 * [A0] has module access 90 * [A1] can access all public types in m1 91 * [A2] can access public types in packages exported by modules that m1 reads 92 * [A3] cannot access public types in non-exported modules of modules that m1 reads 93 */ 94 public void testLookup() throws Exception { 95 Lookup lookup = MethodHandles.lookup(); 96 assertTrue((lookup.lookupModes() & MODULE) == MODULE); // [A0] 97 98 // m1 99 findConstructor(lookup, p1_Type1, void.class); // [A1] 100 findConstructor(lookup, p2_Type2, void.class); // [A1] 101 102 // m2 103 findConstructor(lookup, q1_Type1, void.class); // [A2] 104 findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A3] 105 106 // java.base 107 findConstructor(lookup, Object.class, void.class); // [A2] 108 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); // [A3] 109 110 // unnamed 111 findConstructor(lookup, unnamedClass, void.class); // [A3] 112 } 113 114 /** 115 * Hop to lookup class in the same module 116 * 117 * [A0] module and public access is not lost 118 */ 119 public void testToSameModule() throws Exception { 120 Lookup lookup = MethodHandles.lookup().in(p2_Type2); 121 assertTrue(lookup.lookupModes() == (MODULE|PUBLIC)); // [A0] 122 123 // m1 124 findConstructor(lookup, p1_Type1, void.class); 125 findConstructor(lookup, p2_Type2, void.class); 126 127 // m2 128 findConstructor(lookup, q1_Type1, void.class); 129 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 130 131 // java.base 132 findConstructor(lookup, Object.class, void.class); 133 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 134 135 // unnamed 136 findConstructor(lookup, unnamedClass, void.class); 137 } 138 139 /** 140 * Hop to lookup class in another named module 141 * 142 * [A0] has no access 143 */ 144 public void testFromNamedToNamedModule() throws Exception { 145 Lookup lookup = MethodHandles.lookup().in(q1_Type1); 146 assertTrue(lookup.lookupModes() == 0); // [A0] 147 148 // m1 149 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 150 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 151 152 // m2 153 findConstructorExpectingIAE(lookup, q1_Type1, void.class); 154 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 155 156 // java.base 157 findConstructorExpectingIAE(lookup, Object.class, void.class); 158 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 159 160 // unnamed 161 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 162 } 163 164 /** 165 * Hop to lookup class in an unnamed module 166 * 167 * [A0] has no access 168 */ 169 public void testFromNamedToUnnamedModule() throws Exception { 170 Lookup lookup = MethodHandles.lookup().in(unnamedClass); 171 assertTrue(lookup.lookupModes() == 0); // [A0] 172 173 // m1 174 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 175 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 176 177 // m2 178 findConstructorExpectingIAE(lookup, q1_Type1, void.class); 179 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 180 181 // java.base 182 findConstructorExpectingIAE(lookup, Object.class, void.class); 183 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 184 185 // unnamed 186 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 187 } 188 189 /** 190 * Hop from unnamed to named module. 191 * 192 * [A0] retains PUBLIC access 193 */ 194 public void testFromUnnamedToNamedModule() throws Exception { 195 Lookup lookup = MethodHandles.lookup(); 196 lookup = MethodHandles.privateLookupIn(unnamedClass, lookup).in(p1_Type1); 197 assertTrue(lookup.lookupModes() == PUBLIC); // A0 198 199 // m1 200 findConstructor(lookup, p1_Type1, void.class); 201 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 202 203 // m2 204 findConstructor(lookup, q1_Type1, void.class); 205 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 206 207 // java.base 208 findConstructor(lookup, Object.class, void.class); 209 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 210 211 // unnamed 212 findConstructor(lookup, unnamedClass, void.class); 213 } 214 215 /** 216 * MethodHandles.publicLookup() 217 * 218 * [A0] has PUBLIC|UNCONDITIONAL access 219 */ 220 public void testPublicLookup() throws Exception { 221 Lookup lookup = MethodHandles.publicLookup(); 222 assertTrue(lookup.lookupModes() == (PUBLIC|UNCONDITIONAL)); // A0 223 224 // m1 225 findConstructor(lookup, p1_Type1, void.class); 226 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 227 228 // m2 229 findConstructor(lookup, q1_Type1, void.class); 230 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 231 232 // java.base 233 findConstructor(lookup, Object.class, void.class); 234 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 235 236 // unnamed 237 findConstructor(lookup, unnamedClass, void.class); 238 } 239 240 /** 241 * Hop from publicLookup to accessible type in java.base 242 */ 243 public void testPublicLookupToBaseModule() throws Exception { 244 Lookup lookup = MethodHandles.publicLookup().in(String.class); 245 assertTrue(lookup.lookupModes() == PUBLIC); // A0 246 247 // m1 248 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 249 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 250 251 // m2 252 findConstructorExpectingIAE(lookup, q1_Type1, void.class); 253 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 254 255 // java.base 256 findConstructor(lookup, Object.class, void.class); 257 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 258 259 // unnamed 260 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 261 } 262 263 264 /** 265 * Hop from publicLookup to accessible type in named module. 266 * 267 * [A0] has PUBLIC access 268 */ 269 public void testPublicLookupToAccessibleTypeInNamedModule() throws Exception { 270 Lookup lookup = MethodHandles.publicLookup().in(p1_Type1); 271 assertTrue(lookup.lookupModes() == PUBLIC); // A0 272 273 // m1 274 findConstructor(lookup, p1_Type1, void.class); 275 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 276 277 // m2 278 findConstructor(lookup, q1_Type1, void.class); 279 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 280 281 // java.base 282 findConstructor(lookup, Object.class, void.class); 283 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 284 285 // unnamed 286 findConstructor(lookup, unnamedClass, void.class); 287 } 288 289 /** 290 * Teleport from publicLookup to inaccessible type in named module. 291 * 292 * [A0] has no access 293 */ 294 public void testPublicLookupToInaccessibleTypeInNamedModule() throws Exception { 295 Lookup lookup = MethodHandles.publicLookup().in(p2_Type2); 296 assertTrue(lookup.lookupModes() == 0); // A0 297 298 // m1 299 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 300 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 301 302 // m2 303 findConstructorExpectingIAE(lookup, q1_Type1, void.class); 304 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 305 306 // java.base 307 findConstructorExpectingIAE(lookup, Object.class, void.class); 308 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 309 310 // unnamed 311 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 312 } 313 314 /** 315 * Teleport from publicLookup to public type in unnamed module 316 * 317 * [A0] has PUBLIC access 318 */ 319 public void testPublicLookupToUnnamedModule() throws Exception { 320 Lookup lookup = MethodHandles.publicLookup().in(unnamedClass); 321 assertTrue(lookup.lookupModes() == PUBLIC); // A0 322 323 // m1 324 findConstructor(lookup, p1_Type1, void.class); 325 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 326 327 // m2 328 findConstructor(lookup, q1_Type1, void.class); 329 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 330 331 // java.base 332 findConstructor(lookup, Object.class, void.class); 333 findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); 334 335 // unnamed 336 findConstructor(lookup, unnamedClass, void.class); 337 } 338 339 /** 340 * Invokes Lookup findConstructor with a method type constructored from the 341 * given return and parameter types, expecting IllegalAccessException to be 342 * thrown. 343 */ 344 static void findConstructorExpectingIAE(Lookup lookup, 345 Class<?> clazz, 346 Class<?> rtype, 347 Class<?>... ptypes) throws Exception { 348 try { 349 findConstructor(lookup, clazz, rtype, ptypes); 350 assertTrue(false); 351 } catch (IllegalAccessException expected) { } 352 } 353 354 /** 355 * Invokes Lookup findConstructor with a method type constructored from the 356 * given return and parameter types. 357 */ 358 static MethodHandle findConstructor(Lookup lookup, 359 Class<?> clazz, 360 Class<?> rtype, 361 Class<?>... ptypes) throws Exception { 362 MethodType mt = MethodType.methodType(rtype, ptypes); 363 return lookup.findConstructor(clazz, mt); 364 } 365 }