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