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 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 { 292 void checkLoad(Proxy proxy, ClassLoader expectedLoader); 293 } 294 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 { 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 { 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 { 412 public Object invoke(Object proxy, Method method, Object[] args) 413 throws Throwable {return null;} 414 } 415 }