1d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit/** 2d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Copyright (C) 2008 Google Inc. 3d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * 4d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Licensed under the Apache License, Version 2.0 (the "License"); 5d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * you may not use this file except in compliance with the License. 6d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * You may obtain a copy of the License at 7d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * 8d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * http://www.apache.org/licenses/LICENSE-2.0 9d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * 10d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Unless required by applicable law or agreed to in writing, software 11d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * distributed under the License is distributed on an "AS IS" BASIS, 12d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * See the License for the specific language governing permissions and 14d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * limitations under the License. 15d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 16d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 17d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitpackage com.googlecode.guice; 18d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 19b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport static com.google.inject.matcher.Matchers.any; 20b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 21d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport com.google.inject.AbstractModule; 22d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport com.google.inject.Binder; 23d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport com.google.inject.Guice; 24d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport com.google.inject.Injector; 25d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport com.google.inject.Module; 26a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkitimport com.googlecode.guice.PackageVisibilityTestModule.PublicUserOfPackagePrivate; 27b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 28b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport junit.framework.TestCase; 29b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 30b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport org.aopalliance.intercept.MethodInterceptor; 31b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport org.aopalliance.intercept.MethodInvocation; 32b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 33d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.io.File; 34d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.lang.ref.Reference; 35d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.lang.ref.WeakReference; 361c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlinimport java.lang.reflect.Constructor; 37eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkitimport java.lang.reflect.Method; 38d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.net.MalformedURLException; 39d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.net.URL; 40d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitimport java.net.URLClassLoader; 418743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruberimport java.util.concurrent.TimeoutException; 42d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 43d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit/** 4446db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit * This test is in a separate package so we can test package-level visibility 4546db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit * with confidence. 4646db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit * 47d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * @author mcculls@gmail.com (Stuart McCulloch) 48d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 49d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkitpublic class BytecodeGenTest extends TestCase { 50d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 513697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit private final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); 523697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit 53d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit private final Module interceptorModule = new AbstractModule() { 54d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit protected void configure() { 55d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit bindInterceptor(any(), any(), new MethodInterceptor() { 56d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit public Object invoke(MethodInvocation chain) 57d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit throws Throwable { 58d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit return chain.proceed() + " WORLD"; 59d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 60d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit }); 61d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 62d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit }; 63d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 641c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin private final Module noopInterceptorModule = new AbstractModule() { 651c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin protected void configure() { 661c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin bindInterceptor(any(), any(), new MethodInterceptor() { 671c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public Object invoke(MethodInvocation chain) 681c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin throws Throwable { 691c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin return chain.proceed(); 701c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 711c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin }); 721c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 731c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin }; 741c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 7585fa885aecb69448bd624a56c8ea3bcb3c84ef1flimpbizkit public void testPackageVisibility() { 76a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit Injector injector = Guice.createInjector(new PackageVisibilityTestModule()); 77a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass. 78a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit } 79a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit 80a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit public void testInterceptedPackageVisibility() { 81a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule()); 8285fa885aecb69448bd624a56c8ea3bcb3c84ef1flimpbizkit injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass. 8385fa885aecb69448bd624a56c8ea3bcb3c84ef1flimpbizkit } 848743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber 85a102c17638ec586de3d6930c8ef794c751d157d6sberlin public void testEnhancerNaming() { 86a102c17638ec586de3d6930c8ef794c751d157d6sberlin Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule()); 87a102c17638ec586de3d6930c8ef794c751d157d6sberlin PublicUserOfPackagePrivate pupp = injector.getInstance(PublicUserOfPackagePrivate.class); 88a102c17638ec586de3d6930c8ef794c751d157d6sberlin assertTrue(pupp.getClass().getName().startsWith( 89a102c17638ec586de3d6930c8ef794c751d157d6sberlin PublicUserOfPackagePrivate.class.getName() + "$$EnhancerByGuice$$")); 90a102c17638ec586de3d6930c8ef794c751d157d6sberlin } 918743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber 92ec76179f50f9d8c340b311c6b019c00526566b66sberlin // TODO(sameb): Figure out how to test FastClass naming tests. 9385fa885aecb69448bd624a56c8ea3bcb3c84ef1flimpbizkit 94d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit /** 95d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Custom URL classloader with basic visibility rules 96d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 97d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit static class TestVisibilityClassLoader 98d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit extends URLClassLoader { 99d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 1001c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin boolean hideInternals; 1011c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 1021c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public TestVisibilityClassLoader(boolean hideInternals) { 103d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit super(new URL[0]); 104d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 1051c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin this.hideInternals = hideInternals; 1061c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 107d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit final String[] classpath = System.getProperty("java.class.path").split(File.pathSeparator); 108d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit for (final String element : classpath) { 109d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit try { 110d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // is it a remote/local URL? 111d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit addURL(new URL(element)); 112d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } catch (final MalformedURLException e1) { 113d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit try { 114d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // nope - perhaps it's a filename? 115d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit addURL(new File(element).toURI().toURL()); 116d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } catch (final MalformedURLException e2) { 117d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit throw new RuntimeException(e1); 118d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 119d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 120d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 121d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 122d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 123d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit /** 124d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Classic parent-delegating classloaders are meant to override findClass. 125d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * However, non-delegating classloaders (as used in OSGi) instead override 126d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * loadClass to provide support for "class-space" separation. 127d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 128d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit @Override 129d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit protected Class<?> loadClass(final String name, final boolean resolve) 130d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit throws ClassNotFoundException { 131d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 132eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit synchronized (this) { 133eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit // check our local cache to avoid duplicates 134eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit final Class<?> clazz = findLoadedClass(name); 135eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit if (clazz != null) { 136eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit return clazz; 137eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit } 138eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit } 139eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit 140d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit if (name.startsWith("java.")) { 141d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 142d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // standard bootdelegation of java.* 143d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit return super.loadClass(name, resolve); 144d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 145eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit } else if (!name.contains(".internal.") && !name.contains(".cglib.")) { 146d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 147d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit /* 148d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * load public and test classes directly from the classpath - we don't 149d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * delegate to our parent because then the loaded classes would also be 150d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * able to see private internal Guice classes, as they are also loaded 151d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * by the parent classloader. 152d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 153d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit final Class<?> clazz = findClass(name); 154d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit if (resolve) { 155d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit resolveClass(clazz); 156d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 157d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit return clazz; 158d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 159d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 160d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // hide internal non-test classes 1611c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin if (hideInternals) { 1621c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin throw new ClassNotFoundException(); 1631c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 1641c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin return super.loadClass(name, resolve); 165d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 166d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 167d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 168e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit /** as loaded by another class loader */ 169e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit private Class<ProxyTest> proxyTestClass; 170e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit private Class<ProxyTestImpl> realClass; 171e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit private Module testModule; 172e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit 173e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit @SuppressWarnings("unchecked") 174e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit protected void setUp() throws Exception { 175e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit super.setUp(); 176e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit 1771c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin ClassLoader testClassLoader = new TestVisibilityClassLoader(true); 178e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit proxyTestClass = (Class<ProxyTest>) testClassLoader.loadClass(ProxyTest.class.getName()); 179e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit realClass = (Class<ProxyTestImpl>) testClassLoader.loadClass(ProxyTestImpl.class.getName()); 180e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit 181e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit testModule = new AbstractModule() { 182e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit public void configure() { 183e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit bind(proxyTestClass).to(realClass); 184e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit } 185e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit }; 186e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit } 187e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit 188d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit interface ProxyTest { 189d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit String sayHello(); 190d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 191d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 192d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit /** 193d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * Note: this class must be marked as public or protected so that the Guice 194d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * custom classloader will intercept it. Private and implementation classes 195d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * are not intercepted by the custom classloader. 196ec76179f50f9d8c340b311c6b019c00526566b66sberlin * 19746db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit * @see com.google.inject.internal.BytecodeGen.Visibility 198d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 199d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit public static class ProxyTestImpl implements ProxyTest { 200d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 201d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit static { 202eb06177abdd178c9cc05312be7147e2ccc20becflimpbizkit //System.out.println(ProxyTestImpl.class.getClassLoader()); 203d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 204d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 205d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit public String sayHello() { 206d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit return "HELLO"; 207d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 208d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 209d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 210e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit public void testProxyClassLoading() throws Exception { 211e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit Object testObject = Guice.createInjector(interceptorModule, testModule) 212e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit .getInstance(proxyTestClass); 213d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 214e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit // verify method interception still works 215e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit Method m = realClass.getMethod("sayHello"); 216e731d19e9286db34e12c13e73e060e3bfe879837limpbizkit assertEquals("HELLO WORLD", m.invoke(testObject)); 217d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 218d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 219a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit public void testSystemClassLoaderIsUsedIfProxiedClassUsesIt() { 220d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit ProxyTest testProxy = Guice.createInjector(interceptorModule, new Module() { 221d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit public void configure(Binder binder) { 222d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit binder.bind(ProxyTest.class).to(ProxyTestImpl.class); 223d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 224d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit }).getInstance(ProxyTest.class); 225d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 2263697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit if (ProxyTest.class.getClassLoader() == systemClassLoader) { 2273697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit assertSame(testProxy.getClass().getClassLoader(), systemClassLoader); 2283697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit } else { 2293697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit assertNotSame(testProxy.getClass().getClassLoader(), systemClassLoader); 2303697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit } 231a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit } 2328743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber 233a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit public void testProxyClassUnloading() { 234a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit Object testObject = Guice.createInjector(interceptorModule, testModule) 235a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit .getInstance(proxyTestClass); 236a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit assertNotNull(testObject.getClass().getClassLoader()); 2373697a672aa70dc38d89270b6ac434cff16c053d8limpbizkit assertNotSame(testObject.getClass().getClassLoader(), systemClassLoader); 238a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit 239d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // take a weak reference to the generated proxy class 240a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit Reference<Class<?>> clazzRef = new WeakReference<Class<?>>(testObject.getClass()); 241d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 242d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit assertNotNull(clazzRef.get()); 243d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 244d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit // null the proxy 245a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit testObject = null; 246d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 247d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit /* 248d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * this should be enough to queue the weak reference 249d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit * unless something is holding onto it accidentally. 250d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit */ 2518743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber final int MAX_COUNT = 100; 252f7ac6ea677ccfff6c3bec7db1d3621e6b6cf4097sberlin String[] buf; 253d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit System.gc(); 2548743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber //TODO(cgruber): Use com.google.common.testing.GcFinalization and a countdown latch to un-flake. 2558743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber for (int count = 0 ; clazzRef.get() != null ; count++) { 2568743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber buf = new String[8 * 1024 * 1024]; 2578743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber buf = null; 2588743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber System.gc(); 2598743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber assertTrue("Timeout waiting for class to be unloaded. This may be a flaky result.", 2608743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber count <= MAX_COUNT); 2618743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber } 262d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 26346db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit // This test could be somewhat flaky when the GC isn't working. 26446db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit // If it fails, run the test again to make sure it's failing reliably. 2658743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber assertNull("Proxy class was not unloaded.", clazzRef.get()); 266d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 267a7184cfac7879bace6ea08d67adad86c21f2a19blimpbizkit 268d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit public void testProxyingPackagePrivateMethods() { 269d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit Injector injector = Guice.createInjector(interceptorModule); 2709da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit assertEquals("HI WORLD", injector.getInstance(PackageClassPackageMethod.class).sayHi()); 2719da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit assertEquals("HI WORLD", injector.getInstance(PublicClassPackageMethod.class).sayHi()); 27246db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit assertEquals("HI WORLD", injector.getInstance(ProtectedClassProtectedMethod.class).sayHi()); 273d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 274d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit 2759da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit static class PackageClassPackageMethod { 2769da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit String sayHi() { 2779da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit return "HI"; 2789da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit } 2799da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit } 2809da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit 2819da27072fad763a3bc2b869d2fd9b772269bdb45limpbizkit public static class PublicClassPackageMethod { 282d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit String sayHi() { 283d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit return "HI"; 284d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 285d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit } 28646db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit 28746db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit protected static class ProtectedClassProtectedMethod { 28846db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit protected String sayHi() { 28946db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit return "HI"; 29046db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit } 29146db36a3269b4f46528470cf70a8d6a04bcc24e4limpbizkit } 2921c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 2931c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin static class Hidden { 2941c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 2951c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 2961c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public static class HiddenMethodReturn { 2971c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public Hidden method() { 2981c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin return new Hidden(); 2991c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 3001c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 3011c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3021c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public static class HiddenMethodParameter { 3031c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public void method(Hidden h) { 3041c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 3051c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 3061c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3071c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin public void testClassLoaderBridging() throws Exception { 3081c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin ClassLoader testClassLoader = new TestVisibilityClassLoader(false); 3091c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3101c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Class hiddenMethodReturnClass = testClassLoader.loadClass(HiddenMethodReturn.class.getName()); 3111c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Class hiddenMethodParameterClass = testClassLoader.loadClass(HiddenMethodParameter.class.getName()); 3121c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3131c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Injector injector = Guice.createInjector(noopInterceptorModule); 3141c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3151c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Class hiddenClass = testClassLoader.loadClass(Hidden.class.getName()); 3161c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Constructor ctor = hiddenClass.getDeclaredConstructor(); 3171c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3181c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin ctor.setAccessible(true); 3191c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3201c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin // don't use bridging for proxies with private parameters 3211c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Object o1 = injector.getInstance(hiddenMethodParameterClass); 3221c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin o1.getClass().getDeclaredMethod("method", hiddenClass).invoke(o1, ctor.newInstance()); 3231c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin 3241c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin // don't use bridging for proxies with private return types 3251c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin Object o2 = injector.getInstance(hiddenMethodReturnClass); 3261c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin o2.getClass().getDeclaredMethod("method").invoke(o2); 3271c6ff880b9a83a833c6fc5fb4fc0e3a15bfb1f80sberlin } 328d8a06a4770ba6f6ea74473c8c03df5d56b5e1d1flimpbizkit} 329