org.astrogrid.samp.client
Class HubConnector

java.lang.Object
  extended by org.astrogrid.samp.client.HubConnector
Direct Known Subclasses:
GuiHubConnector

public class HubConnector
extends Object

Manages a client's connection to SAMP hubs. Normally SAMP client applications will use one instance of this class for as long as they are running. It provides the following services:

This object provides a getConnection() method which provides the currently active HubConnection object if one exists or can be acquired. The HubConnection can be used for direct calls on the running hub, but in some cases similar methods with additional functionality exist in this class:

declareMetadata
declareSubscriptions
These methods not only make the relevant declarations to the existing hub connection, if one exists, but will retain the metadata and subscriptions information and declare them to other connections if the hub connection is terminated and restarted (with either the same or a different hub) over the lifetime of this object.
callAndWait
Provides identical semantics to the similarly named HubConnection method, but communicates with the hub asynchronously and fakes the synchrony at the client end. This is more robust and almost certainly a better idea.
call
callAll
Convenience methods to make asynchronous calls without having to worry about registering handlers which match up message tags.

It is good practice to call setActive(false) when this object is finished with; however if it is not called explicitly, any open connection will unregister itself on object finalisation or JVM termination, as long as the JVM shuts down cleanly.

Examples

Here is an example of what use of this class might look like:
   // Construct a connector
   ClientProfile profile = DefaultClientProfile.getProfile();
   HubConnector conn = new HubConnector(profile)

   // Configure it with metadata about this application
   Metadata meta = new Metadata();
   meta.setName("Foo");
   meta.setDescriptionText("Application that does stuff");
   conn.declareMetadata(meta);

   // Prepare to receive messages with specific MType(s)
   conn.addMessageHandler(new AbstractMessageHandler("stuff.do") {
       public Map processCall(HubConnection c, String senderId, Message msg) {
           // do stuff
       }
   });

   // This step required even if no custom message handlers added.
   conn.declareSubscriptions(conn.computeSubscriptions());

   // Keep a look out for hubs if initial one shuts down
   conn.setAutoconnect(10);

   // Broadcast a message
   conn.getConnection().notifyAll(new Message("stuff.event.doing"));
 

A real example, including use of the GUI hooks, can be found in the HubMonitor client source code.

Backwards Compatibility Note

This class does less than it did in earlier versions; the functionality which is no longer here can now be found in the GuiHubConnector class instead.

Since:
15 Jul 2008
Author:
Mark Taylor

Constructor Summary
HubConnector(ClientProfile profile)
          Constructs a HubConnector based on a given profile instance.
HubConnector(ClientProfile profile, TrackedClientSet clientSet)
          Constructs a HubConnector based on a given profile instance using a custom client set implementation.
 
Method Summary
 void addMessageHandler(MessageHandler handler)
          Adds a MessageHandler to this connector, which allows it to respond to incoming messages.
 void addResponseHandler(ResponseHandler handler)
          Adds a ResponseHandler to this connector, which allows it to receive replies from messages sent asynchronously.
 void call(String recipientId, Map msg, ResultHandler resultHandler, int timeout)
          Sends a message asynchronously to a single client, making a callback on a supplied ResultHandler object when the result arrives.
 void callAll(Map msg, ResultHandler resultHandler, int timeout)
          Sends a message asynchronously to all subscribed clients, making callbacks on a supplied ResultHandler object when the results arrive.
 Response callAndWait(String recipientId, Map msg, int timeout)
          Sends a message synchronously to a client, waiting for the response.
 Subscriptions computeSubscriptions()
          Works out the subscriptions map for this connector.
 void configureConnection(HubConnection connection)
          Configures a connection with a hub in accordance with the state of this object.
protected  void connectionChanged(boolean isConnected)
          Method which is called every time this connector changes its connection status (from disconnected to connected, or vice versa).
protected  HubConnection createConnection()
          Invoked by this class to create a hub connection.
 String createTag(Object owner)
          Generates a new msgTag for use with this connector.
 void declareMetadata(Map meta)
          Declares the metadata for this client.
 void declareSubscriptions(Map subscriptions)
          Declares the MType subscriptions for this client.
protected  void disconnect()
          Unregisters from the currently connected hub, if any.
 Map getClientMap()
          Returns a map which keeps track of other clients currently registered with the hub to which this object is connected, including their currently declared metadata and subscriptions.
