|
@@ -68,6 +68,7 @@ public class DefaultClient implements Client
|
|
private Connector fast;
|
|
private Connector fast;
|
|
private MessageListenerRegistry<Client> messageListeners = new MessageListenerRegistry<Client>();
|
|
private MessageListenerRegistry<Client> messageListeners = new MessageListenerRegistry<Client>();
|
|
private List<ClientStateListener> stateListeners = new CopyOnWriteArrayList<ClientStateListener>();
|
|
private List<ClientStateListener> stateListeners = new CopyOnWriteArrayList<ClientStateListener>();
|
|
|
|
+ private List<ErrorListener<? super Client>> errorListeners = new CopyOnWriteArrayList<ErrorListener<? super Client>>();
|
|
private Redispatch dispatcher = new Redispatch();
|
|
private Redispatch dispatcher = new Redispatch();
|
|
private ConnectorAdapter reliableAdapter;
|
|
private ConnectorAdapter reliableAdapter;
|
|
private ConnectorAdapter fastAdapter;
|
|
private ConnectorAdapter fastAdapter;
|
|
@@ -93,9 +94,9 @@ public class DefaultClient implements Client
|
|
|
|
|
|
this.reliable = reliable;
|
|
this.reliable = reliable;
|
|
this.fast = fast;
|
|
this.fast = fast;
|
|
- reliableAdapter = new ConnectorAdapter(reliable, dispatcher, true);
|
|
|
|
|
|
+ reliableAdapter = new ConnectorAdapter(reliable, dispatcher, dispatcher, true);
|
|
if( fast != null ) {
|
|
if( fast != null ) {
|
|
- fastAdapter = new ConnectorAdapter(fast, dispatcher, false);
|
|
|
|
|
|
+ fastAdapter = new ConnectorAdapter(fast, dispatcher, dispatcher, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -230,7 +231,15 @@ public class DefaultClient implements Client
|
|
public void close()
|
|
public void close()
|
|
{
|
|
{
|
|
checkRunning();
|
|
checkRunning();
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ closeConnections( null );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ protected void closeConnections( DisconnectInfo info )
|
|
|
|
+ {
|
|
|
|
+ if( !isRunning )
|
|
|
|
+ return;
|
|
|
|
+
|
|
// Send a close message
|
|
// Send a close message
|
|
|
|
|
|
// Tell the thread it's ok to die
|
|
// Tell the thread it's ok to die
|
|
@@ -246,7 +255,7 @@ public class DefaultClient implements Client
|
|
// Just in case we never fully connected
|
|
// Just in case we never fully connected
|
|
connecting.countDown();
|
|
connecting.countDown();
|
|
|
|
|
|
- fireDisconnected(null);
|
|
|
|
|
|
+ fireDisconnected(info);
|
|
|
|
|
|
isRunning = false;
|
|
isRunning = false;
|
|
}
|
|
}
|
|
@@ -280,6 +289,16 @@ public class DefaultClient implements Client
|
|
{
|
|
{
|
|
messageListeners.removeMessageListener( listener, classes );
|
|
messageListeners.removeMessageListener( listener, classes );
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ public void addErrorListener( ErrorListener<? super Client> listener )
|
|
|
|
+ {
|
|
|
|
+ errorListeners.add( listener );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void removeErrorListener( ErrorListener<? super Client> listener )
|
|
|
|
+ {
|
|
|
|
+ errorListeners.remove( listener );
|
|
|
|
+ }
|
|
|
|
|
|
protected void fireConnected()
|
|
protected void fireConnected()
|
|
{
|
|
{
|
|
@@ -295,6 +314,27 @@ public class DefaultClient implements Client
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Either calls the ErrorListener or closes the connection
|
|
|
|
+ * if there are no listeners.
|
|
|
|
+ */
|
|
|
|
+ protected void handleError( Throwable t )
|
|
|
|
+ {
|
|
|
|
+ // If there are no listeners then close the connection with
|
|
|
|
+ // a reason
|
|
|
|
+ if( errorListeners.isEmpty() ) {
|
|
|
|
+ DisconnectInfo info = new DisconnectInfo();
|
|
|
|
+ info.reason = "Connection Error";
|
|
|
|
+ info.error = t;
|
|
|
|
+ closeConnections(info);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for( ErrorListener l : errorListeners ) {
|
|
|
|
+ l.handleError( this, t );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
protected void dispatch( Message m )
|
|
protected void dispatch( Message m )
|
|
{
|
|
{
|
|
// Pull off the connection management messages we're
|
|
// Pull off the connection management messages we're
|
|
@@ -312,8 +352,7 @@ public class DefaultClient implements Client
|
|
log.log( Level.SEVERE, "Connection terminated, reason:{0}.", reason );
|
|
log.log( Level.SEVERE, "Connection terminated, reason:{0}.", reason );
|
|
DisconnectInfo info = new DisconnectInfo();
|
|
DisconnectInfo info = new DisconnectInfo();
|
|
info.reason = reason;
|
|
info.reason = reason;
|
|
- fireDisconnected(info);
|
|
|
|
- close();
|
|
|
|
|
|
+ closeConnections(info);
|
|
}
|
|
}
|
|
|
|
|
|
// Make sure client MessageListeners are called single-threaded
|
|
// Make sure client MessageListeners are called single-threaded
|
|
@@ -324,11 +363,19 @@ public class DefaultClient implements Client
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- protected class Redispatch implements MessageListener<Object>
|
|
|
|
|
|
+ protected class Redispatch implements MessageListener<Object>, ErrorListener<Object>
|
|
{
|
|
{
|
|
public void messageReceived( Object source, Message m )
|
|
public void messageReceived( Object source, Message m )
|
|
{
|
|
{
|
|
dispatch( m );
|
|
dispatch( m );
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ public void handleError( Object source, Throwable t )
|
|
|
|
+ {
|
|
|
|
+ // Only doing the DefaultClient.this to make the code
|
|
|
|
+ // checker happy... it compiles fine without it but I
|
|
|
|
+ // don't like red lines in my editor. :P
|
|
|
|
+ DefaultClient.this.handleError( t );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|