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 }
--- EOF ---