File: LoadProxyClasses.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (415 lines) | stat: -rw-r--r-- 17,104 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 *
 * @summary functional test for RMIClassLoader.loadProxyClass; test
 * ensures that the default RMI class loader provider implements
 * RMIClassLoader.loadProxyClass correctly.
 *
 * @author Laird Dornin
 *
 * @library ../../../testlibrary
 * @modules java.rmi/sun.rmi.registry
 *          java.rmi/sun.rmi.server
 *          java.rmi/sun.rmi.transport
 *          java.rmi/sun.rmi.transport.tcp
 * @build TestLibrary FnnClass FnnUnmarshal NonpublicInterface
 *     NonpublicInterface1 PublicInterface PublicInterface1
 * @run main/othervm/policy=security.policy
 *     -Djava.rmi.server.useCodebaseOnly=false LoadProxyClasses
 */

import java.rmi.server.RMIClassLoader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.MarshalledObject;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.Serializable;
import java.io.IOException;

import java.util.Arrays;
import java.util.zip.Checksum;

/**
 *  Invokes RMIClassLoader.loadProxyClass() to load a proxy class with
 *  multiple interfaces using using RMI class unmarshalling.  Test is
 *  composed of cases which each unmarshal a proxy class in a
 *  different environment.  All of the cases create needed class
 *  loaders, load appropriate interfaces, create a proxy class that
 *  implements those interfaces, create a marshalled object from that
 *  proxy class, and finally call .get() on that object.  Get of the
 *  object should pass in some cases and fail in others.
 *
 *  1. Nonpublic interface loaded from the parent of the First
 *  Non-Null class Loader on the execution stack (FNNL).  Public
 *  interface loaded from grandparent of FNNL parent. Proxy class must
 *  be defined in non-null FNNL parent. Should succeed.
 *
 *  2. Nonpublic interface (java.util.zip.ZipConstants) and public
 *  interface (java.util.zip.CheckSum) loaded from bootclasspath,
 *  proxy class defined in null/boot class loader.  Should succeed.
 *
 *  3. Public interface classes loaded in FNNL are also available in
 *  RMI loader parent.  FNNL is grandparent of RMI loader. Proxy class
 *  must be defined in RMI class loader. Should succeed. public
 *  interface must be defined in FNNL.
 *
 *  4. Non-public interfaces have multiple class loaders. Should fail
 *  with a LinkageError.
 *
 *  5. Interface classes loaded from RMI class loader. Proxy class
 *  defined in RMI class loader.
 *
 *  6. Not all interfaces classes can be loaded from a single class
 *  loader; should fail with ClassNotFoundException.  All interface
 *  classes will exist (but not all interfaces will be available from
 *  one class loader).
 *
 *  7. prove that proxy loader has correct annotation.
 *
 *  8. REMIND: may want to add a case where the FNNL is null (This
 *  would be for class unmarshalling in the implemntation of a remote
 *  method invocation).
 */
public class LoadProxyClasses {

    private static URL publicUrl = null;

    public static boolean boomerangSemantics = false;

