package org.prevayler.foundation.network;
import java.io.IOException;
/**
* Inbound channel for a Server's network.
* Completes SessionId exchange in order to reconnect to the correct
* session. Informs the outbound channel of network reconnection.
* Forwards inbound data direct to the client. If an error occurs, closes
* the session and notifies the outbound channel (StubbornNetworkProxy).
*/
public class StubbornServerReceiverImpl implements ObjectReceiver, StubbornNetworkClientConnector {
private ObjectReceiver _provider;
private ObjectReceiver _client;
private StubbornNetworkProxy _proxy;
private Service _clientService;
private SessionsManager _sessionsManager;
private boolean _isOpen;
private NetworkSessionId _sessionId;
/**
* Provider has called in with a connection, need to get it going.
* First, I wait for their session id. If it matches an existing
* session, I hook them back together, if it is not found (ugh) or
* if it is zero (new session no history), I send them a new id.
*/
public StubbornServerReceiverImpl( ObjectReceiver provider, Service service, SessionsManager stubbornService){
_provider=provider;
_clientService=service;
_sessionsManager=stubbornService;
_isOpen=false;
}
public StubbornServerReceiverImpl( Service service, ObjectSocket socket, SessionsManager sessionsManager){
_clientService=service;
_sessionsManager=sessionsManager;
_provider=new NetworkClientObjectReceiverImpl(socket,this);
_isOpen=false;
}
public void receive( Object object) throws IOException {
if (_isOpen) {
_client.receive(object);
}
else {
handleSession(object);
}
}
public synchronized void close() throws IOException {
_isOpen=false;
if (_proxy != null) _proxy.disconnect();
}
private void handleSession( Object object){
if (!(object instanceof NetworkSessionId)) {
closeSession();
}
StubbornNetworkProxy proxy=reestablishSession((NetworkSessionId)object);
_isOpen=true;
send(_sessionId);
if (!_isOpen) {
return;
}
_proxy=proxy;
_proxy.connect(_provider,this);
}
private StubbornNetworkProxy establishNewSession(){
StubbornNetworkProxy proxy=new StubbornNetworkProxy();
_client=_clientService.serverFor(proxy);
proxy.setClient(_client);
_sessionId=_sessionsManager.add(proxy);
return proxy;
}
private StubbornNetworkProxy reestablishSession( NetworkSessionId sessionId){
StubbornNetworkProxy proxy=_sessionsManager.find(sessionId);
if (proxy == null) {
proxy=establishNewSession();
}
else {
_sessionId=sessionId;
}
return proxy;
}
private void closeSession(){
try {
_provider.close();
}
catch ( IOException ignore) {
}
finally {
_isOpen=false;
}
}
private void send( Object object){
try {
_provider.receive(object);
}
catch ( IOException unex) {
closeSession();
}
}
public void disconnect(){
_sessionsManager.remove(_sessionId);
_sessionId=null;
_proxy=null;
_isOpen=false;
}
}