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
24package jdk.test;
25
26import java.lang.reflect.Constructor;
27import java.lang.reflect.InvocationHandler;
28import java.lang.reflect.InvocationTargetException;
29import java.lang.reflect.Proxy;
30import java.util.Arrays;
31
32public class ProxyTest {
33    public static class Data {
34        private static int count = 0;
35        final int testcase;
36        final ClassLoader loader;
37        final Module module;
38        final Class<?>[] interfaces;
39        // Expected the proxy class in the specified module
40        public Data(Module m, ClassLoader loader, Class<?>... interfaces) {
41            this.module = m;
42            this.loader = loader;
43            this.interfaces = interfaces;
44            this.testcase = ++count;
45        }
46        // Expected the proxy class in a dynamic module
47        public Data(ClassLoader loader, Class<?>... interfaces) {
48            this(null, loader, interfaces);
49        }
50
51        @Override
52        public String toString() {
53            String expected = module != null
54                    ? (module.isNamed() ? module.getName() : "unnamed")
55                    : "dynamic";
56            return String.format("%2d: Expected: %s %s loader: %s", testcase, expected,
57                    Arrays.toString(interfaces), loader);
58        }
59    }
60
61    public void test(Data d) {
62        System.out.println(d);
63
64        if (d.module != null) {
65            testProxyClass(d.module, d.loader, d.interfaces);
66        } else {
67            testDynamicModule(d);
68        }
69    }
70
71    private void testDynamicModule(Data d) {
72        Class<?> proxyClass = Proxy.getProxyClass(d.loader, d.interfaces);
73        assertDynamicModule(proxyClass.getModule(), d.loader, proxyClass);
74
75        Object proxy = Proxy.newProxyInstance(d.loader, d.interfaces, handler);
76        assertDynamicModule(proxy.getClass().getModule(), d.loader, proxy.getClass());
77    }
78
79    private static void testProxyClass(Module module, ClassLoader ld, Class<?>... interfaces) {
80        Class<?> proxyClass = Proxy.getProxyClass(ld, interfaces);
81        assertEquals(proxyClass.getModule(), module);
82
83        Object proxy = Proxy.newProxyInstance(ld, interfaces, handler);
84        assertEquals(proxy.getClass().getModule(), module);
85    }
86
87    public static void assertDynamicModule(Module m, ClassLoader ld, Class<?> proxyClass) {
88        if (!m.isNamed() || !m.getName().startsWith("jdk.proxy")) {
89            throw new RuntimeException(m.getName() + " not dynamic module");
90        }
91
92        if (ld != m.getClassLoader() || proxyClass.getClassLoader() != ld) {
93            throw new RuntimeException("unexpected class loader");
94        }
95
96        try {
97            Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
98            cons.newInstance(handler);
99            throw new RuntimeException("Expected IllegalAccessException: " + proxyClass);
100        } catch (IllegalAccessException e) {
101            // expected
102        } catch (NoSuchMethodException|InstantiationException|InvocationTargetException e) {
103            throw new RuntimeException(e);
104        }
105    }
106
107    public static void assertEquals(Object o1, Object o2) {
108        if (o1 != o2) {
109            throw new RuntimeException(o1 + " != " + o2);
110        }
111    }
112    private final static InvocationHandler handler =
113        (proxy, m, params) -> { throw new RuntimeException(m.toString()); };
114}
115