ecologylab.services.distributed.server.clientmanager
Class AbstractClientManager

java.lang.Object
  extended by ecologylab.generic.Debug
      extended by ecologylab.services.distributed.server.clientmanager.AbstractClientManager
All Implemented Interfaces:
NetworkingConstants, ServerConstants
Direct Known Subclasses:
ClientManager, HTTPClientManager

public abstract class AbstractClientManager
extends Debug
implements ServerConstants

The base class for all ContextManagers, objects which track the state and respond to clients on a server. There is a one-to-one correspondence between connected clients and ContextManager instances. AbstractContextManager handles all encoding and decoding of messages, as well as translating them. Hook methods provide places where subclasses may modify behavior for specific purposes. Typical usage is to have the context manager's request queue be filled by a network thread, while it is emptied by a working thread. The normal cycle for filling the queue is to call acquireIncomingSequenceBuf() to clear and get the incomingCharBuffer, then fill it externally (normally passing it as an argument to a CharsetDecoder.decode call), then calling processIncomingSequenceBufToQueue() to release it and let the ContextManager store the characters, converting messages into objects as they become available. For a complete, basic implementation (which is suitable for most uses), see ContextManager.

Author:
Zachary O. Toups (toupsz@cs.tamu.edu)

Field Summary
protected  NIOServerFrontend frontend
          The frontend for the server that is running the ContextManager.
protected  java.lang.StringBuilder headerBufOutgoing
          Stores outgoing header character data.
protected  java.util.HashMap<java.lang.String,java.lang.String> headerMap
          Stores the key-value pairings from a parsed HTTP-like header on an incoming message.
protected  boolean initialized
          Indicates whether the first request message has been received.
protected  int maxPacketSize
           
protected  boolean messageWaiting
          Indicates whether or not one or more messages are queued for execution by this ContextManager.
protected  java.lang.StringBuilder msgBufIncoming
          Stores incoming character data until it can be parsed into an XML message and turned into a Java object.
protected  java.lang.StringBuilder msgBufOutgoing
          Stores outgoing character data for ResponseMessages.
protected  Scope<?> registry
          The ObjectRegistry that is used by the processRequest method of each incoming RequestMessage.
protected  java.util.Queue<MessageWithMetadata<RequestMessage>> requestQueue
          A queue of the requests to be performed by this ContextManager.
protected  NIOServerBackend server
          The network communicator that will handle all the reading and writing for the socket associated with this ContextManager
protected  java.lang.Object sessionId
          sessionId uniquely identifies this ContextManager.
protected  java.nio.channels.SelectionKey socketKey
          The selection key for this context manager.
protected  java.lang.StringBuilder startLine
           
protected  int startReadIndex
           
protected  TranslationSpace translationSpace
          Used to translate incoming message XML strings into RequestMessages.
 
Fields inherited from interface ecologylab.services.distributed.common.ServerConstants
GARBAGE_CONNECTION_CLEANUP_TIMEOUT, MAX_CONNECTIONS, MAXIMUM_TRANSMISSION_ERRORS
 
Fields inherited from interface ecologylab.services.distributed.common.NetworkingConstants
CHARACTER_ENCODING, CONTENT_LENGTH_STRING, CONTENT_LENGTH_STRING_LENGTH, DECODER, ENCODER, HTTP_HEADER_LINE_DELIMITER, HTTP_HEADER_TERMINATOR, MAX_HTTP_HEADER_LENGTH, MAX_PACKET_SIZE_BYTES, MAX_PACKET_SIZE_CHARACTERS, UNIQUE_IDENTIFIER_STRING
 
Constructor Summary
AbstractClientManager(java.lang.Object sessionId, int maxPacketSize, NIOServerBackend server, NIOServerFrontend frontend, java.nio.channels.SelectionKey socket, TranslationSpace translationSpace, Scope<?> registry)
          Creates a new ContextManager.
 
Method Summary
protected abstract  void clearOutgoingMessageBuffer(java.lang.StringBuilder outgoingMessageBuf)
           
protected abstract  void clearOutgoingMessageHeaderBuffer(java.lang.StringBuilder outgoingMessageHeaderBuf)
           
protected abstract  void createHeader(java.lang.StringBuilder outgoingMessageBuf, java.lang.StringBuilder outgoingMessageHeaderBuf, RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid)
           
protected  void enqueueRequest(MessageWithMetadata<RequestMessage> request)
          Adds the given request to this's request queue.
 long getLastActivity()
          Indicates the last System timestamp was when the ContextManager had any activity.
protected  MessageWithMetadata<RequestMessage> getNextRequest()
          Returns the next message in the request queue.
 java.nio.channels.SelectionKey getSocketKey()
           
 boolean isInitialized()
          Indicates whether or not this context manager has been initialized.
 boolean isMessageWaiting()
          Indicates whether there are any messages queued up to be processed.
