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