protected  TrackedClientSet getClientSet()
          Returns the tracked client set implementation which is used to keep track of the currently registered clients.
 HubConnection getConnection()
          If necessary attempts to acquire, and returns, a connection to a running hub.
 Metadata getMetadata()
          Returns this client's own metadata.
 Subscriptions getSubscriptions()
          Returns this client's own subscriptions.
 boolean isConnected()
          Indicates whether this connector is currently registered with a running hub.
 void removeMessageHandler(MessageHandler handler)
          Removes a previously-added MessageHandler to this connector.
 void removeResponseHandler(ResponseHandler handler)
          Removes a ResponseHandler from this connector.
 void setActive(boolean active)
          Sets whether this connector is active or not.
 void setAutoconnect(int autoSec)
          Sets the interval at which this connector attempts to connect to a hub if no connection currently exists.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

HubConnector

public HubConnector(ClientProfile profile)
Constructs a HubConnector based on a given profile instance. A default client set implementation is used.

Parameters:
profile - profile implementation

HubConnector

public HubConnector(ClientProfile profile,
                    TrackedClientSet clientSet)
Constructs a HubConnector based on a given profile instance using a custom client set implementation.

Parameters:
profile - profile implementation
clientSet - object to keep track of registered clients
Method Detail

setAutoconnect

public void setAutoconnect(int autoSec)
Sets the interval at which this connector attempts to connect to a hub if no connection currently exists. Otherwise, a connection will be attempted whenever getConnection() is called.

Parameters:
autoSec - number of seconds between attempts; <=0 means no automatic connections are attempted

declareMetadata

public void declareMetadata(Map meta)
Declares the metadata for this client. This declaration affects the current connection and any future ones.

Parameters:
meta - Metadata-like map

getMetadata

public Metadata getMetadata()
Returns this client's own metadata.

Returns:
metadata

declareSubscriptions

public void declareSubscriptions(Map subscriptions)
Declares the MType subscriptions for this client. This declaration affects the current connection and any future ones.

Note that this call must be made, with a subscription list which includes the various hub administrative messages, in order for this connector to act on those messages (for instance to update its client map and so on). For this reason, it is usual to call it with the subs argument given by the result of calling computeSubscriptions().

Parameters:
subscriptions - Subscriptions-like map

getSubscriptions

public Subscriptions getSubscriptions()
Returns this client's own subscriptions.

Returns:
subscriptions

computeSubscriptions

public Subscriptions computeSubscriptions()
Works out the subscriptions map for this connector. This is based on the subscriptions declared by for any MessageHandlers installed in this connector as well as any MTypes which this connector implements internally. The result of this method is usually a suitable value to pass to declareSubscriptions(java.util.Map). However you might wish to remove some entries from the result if there are temporarily unsubscribed services.

Returns:
subscription list for MTypes apparently implemented by this connector

addMessageHandler

public void addMessageHandler(MessageHandler handler)
Adds a MessageHandler to this connector, which allows it to respond to incoming messages. Note that this does not in itself update the list of subscriptions for this connector; you may want to follow it with a call to
    declareSubscriptions(computeSubscriptions());
 

Parameters:
handler - handler to add

removeMessageHandler

public void removeMessageHandler(MessageHandler handler)
Removes a previously-added MessageHandler to this connector. Note that this does not in itself update the list of subscriptions for this connector; you may want to follow it with a call to
    declareSubscriptions(computeSubscriptions());
 

Parameters:
handler - handler to remove

addResponseHandler

public void addResponseHandler(ResponseHandler handler)
Adds a ResponseHandler to this connector, which allows it to receive replies from messages sent asynchronously.

Note however that this class's callAndWait method can provide a synchronous facade for fully asynchronous messaging, which in many cases will be more convenient than installing your own response handlers to deal with asynchronous replies.

Parameters:
handler - handler to add

removeResponseHandler

public void removeResponseHandler(ResponseHandler handler)
Removes a ResponseHandler from this connector.

Parameters:
handler - handler to remove

setActive

public void setActive(boolean active)
Sets whether this connector is active or not. If set false, any existing connection will be terminated (the client will unregister) and autoconnection attempts will be suspended. If set true, if there is no existing connection an attempt will be made to register, and autoconnection attempts will begin if applicable.

Parameters:
active - whether this connector should be active
See Also:
setAutoconnect(int)

callAndWait

public Response callAndWait(String recipientId,
                            Map msg,
                            int timeout)
                     throws SampException
