HashMap config = new HashMap();
config.put(InvokerLocator.FORCE_REMOTE, "true");
config.put(Bisocket.IS_CALLBACK_SERVER, "true");
config.put(Bisocket.PING_FREQUENCY, TEST_PING_FREQUENCY_STRING);
addExtraClientConfig(config);
Client client = new Client(serverLocator, config);
client.connect();
log.info("client is connected");
assertTrue(client.getInvoker() instanceof BisocketClientInvoker);
DelayedCallbackHandler callbackHandler = new DelayedCallbackHandler();
client.addListener(callbackHandler, new HashMap());
log.info("client added callback handler");
// Shut down control connection on client side, so that pings can't be sent
// from server.
Field field = Client.class.getDeclaredField("callbackConnectors");
field.setAccessible(true);
Map callbackConnectors = (Map) field.get(client);
assertEquals(1, callbackConnectors.size());
Set callbackConnectorSet = (Set) callbackConnectors.values().iterator().next();
assertEquals(1, callbackConnectorSet.size());
Connector callbackConnector = (Connector) callbackConnectorSet.iterator().next();
ServerInvoker cbsi = callbackConnector.getServerInvoker();
assertTrue(cbsi instanceof BisocketServerInvoker);
field = BisocketServerInvoker.class.getDeclaredField("controlConnectionThreadMap");
field.setAccessible(true);
Map controlConnectionThreadMap = (Map) field.get(cbsi);
assertEquals(1, controlConnectionThreadMap.size());
Thread t = (Thread) controlConnectionThreadMap.values().iterator().next();
Class[] classes = BisocketServerInvoker.class.getDeclaredClasses();
Class controlConnectionThreadClass = null;
for (int i = 0; i < classes.length; i++)
{
log.info(classes[i]);
String fqn = classes[i].getName();
String className = fqn.substring(fqn.lastIndexOf('.') + 1);
log.info(className);
if ("BisocketServerInvoker$ControlConnectionThread".equals(className))
{
controlConnectionThreadClass = classes[i];
break;
}
}
assertNotNull(controlConnectionThreadClass);
assertEquals(t.getClass(), controlConnectionThreadClass);
field = controlConnectionThreadClass.getDeclaredField("controlSocket");
field.setAccessible(true);
Socket controlSocket = (Socket) field.get(t);
assertNotNull(controlSocket);
controlSocket.close();
log.info("CLOSED CONTROL SOCKET");
// Shut down the only existing ServerThread on the server side, and therefore
// the only existing pooled connection on the client side, forcing the
// next invocation to depend on the creation of a new control connection.
field = SocketServerInvoker.class.getDeclaredField("clientpool");
field.setAccessible(true);
ServerInvoker serverInvoker = connector.getServerInvoker();
assertTrue(serverInvoker instanceof BisocketServerInvoker);
LRUPool clientpool = (LRUPool) field.get(serverInvoker);
Set serverThreads = clientpool.getContents();
assertEquals(1, serverThreads.size());
((ServerThread)serverThreads.iterator().next()).shutdown();
HashMap metadata = new HashMap();
metadata.put(COUNTER, new Integer(0));
client.invoke(INVOCATION_TEST, metadata);
field = controlConnectionThreadClass.getDeclaredField("MAX_INITIAL_ATTEMPTS");
field.setAccessible(true);
int MAX_INITIAL_ATTEMPTS = ((Integer) field.get(null)).intValue();
Thread.sleep(TEST_PING_FREQUENCY * MAX_INITIAL_ATTEMPTS);
log.info("********************** EXCEPTION EXPECTED ****************************");
client.invoke(CALLBACK_TEST);
log.info("***********************************************************************");
// Callback should not be possible because contol connection is disabled.
assertEquals(0, callbackHandler.callbackCounter);
Thread.sleep(TEST_PING_FREQUENCY * MAX_INITIAL_ATTEMPTS);
client.invoke(CALLBACK_TEST);
// Callback should be possible because control connection has been replaced.
assertEquals(1, callbackHandler.callbackCounter);
client.removeListener(callbackHandler);
client.disconnect();
}