/*
* StubbornServerReceiverImpl.java
*
*
*/
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; /* the network layer */
private ObjectReceiver _client; /* the replicator */
private StubbornNetworkProxy _proxy; /* the proxy for the client */
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;
}
}