@Override
  public void sessionClosed(IoSession session) throws Exception {
    super.sessionClosed(session);

    IoHandler handler = handlers.remove(session);
    handler.sessionClosed(session);
  }
  @Override
  public void messageReceived(IoSession session, Object message) throws Exception {
    super.messageReceived(session, message);

    IoHandler handler = handlers.get(session);
    handler.messageReceived(session, message);
  }
  @Override
  public void sessionOpened(IoSession session) throws Exception {
    super.sessionOpened(session);

    IoHandler handler = new MinaNetworkClientHandler(networkService, eventAdminTracker);
    handlers.put(session, handler);
    handler.sessionOpened(session);
  }
  @Test
  public void testSessionLifecycle() throws Exception {
    IoServiceListenerSupport support = new IoServiceListenerSupport(mockService);

    DummySession session = new DummySession();
    session.setService(mockService);
    session.setLocalAddress(ADDRESS);

    IoHandler handler = EasyMock.createStrictMock(IoHandler.class);
    session.setHandler(handler);

    IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class);

    // Test creation
    listener.sessionCreated(session);
    handler.sessionCreated(session);
    handler.sessionOpened(session);

    EasyMock.replay(listener);
    EasyMock.replay(handler);

    support.add(listener);
    support.fireSessionCreated(session);

    EasyMock.verify(listener);
    EasyMock.verify(handler);

    assertEquals(1, support.getManagedSessions().size());
    assertSame(session, support.getManagedSessions().get(session.getId()));

    // Test destruction & other side effects
    EasyMock.reset(listener);
    EasyMock.reset(handler);
    handler.sessionClosed(session);
    listener.sessionDestroyed(session);

    EasyMock.replay(listener);
    //// Activate more than once
    support.fireSessionCreated(session);
    //// Deactivate
    support.fireSessionDestroyed(session);
    //// Deactivate more than once
    support.fireSessionDestroyed(session);

    EasyMock.verify(listener);

    assertTrue(session.isClosing());
    assertEquals(0, support.getManagedSessions().size());
    assertNull(support.getManagedSessions().get(session.getId()));
  }
  @Test
  public void testConnectorActivation() throws Exception {
    IoConnector connector = EasyMock.createStrictMock(IoConnector.class);

    IoServiceListenerSupport support = new IoServiceListenerSupport(connector);

    final DummySession session = new DummySession();
    session.setService(connector);
    session.setRemoteAddress(ADDRESS);

    IoHandler handler = EasyMock.createStrictMock(IoHandler.class);
    session.setHandler(handler);

    IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class);

    // Creating a session should activate a service automatically.
    listener.serviceActivated(connector);
    listener.sessionCreated(session);
    handler.sessionCreated(session);
    handler.sessionOpened(session);

    EasyMock.replay(listener);
    EasyMock.replay(handler);

    support.add(listener);
    support.fireSessionCreated(session);

    EasyMock.verify(listener);
    EasyMock.verify(handler);

    // Destroying a session should deactivate a service automatically.
    EasyMock.reset(listener);
    EasyMock.reset(handler);
    listener.sessionDestroyed(session);
    handler.sessionClosed(session);
    listener.serviceDeactivated(connector);

    EasyMock.replay(listener);
    EasyMock.replay(handler);

    support.fireSessionDestroyed(session);

    EasyMock.verify(listener);
    EasyMock.verify(handler);

    assertEquals(0, support.getManagedSessions().size());
    assertNull(support.getManagedSessions().get(session.getId()));
  }
  @Test
  public void testDisconnectOnUnbind() throws Exception {
    IoAcceptor acceptor = EasyMock.createStrictMock(IoAcceptor.class);

    final IoServiceListenerSupport support = new IoServiceListenerSupport(acceptor);

    final DummySession session = new DummySession();
    session.setService(acceptor);
    session.setLocalAddress(ADDRESS);

    IoHandler handler = EasyMock.createStrictMock(IoHandler.class);
    session.setHandler(handler);

    final IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class);

    // Activate a service and create a session.
    listener.serviceActivated(acceptor);
    listener.sessionCreated(session);
    handler.sessionCreated(session);
    handler.sessionOpened(session);

    EasyMock.replay(listener);
    EasyMock.replay(handler);

    support.add(listener);
    support.fireServiceActivated();
    support.fireSessionCreated(session);

    EasyMock.verify(listener);
    EasyMock.verify(handler);

    // Deactivate a service and make sure the session is closed & destroyed.
    EasyMock.reset(listener);
    EasyMock.reset(handler);

    listener.serviceDeactivated(acceptor);
    EasyMock.expect(acceptor.isCloseOnDeactivation()).andReturn(true);
    listener.sessionDestroyed(session);
    handler.sessionClosed(session);

    EasyMock.replay(listener);
    EasyMock.replay(acceptor);
    EasyMock.replay(handler);

    new Thread() {
      // Emulate I/O service
      @Override
      public void run() {
        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
          // e.printStackTrace();
        }
        // This synchronization block is a workaround for
        // the visibility problem of simultaneous EasyMock
        // state update. (not sure if it fixes the failing test yet.)
        synchronized (listener) {
          support.fireSessionDestroyed(session);
        }
      }
    }.start();
    support.fireServiceDeactivated();

    synchronized (listener) {
      EasyMock.verify(listener);
    }
    EasyMock.verify(acceptor);
    EasyMock.verify(handler);

    assertTrue(session.isClosing());
    assertEquals(0, support.getManagedSessions().size());
    assertNull(support.getManagedSessions().get(session.getId()));
  }