PrivateLookupInTests.java revision 16177:89ef4b822745
1/*
2 * Copyright (c) 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 */
23package p;
24
25import java.lang.invoke.MethodHandle;
26import java.lang.invoke.MethodHandles;
27import java.lang.invoke.MethodHandles.Lookup;
28import java.lang.reflect.Modifier;
29import java.lang.reflect.Module;
30
31import static java.lang.invoke.MethodHandles.Lookup.*;
32
33import org.testng.annotations.BeforeTest;
34import org.testng.annotations.Test;
35import static org.testng.Assert.*;
36
37/**
38 * Unit tests for MethodHandles.privateLookupIn
39 */
40
41@Test
42public class PrivateLookupInTests {
43
44    /**
45     * A public and non-public types in the test module but in a different
46     * package to the test class.
47     *
48     * package p.internal;
49     * public class PublicType {
50     * }
51     *
52     * package p.internal;
53     * class NonPublicType {
54     *     private static final Object obj = ...
55     * }
56     */
57    private Class<?> publicType;
58    private Class<?> nonPublicType;
59
60    // initialize and sanity check publicType/nonPublicType
61    @BeforeTest
62    public void init() throws Exception {
63        publicType = Class.forName("p.internal.PublicType");
64        assertTrue(this.getClass().getModule() == publicType.getModule());
65        assertNotEquals(this.getClass().getPackageName(), publicType.getPackageName());
66        assertTrue(Modifier.isPublic(publicType.getModifiers()));
67
68        nonPublicType = Class.forName("p.internal.NonPublicType");
69        assertTrue(this.getClass().getModule() == nonPublicType.getModule());
70        assertNotEquals(this.getClass().getPackageName(), nonPublicType.getPackageName());
71        assertFalse(Modifier.isPublic(nonPublicType.getModifiers()));
72    }
73
74    // Invoke MethodHandles.privateLookupIn with a full-power caller
75    public void testAllAccessCallerSameModule() throws Throwable {
76        Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, MethodHandles.lookup());
77        assertTrue(lookup.lookupClass() == nonPublicType);
78        assertTrue(lookup.hasPrivateAccess());
79
80        // get obj field
81        MethodHandle mh = lookup.findStaticGetter(nonPublicType, "obj", Object.class);
82        Object obj = mh.invokeExact();
83    }
84
85    // Invoke MethodHandles.privateLookupIn with a reduced-power caller
86    public void testReducedAccessCallerSameModule() throws Throwable {
87        // drop access
88        Lookup caller = MethodHandles.lookup().in(publicType);
89        assertTrue((caller.lookupModes() & PRIVATE) == 0);
90        assertTrue((caller.lookupModes() & PACKAGE) == 0);
91        assertTrue((caller.lookupModes() & MODULE) != 0);
92
93        Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, caller);
94        assertTrue(lookup.lookupClass() == nonPublicType);
95        assertTrue(lookup.hasPrivateAccess());
96
97        // use it
98        MethodHandle mh = lookup.findStaticGetter(nonPublicType, "obj", Object.class);
99        Object obj = mh.invokeExact();
100    }
101
102    // Invoke MethodHandles.privateLookupIn with the public lookup as caller
103    @Test(expectedExceptions = {IllegalAccessException.class})
104    public void testPublicLookupSameModule() throws Exception {
105        Lookup caller = MethodHandles.publicLookup();
106        Lookup lookup = MethodHandles.privateLookupIn(publicType, caller);
107    }
108
109    // test reads m1, open module m1 containing p1
110    public void testTargetClassInOpenModule() throws Throwable {
111        // m1/p1.Type
112        Class<?> clazz = Class.forName("p1.Type");
113        assertEquals(clazz.getModule().getName(), "m1");
114
115        // ensure that this module reads m1
116        Module thisModule = getClass().getModule();
117        Module m1 = clazz.getModule();
118        thisModule.addReads(clazz.getModule());
119        assertTrue(m1.isOpen("p1", thisModule));
120
121        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
122        assertTrue(lookup.lookupClass() == clazz);
123        assertTrue(lookup.hasPrivateAccess());
124
125        // get obj field
126        MethodHandle mh = lookup.findStaticGetter(clazz, "obj", Object.class);
127        Object obj = mh.invokeExact();
128    }
129
130    // test does not read m2, m2 opens p2 to test
131    @Test(expectedExceptions = {IllegalAccessException.class})
132    public void testCallerDoesNotRead() throws Throwable {
133        // m2/p2.Type
134        Class<?> clazz = Class.forName("p2.Type");
135        assertEquals(clazz.getModule().getName(), "m2");
136
137        Module thisModule = getClass().getModule();
138        Module m2 = clazz.getModule();
139        assertFalse(thisModule.canRead(m2));
140        assertTrue(m2.isOpen("p2", thisModule));
141
142        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
143    }
144
145    // test reads m3, m3 does not open p3 to test
146    @Test(expectedExceptions = {IllegalAccessException.class})
147    public void testNotOpenToCaller() throws Throwable {
148        // m3/p2.Type
149        Class<?> clazz = Class.forName("p3.Type");
150        assertEquals(clazz.getModule().getName(), "m3");
151
152        Module thisModule = getClass().getModule();
153        Module m3 = clazz.getModule();
154        thisModule.addReads(clazz.getModule());
155        assertFalse(m3.isOpen("p3", thisModule));
156
157        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
158    }
159
160    // Invoke MethodHandles.privateLookupIn with a primitive class
161    @Test(expectedExceptions = {IllegalArgumentException.class})
162    public void testPrimitiveClassAsTargetClass() throws Exception {
163        MethodHandles.privateLookupIn(int.class, MethodHandles.lookup());
164    }
165
166    // Invoke MethodHandles.privateLookupIn with an array class
167    @Test(expectedExceptions = {IllegalArgumentException.class})
168    public void testArrayClassAsTargetClass() throws Exception {
169        MethodHandles.privateLookupIn(PrivateLookupInTests[].class, MethodHandles.lookup());
170    }
171
172    // Invoke MethodHandles.privateLookupIn with a primitive array class
173    @Test(expectedExceptions = {IllegalArgumentException.class})
174    public void testPrimitiveArrayClassAsTargetClass() throws Exception {
175        MethodHandles.privateLookupIn(int[].class, MethodHandles.lookup());
176    }
177
178    // Invoke MethodHandles.privateLookupIn with null
179    @Test(expectedExceptions = {NullPointerException.class})
180    public void testNullTargetClass() throws Exception {
181        MethodHandles.privateLookupIn(null, MethodHandles.lookup());
182    }
183
184    // Invoke MethodHandles.privateLookupIn with null
185    @Test(expectedExceptions = {NullPointerException.class})
186    public void testNullCaller() throws Exception {
187        MethodHandles.privateLookupIn(getClass(), null);
188    }
189}
190