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; } }