1 /* 2 * Copyright (c) 2000, 2013, 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 /* @test 25 * 26 * @summary functional test for RMIClassLoader.loadProxyClass; test 27 * ensures that the default RMI class loader provider implements 28 * RMIClassLoader.loadProxyClass correctly. 29 * 30 * @author Laird Dornin 31 * 32 * @library ../../../testlibrary 33 * @modules java.rmi/sun.rmi.registry 34 * java.rmi/sun.rmi.server 35 * java.rmi/sun.rmi.transport 36 * java.rmi/sun.rmi.transport.tcp 37 * @build TestLibrary FnnClass FnnUnmarshal NonpublicInterface 38 * NonpublicInterface1 PublicInterface PublicInterface1 39 * @run main/othervm/policy=security.policy 40 * -Djava.rmi.server.useCodebaseOnly=false LoadProxyClasses 41 */ 42 43 import java.rmi.server.RMIClassLoader; 44 import java.lang.reflect.InvocationHandler; 45 import java.lang.reflect.Method; 46 import java.lang.reflect.Proxy; 47 import java.rmi.MarshalledObject; 48 import java.net.URL; 49 import java.net.URLClassLoader; 50 import java.io.Serializable; 51 import java.io.IOException; 52 53 import java.util.Arrays; 54 import java.util.zip.Checksum; 55 56 /** 57 * Invokes RMIClassLoader.loadProxyClass() to load a proxy class with 58 * multiple interfaces using using RMI class unmarshalling. Test is 59 * composed of cases which each unmarshal a proxy class in a 60 * different environment. All of the cases create needed class 61 * loaders, load appropriate interfaces, create a proxy class that 62 * implements those interfaces, create a marshalled object from that 63 * proxy class, and finally call .get() on that object. Get of the 64 * object should pass in some cases and fail in others. 65 * 66 * 1. Nonpublic interface loaded from the parent of the First 67 * Non-Null class Loader on the execution stack (FNNL). Public 68 * interface loaded from grandparent of FNNL parent. Proxy class must 69 * be defined in non-null FNNL parent. Should succeed. 70 * 71 * 2. Nonpublic interface (java.util.zip.ZipConstants) and public 72 * interface (java.util.zip.CheckSum) loaded from bootclasspath, 73 * proxy class defined in null/boot class loader. Should succeed. 74 * 75 * 3. Public interface classes loaded in FNNL are also available in 76 * RMI loader parent. FNNL is grandparent of RMI loader. Proxy class 77 * must be defined in RMI class loader. Should succeed. public 78 * interface must be defined in FNNL. 79 * 80 * 4. Non-public interfaces have multiple class loaders. Should fail 81 * with a LinkageError. 82 * 83 * 5. Interface classes loaded from RMI class loader. Proxy class 84 * defined in RMI class loader. 85 * 86 * 6. Not all interfaces classes can be loaded from a single class 87 * loader; should fail with ClassNotFoundException. All interface 88 * classes will exist (but not all interfaces will be available from 89 * one class loader). 90 * 91 * 7. prove that proxy loader has correct annotation. 92 * 93 * 8. REMIND: may want to add a case where the FNNL is null (This 94 * would be for class unmarshalling in the implemntation of a remote 95 * method invocation). 96 */ 97 public class LoadProxyClasses { 98 99 private static URL publicUrl = null; 100 101 public static boolean boomerangSemantics = false; 102 main(String[] args)103 public static void main(String[] args) { 104 try { 105 System.err.println("\nFunctional test to verify that RMI " + 106 "loads proxy classes correctly\n"); 107 108 /* install proxy interfaces */ 109 publicUrl = 110 TestLibrary.installClassInCodebase("PublicInterface", 111 "public"); 112 URL publicUrl1 = 113 TestLibrary.installClassInCodebase("PublicInterface1", 114 "public1"); 115 URL nonpublicUrl = 116 TestLibrary.installClassInCodebase("NonpublicInterface", 117 "nonpublic", false); 118 URL nonpublicUrl1 = 119 TestLibrary.installClassInCodebase("NonpublicInterface1", 120 "nonpublic1", false); 121 URL bothNonpublicUrl = 122 TestLibrary.installClassInCodebase("NonpublicInterface", 123 "bothNonpublic"); 124 TestLibrary.installClassInCodebase("NonpublicInterface1", 125 "bothNonpublic"); 126 URL fnnUrl = 127 TestLibrary.installClassInCodebase("FnnClass", "fnn"); 128 129 TestLibrary.suggestSecurityManager(null); 130 131 132 /* Case 1 */ 133 ClassLoader grandParentPublic = 134 new URLClassLoader(new URL[] {publicUrl}); 135 ClassLoader parentNonpublic = 136 new URLClassLoader(new URL[] {nonpublicUrl}, 137 grandParentPublic); 138 URLClassLoader fnnLoader1 = 139 new URLClassLoader(new URL[] {fnnUrl}, parentNonpublic); 140 141 Class nonpublicInterface = 142 fnnLoader1.loadClass("NonpublicInterface"); 143 Class publicInterface = 144 fnnLoader1.loadClass("PublicInterface"); 145 146 Proxy proxy1 = (Proxy) Proxy.newProxyInstance(parentNonpublic, 147 new Class[] {nonpublicInterface, publicInterface}, 148 new TestInvocationHandler()); 149 unmarshalProxyClass(proxy1, fnnLoader1, parentNonpublic, 1, null); 150 151 152 153 /* Case 2 */ 154 Class zipConstantsClass = 155 Class.forName("java.util.zip.ZipConstants"); 156 URLClassLoader fnnLoader2 = 157 new URLClassLoader(new URL[] {fnnUrl}); 158 Proxy proxy2 = (Proxy) Proxy.newProxyInstance(null, 159 new Class[] {zipConstantsClass, Checksum.class}, 160 new TestInvocationHandler()); 161 unmarshalProxyClass(proxy2, fnnLoader2, 162 (ClassLoader) null, 2, null); 163 164 165 166 /* Case 3 */ 167 Thread currentThread = Thread.currentThread(); 168 ClassLoader fnnLoader3 = new URLClassLoader( 169 new URL[] {publicUrl, fnnUrl}); 170 ClassLoader newCtxLoader = 171 new URLClassLoader(new URL[] {publicUrl}, fnnLoader3); 172 Class publicInterface3 = 173 fnnLoader3.loadClass("PublicInterface"); 174 ClassLoader currentCtxLoader = 175 currentThread.getContextClassLoader(); 176 currentThread.setContextClassLoader(newCtxLoader); 177 178 Proxy proxy3 = (Proxy) Proxy.newProxyInstance(newCtxLoader, 179 new Class[] {publicInterface3}, 180 new TestInvocationHandler()); 181 182 unmarshalProxyClass(proxy3, fnnLoader3, fnnLoader3, 183 3, new Case3Checker()); 184 185 currentThread.setContextClassLoader(currentCtxLoader); 186 187 188 189 /* Case 4 */ 190 ClassLoader bothNonpublicLoader = 191 new URLClassLoader(new URL[] {bothNonpublicUrl}); 192 Class nonpublicInterface4a = 193 bothNonpublicLoader.loadClass("NonpublicInterface"); 194 Class nonpublicInterface4b = 195 bothNonpublicLoader.loadClass("NonpublicInterface1"); 196 Proxy proxy4 = (Proxy) Proxy.newProxyInstance(bothNonpublicLoader, 197 new Class[] {nonpublicInterface4a, nonpublicInterface4b}, 198 new TestInvocationHandler()); 199 200 ClassLoader nonpublicLoaderA = 201 new URLClassLoader(new URL[] {nonpublicUrl}); 202 ClassLoader nonpublicLoaderB = 203 new URLClassLoader(new URL[] {nonpublicUrl1}, nonpublicLoaderA); 204 currentCtxLoader = 205 currentThread.getContextClassLoader(); 206 currentThread.setContextClassLoader(nonpublicLoaderB); 207 208 IllegalAccessError illegal = null; 209 try { 210 unmarshalProxyClass(proxy4, fnnLoader2, nonpublicLoaderB, 211 4, null); 212 } catch (IllegalAccessError e) { 213 illegal = e; 214 } 215 216 if (illegal == null) { 217 TestLibrary.bomb("case4: IllegalAccessError not thrown " + 218 "when multiple nonpublic interfaces have \n" + 219 "different class loaders"); 220 } else { 221 System.err.println("\ncase4: IllegalAccessError correctly " + 222 "thrown \n when trying to load proxy " + 223 "with multiple nonpublic interfaces in \n" + 224 " different class loaders"); 225 } 226 currentThread.setContextClassLoader(currentCtxLoader); 227 228 229 230 /* Case 5*/ 231 ClassLoader publicLoader = 232 new URLClassLoader(new URL[] {publicUrl}); 233 Class publicInterface5 = 234 publicLoader.loadClass("PublicInterface"); 235 Proxy proxy5 = (Proxy) Proxy.newProxyInstance(publicLoader, 236 new Class[] {publicInterface5}, 237 new TestInvocationHandler()); 238 239 currentCtxLoader = 240 currentThread.getContextClassLoader(); 241 currentThread.setContextClassLoader(publicLoader); 242 unmarshalProxyClass(proxy5, fnnLoader2, publicLoader, 5, 243 new Case5Checker()); 244 currentThread.setContextClassLoader(currentCtxLoader); 245 246 247 248 /* Case 6 */ 249 ClassLoader fnnLoader6 = 250 new URLClassLoader(new URL[] {fnnUrl, publicUrl}); 251 ClassLoader publicLoader6 = 252 new URLClassLoader(new URL[] {publicUrl1}, fnnLoader6); 253 254 Class publicInterface6a = 255 publicLoader6.loadClass("PublicInterface1"); 256 Class publicInterface6b = 257 fnnLoader6.loadClass("PublicInterface"); 258 Proxy proxy6 = (Proxy) Proxy.newProxyInstance(publicLoader6, 259 new Class[] {publicInterface6a, publicInterface6b}, 260 new TestInvocationHandler()); 261 ClassNotFoundException cnfe = null; 262 try { 263 unmarshalProxyClass(proxy6, fnnLoader6, publicLoader6, 6, 264 null); 265 } catch (ClassNotFoundException e) { 266 cnfe = e; 267 } 268 if (cnfe == null) { 269 TestLibrary.bomb("ClassNotFoundException not thrown " + 270 "when not all proxy interfaces could " + 271 " be found in a single class loader "); 272 } else { 273 System.err.println("Case6: ClassNotFoundException " + 274 "correctly thrown when not all proxy" + 275 " interfaces could be found in a " + 276 "single class loader"); 277 cnfe.printStackTrace(); 278 } 279 280 System.err.println("TEST PASSED"); 281 282 } catch (Exception e) { 283 if (e instanceof RuntimeException) { 284 throw (RuntimeException) e; 285 } 286 TestLibrary.bomb(e); 287 } 288 } 289 290 291 private interface LoadChecker { checkLoad(Proxy proxy, ClassLoader expectedLoader)292 void checkLoad(Proxy proxy, ClassLoader expectedLoader); 293 } 294 unmarshalProxyClass(Proxy proxy, ClassLoader fnnLoader, ClassLoader expectedLoader, int n, LoadChecker checker)295 private static Proxy unmarshalProxyClass(Proxy proxy, 296 ClassLoader fnnLoader, 297 ClassLoader expectedLoader, 298 int n, 299 LoadChecker checker) 300 throws ClassNotFoundException, IOException, 301 InstantiationException, IllegalAccessException 302 { 303 FnnUnmarshal fnnUnmarshal = (FnnUnmarshal) 304 fnnLoader.loadClass("FnnClass").newInstance(); 305 Proxy unmarshalled = (Proxy) 306 fnnUnmarshal.unmarshal(new MarshalledObject(proxy)); 307 ClassLoader unmarshalledLoader = 308 unmarshalled.getClass().getClassLoader(); 309 310 if (checker != null) { 311 checker.checkLoad(unmarshalled, expectedLoader); 312 } else { 313 if (unmarshalledLoader != expectedLoader) { 314 TestLibrary.bomb("case" + n + ": proxy class not " + 315 "placed into incorrect loader: " + 316 unmarshalledLoader); 317 } else { 318 System.err.println("\ncase" + n + ": proxy class correctly" + 319 " placed into expected loader: " + 320 expectedLoader); 321 } 322 } 323 return proxy; 324 } 325 326 private static class Case3Checker implements LoadChecker { checkLoad(Proxy proxy, ClassLoader expectedLoader)327 public void checkLoad(Proxy proxy, ClassLoader expectedLoader) { 328 ClassLoader ifaceLoader = 329 proxy.getClass().getInterfaces()[0].getClassLoader(); 330 ClassLoader proxyLoader = proxy.getClass().getClassLoader(); 331 332 boolean proxyOk = false; 333 334 if (boomerangSemantics) { 335 ClassLoader ctxLoader = 336 Thread.currentThread().getContextClassLoader(); 337 if (proxyLoader == ctxLoader) { 338 proxyOk = true; 339 } 340 } else if (proxyLoader.getClass(). 341 getName().indexOf("sun.rmi") >= 0) 342 { 343 proxyOk = true; 344 } 345 346 if (proxyOk) { 347 System.err.println("\ncase3: proxy loaded in" + 348 " correct loader: " + proxyLoader + 349 Arrays.asList(((URLClassLoader) 350 proxyLoader).getURLs())); 351 } else { 352 TestLibrary.bomb("case3: proxy class loaded in " + 353 "incorrect loader: " + proxyLoader + 354 Arrays.asList(((URLClassLoader) 355 proxyLoader).getURLs())); 356 } 357 358 if (ifaceLoader == expectedLoader) { 359 System.err.println("case3: proxy interface loaded in" + 360 " correct loader: " + ifaceLoader); 361 } else { 362 TestLibrary.bomb("public proxy interface loaded in " + 363 "incorrect loader: " + ifaceLoader); 364 } 365 } 366 } 367 368 private static class Case5Checker implements LoadChecker { checkLoad(Proxy proxy, ClassLoader expectedLoader)369 public void checkLoad(Proxy proxy, ClassLoader expectedLoader) { 370 ClassLoader proxyLoader = proxy.getClass().getClassLoader(); 371 372 String proxyAnnotation = 373 RMIClassLoader.getClassAnnotation(proxy.getClass()); 374 375 if ((proxyAnnotation == null) || 376 !proxyAnnotation.equals(publicUrl.toString())) 377 { 378 TestLibrary.bomb("proxy class had incorrect annotation: " + 379 proxyAnnotation); 380 } else { 381 System.err.println("proxy class had correct annotation: " + 382 proxyAnnotation); 383 } 384 385 boolean proxyOk = false; 386 387 if (boomerangSemantics) { 388 ClassLoader ctxLoader = 389 Thread.currentThread().getContextClassLoader(); 390 if (proxyLoader == ctxLoader) { 391 proxyOk = true; 392 } 393 } else if (proxyLoader.getClass(). 394 getName().indexOf("sun.rmi") >= 0) 395 { 396 proxyOk = true; 397 } 398 399 if (proxyOk) { 400 System.err.println("\ncase5: proxy loaded from" + 401 " correct loader: " + proxyLoader); 402 } else { 403 TestLibrary.bomb("case5: proxy interface loaded from " + 404 "incorrect loader: " + proxyLoader); 405 } 406 } 407 } 408 409 private static class TestInvocationHandler 410 implements InvocationHandler, Serializable 411 { invoke(Object proxy, Method method, Object[] args)412 public Object invoke(Object proxy, Method method, Object[] args) 413 throws Throwable {return null;} 414 } 415 } 416