protected  int parseHeader(int startChar, java.lang.StringBuilder allIncomingChars)
          Parses the header of an incoming set of characters (i.e.
protected  ResponseMessage performService(RequestMessage requestMessage)
          Appends the sender's IP address to the incoming message and calls performService on the given RequestMessage using the local ObjectRegistry.
protected abstract  void prepareBuffers(java.lang.StringBuilder incomingMessageBuf, java.lang.StringBuilder outgoingMessageBuf, java.lang.StringBuilder outgoingMessageHeaderBuf)
           
 void processAllMessagesAndSendResponses()
          Calls processRequest(RequestMessage) on each queued message as they are acquired through getNextRequest() and finishing when isMessageWaiting() returns false.
 void processIncomingSequenceBufToQueue(java.nio.CharBuffer incomingSequenceBuf)
          Extracts messages from the given CharBuffer, using HTTP-like headers, converting them into RequestMessage instances, then enqueues those instances.
 void setSocket(java.nio.channels.SelectionKey socket)
          Sets the SelectionKey, and sets the new SelectionKey to have the same attachment (session id) as the old one.
 void shutdown()
          Hook method for having shutdown behavior.
protected abstract  void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, ResponseMessage responseMessage, java.lang.StringBuilder messageBuffer)
           
protected  RequestMessage translateStringToRequestMessage(java.lang.CharSequence messageString)
          Translates the given XML String into a RequestMessage object.
 
Methods inherited from class ecologylab.generic.Debug
classSimpleName, closeLoggingFile, debug, debug, debug, debug, debugA, debugA, debugA, debugI, debugI, debugI, error, error, getClassName, getClassName, getInteractive, getPackageName, getPackageName, getPackageName, initialize, level, level, level, logToFile, print, print, println, println, println, println, println, println, printlnA, printlnA, printlnA, printlnI, printlnI, printlnI, printlnI, setLoggingFile, show, show, superString, toggleInteractive, toString, toString, warning, warning, weird, weird
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

headerMap

protected final java.util.HashMap<java.lang.String,java.lang.String> headerMap
Stores the key-value pairings from a parsed HTTP-like header on an incoming message.


startReadIndex

protected int startReadIndex

msgBufIncoming

protected final java.lang.StringBuilder msgBufIncoming
Stores incoming character data until it can be parsed into an XML message and turned into a Java object.


msgBufOutgoing

protected final java.lang.StringBuilder msgBufOutgoing
Stores outgoing character data for ResponseMessages.


headerBufOutgoing

protected final java.lang.StringBuilder headerBufOutgoing
Stores outgoing header character data.


startLine

protected final java.lang.StringBuilder startLine

messageWaiting

protected boolean messageWaiting
Indicates whether or not one or more messages are queued for execution by this ContextManager.


requestQueue

protected final java.util.Queue<MessageWithMetadata<RequestMessage>> requestQueue
A queue of the requests to be performed by this ContextManager. Subclasses may override functionality and not use requestQueue.


registry

protected Scope<?> registry
The ObjectRegistry that is used by the processRequest method of each incoming RequestMessage.


server

protected NIOServerBackend server
The network communicator that will handle all the reading and writing for the socket associated with this ContextManager


frontend

protected NIOServerFrontend frontend
The frontend for the server that is running the ContextManager. This is needed in case the client attempts to restore a session, in which case the frontend must be queried for the old ContextManager.


socketKey

protected java.nio.channels.SelectionKey socketKey
The selection key for this context manager.


sessionId

protected java.lang.Object sessionId
sessionId uniquely identifies this ContextManager. It is used to restore the state of a lost connection.


maxPacketSize

protected int maxPacketSize

translationSpace

protected TranslationSpace translationSpace
Used to translate incoming message XML strings into RequestMessages.


initialized

protected boolean initialized
Indicates whether the first request message has been received. The first request may be an InitConnection, which has special properties.

Constructor Detail

AbstractClientManager

public AbstractClientManager(java.lang.Object sessionId,
                             int maxPacketSize,
                             NIOServerBackend server,
                             NIOServerFrontend frontend,
                             java.nio.channels.SelectionKey socket,
                             TranslationSpace translationSpace,
                             Scope<?> registry)
Creates a new ContextManager.

Parameters:
sessionId -
maxPacketSize -
server -
frontend -
socket -
translationSpace -
registry -
Method Detail

processIncomingSequenceBufToQueue

public final void processIncomingSequenceBufToQueue(java.nio.CharBuffer incomingSequenceBuf)
                                             throws java.nio.charset.CharacterCodingException,
                                                    BadClientException
Extracts messages from the given CharBuffer, using HTTP-like headers, converting them into RequestMessage instances, then enqueues those instances. enqueueStringMessage will normally be called repeatedly, as new data comes in from a client. It will automatically parse messages that are split up over multiple reads, and will handle multiple messages in one read, if necessary.

Parameters:
message - the CharBuffer containing one or more messages, or pieces of messages.
Throws:
java.nio.charset.CharacterCodingException
BadClientException

