/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.connectivity;
import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/**
* Implements a server thread. Each request from the client gets its own instance. <p/>Response to three different
* commands: <br/>Command.CREATE, Command.INVOKE and Command.CLOSE. <p/>It redirects the method invocation to the
* Invoker for the class.
*
* @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a>
*/
public class RemoteProxyServerThread implements Runnable {
/**
* The socket.
*/
private final Socket m_socket;
/**
* The input stream.
*/
private ObjectInputStream m_in = null;
/**
* The output stream.
*/
private ObjectOutputStream m_out = null;
/**
* The class loader to use.
*/
private ClassLoader m_loader = null;
/**
* The custom invoker instance.
*/
private Invoker m_invoker = null;
/**
* The time-out for the socket.
*/
private int m_timeout = 60000;
/**
* Is-running flag.
*/
private boolean m_running = true;
/**
* Creates a new instance.
*
* @param clientSocket the client socket
* @param loader the classloader to use
* @param invoker the invoker that makes the method invocation in the client thread
*/
public RemoteProxyServerThread(final Socket clientSocket,
final ClassLoader loader,
final Invoker invoker,
final int timeout) {
if (clientSocket == null) {
throw new IllegalArgumentException("client socket can not be null");
}
m_socket = clientSocket;
m_loader = loader;
m_invoker = invoker;
m_timeout = timeout;
}
/**
* Does the actual work of serving the client.
*/
public void run() {
Thread.currentThread().setContextClassLoader(m_loader);
try {
m_socket.setTcpNoDelay(true);
m_socket.setSoTimeout(m_timeout);
m_in = new ObjectInputStream(m_socket.getInputStream());
m_out = new ObjectOutputStream(m_socket.getOutputStream());
} catch (IOException e) {
throw new WrappedRuntimeException(e);
}
while (m_running) {
try {
switch (m_in.read()) {
case Command.CREATE:
handleCreateCommand();
break;
case Command.INVOKE:
handleInvocationCommand();
break;
case Command.CLOSE:
m_running = false;
break;
default:
break;
}
} catch (Exception e) {
close();
throw new WrappedRuntimeException(e);
}
}
close();
}
/**
* Handles the command CREATE.
*
* @throws IOException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
private void handleCreateCommand() throws IOException,
ClassNotFoundException,
InstantiationException,
IllegalAccessException {
final String className = (String) m_in.readObject();
Class klass = Class.forName(className, false, m_loader);
final Object instance = klass.newInstance();
final String handle = RemoteProxy.wrapInstance(instance);
m_out.writeObject(handle);
m_out.flush();
}
/**
* Handles the command INVOKE.
*
* @throws IOException
* @throws ClassNotFoundException
*/
private void handleInvocationCommand() throws IOException, ClassNotFoundException {
final Object context = m_in.readObject();
final String handle = (String) m_in.readObject();
final String methodName = (String) m_in.readObject();
final Class[] paramTypes = (Class[]) m_in.readObject();
final Object[] args = (Object[]) m_in.readObject();
Object result = null;
try {
result = m_invoker.invoke(handle, methodName, paramTypes, args, context);
} catch (Exception e) {
result = e;
}
m_out.writeObject(result);
m_out.flush();
}
/**
* Close the input/output streams along with the socket.
*/
private void close() {
try {
if (m_in != null) {
m_in.close();
}
if (m_out != null) {
m_out.close();
}
if (m_socket != null) {
m_socket.close();
}
} catch (IOException e) {
throw new WrappedRuntimeException(e);
}
}
}