modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientFactory.java | 8 modules/enterprise/server/client-api/pom.xml | 7 modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java | 15 + modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java | 101 ++++++++++ 4 files changed, 127 insertions(+), 4 deletions(-)
New commits: commit c9cc6ed13db6d9d246611f627323abc86bd3f461 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Jan 31 19:11:25 2012 +0100
[BZ 786194] - Make sure to set the correct context classloader when simplifying the interfaces for the LocalClientProxy.
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml index 29ac29a..f200744 100644 --- a/modules/enterprise/server/client-api/pom.xml +++ b/modules/enterprise/server/client-api/pom.xml @@ -40,6 +40,13 @@ <version>1.0</version> <scope>provided</scope> </dependency> + + <dependency> + <groupId>org.rhq</groupId> + <artifactId>test-utils</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> </dependencies>
<profiles> diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java new file mode 100644 index 0000000..3b949e3 --- /dev/null +++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java @@ -0,0 +1,101 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2012 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.client.test; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + +import org.jmock.Expectations; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.enterprise.client.LocalClient; +import org.rhq.enterprise.server.alert.AlertManagerLocal; +import org.rhq.enterprise.server.alert.AlertManagerRemote; +import org.rhq.test.JMockTest; + +/** + * + * + * @author Lukas Krejci + */ +public class LocalClientTest extends JMockTest { + + public static class FakeContextFactory implements InitialContextFactory { + @Override + public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { + return CONTEXT_MOCK_FOR_TEST; + } + } + + public static Context CONTEXT_MOCK_FOR_TEST = null; + + @BeforeClass + public void setUpNaming() { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FakeContextFactory.class.getName()); + } + + @Test + public void testResilienceAgainstContextClassloaders() throws Exception { + CONTEXT_MOCK_FOR_TEST = context.mock(Context.class); + final AlertManagerRemote alertManagerMock = (AlertManagerRemote) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { AlertManagerRemote.class, AlertManagerLocal.class }, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } + + }); + + context.checking(new Expectations() {{ + allowing(CONTEXT_MOCK_FOR_TEST).lookup(with(any(String.class))); + will(returnValue(alertManagerMock)); + + allowing(CONTEXT_MOCK_FOR_TEST).close(); + }}); + + ClassLoader origCl = Thread.currentThread().getContextClassLoader(); + try { + ClassLoader differentCl = new URLClassLoader(new URL[0], getClass().getClassLoader()); + + Thread.currentThread().setContextClassLoader(differentCl); + + LocalClient lc = new LocalClient(null); + + //this call creates the proxy and is theoretically prone to the context classloader + AlertManagerRemote am = lc.getAlertManager(); + + //check that both the original and simplified methods exist on the returned object + am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class }); + am.getClass().getMethod("deleteAlerts", new Class<?>[] { int[].class }); + } finally { + Thread.currentThread().setContextClassLoader(origCl); + } + } +}
commit ef9f0ada2d2ac587d701da5ea03507b2fb74b8c3 Author: Lukas Krejci lkrejci@redhat.com Date: Mon Jan 30 18:37:21 2012 +0100
Make sure to set the correct context classloader when running inside a EJB container.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientFactory.java index 6f15e81..2c1258d 100644 --- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientFactory.java +++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientFactory.java @@ -199,7 +199,13 @@ public class ResourceClientFactory { } }
- return customClass.toClass(); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(ResourceClientProxy.class.getClassLoader()); + return customClass.toClass(); + } finally { + Thread.currentThread().setContextClassLoader(cl); + } } catch (NotFoundException e) { LOG.error("Could not create custom interface for resource with id " + proxy.getId(), e); } catch (CannotCompileException e) { diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java index 2414bf6..2e48048 100644 --- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java +++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java @@ -432,10 +432,19 @@ public class LocalClient implements RhqFacade { private <T> T getProxy(Object slsb, Class<T> iface) { RhqManagers manager = RhqManagers.forInterface(iface);
- Class<?> simplified = InterfaceSimplifier.simplify(iface); + Class<?> simplified = null; + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(iface.getClassLoader()); + simplified = InterfaceSimplifier.simplify(iface); + } finally { + Thread.currentThread().setContextClassLoader(cl); + }
- Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified }, - new LocalClientProxy(slsb, this, manager)); + Object proxy = + Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified }, new LocalClientProxy(slsb, + this, manager));
return iface.cast(proxy); }
rhq-commits@lists.fedorahosted.org