1/*
2 * Copyright (c) 2015, 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
24import java.lang.reflect.Constructor;
25import java.lang.reflect.InvocationHandler;
26import java.lang.reflect.Proxy;
27
28/*
29 * @test
30 * @summary Basic test of proxy module mapping and the access to Proxy class
31 * @modules java.base/sun.invoke
32 */
33
34public class ProxyModuleMapping {
35    public static void main(String... args) throws Exception {
36        ClassLoader ld = ProxyModuleMapping.class.getClassLoader();
37        Module unnamed = ld.getUnnamedModule();
38        new ProxyModuleMapping(unnamed, Runnable.class).test();
39
40        // unnamed module gets access to sun.invoke package (e.g. via --add-exports)
41        new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test();
42
43        Class<?> modulePrivateIntf = Class.forName("sun.net.ProgressListener");
44        new ProxyModuleMapping(modulePrivateIntf).test();
45    }
46
47    final Module target;
48    final ClassLoader loader;
49    final Class<?>[] interfaces;
50    ProxyModuleMapping(Module m, Class<?>... interfaces) {
51        this.target = m;
52        this.loader = m.getClassLoader();
53        this.interfaces = interfaces;
54    }
55
56    ProxyModuleMapping(Class<?>... interfaces) {
57        this.target = null;  // expected to be dynamic module
58        this.loader = interfaces[0].getClassLoader();   // same class loader
59        this.interfaces = interfaces;
60    }
61
62    void test() throws Exception {
63        verifyProxyClass();
64        verifyNewProxyInstance();
65    }
66
67    void verifyProxyClass() throws Exception {
68        Class<?> c = Proxy.getProxyClass(loader, interfaces);
69        Module m = c.getModule();
70        if (target != null && m != target) {
71            throw new RuntimeException(c.getModule() + " not expected: " + target);
72        }
73        // expect dynamic module
74        if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
75            throw new RuntimeException("Unexpected:" + m);
76        }
77
78        Module module = c.getModule();
79        try {
80            Constructor<?> cons = c.getConstructor(InvocationHandler.class);
81            cons.newInstance(ih);
82            if (module.isNamed()) {
83                throw new RuntimeException("expected IAE not thrown");
84            }
85        } catch (IllegalAccessException e) {
86            if (!module.isNamed()) {
87                throw e;
88            }
89        }
90    }
91
92    void verifyNewProxyInstance() throws Exception {
93        Object o = Proxy.newProxyInstance(loader, interfaces, ih);
94        Module m = o.getClass().getModule();
95        if (target != null && m != target) {
96            throw new RuntimeException(m + " not expected: " + target);
97        }
98        if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
99            throw new RuntimeException(m + " not expected: dynamic module");
100        }
101    }
102    private final static InvocationHandler ih =
103        (proxy, m, params) -> { System.out.println(m); return null; };
104}
105