View Javadoc

1   /*
2    * Created on 17 Nov 2007
3    *
4    */
5   package org.sourceforge.jemmrpc.client;
6   
7   import java.io.IOException;
8   import java.net.Socket;
9   import java.util.HashMap;
10  import java.util.concurrent.ExecutorService;
11  import java.util.concurrent.Executors;
12  
13  import org.apache.log4j.Logger;
14  import org.sourceforge.jemmrpc.example.echo.EchoClient;
15  import org.sourceforge.jemmrpc.example.echo.EchoServer;
16  import org.sourceforge.jemmrpc.shared.IFUtilities;
17  import org.sourceforge.jemmrpc.shared.RPCHandler;
18  import org.sourceforge.jemmrpc.shared.RPCHandlerListener;
19  
20  /**
21   * RPCClient is the client end of an interface RPC connection. The class allows the client program
22   * to both make RPC calls to a server instance and also present interfaces for the server to call
23   * back on. See {@link EchoClient}/{@link EchoServer} for a simple example.
24   *
25   * @author Rory Graves
26   */
27  public class RPCClient implements RPCHandlerListener
28  {
29      protected static final Logger logger = Logger.getLogger(RPCClient.class);
30  
31      /** A map of the local interfaces offered by the client to the server */
32      protected HashMap<Class<?>, Object> localIFMap = new HashMap<Class<?>, Object>();
33  
34      /** The server hostname */
35      protected String hostname;
36  
37      /** The server port */
38      protected int port;
39  
40      /** The connection socket */
41      protected Socket socket;
42  
43      /** The underlying RPCHandler (calls are delegated) */
44      protected RPCHandler rpcHandler;
45  
46      /** A thread pool for handling server callback requests */
47      protected ExecutorService threadPool;
48  
49      protected volatile boolean connected = false;
50  
51      /**
52       * Creates an instance of Client. The client attempts to connect to the hostname/port specified
53       * and will throw an IOException on error
54       *
55       * @param hostname The servers hostname
56       * @param port The server's port
57       */
58      public RPCClient(String hostname, int port)
59      {
60          this.hostname = hostname;
61          this.port = port;
62      }
63  
64      /**
65       * Make the connection to the remote server.
66       *
67       * @throws IOException On connection error.
68       */
69      public void connect() throws IOException
70      {
71          logger.info("Connecting to: " + hostname + ":" + port);
72          socket = new Socket(hostname, port);
73          threadPool = Executors.newFixedThreadPool(10);
74          rpcHandler = new RPCHandler(true, socket, localIFMap, threadPool, null);
75          rpcHandler.setHandlerListener(this);
76          rpcHandler.start();
77          connected = true;
78      }
79  
80      /**
81       * Register an interface that the client offers for callback from the server.
82       *
83       * @param ifClass The interface being offered.
84       * @param ifImplentor The implementor of the interface that will process the requests
85       */
86      public void registerIF(Class<?> ifClass, Object ifImplentor)
87      {
88          IFUtilities.validateInterface(ifClass);
89  
90          if (ifImplentor.getClass().isInstance(ifClass))
91              throw new IllegalArgumentException(
92                      "given object does not implement interface");
93  
94          if (connected)
95              throw new IllegalStateException(
96                      "Can not register interface after connection to server established");
97  
98          localIFMap.put(ifClass, ifImplentor);
99      }
100 
101     /**
102      * Get a remote interface implemented by the server.
103      *
104      * @param ifClass The interface required.
105      * @return A proxy object implementing the remote interface.
106      */
107     public synchronized Object getServerIF(Class<?> ifClass)
108     {
109         if (!connected)
110             throw new IllegalStateException(
111                     "Can not get remote interfaces until connection to server established");
112 
113         return rpcHandler.getRemoteIF(ifClass);
114     }
115 
116     /**
117      * Close the connection to the server.
118      */
119     public void close()
120     {
121         connected = false;
122         rpcHandler.close();
123         threadPool.shutdown();
124     }
125 
126     /**
127      * Returns whether the client is connected to the server
128      *
129      * @return True if the client is connected, false otherwise.
130      */
131     public boolean isConnected()
132     {
133         return connected;
134     }
135 
136     /*
137      * (non-Javadoc)
138      *
139      * @see org.sourceforge.jemm.comm.shared.RPCHandlerListener#connectionTerminated()
140      */
141     public void connectionTerminated()
142     {
143         connected = false;
144     }
145 }