001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.aspectwerkz.connectivity;
005:
006: import com.tc.aspectwerkz.exception.WrappedRuntimeException;
007:
008: import java.io.IOException;
009: import java.io.ObjectInputStream;
010: import java.io.ObjectOutputStream;
011: import java.net.Socket;
012:
013: /**
014: * Implements a server thread. Each request from the client gets its own instance. <p/>Response to three different
015: * commands: <br/>Command.CREATE, Command.INVOKE and Command.CLOSE. <p/>It redirects the method invocation to the
016: * Invoker for the class.
017: *
018: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
019: */
020: public class RemoteProxyServerThread implements Runnable {
021: /**
022: * The socket.
023: */
024: private final Socket m_socket;
025:
026: /**
027: * The input stream.
028: */
029: private ObjectInputStream m_in = null;
030:
031: /**
032: * The output stream.
033: */
034: private ObjectOutputStream m_out = null;
035:
036: /**
037: * The class loader to use.
038: */
039: private ClassLoader m_loader = null;
040:
041: /**
042: * The custom invoker instance.
043: */
044: private Invoker m_invoker = null;
045:
046: /**
047: * The time-out for the socket.
048: */
049: private int m_timeout = 60000;
050:
051: /**
052: * Is-running flag.
053: */
054: private boolean m_running = true;
055:
056: /**
057: * Creates a new instance.
058: *
059: * @param clientSocket the client socket
060: * @param loader the classloader to use
061: * @param invoker the invoker that makes the method invocation in the client thread
062: */
063: public RemoteProxyServerThread(final Socket clientSocket,
064: final ClassLoader loader, final Invoker invoker,
065: final int timeout) {
066: if (clientSocket == null) {
067: throw new IllegalArgumentException(
068: "client socket can not be null");
069: }
070: m_socket = clientSocket;
071: m_loader = loader;
072: m_invoker = invoker;
073: m_timeout = timeout;
074: }
075:
076: /**
077: * Does the actual work of serving the client.
078: */
079: public void run() {
080: Thread.currentThread().setContextClassLoader(m_loader);
081: try {
082: m_socket.setTcpNoDelay(true);
083: m_socket.setSoTimeout(m_timeout);
084: m_in = new ObjectInputStream(m_socket.getInputStream());
085: m_out = new ObjectOutputStream(m_socket.getOutputStream());
086: } catch (IOException e) {
087: throw new WrappedRuntimeException(e);
088: }
089: while (m_running) {
090: try {
091: switch (m_in.read()) {
092: case Command.CREATE:
093: handleCreateCommand();
094: break;
095: case Command.INVOKE:
096: handleInvocationCommand();
097: break;
098: case Command.CLOSE:
099: m_running = false;
100: break;
101: default:
102: break;
103: }
104: } catch (Exception e) {
105: close();
106: throw new WrappedRuntimeException(e);
107: }
108: }
109: close();
110: }
111:
112: /**
113: * Handles the command CREATE.
114: *
115: * @throws IOException
116: * @throws ClassNotFoundException
117: * @throws InstantiationException
118: * @throws IllegalAccessException
119: */
120: private void handleCreateCommand() throws IOException,
121: ClassNotFoundException, InstantiationException,
122: IllegalAccessException {
123: final String className = (String) m_in.readObject();
124: Class klass = Class.forName(className, false, m_loader);
125: final Object instance = klass.newInstance();
126: final String handle = RemoteProxy.wrapInstance(instance);
127: m_out.writeObject(handle);
128: m_out.flush();
129: }
130:
131: /**
132: * Handles the command INVOKE.
133: *
134: * @throws IOException
135: * @throws ClassNotFoundException
136: */
137: private void handleInvocationCommand() throws IOException,
138: ClassNotFoundException {
139: final Object context = m_in.readObject();
140: final String handle = (String) m_in.readObject();
141: final String methodName = (String) m_in.readObject();
142: final Class[] paramTypes = (Class[]) m_in.readObject();
143: final Object[] args = (Object[]) m_in.readObject();
144: Object result = null;
145: try {
146: result = m_invoker.invoke(handle, methodName, paramTypes,
147: args, context);
148: } catch (Exception e) {
149: result = e;
150: }
151: m_out.writeObject(result);
152: m_out.flush();
153: }
154:
155: /**
156: * Close the input/output streams along with the socket.
157: */
158: private void close() {
159: try {
160: if (m_in != null) {
161: m_in.close();
162: }
163: if (m_out != null) {
164: m_out.close();
165: }
166: if (m_socket != null) {
167: m_socket.close();
168: }
169: } catch (IOException e) {
170: throw new WrappedRuntimeException(e);
171: }
172: }
173: }
|