/**
*
*/
package ecologylab.oodss.distributed.impl;
import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import java.nio.channels.SelectionKey;
import ecologylab.collections.Scope;
import ecologylab.net.NetTools;
import ecologylab.oodss.distributed.common.SessionObjects;
import ecologylab.oodss.distributed.server.NIOServerDataReader;
import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager;
import ecologylab.oodss.messages.InitConnectionRequest;
import ecologylab.serialization.SimplTypesScope;
/**
* Provides access to an NIOServerIOThread, which handles the details of network connections.
* Subclasses extend and provide functionality for actually processing messages.
*
* @author Zachary O. Toups (zach@ecologylab.net)
*/
public abstract class AbstractNIOServer<S extends Scope> extends Manager implements
NIOServerDataReader, Runnable, SessionObjects
{
private NIOServerIOThread backend;
protected SimplTypesScope translationScope;
protected S applicationObjectScope;
/**
* Creates an instance of an NIOServer of some flavor. Creates the backend using the information
* in the arguments.
*
* Registers itself as the MAIN_START_AND_STOPPABLE in the object registry.
*
* @param portNumber
* @param inetAddress
* @param translationScope
* @param objectRegistry
* @throws IOException
* @throws BindException
*/
protected AbstractNIOServer(int portNumber, InetAddress[] inetAddress,
SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout,
int maxMessageLength) throws IOException, BindException
{
backend = this.generateBackend(portNumber, inetAddress, composeTranslations(portNumber,
inetAddress[0], requestTranslationSpace), objectRegistry, idleConnectionTimeout,
maxMessageLength);
debug("setting up NIO Server...");
// we get these from the backend, because it ensures that they are
// configured if they are passed in null
this.translationScope = backend.translationScope;
this.applicationObjectScope = (S) backend.objectRegistry;
this.applicationObjectScope.put(MAIN_START_AND_STOPPABLE, this);
this.applicationObjectScope.put(MAIN_SHUTDOWNABLE, this);
}
static final Class[] OUR_TRANSLATIONS =
{ InitConnectionRequest.class, };
public static SimplTypesScope composeTranslations(int portNumber, InetAddress inetAddress,
SimplTypesScope requestTranslationSpace)
{
return composeTranslations(OUR_TRANSLATIONS, "nio_server_base: ", portNumber, inetAddress
.toString(), requestTranslationSpace);
}
public static SimplTypesScope composeTranslations(Class[] newTranslations, String prefix,
int portNumber, String inetAddress, SimplTypesScope requestTranslationSpace)
{
return SimplTypesScope.get(prefix + inetAddress.toString() + ":" + portNumber,
requestTranslationSpace, newTranslations);
}
/**
* Creates an instance of an NIOServer of some flavor. Creates the backend using the information
* in the arguments.
*
* Registers itself as the MAIN_START_AND_STOPPABLE in the object registry.
*
* @param portNumber
* @param inetAddress
* @param translationScope
* @param objectRegistry
* @throws IOException
* @throws BindException
*/
protected AbstractNIOServer(int portNumber, InetAddress inetAddress,
SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout,
int maxMessageLength) throws IOException, BindException
{
this(portNumber, NetTools.wrapSingleAddress(inetAddress), requestTranslationSpace,
objectRegistry, idleConnectionTimeout, maxMessageLength);
}
protected NIOServerIOThread generateBackend(int portNumber, InetAddress[] inetAddresses,
SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout,
int maxMessageLength) throws BindException, IOException
{
return NIOServerIOThread.getInstance(portNumber, inetAddresses, this, requestTranslationSpace,
objectRegistry, idleConnectionTimeout, maxMessageLength);
}
protected abstract BaseSessionManager generateContextManager(String sessionId, SelectionKey sk,
SimplTypesScope translationScope, Scope globalScope);
/**
* @see ecologylab.generic.StartAndStoppable#start()
*/
@Override
public void start()
{
try
{
backend.openSelector();
backend.registerAcceptWithSelector();
backend.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* @see ecologylab.generic.StartAndStoppable#stop()
*/
@Override
public void stop()
{
backend.stop();
}
/**
* @return the backend
*/
public NIOServerIOThread getBackend()
{
return backend;
}
/**
* @return the global scope for this server
*/
public Scope getGlobalScope()
{
return applicationObjectScope;
}
/**
* @return the translationScope
*/
public SimplTypesScope getTranslationSpace()
{
return translationScope;
}
}