View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.connectivity;
9   
10  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  
12  import java.io.IOException;
13  import java.io.ObjectInputStream;
14  import java.io.ObjectOutputStream;
15  import java.net.Socket;
16  
17  /***
18   * Implements a server thread. Each request from the client gets its own instance. <p/>Response to three different
19   * commands: <br/>Command.CREATE, Command.INVOKE and Command.CLOSE. <p/>It redirects the method invocation to the
20   * Invoker for the class.
21   * 
22   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
23   */
24  public class RemoteProxyServerThread implements Runnable {
25      /***
26       * The socket.
27       */
28      private final Socket m_socket;
29  
30      /***
31       * The input stream.
32       */
33      private ObjectInputStream m_in = null;
34  
35      /***
36       * The output stream.
37       */
38      private ObjectOutputStream m_out = null;
39  
40      /***
41       * The class loader to use.
42       */
43      private ClassLoader m_loader = null;
44  
45      /***
46       * The custom invoker instance.
47       */
48      private Invoker m_invoker = null;
49  
50      /***
51       * The time-out for the socket.
52       */
53      private int m_timeout = 60000;
54  
55      /***
56       * Is-running flag.
57       */
58      private boolean m_running = true;
59  
60      /***
61       * Creates a new instance.
62       * 
63       * @param clientSocket the client socket
64       * @param loader the classloader to use
65       * @param invoker the invoker that makes the method invocation in the client thread
66       */
67      public RemoteProxyServerThread(final Socket clientSocket,
68                                     final ClassLoader loader,
69                                     final Invoker invoker,
70                                     final int timeout) {
71          if (clientSocket == null) {
72              throw new IllegalArgumentException("client socket can not be null");
73          }
74          m_socket = clientSocket;
75          m_loader = loader;
76          m_invoker = invoker;
77          m_timeout = timeout;
78      }
79  
80      /***
81       * Does the actual work of serving the client.
82       */
83      public void run() {
84          Thread.currentThread().setContextClassLoader(m_loader);
85          try {
86              m_socket.setTcpNoDelay(true);
87              m_socket.setSoTimeout(m_timeout);
88              m_in = new ObjectInputStream(m_socket.getInputStream());
89              m_out = new ObjectOutputStream(m_socket.getOutputStream());
90          } catch (IOException e) {
91              throw new WrappedRuntimeException(e);
92          }
93          while (m_running) {
94              try {
95                  switch (m_in.read()) {
96                      case Command.CREATE:
97                          handleCreateCommand();
98                          break;
99                      case Command.INVOKE:
100                         handleInvocationCommand();
101                         break;
102                     case Command.CLOSE:
103                         m_running = false;
104                         break;
105                     default:
106                         break;
107                 }
108             } catch (Exception e) {
109                 close();
110                 throw new WrappedRuntimeException(e);
111             }
112         }
113         close();
114     }
115 
116     /***
117      * Handles the command CREATE.
118      * 
119      * @throws IOException
120      * @throws ClassNotFoundException
121      * @throws InstantiationException
122      * @throws IllegalAccessException
123      */
124     private void handleCreateCommand() throws IOException,
125             ClassNotFoundException,
126             InstantiationException,
127             IllegalAccessException {
128         final String className = (String) m_in.readObject();
129         Class klass = m_loader.loadClass(className);
130         final Object instance = klass.newInstance();
131         final String handle = RemoteProxy.wrapInstance(instance);
132         m_out.writeObject(handle);
133         m_out.flush();
134     }
135 
136     /***
137      * Handles the command INVOKE.
138      * 
139      * @throws IOException
140      * @throws ClassNotFoundException
141      */
142     private void handleInvocationCommand() throws IOException, ClassNotFoundException {
143         final Object context = m_in.readObject();
144         final String handle = (String) m_in.readObject();
145         final String methodName = (String) m_in.readObject();
146         final Class[] paramTypes = (Class[]) m_in.readObject();
147         final Object[] args = (Object[]) m_in.readObject();
148         Object result = null;
149         try {
150             result = m_invoker.invoke(handle, methodName, paramTypes, 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 }