/** * EasyBeans * Copyright (C) 2007 Bull S.A.S. * Contact: easybeans@ow2.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * -------------------------------------------------------------------------- * $Id: TestSingleSmartFactory.java 5369 2010-02-24 14:58:19Z benoitf $ * -------------------------------------------------------------------------- */ package org.ow2.easybeans.component.smartclient.test; import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; import org.ow2.easybeans.component.smartclient.client.AskingClassLoader; import org.ow2.easybeans.component.smartclient.server.SmartClientEndPointComponent; import org.ow2.easybeans.component.smartclient.spi.SmartContextFactory; import org.ow2.util.url.URLUtils; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * Tests for the Smart Factory. * @author Florent BENOIT */ public class TestSingleSmartFactory { /** * RMi registry port. */ public static final int RMI_REGISTRY_PORT = 15100; /** * Other RMi registry port. */ public static final int RMI2_REGISTRY_PORT = 15102; /** * Smart endpoint port number. */ public static final int SMART_ENDPOINT_PORT = 15101; /** * Smart endpoint 2 port number. */ public static final int SMART2_ENDPOINT_PORT = 15103; /** * RMi Factory. */ private static final String JRMP_RMI_FACTORY = "com.sun.jndi.rmi.registry.RegistryContextFactory"; /** * Tmp directory for dumping files. */ private File tmpDir = null; /** * Registry object. */ private Registry registry = null; /** * Other Registry object. */ private Registry registry2 = null; /** * Endpoint. */ private SmartClientEndPointComponent endpoint = null; /** * Other Endpoint. */ private SmartClientEndPointComponent endpoint2 = null; /** * Endpoint classloader. */ private ClassLoader endpointClassLoader = null; /** * Initial Context. */ private Context initialContext = null; /** * Other Initial Context. */ private Context initialContext2 = null; /** * Initialize a registry and smart context. * @throws Exception if components are not initialized */ @BeforeClass public void init() throws Exception { // Create a registry this.registry = LocateRegistry.createRegistry(RMI_REGISTRY_PORT); // Create the associated registry component DummyRegistryComponent registryComponent = new DummyRegistryComponent(); registryComponent.setProviderURL("rmi://localhost:" + RMI_REGISTRY_PORT); // Create a registry this.registry2 = LocateRegistry.createRegistry(RMI2_REGISTRY_PORT); // Create the associated registry component DummyRegistryComponent registry2Component = new DummyRegistryComponent(); registry2Component.setProviderURL("rmi://localhost:" + RMI2_REGISTRY_PORT); // Dir for dumping generated class this.tmpDir = new File(System.getProperty("java.io.tmpdir") + File.separator + System.getProperty("user.name") + File.separator + "easybeans-smart-test"); if (!this.tmpDir.exists()) { this.tmpDir.mkdirs(); } // Create a Smart Endpoint component on a special classloader in order // to provide class only on this classloader and to be able to download // the class final URL tmpDirURL = URLUtils.fileToURL(this.tmpDir); PrivilegedAction<URLClassLoader> privilegedAction = new PrivilegedAction<URLClassLoader>() { public URLClassLoader run() { return new URLClassLoader(new URL[] {tmpDirURL}, Thread.currentThread().getContextClassLoader()); } }; this.endpointClassLoader = AccessController.doPrivileged(privilegedAction); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.endpointClassLoader); this.endpoint = new SmartClientEndPointComponent(); this.endpoint.setPortNumber(SMART_ENDPOINT_PORT); this.endpoint.setRegistryComponent(registryComponent); this.endpoint.init(); this.endpoint.start(); this.endpoint2 = new SmartClientEndPointComponent(); this.endpoint2.setPortNumber(SMART2_ENDPOINT_PORT); this.endpoint2.setRegistryComponent(registry2Component); this.endpoint2.init(); this.endpoint2.start(); } finally { Thread.currentThread().setContextClassLoader(oldCl); } } /** * Try to access to the remote factory. * @throws Exception if it fails */ @Test public void testAccessSmartFactory() throws Exception { Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.PROVIDER_URL, "smart://localhost:" + SMART_ENDPOINT_PORT); env.put(SmartContextFactory.EASYBEANS_SMART_JNDI_FACTORY, JRMP_RMI_FACTORY); env.put(Context.INITIAL_CONTEXT_FACTORY, SmartContextFactory.class.getName()); this.initialContext = new InitialContext(env); } /** * Try to access to the other remote factory. * @throws Exception if it fails */ @Test public void testAccessSmartFactory2() throws Exception { Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.PROVIDER_URL, "smart://localhost:" + SMART2_ENDPOINT_PORT); env.put(SmartContextFactory.EASYBEANS_SMART_JNDI_FACTORY, JRMP_RMI_FACTORY); env.put(Context.INITIAL_CONTEXT_FACTORY, SmartContextFactory.class.getName()); this.initialContext2 = new InitialContext(env); } /** * Check if the Initial Context when using smart context is linked to the * remote RMIi context. * @throws Exception if environment is not retrieved. */ @Test(dependsOnMethods = "testAccessSmartFactory") public void testGetProviderURL() throws Exception { Assert.assertEquals(this.initialContext.getEnvironment().get(Context.PROVIDER_URL), "rmi://localhost:" + RMI_REGISTRY_PORT); } /** * Check if the Initial Context when using smart context is linked to the * remote RMIi context. * @throws Exception if environment is not retrieved. */ @Test(dependsOnMethods = "testAccessSmartFactory2") public void testGetProviderURL2() throws Exception { Assert.assertEquals(this.initialContext2.getEnvironment().get(Context.PROVIDER_URL), "rmi://localhost:" + RMI2_REGISTRY_PORT); } /** * Helper method that try to load a class that was dynamically generated on * the endpoint side ! * @param askingClassLoader the classloader that download classes * @param className the name of the class * @param methodContent the content of the method to check * @throws Exception if class is not obtained. */ protected void downloadAndUseClass(final AskingClassLoader askingClassLoader, final String className, final String methodContent) throws Exception { // Define our class String packageName = "testSingleSmartFactory"; String fullClassName = packageName + "." + className; byte[] bytes = GenerateClass.getByteForClass(fullClassName.replace('.', '/'), methodContent); // Dump this bytes to a classrugby chabal file (if done in memory the endpoint can't // get the bytes) File pkgDir = new File(this.tmpDir, packageName); pkgDir.mkdir(); FileOutputStream fos = new FileOutputStream(new File(pkgDir, className + ".class")); fos.write(bytes); fos.close(); // Try to find my class (that was generated at runtime !) Class<?> myClass = askingClassLoader.loadClass(fullClassName); Assert.assertNotNull(myClass, "the class '" + className + "' was not found"); // build an instance Object o = myClass.newInstance(); Method helloMethod = myClass.getMethod("hello"); Assert.assertNotNull(helloMethod, "the method hello was not found on '" + helloMethod + "'."); // Call method Assert.assertEquals(methodContent, helloMethod.invoke(o)); } /** * Try to load a class that was dynamically generated on the endpoint side ! * @throws Exception if class is not obtained. */ @Test public void testLoadingClass() throws Exception { AskingClassLoader askingClassLoader = new AskingClassLoader("localhost", SMART_ENDPOINT_PORT); downloadAndUseClass(askingClassLoader, "buildclass", "hello smart factory !"); } /** * Try to load a class that was dynamically generated on the endpoint side ! * @throws Exception if class is not obtained. */ @Test public void testLoadingClass2() throws Exception { AskingClassLoader askingClassLoader = new AskingClassLoader("localhost", SMART2_ENDPOINT_PORT); downloadAndUseClass(askingClassLoader, "buildclass2", "hello smart factory 2!"); } /** * Stop all registries started. * @throws Exception if registry is not stopped */ @AfterClass(alwaysRun = true) public void stopRegistry() throws Exception { if (this.registry != null) { UnicastRemoteObject.unexportObject(this.registry, true); this.registry = null; } if (this.registry2 != null) { UnicastRemoteObject.unexportObject(this.registry2, true); this.registry2 = null; } } /** * Stop all endpoint started. * @throws Exception if endpoint is not stopped */ @AfterClass(alwaysRun = true) public void stopEndPoint() throws Exception { if (this.endpoint != null) { this.endpoint.stop(); } if (this.endpoint2 != null) { this.endpoint2.stop(); } } }