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