/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.remoting.classloader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import org.jboss.logging.Logger;
import org.jboss.remoting.invocation.NameBasedInvocation;
import org.jboss.test.remoting.ComplexReturn;
import org.jboss.test.remoting.transport.mock.MockTest;
import junit.framework.TestCase;
/**
* This is a copy of org.jboss.test.remoting.transport.socket.InvokerClientTest but
* uses custom classloader (and reflection) to load and make the remoting calls.
*
* @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
*/
public class InvokerClientTest extends TestCase
{
private int port = 8081;
private String transport = "socket";
private static final Logger log = Logger.getLogger(InvokerClientTest.class);
public void testArrayReturn() throws Throwable
{
String[] classUrls = new String[]{"org.jboss.util.threadpool.ThreadPool",
"javax.management.MBeanServerConnection",
"javax.servlet.ServletInputStream",
"org.apache.coyote.Adapter",
"org.jboss.serial.io.JBossObjectOutputStream",
"EDU.oswego.cs.dl.util.concurrent.SynchronizedLong"};
URL[] urls = getLibUrls(classUrls);
URLClassLoader urlclassloader = new URLClassLoader(urls, null);
TestClassLoader classloader = new TestClassLoader(urlclassloader);
/*
Class invokerLocator = loadClass("org.jboss.remoting.InvokerLocator", classloader);
Constructor invokerLocatorConstructor = invokerLocator.getConstructor(new Class[] { String.class});
Object invokerLocatorInstance = invokerLocatorConstructor.newInstance(new Object[] { transport + "://localhost:" + port});
loadClass("org.jboss.remoting.Invoker", classloader);
loadClass("org.jboss.remoting.loading.ClassByteClassLoader", classloader);
loadClass("org.jboss.remoting.transport.ClientInvoker", classloader);
loadClass("org.jboss.remoting.AbstractInvoker", classloader);
loadClass("org.jboss.remoting.transport.local.LocalClientInvoker", classloader);
loadClass("org.jboss.remoting.InvokerRegistry", classloader);
loadClass("org.jboss.remoting.InvalidConfigurationException", classloader);
loadClass("org.jboss.remoting.RemoteClientInvoker", classloader);
loadClass("org.jboss.remoting.transport.socket.SocketClientInvoker", classloader);
Class clientClz = loadClass("org.jboss.remoting.Client", classloader);
Constructor clientConstructor = clientClz.getConstructor(new Class[] {invokerLocator, String.class});
Object clientInstance = clientConstructor.newInstance(new Object[] {invokerLocatorInstance, "mock"});
*/
Class invokerLocator = Class.forName("org.jboss.remoting.InvokerLocator", false, classloader);
Constructor invokerLocatorConstructor = invokerLocator.getConstructor(new Class[]{String.class});
Object invokerLocatorInstance = invokerLocatorConstructor.newInstance(new Object[]{transport + "://localhost:" + port});
Class clientClz = Class.forName("org.jboss.remoting.Client", false, classloader);
Constructor clientConstructor = clientClz.getConstructor(new Class[]{invokerLocator, String.class});
Object clientInstance = clientConstructor.newInstance(new Object[]{invokerLocatorInstance, "mock"});
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
System.out.println("context classloader: " + contextClassLoader);
System.out.println("test classloader: " + classloader);
Class.forName("org.jboss.test.remoting.ComplexReturn", false, contextClassLoader);
Method connectMethod = clientClz.getMethod("connect", new Class[]{});
connectMethod.invoke(clientInstance, null);
// simple invoke, should return bar
Object ret = null;
NameBasedInvocation nbinv = new NameBasedInvocation("testComplexReturn",
new Object[]{null},
new String[]{String.class.getName()});
Method invokeMethod = clientClz.getMethod("invoke", new Class[]{Object.class, Map.class});
ret = invokeMethod.invoke(clientInstance, new Object[]{nbinv, null});
ComplexReturn complexRet = (ComplexReturn) ret;
MockTest[] mockTests = complexRet.getMockTests();
assertTrue("ComplexReturn's array should contain 2 items",
2 == mockTests.length);
if(2 == mockTests.length)
{
log.debug("PASS");
}
else
{
log.debug("FAILED - testArrayReturn1");
}
for(int x = 0; x < mockTests.length; x++)
{
System.err.println(mockTests[x]);
MockTest test = mockTests[x];
assertNotNull("MockTest should not be null", test);
if(test != null)
{
log.debug("PASS");
}
else
{
log.debug("FAILED - testArrayReturn2");
}
}
nbinv = new NameBasedInvocation("testThrowException",
new Object[]{null},
new String[]{String.class.getName()});
invokeMethod = clientClz.getMethod("invoke", new Class[]{Object.class, Map.class});
try
{
ret = invokeMethod.invoke(clientInstance, new Object[]{nbinv, null});
assertTrue("Should have thrown exception and not reached this assert.", false);
}
catch(Exception e)
{
assertTrue("Got exception thrown as expected", true);
}
invokeMethod = clientClz.getMethod("disconnect", new Class[]{});
invokeMethod.invoke(clientInstance, new Object[]{});
}
private URL[] getLibUrls(String[] classNames) throws Exception
{
URL[] urls = new URL[classNames.length + 1];
String url = null;
int i = -1;
int x = 0;
for(; x < classNames.length; x++)
{
String className = classNames[x];
int index = className.lastIndexOf('.');
String fileName = className.substring(index + 1);
Class clz = log.getClass().forName(className);
URL fileURL = clz.getResource(fileName + ".class");
if(fileURL == null)
{
throw new Exception(fileName + ".class file not found");
}
String fullURL = fileURL.getPath();
i = fullURL.indexOf("!");
url = fullURL.substring(0, i);
urls[x] = new URL(url);
}
String fileSep = System.getProperty("file.separator");
i = url.indexOf("lib");
String remotingJarPath = url.substring(0, i);
remotingJarPath = remotingJarPath + "output" + fileSep + "lib" + fileSep + "jboss-remoting.jar";
urls[x] = new URL(remotingJarPath);
return urls;
}
private static Class loadClass(String className, TestClassLoader classLoader) throws Exception
{
int index = className.lastIndexOf('.');
String fileName = className.substring(index + 1);
Class clz = log.getClass().forName(className);
URL fileURL = clz.getResource(fileName + ".class");
if(fileURL == null)
{
throw new Exception(fileName + ".class file not found");
}
File testFile = new File(fileURL.getFile());
FileInputStream fileInput = new FileInputStream(testFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buf[] = new byte[4096];
while(true)
{
int c = fileInput.read(buf);
if(c < 0)
{
break;
}
out.write(buf, 0, c);
}
byte[] bytes = out.toByteArray();
return classLoader.loadClass(className, bytes);
}
public static class TestClassLoader extends ClassLoader
{
/**
* Creates a new class loader using the specified parent class loader for
* delegation.
* <p/>
* <p> If there is a security manager, its {@link
* SecurityManager#checkCreateClassLoader()
* <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
* a security exception. </p>
*
* @param parent The parent class loader
* @throws SecurityException If a security manager exists and its
* <tt>checkCreateClassLoader</tt> method doesn't allow creation
* of a new class loader.
* @since 1.2
*/
protected TestClassLoader(ClassLoader parent)
{
super(parent);
}
protected Class loadClass(String className, byte[] classBytes) throws ClassNotFoundException
{
Class c = defineClass(className, classBytes, 0, classBytes.length);
resolveClass(c);
return Class.forName(className, false, this);
}
}
}