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 = Class.forName(className, false, m_loader);
    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 }