KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > net > invoke > DisconnectionTestCase


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Exoffice Technologies. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Exoffice Technologies. Exolab is a registered
23  * trademark of Exoffice Technologies.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42  *
43  * $Id: DisconnectionTestCase.java,v 1.3 2005/06/04 14:54:17 tanderson Exp $
44  */

45 package org.exolab.jms.net.invoke;
46
47 import java.rmi.RemoteException JavaDoc;
48 import java.util.Map JavaDoc;
49 import java.util.HashMap JavaDoc;
50
51 import EDU.oswego.cs.dl.util.concurrent.Latch;
52
53 import org.exolab.jms.net.Callback;
54 import org.exolab.jms.net.CallbackService;
55 import org.exolab.jms.net.CallbackServiceImpl;
56 import org.exolab.jms.net.connector.Caller;
57 import org.exolab.jms.net.connector.CallerListener;
58 import org.exolab.jms.net.orb.ORB;
59 import org.exolab.jms.net.proxy.Proxy;
60 import org.exolab.jms.net.registry.Registry;
61
62
63 /**
64  * Tests disconnection.
65  *
66  * @author <a HREF="mailto:tma@netspace.net.au">Tim Anderson</a>
67  * @version $Revision: 1.3 $ $Date: 2005/06/04 14:54:17 $
68  */

69 public class DisconnectionTestCase extends ORBTestCase {
70
71     /**
72      * Construct a new <code>DisconnectionTestCase</code>.
73      *
74      * @param name the name of test case
75      * @param uri the server export URI
76      */

77     public DisconnectionTestCase(String JavaDoc name, String JavaDoc uri) {
78         super(name, uri);
79     }
80
81     /**
82      * Construct a new <code>DisconnectionTestCase</code>.
83      *
84      * @param name the name of test case
85      * @param uri the server export URI
86      * @param properties connection properties. May be <code>null</code>
87      */

88     public DisconnectionTestCase(String JavaDoc name, String JavaDoc uri, Map JavaDoc properties) {
89         super(name, uri, properties);
90     }
91
92     /**
93      * Construct a new <code>DisconnectionTestCase</code>.
94      *
95      * @param name the name of test case
96      * @param uri the server export URI
97      * @param routeURI the route URI
98      */

99     public DisconnectionTestCase(String JavaDoc name, String JavaDoc uri, String JavaDoc routeURI) {
100         super(name, uri, routeURI);
101     }
102
103     /**
104      * Construct a new <code>DisconnectionTestCase</code>.
105      *
106      * @param name the name of test case
107      * @param uri the export URI
108      * @param routeURI the route URI
109      * @param connectionProps connection properties. May be <code>null</code>
110      * @param acceptorProps acceptor properites. May be <code>null</code>
111      */

112     public DisconnectionTestCase(String JavaDoc name, String JavaDoc uri, String JavaDoc routeURI,
113                                  Map JavaDoc connectionProps, Map JavaDoc acceptorProps) {
114         super(name, uri, routeURI, connectionProps, acceptorProps);
115     }
116
117     /**
118      * Verifies that the client is notified when the server is shut down.
119      *
120      * @throws Exception for any error
121      */

122     public void testServerDisconnect() throws Exception JavaDoc {
123         final Latch latch = new Latch();
124         CallerListener listener = new CallerListener() {
125             public void disconnected(Caller caller) {
126                 latch.release();
127             }
128         };
129         ORB client = getClientORB();
130         client.addCallerListener(getServerURI(), listener);
131
132         ORB server = getORB();
133         server.getRegistry();
134
135         // get the registry proxy. This will establish a connection to the
136
// server.
137
Registry registry = getRegistry();
138         assertNotNull(registry);
139
140         server.shutdown();
141
142         if (!latch.attempt(10 * 1000)) {
143             fail("CallerListener not notified of disconnection");
144         }
145     }
146
147     /**
148      * Verifies that the server is notified when the client is shut down.
149      *
150      * @throws Exception for any error
151      */

152     public void testClientDisconnect() throws Exception JavaDoc {
153         Latch latch = new Latch();
154         ORB server = getORB();
155         CallbackServer serviceImpl = new CallbackServer(server, latch);
156
157         Proxy proxy = server.exportObject(serviceImpl);
158         server.getRegistry().bind("service", proxy);
159
160         ORB client = getClientORB();
161         Registry registry = client.getRegistry(getConnectionProperties());
162         CallbackService service = (CallbackService) registry.lookup("service");
163
164         LoggingCallback callback = new LoggingCallback();
165         Callback callbackProxy = (Callback) client.exportObjectTo(callback,
166                                                                   getServerURI());
167         service.addCallback(callbackProxy);
168
169         assertNull(serviceImpl.getException());
170         client.shutdown();
171
172         if (!latch.attempt(10 * 1000)) {
173             fail("CallerListener not notified of disconnection");
174         }
175         assertNull(serviceImpl.getException());
176     }
177
178     /**
179      * Verifies that the client is notified when the connection is closed
180      * through inactivity.
181      *
182      * @throws Exception for any error
183      */

184     public void testInactive() throws Exception JavaDoc {
185         final Latch latch = new Latch();
186         CallerListener listener = new CallerListener() {
187             public void disconnected(Caller caller) {
188                 latch.release();
189             }
190         };
191
192         ORB server = getORB();
193         CallbackServer serviceImpl = new CallbackServer(server, latch);
194
195         Proxy proxy = server.exportObject(serviceImpl);
196         server.getRegistry().bind("service", proxy);
197
198         ORB client = getClientORB();
199         client.addCallerListener(getServerURI(), listener);
200
201         Registry registry = getRegistry(); // will establish a connection
202
assertNotNull(registry);
203         CallbackService service = (CallbackService) registry.lookup("service");
204         assertNotNull(service);
205
206         // make sure the connection isn't reaped through inactivity
207
// while there are proxies associated with it.
208
for (int i = 0; i < 10; ++i) {
209             Runtime.getRuntime().gc();
210             if (latch.attempt(1000)) {
211                 break;
212             }
213         }
214         if (latch.attempt(0)) {
215             fail("Connection terminated when there were active proxies");
216         }
217
218         // clear registry proxy and ensure the connection isn't reaped.
219
// Registry proxy is constructed differently to those serialized
220
// over the wire.
221

222         registry = null;
223         for (int i = 0; i < 10; ++i) {
224             Runtime.getRuntime().gc();
225             if (latch.attempt(1000)) {
226                 break;
227             }
228         }
229         if (latch.attempt(0)) {
230             fail("Connection terminated when there were active proxies");
231         }
232
233         // clear proxy reference so the connection can be GC'ed
234
service = null;
235
236         // wait for the notification. Need to force the GC to run...
237
for (int i = 0; i < 10; ++i) {
238             Runtime.getRuntime().gc();
239             if (latch.attempt(1000)) {
240                 break;
241             }
242         }
243         if (!latch.attempt(0)) {
244             fail("CallerListener not notified of disconnection");
245         }
246     }
247
248    /**
249      * Returns properties for configuring the client ORB.
250      * This configures the default connection pool to reap connections every
251      * 5 seconds.
252      *
253      * @return the properties for configuring the client ORB.
254      */

255     protected Map JavaDoc getClientProperties() {
256        Map JavaDoc properties = super.getClientProperties();
257        return addReapIntervalProperty(properties);
258     }
259
260     /**
261      * Returns the acceptor properties to use when accepting connections.
262      * This configures the default connection pool to reap connections every
263      * 5 seconds.
264      *
265      * @return the acceptor properties, or <code>null</code> if the default
266      * connection properties should be used
267      * @throws Exception for any error
268      */

269     protected Map JavaDoc getAcceptorProperties() throws Exception JavaDoc {
270         Map JavaDoc properties = super.getAcceptorProperties();
271         return addReapIntervalProperty(properties);
272     }
273
274     /**
275      * Adds a 5 second reap interval property to ORB configuration properties.
276      *
277      * @param properties the properties to add to. May be <code>null</code>
278      * @return the updated configuration properties
279      */

280     private Map JavaDoc addReapIntervalProperty(Map JavaDoc properties) {
281         if (properties == null) {
282             properties = new HashMap JavaDoc();
283         }
284         properties.put("org.exolab.jms.net.pool.reapInterval", "5");
285         return properties;
286     }
287
288     /**
289      * {@link CallbackService} implementation that detects disconnection of its
290      * client.
291      */

292     private static class CallbackServer extends CallbackServiceImpl
293             implements CallerListener {
294
295         /**
296          * The ORB.
297          */

298         private final ORB _orb;
299
300         /**
301          * The latch to notify when disconnect() is invoked.
302          */

303         private final Latch _latch;
304
305         /**
306          * Any exception raised during the test. Should be null.
307          */

308         private Exception JavaDoc _exception;
309
310
311         /**
312          * Construct a new <code>CallbackServer</code>.
313          *
314          * @param orb the ORB to use
315          * @param latch the latch to notify when disconnect() is invoked.
316          */

317         public CallbackServer(ORB orb, Latch latch) {
318             _orb = orb;
319             _latch = latch;
320         }
321
322         /**
323          * Register a callback.
324          *
325          * @param callback the callback to register
326          */

327         public synchronized void addCallback(Callback callback) {
328             super.addCallback(callback);
329             try {
330                 Caller caller = _orb.getCaller();
331                 _orb.addCallerListener(caller.getRemoteURI().toString(), this);
332             } catch (RemoteException JavaDoc exception) {
333                 _exception = exception;
334             }
335         }
336
337         /**
338          * Notifies that a caller has been disconnected.
339          *
340          * @param caller the caller that was disconnected
341          */

342         public void disconnected(Caller caller) {
343             try {
344                 _latch.release();
345                 _orb.removeCallerListener(caller.getRemoteURI().toString(),
346                                           this);
347             } catch (RemoteException JavaDoc exception) {
348                 _exception = exception;
349             }
350         }
351
352         /**
353          * Returns any exception raised.
354          *
355          * @return any exception raised, or <code>null</code>
356          */

357         public Exception JavaDoc getException() {
358             return _exception;
359         }
360     }
361 }
362
Popular Tags