    public static void main(String[] args) {
        try {
            System.err.println("\nFunctional test to verify that RMI " +
                               "loads proxy classes correctly\n");

            /* install proxy interfaces */
            publicUrl =
                TestLibrary.installClassInCodebase("PublicInterface",
                                                   "public");
            URL publicUrl1 =
                TestLibrary.installClassInCodebase("PublicInterface1",
                                                   "public1");
            URL nonpublicUrl =
                TestLibrary.installClassInCodebase("NonpublicInterface",
                                                   "nonpublic", false);
            URL nonpublicUrl1 =
                TestLibrary.installClassInCodebase("NonpublicInterface1",
                                                   "nonpublic1", false);
            URL bothNonpublicUrl =
                TestLibrary.installClassInCodebase("NonpublicInterface",
                                                   "bothNonpublic");
            TestLibrary.installClassInCodebase("NonpublicInterface1",
                                               "bothNonpublic");
            URL fnnUrl =
                TestLibrary.installClassInCodebase("FnnClass", "fnn");

            TestLibrary.suggestSecurityManager(null);


            /* Case 1 */
            ClassLoader grandParentPublic =
                new URLClassLoader(new URL[] {publicUrl});
            ClassLoader parentNonpublic =
                new URLClassLoader(new URL[] {nonpublicUrl},
                                   grandParentPublic);
            URLClassLoader fnnLoader1 =
                new URLClassLoader(new URL[] {fnnUrl}, parentNonpublic);

            Class nonpublicInterface =
                fnnLoader1.loadClass("NonpublicInterface");
            Class publicInterface =
                fnnLoader1.loadClass("PublicInterface");

            Proxy proxy1 = (Proxy) Proxy.newProxyInstance(parentNonpublic,
                new Class[] {nonpublicInterface, publicInterface},
                new TestInvocationHandler());
            unmarshalProxyClass(proxy1, fnnLoader1, parentNonpublic, 1, null);



            /* Case 2 */
            Class zipConstantsClass =
                Class.forName("java.util.zip.ZipConstants");
            URLClassLoader fnnLoader2 =
                new URLClassLoader(new URL[] {fnnUrl});
            Proxy proxy2 = (Proxy) Proxy.newProxyInstance(null,
                new Class[] {zipConstantsClass, Checksum.class},
                new TestInvocationHandler());
            unmarshalProxyClass(proxy2, fnnLoader2,
                                (ClassLoader) null, 2, null);



            /* Case 3 */
            Thread currentThread = Thread.currentThread();
            ClassLoader fnnLoader3 = new URLClassLoader(
                new URL[] {publicUrl, fnnUrl});
            ClassLoader newCtxLoader =
                new URLClassLoader(new URL[] {publicUrl}, fnnLoader3);
            Class publicInterface3 =
                fnnLoader3.loadClass("PublicInterface");
            ClassLoader currentCtxLoader =
                currentThread.getContextClassLoader();
            currentThread.setContextClassLoader(newCtxLoader);

            Proxy proxy3 = (Proxy) Proxy.newProxyInstance(newCtxLoader,
                new Class[] {publicInterface3},
                new TestInvocationHandler());

            unmarshalProxyClass(proxy3, fnnLoader3, fnnLoader3,
                3, new Case3Checker());

            currentThread.setContextClassLoader(currentCtxLoader);



            /* Case 4 */
            ClassLoader bothNonpublicLoader =
                new URLClassLoader(new URL[] {bothNonpublicUrl});
            Class nonpublicInterface4a =
                bothNonpublicLoader.loadClass("NonpublicInterface");
            Class nonpublicInterface4b =
                bothNonpublicLoader.loadClass("NonpublicInterface1");
            Proxy proxy4 = (Proxy) Proxy.newProxyInstance(bothNonpublicLoader,
                new Class[] {nonpublicInterface4a, nonpublicInterface4b},
                new TestInvocationHandler());

            ClassLoader nonpublicLoaderA =
                new URLClassLoader(new URL[] {nonpublicUrl});
            ClassLoader nonpublicLoaderB =
                new URLClassLoader(new URL[] {nonpublicUrl1}, nonpublicLoaderA);
            currentCtxLoader =
                currentThread.getContextClassLoader();
            currentThread.setContextClassLoader(nonpublicLoaderB);

            IllegalAccessError illegal = null;
            try {
                unmarshalProxyClass(proxy4, fnnLoader2, nonpublicLoaderB,
                                    4, null);
            } catch (IllegalAccessError e) {
                illegal = e;
            }

            if (illegal == null) {
                TestLibrary.bomb("case4: IllegalAccessError not thrown " +
                                 "when multiple nonpublic interfaces have \n" +
                                 "different class loaders");
            } else {
                System.err.println("\ncase4: IllegalAccessError correctly " +
                                   "thrown \n when trying to load proxy " +
                                   "with multiple nonpublic interfaces in \n" +
                                   "  different class loaders");
            }
            currentThread.setContextClassLoader(currentCtxLoader);



            /* Case 5*/
            ClassLoader publicLoader =
                new URLClassLoader(new URL[] {publicUrl});
            Class publicInterface5 =
                publicLoader.loadClass("PublicInterface");
            Proxy proxy5 = (Proxy) Proxy.newProxyInstance(publicLoader,
                new Class[] {publicInterface5},
                new TestInvocationHandler());

            currentCtxLoader =
                currentThread.getContextClassLoader();
            currentThread.setContextClassLoader(publicLoader);
            unmarshalProxyClass(proxy5, fnnLoader2, publicLoader, 5,
                                new Case5Checker());
            currentThread.setContextClassLoader(currentCtxLoader);



            /* Case 6 */
            ClassLoader fnnLoader6 =
                new URLClassLoader(new URL[] {fnnUrl, publicUrl});
            ClassLoader publicLoader6 =
                new URLClassLoader(new URL[] {publicUrl1}, fnnLoader6);

            Class publicInterface6a =
                publicLoader6.loadClass("PublicInterface1");
            Class publicInterface6b =
                fnnLoader6.loadClass("PublicInterface");
            Proxy proxy6 = (Proxy) Proxy.newProxyInstance(publicLoader6,
                new Class[] {publicInterface6a, publicInterface6b},
                new TestInvocationHandler());
            ClassNotFoundException cnfe = null;
            try {
                unmarshalProxyClass(proxy6, fnnLoader6, publicLoader6, 6,
                                    null);
            } catch (ClassNotFoundException e) {
                cnfe = e;
            }
            if (cnfe == null) {
                TestLibrary.bomb("ClassNotFoundException not thrown " +
                                 "when not all proxy interfaces could " +
                                 " be found in a single class loader ");
            } else {
                System.err.println("Case6: ClassNotFoundException " +
                                   "correctly thrown when not all proxy" +
                                   " interfaces could be found in a " +
                                   "single class loader");
                cnfe.printStackTrace();
            }

            System.err.println("TEST PASSED");

        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            TestLibrary.bomb(e);
        }
    }