getLastActivity

public final long getLastActivity()
Indicates the last System timestamp was when the ContextManager had any activity.

Returns:
the last System timestamp indicating when the ContextManager had any activity.

getSocketKey

public java.nio.channels.SelectionKey getSocketKey()
Returns:
the socket

isMessageWaiting

public boolean isMessageWaiting()
Indicates whether there are any messages queued up to be processed. isMessageWaiting() should be overridden if getNextRequest() is overridden so that it properly reflects the way that getNextRequest() works; it may also be important to override enqueueRequest().

Returns:
true if getNextRequest() can return a value, false if it cannot.

processAllMessagesAndSendResponses

public final void processAllMessagesAndSendResponses()
                                              throws BadClientException
Calls processRequest(RequestMessage) on each queued message as they are acquired through getNextRequest() and finishing when isMessageWaiting() returns false. The functionality of processAllMessagesAndSendResponses() may be overridden by overridding the following methods: isMessageWaiting(), processRequest(RequestMessage), getNextRequest().

Throws:
BadClientException

setSocket

public void setSocket(java.nio.channels.SelectionKey socket)
Sets the SelectionKey, and sets the new SelectionKey to have the same attachment (session id) as the old one.

Parameters:
socket - the socket to set

shutdown

public void shutdown()
Hook method for having shutdown behavior. This method is called whenever the client terminates their connection or when the server is shutting down.


clearOutgoingMessageBuffer

protected abstract void clearOutgoingMessageBuffer(java.lang.StringBuilder outgoingMessageBuf)

clearOutgoingMessageHeaderBuffer

protected abstract void clearOutgoingMessageHeaderBuffer(java.lang.StringBuilder outgoingMessageHeaderBuf)

createHeader

protected abstract void createHeader(java.lang.StringBuilder outgoingMessageBuf,
                                     java.lang.StringBuilder outgoingMessageHeaderBuf,
                                     RequestMessage incomingRequest,
                                     ResponseMessage outgoingResponse,
                                     long uid)

enqueueRequest

protected void enqueueRequest(MessageWithMetadata<RequestMessage> request)
Adds the given request to this's request queue. enqueueRequest(RequestMessage) is a hook method for ContextManagers that need to implement other functionality, such as prioritizing messages. If enqueueRequest(RequestMessage) is overridden, the following methods should also be overridden: isMessageWaiting(), getNextRequest().

Parameters:
request -

getNextRequest

protected MessageWithMetadata<RequestMessage> getNextRequest()
Returns the next message in the request queue. getNextRequest() may be overridden to provide specific functionality, such as a priority queue. In this case, it is important to override the following methods: isMessageWaiting(), enqueueRequest().

Returns:
the next message in the requestQueue.

parseHeader

protected int parseHeader(int startChar,
                          java.lang.StringBuilder allIncomingChars)
Parses the header of an incoming set of characters (i.e. a message from a client to a server), loading all of the HTTP-like headers into the given headerMap. If headerMap is null, this method will throw a null pointer exception.

Parameters:
allIncomingChars - - the characters read from an incoming stream.
headerMap - - the map into which all of the parsed headers will be placed.
Returns:
the length of the parsed header, or -1 if it was not yet found.

performService

protected ResponseMessage performService(RequestMessage requestMessage)
Appends the sender's IP address to the incoming message and calls performService on the given RequestMessage using the local ObjectRegistry. performService(RequestMessage) may be overridden by subclasses to provide more specialized functionality. Generally, overrides should then call super.performService(RequestMessage) so that the IP address is appended to the message.

Parameters:
requestMessage -
Returns:

prepareBuffers

protected abstract void prepareBuffers(java.lang.StringBuilder incomingMessageBuf,
                                       java.lang.StringBuilder outgoingMessageBuf,
                                       java.lang.StringBuilder outgoingMessageHeaderBuf)

translateResponseMessageToStringBufferContents

protected abstract void translateResponseMessageToStringBufferContents(RequestMessage requestMessage,
                                                                       ResponseMessage responseMessage,
                                                                       java.lang.StringBuilder messageBuffer)
                                                                throws XMLTranslationException
Throws:
XMLTranslationException

translateStringToRequestMessage

protected RequestMessage translateStringToRequestMessage(java.lang.CharSequence messageString)
                                                  throws XMLTranslationException,
                                                         java.io.UnsupportedEncodingException
Translates the given XML String into a RequestMessage object. translateStringToRequestMessage(String) may be overridden to provide specific functionality, such as a ContextManager that does not use XML Strings.

Parameters:
messageString - - an XML String representing a RequestMessage object.
Returns:
the RequestMessage created by translating messageString into an object.
Throws:
XMLTranslationException - if an error occurs when translating from XML into a RequestMessage.
java.io.UnsupportedEncodingException - if the String is not encoded properly.

isInitialized

public boolean isInitialized()
Indicates whether or not this context manager has been initialized. Normally, this means that it has shared a session id with the client.

Returns: