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 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ExceptionTestCase.java,v 1.4 2005/05/24 05:50:56 tanderson Exp $
44 */
45 package org.exolab.jms.net.invoke;
46
47 import java.rmi.RemoteException;
48 import java.util.Map;
49 import java.util.HashMap;
50 import java.io.IOException;
51
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54 import junit.framework.AssertionFailedError;
55 import junit.framework.Protectable;
56 import junit.framework.TestCase;
57
58 import org.exolab.jms.net.ExceptionService;
59 import org.exolab.jms.net.ExceptionServiceImpl;
60 import org.exolab.jms.net.orb.ORB;
61 import org.exolab.jms.net.orb.ORBFactory;
62 import org.exolab.jms.net.proxy.Proxy;
63 import org.exolab.jms.net.proxy.RemoteInvocationException;
64 import org.exolab.jms.net.registry.Registry;
65 import org.exolab.jms.net.util.SSLUtil;
66
67
68 /***
69 * Tests exception handling.
70 *
71 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
72 * @version $Revision: 1.4 $ $Date: 2005/05/24 05:50:56 $
73 */
74 public abstract class ExceptionTestCase extends TestCase {
75
76 /***
77 * The export URI.
78 */
79 private final String _uri;
80
81 /***
82 * The route URI.
83 */
84 private final String _routeURI;
85
86 /***
87 * Connection properties used when establishing a connection to the remote
88 * ORB. May be <code>null</code>
89 */
90 private final Map _connectionProps;
91
92 /***
93 * Connection properties used when constructing the local ORB. May
94 * be <code>null</code>
95 */
96 private final Map _acceptorProps;
97
98 /***
99 * The ORB.
100 */
101 private ORB _orb;
102
103 /***
104 * The exception service proxy.
105 */
106 private ExceptionService _service;
107
108 /***
109 * The logger.
110 */
111 private static final Log _log = LogFactory.getLog(ExceptionTestCase.class);
112
113 /***
114 * Exception service name.
115 */
116 private static final String EXCEPTION_SERVICE = "exception";
117
118
119 /***
120 * Construct an instance of this class for a specific test case.
121 *
122 * @param name the name of test case
123 * @param uri the export URI
124 */
125 public ExceptionTestCase(String name, String uri) {
126 this(name, uri, null, null);
127 }
128
129 /***
130 * Construct an instance of this class for a specific test case.
131 *
132 * @param name the name of test case
133 * @param uri the export URI
134 * @param routeURI the route URI
135 */
136 public ExceptionTestCase(String name, String uri, String routeURI) {
137 this(name, uri, routeURI, null, null);
138 }
139
140 /***
141 * Construct an instance of this class for a specific test case.
142 *
143 * @param name the name of test case
144 * @param uri the export URI
145 * @param properties connection properties. May be <code>null</code>
146 */
147 public ExceptionTestCase(String name, String uri, Map properties) {
148 this(name, uri, null, properties, properties);
149 }
150
151 /***
152 * Construct an instance of this class for a specific test case.
153 *
154 * @param name the name of test case
155 * @param uri the export URI
156 * @param routeURI the route URI
157 * @param properties connection properties. May be <code>null</code>
158 */
159 public ExceptionTestCase(String name, String uri, String routeURI,
160 Map properties) {
161 this(name, uri, routeURI, properties, properties);
162 }
163
164 /***
165 * Construct an instance of this class for a specific test case.
166 *
167 * @param name the name of test case
168 * @param uri the export URI
169 * @param routeURI the route URI
170 * @param connectionProps connection properties. May be <code>null</code>
171 * @param acceptorProps acceptor properites. May be <code>null</code>
172 */
173 public ExceptionTestCase(String name, String uri, String routeURI,
174 Map connectionProps, Map acceptorProps) {
175 super(name);
176 _uri = uri;
177 _routeURI = routeURI;
178 _connectionProps = connectionProps;
179 _acceptorProps = acceptorProps;
180 }
181
182 /***
183 * Verifies that a declared <code>Throwable</code> is propagated to the
184 * client.
185 *
186 * @throws Exception for any error
187 */
188 public void testDeclaredThrowable() throws Exception {
189 Protectable protectable = new Protectable() {
190 public void protect() throws Throwable {
191 _service.throwThrowable();
192 }
193 };
194 checkException(protectable, Throwable.class, null);
195 }
196
197 /***
198 * Verifies that a declared <code>Exception</code> is propagated to the
199 * client.
200 *
201 * @throws Exception for any error
202 */
203 public void testDeclaredException() throws Exception {
204 Protectable protectable = new Protectable() {
205 public void protect() throws Throwable {
206 _service.throwException();
207 }
208 };
209 checkException(protectable, Exception.class, null);
210 }
211
212 /***
213 * Verifies that a declared <code>Error</code> is propagated to the client.
214 *
215 * @throws Exception for any error
216 */
217 public void testDeclaredError() throws Exception {
218 Protectable protectable = new Protectable() {
219 public void protect() throws Throwable {
220 _service.throwError();
221 }
222 };
223 checkException(protectable, Error.class, null);
224 }
225
226 /***
227 * Verifies that an undeclared <code>Error</code> is propagated to the
228 * client, wrapped in a {@link RemoteInvocationException}.
229 *
230 * @throws Exception for any error
231 */
232 public void testUndeclaredError() throws Exception {
233 Protectable protectable = new Protectable() {
234 public void protect() throws Throwable {
235 _service.throwUndeclaredError();
236 }
237 };
238 checkException(protectable, RemoteInvocationException.class,
239 Error.class);
240 }
241
242 /***
243 * Verifies that a declared <code>RuntimeException</code> is propagated to
244 * the client.
245 *
246 * @throws Exception for any error
247 */
248 public void testDeclaredRuntimeException() throws Exception {
249 Protectable protectable = new Protectable() {
250 public void protect() throws Throwable {
251 _service.throwRuntimeException();
252 }
253 };
254 checkException(protectable, RuntimeException.class, null);
255 }
256
257 /***
258 * Verifies that an undeclared <code>RuntimeException</code> is propagated
259 * to the client, wrapped in a {@link RemoteInvocationException}.
260 *
261 * @throws Exception for any error
262 */
263 public void testUndeclaredRuntimeException() throws Exception {
264 Protectable protectable = new Protectable() {
265 public void protect() throws Throwable {
266 _service.throwUndeclaredRuntimeException();
267 }
268 };
269 checkException(protectable, RemoteInvocationException.class,
270 RuntimeException.class);
271 }
272
273 /***
274 * Verifies that a declared <code>RemoteException</code> is propagated to
275 * the client.
276 *
277 * @throws Exception for any error
278 */
279 public void testDeclaredRemoteException() throws Exception {
280 Protectable protectable = new Protectable() {
281 public void protect() throws Throwable {
282 _service.throwRemoteException();
283 }
284 };
285 checkException(protectable, RemoteException.class, null);
286 }
287
288 /***
289 * Verifies that an undeclared <code>Error</code> thrown by a method
290 * declaring <code>RemoteException</code> is propagated to the client,
291 * wrapped in a <code>RemoteException</code>.
292 *
293 * @throws Exception for any errror
294 */
295 public void testUndeclaredError2() throws Exception {
296 Protectable protectable = new Protectable() {
297 public void protect() throws Throwable {
298 _service.throwUndeclaredError2();
299 }
300 };
301 checkException(protectable, RemoteException.class, Error.class);
302 }
303
304 /***
305 * Verifies that an undeclared <code>RuntimeException</code> thrown by a
306 * method declaring <code>RemoteException</code> is propagated to the
307 * client, wrapped in a <code>RemoteException</code>.
308 *
309 * @throws Exception for any errror
310 */
311 public void testUndeclaredRuntimeException2() throws Exception {
312 Protectable protectable = new Protectable() {
313 public void protect() throws Throwable {
314 _service.throwUndeclaredRuntimeException2();
315 }
316 };
317 checkException(protectable, RemoteException.class,
318 RuntimeException.class);
319 }
320
321 /***
322 * Verifies that an undeclared <code>RemoteInvocationException</code> thrown
323 * by a method is propagated to the client unchanged.
324 *
325 * @throws Exception for any errror
326 */
327 public void testUndeclaredRemoteInvocationException() throws Exception {
328 Protectable protectable = new Protectable() {
329 public void protect() throws Throwable {
330 _service.throwUndeclaredRemoteInvocationException();
331 }
332 };
333 checkException(protectable, RemoteInvocationException.class, null);
334 }
335
336 /***
337 * Returns connection properties for establishing a connection to the remote
338 * ORB.
339 *
340 * @return the connection properties, or <code>null</code> if the default
341 * connection properties should be used
342 * @throws IOException if a store cannot be found
343 */
344 protected Map getConnectionProperties() throws IOException {
345 Map properties = new HashMap();
346 properties.put(ORB.PROVIDER_URI, getServerURI());
347 if (_connectionProps != null) {
348 properties.putAll(_connectionProps);
349 }
350 return properties;
351 }
352
353 /***
354 * Returns the acceptor properties to use when accepting connections.
355 *
356 * @return the acceptor properties, or <code>null</code> if the default
357 * connection properties should be used
358 * @throws Exception for any error
359 */
360 protected Map getAcceptorProperties() throws Exception {
361 Map properties = new HashMap();
362 properties.put(ORB.PROVIDER_URI, _uri);
363 if (_acceptorProps != null) {
364 properties.putAll(_acceptorProps);
365 }
366 return properties;
367 }
368
369 /***
370 * Helper to return the server URI.
371 *
372 * @return the server URI
373 */
374 protected String getServerURI() {
375 return (_routeURI != null) ? _routeURI : _uri;
376 }
377
378 /***
379 * Sets up the test case.
380 *
381 * @throws Exception for any error
382 */
383 protected void setUp() throws Exception {
384 _log.debug("setUp() [test=" + getName() + ", uri=" + _uri + "]");
385 _orb = ORBFactory.createORB(getAcceptorProperties());
386 if (_routeURI != null) {
387 _orb.addRoute(_uri, _routeURI);
388 }
389 Registry serverRegistry = _orb.getRegistry();
390
391 Proxy proxy = _orb.exportObject(new ExceptionServiceImpl());
392 serverRegistry.bind(EXCEPTION_SERVICE, proxy);
393
394
395 Registry clientRegistry = _orb.getRegistry(getConnectionProperties());
396 _service = (ExceptionService) clientRegistry.lookup(EXCEPTION_SERVICE);
397 }
398
399 /***
400 * Cleans up the test case.
401 *
402 * @throws Exception for any error
403 */
404 protected void tearDown() throws Exception {
405 _log.debug("tearDown() [test=" + getName() + ", uri=" + _uri + "]");
406 _orb.shutdown();
407
408
409 SSLUtil.clearProperties();
410 }
411
412 /***
413 * Verifies that a method throws an exception of the expected type.
414 *
415 * @param protectable wraps the method to invoke
416 * @param expected the expected type of the exception
417 * @param nested the expected type of the nested exception, or
418 * <code>null</code>, if no nested exception is expected
419 */
420 private void checkException(Protectable protectable, Class expected,
421 Class nested) {
422 try {
423 protectable.protect();
424 fail("Expected exception of type=" + expected.getName()
425 + " to be thrown");
426 } catch (RemoteInvocationException exception) {
427 checkExceptionType(exception, expected);
428 if (nested != null) {
429 checkNestedExceptionType(exception.getTargetException(),
430 nested);
431 }
432 } catch (RemoteException exception) {
433 checkExceptionType(exception, expected);
434 if (nested != null) {
435 checkNestedExceptionType(exception.detail, nested);
436 }
437 } catch (AssertionFailedError error) {
438 throw error;
439 } catch (Throwable throwable) {
440 checkExceptionType(throwable, expected);
441 }
442 }
443
444 /***
445 * Verifies that an exception is of the expected type.
446 *
447 * @param exception the exception to check
448 * @param expected the expected exception type
449 */
450 private void checkExceptionType(Throwable exception, Class expected) {
451 Class actual = exception.getClass();
452 if (!actual.equals(expected)) {
453 fail("Expected exception of type=" + expected.getName()
454 + " to be thrown, but got type=" + actual.getName()
455 + ", message=" + exception.getMessage());
456 }
457 }
458
459 /***
460 * Verifies that a nested exception is of the expected type.
461 *
462 * @param exception the exception to check
463 * @param expected the expected exception type
464 */
465 private void checkNestedExceptionType(Throwable exception,
466 Class expected) {
467 Class actual = exception.getClass();
468 if (!actual.equals(expected)) {
469 fail("Expected nested exception of type=" + expected.getName()
470 + " but got type=" + actual.getClass().getName()
471 + ", message=" + exception.getMessage());
472 }
473 }
474
475 }