package ecologylab.oodss.distributed.server.clientsessionmanager; import java.nio.channels.SelectionKey; import ecologylab.collections.Scope; import ecologylab.oodss.distributed.common.ServerConstants; import ecologylab.oodss.distributed.impl.NIOServerIOThread; import ecologylab.oodss.distributed.server.NIOServerProcessor; import ecologylab.oodss.messages.RequestMessage; import ecologylab.oodss.messages.ResponseMessage; import ecologylab.oodss.messages.UpdateMessage; import ecologylab.serialization.SIMPLTranslationException; import ecologylab.serialization.SimplTypesScope; import ecologylab.serialization.formatenums.StringFormat; /** * Stores information about the connection context for the client on the server. Should be extended * for more specific implementations. Handles accumulating incoming messages and translating them * into RequestMessage objects, as well as the ability to perform the messages' services and send * their responses. * * Generally, this class can be driven by one or more threads, depending on the desired * functionality. * * On a server, there will be one ContextManager for each client connection. * * @author Zachary O. Toups (zach@ecologylab.net) */ public class ClientSessionManager<S extends Scope, PARENT extends Scope> extends TCPClientSessionManager<S, PARENT> implements ServerConstants { /** * Creates a new ContextManager. * * @param sessionId * @param maxPacketSize * @param server * @param frontend * @param socketKey * @param translationScope * @param registry */ public ClientSessionManager(String sessionId, int maxPacketSize, NIOServerIOThread server, NIOServerProcessor frontend, SelectionKey socketKey, SimplTypesScope translationScope, PARENT registry) { super(sessionId, maxPacketSize, server, frontend, socketKey, translationScope, registry); } /** * Prepares the internal buffer objects, which are passed in as parameters. * * This is a hook method, custom subclasses may wish to override it with different (or, in some * cases, no) functionality. * * This implementation adds "content-length: " to the outgoingMessageHeaderBuf for performance * purposes. Subclasses that do not use this optimization should override this method with one * that does nothing. */ @Override protected void prepareBuffers(StringBuilder outgoingMessageHeaderBuf) { outgoingMessageHeaderBuf.append(CONTENT_LENGTH_STRING + ":"); } /** * Clears the contents of the outgoingMessageHeaderBuffer so that it is prepared for the next * outgoing message. * * This implementation leaves "content-length:" so that it can be reused for the next message. * * @param outgoingMessageHeaderBuf */ @Override protected void clearOutgoingMessageHeaderBuffer(StringBuilder outgoingMessageHeaderBuf) { outgoingMessageHeaderBuf.delete(CONTENT_LENGTH_STRING_LENGTH + 1, outgoingMessageHeaderBuf .length()); } /** * Clears the contents of the outgoingMessageBuffer so that it is empty and ready to recieve a new * outgoing message. * * @param msgBufOutgoing */ @Override protected void clearOutgoingMessageBuffer(StringBuilder outgoingMessageBuf) { outgoingMessageBuf.delete(0, outgoingMessageBuf.length()); } /** * Generates the outgoing message header. This implementation assumes that the * outgoingMessageHeaderBuf contains "content-length: " and will add the content length, based on * the contents of msgBufOutgoing, however, custom implementations for more specific purposes may * be constructed. * * @param msgBufOutgoing * @param outgoingMessageHeaderBuf * @param incomingRequest * TODO * @param outgoingResponse * TODO */ @Override protected void createHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid) { outgoingMessageHeaderBuf.append(messageSize); outgoingMessageHeaderBuf.append(HTTP_HEADER_LINE_DELIMITER); outgoingMessageHeaderBuf.append(UNIQUE_IDENTIFIER_STRING); outgoingMessageHeaderBuf.append(':'); outgoingMessageHeaderBuf.append(uid); } /** * Generates the outgoing message header (for updates). This implementation * assumes that the outgoingMessageHeaderBuf contains "content-length: " and * will add the content length, based on the contents of msgBufOutgoing, * however, custom implementations for more specific purposes may be * constructed. * * @param messageSize * size of outgoing buffer * @param outgoingMessageHeaderBuf * buffer to put header parts in * @param update * update message going out */ @Override protected void makeUpdateHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, UpdateMessage<?> update) { outgoingMessageHeaderBuf.append(messageSize); } /** * Translates response into an XML string and adds an HTTP-like header, then returns the result. * * translateResponseMessageToString(RequestMessage, ResponseMessage) may be overridden to provide * more specific functionality; for example, for servers that use customized messages instead of * XML. * * @param requestMessage * - the current request. * @param responseMessage * - the ResponseMessage generated by processing requestMessage. * @param messageBuffer * - buffer must be passed in to this method -- it will contain the results of the * translation and will be used by the calling method to send data back to the client. * @return a String that constitutes a complete response message in XML with HTTP-like headers. */ @Override protected void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, ResponseMessage responseMessage, StringBuilder messageBuffer) throws SIMPLTranslationException { // debug("serializing response to client..."); // long currentTime = System.currentTimeMillis(); SimplTypesScope.serialize(responseMessage, messageBuffer, StringFormat.XML); // debug("...done ("+(System.currentTimeMillis()-currentTime)+"ms)"); } }