Sends a message synchronously to a client, waiting for the response. If more seconds elapse than the value of the timeout parameter, an exception will result.

The semantics of this call are, as far as the caller is concerned, identical to that of the similarly named HubConnection method. However, in this case the client communicates with the hub asynchronously and internally simulates the synchrony for the caller, rather than letting the hub do that. This is more robust and almost certainly a better idea.

Parameters:
recipientId - public-id of client to receive message
msg - Message-like map
timeout - timeout in seconds, or <=0 for no timeout
Returns:
response
Throws:
SampException

call

public void call(String recipientId,
                 Map msg,
                 ResultHandler resultHandler,
                 int timeout)
          throws SampException
Sends a message asynchronously to a single client, making a callback on a supplied ResultHandler object when the result arrives. The ResultHandler.done() method will be called after the result has arrived or the timeout elapses, whichever happens first.

This convenience method allows the user to make an asynchronous call without having to worry registering message handlers and matching message tags.

Parameters:
recipientId - public-id of client to receive message
msg - Message-like map
resultHandler - object called back when response arrives or timeout is exceeded
timeout - timeout in seconds, or <=0 for no timeout
Throws:
SampException

callAll

public void callAll(Map msg,
                    ResultHandler resultHandler,
                    int timeout)
             throws SampException
Sends a message asynchronously to all subscribed clients, making callbacks on a supplied ResultHandler object when the results arrive. The ResultHandler.done() method will be called after all the results have arrived or the timeout elapses, whichever happens first.

This convenience method allows the user to make an asynchronous call without having to worry registering message handlers and matching message tags.

Parameters:
msg - Message-like map
resultHandler - object called back when response arrives or timeout is exceeded
timeout - timeout in seconds, or <=0 for no timeout
Throws:
SampException

isConnected

public boolean isConnected()
Indicates whether this connector is currently registered with a running hub. If true, the result of getConnection() will be non-null.

Returns:
true if currently connected to a hub

getConnection

public HubConnection getConnection()
                            throws SampException
If necessary attempts to acquire, and returns, a connection to a running hub. If there is an existing connection representing a registration with a hub, it is returned. If not, and this connector is active, an attempt is made to connect and register, followed by a call to configureConnection, is made.

Note that if setActive(false) has been called, null will be returned.

Returns:
hub connection representing configured registration with a hub if a hub is running; if not, null
Throws:
SampException - in the case of some unexpected error

configureConnection

public void configureConnection(HubConnection connection)
                         throws SampException
Configures a connection with a hub in accordance with the state of this object. The hub is made aware of how to perform callbacks on the registered client, and any current metadata and subscriptions are declared.

Parameters:
connection - connection representing registration with a hub
Throws:
SampException

getClientMap

public Map getClientMap()
Returns a map which keeps track of other clients currently registered with the hub to which this object is connected, including their currently declared metadata and subscriptions. Map keys are public IDs and values are Clients.

This map is synchronized which means that to iterate over any of its views you must synchronize on it. When the map or any of its contents changes, it will receive a Object.notifyAll().

To keep itself up to date, the client map reads hub status messages. These will only be received if declareSubscriptions(computeSubscriptions()) has been called. Hence, this method should only be called after declareSubscriptions(java.util.Map) has been called. If this order is not observed, a warning will be emitted through the logging system.

Returns:
id->Client map

getClientSet

protected TrackedClientSet getClientSet()
Returns the tracked client set implementation which is used to keep track of the currently registered clients.

Returns:
client set implementation

createConnection

protected HubConnection createConnection()
                                  throws SampException
Invoked by this class to create a hub connection. The default implementation just calls profile.register().

Returns:
new hub connection
Throws:
SampException

disconnect

protected void disconnect()
Unregisters from the currently connected hub, if any. Performs any associated required cleanup.


connectionChanged

protected void connectionChanged(boolean isConnected)
Method which is called every time this connector changes its connection status (from disconnected to connected, or vice versa). The default implementation does nothing, but it may be overridden by subclasses wishing to be informed of these events.

Parameters:
isConnected - true if we've just registered; false if we've just unregistered

createTag

public String createTag(Object owner)
Generates a new msgTag for use with this connector. It is guaranteed to return a different value on each invocation. It is advisable to use this method whenever a message tag is required to prevent clashes.

Parameters:
owner - object to identify caller (not really necessary - may be null)
Returns:
unique tag for this connector


Copyright © 2008-2011 AstroGrid. All Rights Reserved.