    private interface LoadChecker {
        void checkLoad(Proxy proxy, ClassLoader expectedLoader);
    }

    private static Proxy unmarshalProxyClass(Proxy proxy,
                                             ClassLoader fnnLoader,
                                             ClassLoader expectedLoader,
                                             int n,
                                             LoadChecker checker)
        throws ClassNotFoundException, IOException,
               InstantiationException, IllegalAccessException
    {
        FnnUnmarshal fnnUnmarshal = (FnnUnmarshal)
                fnnLoader.loadClass("FnnClass").newInstance();
        Proxy unmarshalled = (Proxy)
            fnnUnmarshal.unmarshal(new MarshalledObject(proxy));
        ClassLoader unmarshalledLoader =
            unmarshalled.getClass().getClassLoader();

        if (checker != null) {
            checker.checkLoad(unmarshalled, expectedLoader);
        } else {
            if (unmarshalledLoader != expectedLoader) {
                TestLibrary.bomb("case" + n + ": proxy class not " +
                                 "placed into incorrect loader: " +
                                 unmarshalledLoader);
            } else {
                System.err.println("\ncase" + n + ": proxy class correctly" +
                                   " placed into expected loader: " +
                                   expectedLoader);
            }
        }
        return proxy;
    }

    private static class Case3Checker implements LoadChecker {
        public void checkLoad(Proxy proxy, ClassLoader expectedLoader) {
            ClassLoader ifaceLoader =
                proxy.getClass().getInterfaces()[0].getClassLoader();
            ClassLoader proxyLoader = proxy.getClass().getClassLoader();

            boolean proxyOk = false;

            if (boomerangSemantics) {
                ClassLoader ctxLoader =
                    Thread.currentThread().getContextClassLoader();
                if (proxyLoader == ctxLoader) {
                    proxyOk = true;
                }
            } else if (proxyLoader.getClass().
                       getName().indexOf("sun.rmi") >= 0)
            {
                proxyOk = true;
            }

            if (proxyOk) {
                System.err.println("\ncase3: proxy loaded in" +
                                   " correct loader: " + proxyLoader +
                                   Arrays.asList(((URLClassLoader)
                                                 proxyLoader).getURLs()));
            } else {
                TestLibrary.bomb("case3: proxy class loaded in " +
                                 "incorrect loader: " + proxyLoader +
                                   Arrays.asList(((URLClassLoader)
                                                  proxyLoader).getURLs()));
            }

            if (ifaceLoader == expectedLoader) {
                System.err.println("case3: proxy interface loaded in" +
                                   " correct loader: " + ifaceLoader);
            } else {
                TestLibrary.bomb("public proxy interface loaded in " +
                                 "incorrect loader: " + ifaceLoader);
            }
        }
    }

    private static class Case5Checker implements LoadChecker {
        public void checkLoad(Proxy proxy, ClassLoader expectedLoader) {
            ClassLoader proxyLoader = proxy.getClass().getClassLoader();

            String proxyAnnotation =
                RMIClassLoader.getClassAnnotation(proxy.getClass());

            if ((proxyAnnotation == null) ||
                !proxyAnnotation.equals(publicUrl.toString()))
            {
                TestLibrary.bomb("proxy class had incorrect annotation: " +
                                 proxyAnnotation);
            } else {
                System.err.println("proxy class had correct annotation: " +
                                   proxyAnnotation);
            }

            boolean proxyOk = false;

            if (boomerangSemantics) {
                ClassLoader ctxLoader =
                    Thread.currentThread().getContextClassLoader();
                if (proxyLoader == ctxLoader) {
                    proxyOk = true;
                }
            } else if (proxyLoader.getClass().
                       getName().indexOf("sun.rmi") >= 0)
            {
                proxyOk = true;
            }

            if (proxyOk) {
                System.err.println("\ncase5: proxy loaded from" +
                                   " correct loader: " + proxyLoader);
            } else {
                TestLibrary.bomb("case5: proxy interface loaded from " +
                                 "incorrect loader: " + proxyLoader);
            }
        }
    }

    private static class TestInvocationHandler
        implements InvocationHandler, Serializable
    {
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {return null;}
    }
}