2
* JBoss, Home of Professional Open Source
3
* Copyright 2005, JBoss Inc., and individual contributors as indicated
4
* by the @authors tag. See the copyright.txt in the distribution for a
5
* full listing of individual contributors.
7
* This is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* This software is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this software; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
22
package org.jboss.test.remoting.transport.bisocket;
24
import java.lang.reflect.Field;
25
import java.net.InetAddress;
26
import java.net.Socket;
27
import java.util.HashMap;
30
import java.util.Timer;
31
import java.util.TimerTask;
33
import javax.management.MBeanServer;
35
import junit.framework.TestCase;
37
import org.apache.log4j.ConsoleAppender;
38
import org.apache.log4j.Level;
39
import org.apache.log4j.Logger;
40
import org.apache.log4j.PatternLayout;
41
import org.jboss.remoting.Client;
42
import org.jboss.remoting.InvocationRequest;
43
import org.jboss.remoting.InvokerLocator;
44
import org.jboss.remoting.ServerInvocationHandler;
45
import org.jboss.remoting.ServerInvoker;
46
import org.jboss.remoting.callback.Callback;
47
import org.jboss.remoting.callback.HandleCallbackException;
48
import org.jboss.remoting.callback.InvokerCallbackHandler;
49
import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
50
import org.jboss.remoting.transport.Connector;
51
import org.jboss.remoting.transport.PortUtil;
52
import org.jboss.remoting.transport.bisocket.Bisocket;
53
import org.jboss.remoting.transport.bisocket.BisocketClientInvoker;
54
import org.jboss.remoting.transport.bisocket.BisocketServerInvoker;
55
import org.jboss.test.remoting.transport.bisocket.ServerTimerReuseTestCase.TestCallbackHandler;
56
import org.jboss.test.remoting.transport.bisocket.ServerTimerReuseTestCase.TestInvocationHandler;
60
* TimerReuseTestCase verifies that it is safe to add a callback BisocketClientInvoker
61
* after the static Timer used by the PingTimerTasks has shut down because all previous
62
* PingTimerTasks have ended.
66
* The phenomenon described in JBREM-748 seems to be platform dependent. It's not clear,
67
* for example, how long it takes for a Timer to shut down after all of its tasks have
68
* ended. Therefore, there are multiple test methods that wait varying amounts of
69
* time before installing a second InvokerCallbackHandler.
71
* @author <a href="ron.sigal@jboss.com">Ron Sigal</a>
72
* @version $Revision: 2897 $
74
* Copyright May 31, 2007
77
public class CloseControlSocketTestCase extends TestCase
79
public static int port;
81
private static Logger log = Logger.getLogger(CloseControlSocketTestCase.class);
82
private static boolean firstTime = true;
84
// remoting server connector
85
private Connector connector;
86
private InvokerLocator serverLocator;
87
private SampleInvocationHandler invocationHandler;
90
public void setUp() throws Exception
95
Logger.getLogger("org.jboss.remoting").setLevel(Level.INFO);
96
Logger.getLogger("org.jboss.test.remoting").setLevel(Level.INFO);
97
String pattern = "[%d{ABSOLUTE}] [%t] %5p (%F:%L) - %m%n";
98
PatternLayout layout = new PatternLayout(pattern);
99
ConsoleAppender consoleAppender = new ConsoleAppender(layout);
100
Logger.getRootLogger().addAppender(consoleAppender);
105
public void tearDown()
110
public void testControlSocketClosedWhenDisconnected() throws Throwable
112
log.info("entering " + getName());
115
String host = InetAddress.getLocalHost().getHostAddress();
116
int port = PortUtil.findFreePort(host);
117
String locatorURI = getTransport() + "://" + host + ":" + port;
118
serverLocator = new InvokerLocator(locatorURI);
119
log.info("Starting remoting server with locator uri of: " + locatorURI);
120
HashMap config = new HashMap();
121
config.put(InvokerLocator.FORCE_REMOTE, "true");
122
addExtraServerConfig(config);
123
connector = new Connector(serverLocator, config);
125
invocationHandler = new SampleInvocationHandler();
126
connector.addInvocationHandler("sample", invocationHandler);
130
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
131
HashMap clientConfig = new HashMap();
132
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
133
addExtraClientConfig(clientConfig);
134
Client client = new Client(clientLocator, clientConfig);
136
log.info("client is connected");
139
assertEquals("abc", client.invoke("abc"));
140
log.info("connection is good");
142
// Add callback handler.
143
TestCallbackHandler callbackHandler = new TestCallbackHandler();
144
HashMap metadata = new HashMap();
145
metadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
146
client.addListener(callbackHandler, metadata);
148
// Get control socket.
149
BisocketServerInvoker serverInvoker = (BisocketServerInvoker) connector.getServerInvoker();
150
Field field = ServerInvoker.class.getDeclaredField("callbackHandlers");
151
field.setAccessible(true);
152
Map callbackHandlers = (Map) field.get(serverInvoker);
153
assertEquals(1, callbackHandlers.size());
154
ServerInvokerCallbackHandler serverInvokerCallbackHandler;
155
serverInvokerCallbackHandler = (ServerInvokerCallbackHandler) callbackHandlers.values().iterator().next();
156
field = ServerInvokerCallbackHandler.class.getDeclaredField("callBackClient");
157
field.setAccessible(true);
158
Client callbackClient = (Client) field.get(serverInvokerCallbackHandler);
159
assertNotNull(callbackClient);
160
BisocketClientInvoker callbackClientInvoker = (BisocketClientInvoker) callbackClient.getInvoker();
162
field = BisocketClientInvoker.class.getDeclaredField("controlSocket");
163
field.setAccessible(true);
164
Socket controlSocket = (Socket) field.get(callbackClientInvoker);
165
assertNotNull(controlSocket);
166
assertFalse(controlSocket.isClosed());
168
// Remove callback handler, which will shut down control connection.
169
// Verify that control socket gets closed.
170
client.removeListener(callbackHandler);
171
assertTrue(controlSocket.isClosed());
175
log.info(getName() + " PASSES");
180
Verifies that a control socket is closed when it is replaced.
182
public void testControlSocketClosedWhenReplaced() throws Throwable
184
log.info("entering " + getName());
187
String host = InetAddress.getLocalHost().getHostAddress();
188
int port = PortUtil.findFreePort(host);
189
String locatorURI = getTransport() + "://" + host + ":" + port;
190
serverLocator = new InvokerLocator(locatorURI);
191
log.info("Starting remoting server with locator uri of: " + locatorURI);
192
HashMap config = new HashMap();
193
config.put(InvokerLocator.FORCE_REMOTE, "true");
194
addExtraServerConfig(config);
195
connector = new Connector(serverLocator, config);
197
invocationHandler = new SampleInvocationHandler();
198
connector.addInvocationHandler("sample", invocationHandler);
202
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
203
HashMap clientConfig = new HashMap();
204
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
205
addExtraClientConfig(clientConfig);
206
Client client = new Client(clientLocator, clientConfig);
208
log.info("client is connected");
211
assertEquals("abc", client.invoke("abc"));
212
log.info("connection is good");
214
// Add callback handler.
215
TestCallbackHandler callbackHandler = new TestCallbackHandler();
216
HashMap metadata = new HashMap();
217
metadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
218
client.addListener(callbackHandler, metadata);
220
// Get current control socket.
221
BisocketServerInvoker serverInvoker = (BisocketServerInvoker) connector.getServerInvoker();
222
Field field = ServerInvoker.class.getDeclaredField("callbackHandlers");
223
field.setAccessible(true);
224
Map callbackHandlers = (Map) field.get(serverInvoker);
225
assertEquals(1, callbackHandlers.size());
226
ServerInvokerCallbackHandler serverInvokerCallbackHandler;
227
serverInvokerCallbackHandler = (ServerInvokerCallbackHandler) callbackHandlers.values().iterator().next();
228
field = ServerInvokerCallbackHandler.class.getDeclaredField("callBackClient");
229
field.setAccessible(true);
230
Client callbackClient = (Client) field.get(serverInvokerCallbackHandler);
231
assertNotNull(callbackClient);
232
BisocketClientInvoker callbackClientInvoker = (BisocketClientInvoker) callbackClient.getInvoker();
234
field = BisocketClientInvoker.class.getDeclaredField("controlSocket");
235
field.setAccessible(true);
236
Socket oldControlSocket = (Socket) field.get(callbackClientInvoker);
237
assertNotNull(oldControlSocket);
238
assertFalse(oldControlSocket.isClosed());
240
// Cause recreation of control connection on server.
241
field = Client.class.getDeclaredField("callbackConnectors");
242
field.setAccessible(true);
243
Map callbackConnectors = (Map) field.get(client);
244
assertEquals(1, callbackConnectors.size());
245
Set connectors = (Set) callbackConnectors.values().iterator().next();
246
assertEquals(1, connectors.size());
247
Connector callbackConnector = (Connector) connectors.iterator().next();
248
BisocketServerInvoker callbackInvoker = (BisocketServerInvoker) callbackConnector.getServerInvoker();
249
field = BisocketServerInvoker.class.getDeclaredField("controlConnectionThreadMap");
250
field.setAccessible(true);
251
Map controlConnectionThreadMap = (Map) field.get(callbackInvoker);
252
assertEquals(1, controlConnectionThreadMap.size());
253
Thread controlConnectionThread = (Thread) controlConnectionThreadMap.values().iterator().next();
254
Class[] classes = BisocketServerInvoker.class.getDeclaredClasses();
255
Class ControlConnectionThreadClass = null;
257
for (int i = 0; i < classes.length; i++)
259
if (classes[i].toString().indexOf("ControlConnectionThread") != -1)
261
ControlConnectionThreadClass = classes[i];
266
assertNotNull(ControlConnectionThreadClass);
267
field = ControlConnectionThreadClass.getDeclaredField("listenerId");
268
field.setAccessible(true);
269
String listenerId = (String) field.get(controlConnectionThread);
270
assertNotNull(listenerId);
271
callbackInvoker.createControlConnection(listenerId, false);
273
// Verify old control socket is closed and has been replaced.
275
assertTrue(oldControlSocket.isClosed());
276
field = BisocketClientInvoker.class.getDeclaredField("controlSocket");
277
field.setAccessible(true);
278
Socket newControlSocket = (Socket) field.get(callbackClientInvoker);
279
assertNotNull(newControlSocket);
280
assertNotSame(oldControlSocket, newControlSocket);
281
assertFalse(newControlSocket.isClosed());
284
client.removeListener(callbackHandler);
287
log.info(getName() + " PASSES");
291
protected String getTransport()
297
protected void addExtraClientConfig(Map config) {}
298
protected void addExtraServerConfig(Map config) {}
301
static class SampleInvocationHandler implements ServerInvocationHandler
303
public void addListener(InvokerCallbackHandler callbackHandler)
307
callbackHandler.handleCallback(new Callback("callback"));
309
catch (HandleCallbackException e)
311
log.error("unable to send callback", e);
314
public Object invoke(final InvocationRequest invocation) throws Throwable
316
return invocation.getParameter();
318
public void removeListener(InvokerCallbackHandler callbackHandler) {}
319
public void setMBeanServer(MBeanServer server) {}
320
public void setInvoker(ServerInvoker invoker) {}
323
static class TestCallbackHandler implements InvokerCallbackHandler
326
public void handleCallback(Callback callback) throws HandleCallbackException
b'\\ No newline at end of file'