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: ManagedConnectionFactoryTestCase.java,v 1.4 2005/04/19 12:29:58 tanderson Exp $
44   */
45  package org.exolab.jms.net.connector;
46  
47  import java.security.Principal;
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  import junit.framework.TestCase;
52  
53  import org.exolab.jms.common.security.BasicPrincipal;
54  
55  
56  /***
57   * Tests the {@link ManagedConnectionFactory} interface.
58   *
59   * @version     $Revision: 1.4 $ $Date: 2005/04/19 12:29:58 $
60   * @author      <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
61   */
62  public abstract class ManagedConnectionFactoryTestCase extends TestCase {
63  
64      /***
65       * The managed connection factory.
66       */
67      private ManagedConnectionFactory _factory;
68  
69  
70      /***
71       * Construct an instance of this class for a specific test case.
72       *
73       * @param name the name of test case
74       */
75      public ManagedConnectionFactoryTestCase(String name) {
76          super(name);
77      }
78  
79      /***
80       * Tests {@link ManagedConnectionFactory#createConnectionFactory}.
81       *
82       * @throws Exception for any error
83       */
84      public void testCreateConnectionFactory() throws Exception {
85          ConnectionManager manager = new BasicConnectionManager(
86              _factory, new TestAuthenticator());
87          ConnectionFactory factory = _factory.createConnectionFactory(manager);
88          assertNotNull(factory);
89      }
90  
91      /***
92       * Verifies that a connection attempt fails with {@link ConnectException}
93       * if no acceptor is running.
94       *
95       * @throws Exception for any error
96       */
97      public void testConnectException() throws Exception {
98          try {
99              createConnection(null);
100             fail("Expected " + ConnectException.class.getName()
101                  + " to be thrown");
102         } catch (ConnectException exception) {
103             // the expected behaviour
104         } catch (Exception exception) {
105             fail("Expected " + ConnectException.class.getName()
106                  + " to be thrown, but got exception="
107                  + exception.getClass().getName() + ", message="
108                  + exception.getMessage());
109         }
110     }
111 
112     /***
113      * Tests {@link ManagedConnectionFactory#createManagedConnection}, for
114      * an unauthenticated connection.
115      *
116      * @throws Exception for any error
117      */
118     public void testCreateUnauthenticatedManagedConnection() throws Exception {
119         Principal invalid = new BasicPrincipal("foo", "bar");
120         checkCreateManagedConnection(null, invalid);
121     }
122 
123     /***
124      * Tests {@link ManagedConnectionFactory#createManagedConnection}, for
125      * an authenticated connection.
126      *
127      * @throws Exception for any error
128      */
129     public void testCreateAuthenticatedManagedConnection() throws Exception {
130         Principal principal = new BasicPrincipal("foo", "bar");
131         checkCreateManagedConnection(principal, null);
132     }
133 
134     /***
135      * Tests {@link ManagedConnectionFactory#createManagedConnectionAcceptor}.
136      *
137      * @throws Exception for any error
138      */
139     public void testCreateManagedConnectionAcceptor() throws Exception {
140         ManagedConnectionAcceptor acceptor = createAcceptor(null);
141         assertNotNull(acceptor);
142         acceptor.close();
143     }
144 
145     /***
146      * Tests {@link ManagedConnectionFactory#matchManagedConnections}
147      *
148      * @throws Exception for any error
149      */
150     public void testMatchManagedConnections() throws Exception {
151         ManagedConnection match = null;
152         Principal first = new BasicPrincipal("first", "password");
153         Principal second = new BasicPrincipal("second", "password");
154         Principal[] principals = new Principal[] {first, second};
155 
156         ConnectionRequestInfo info = getManagedConnectionRequestInfo();
157 
158         // set up an acceptor to handle connection requests
159         ManagedConnectionAcceptor acceptor = createAcceptor(principals);
160         TestAcceptorEventListener listener = new TestAcceptorEventListener(
161                 new TestInvocationHandler());
162         acceptor.accept(listener);
163 
164         List connections = new ArrayList();
165         for (int i = 0; i < principals.length; ++i) {
166             match = _factory.matchManagedConnections(connections, principals[i],
167                                                      info);
168             assertNull(match);
169         }
170 
171         // create a connection
172         ManagedConnection connection1 = createConnection(first);
173         connections.add(connection1);
174 
175         // verify it matches for principal 'first', and doesn't match
176         // for principal 'second'
177         match = _factory.matchManagedConnections(connections, first, info);
178         assertEquals(connection1, match);
179         match = _factory.matchManagedConnections(connections, second, info);
180         assertNull(match);
181 
182         // create another connection for a different user
183         ManagedConnection connection2 = createConnection(second);
184         connections.add(connection2);
185 
186         // verify it matches for principal 'second', and doesn't match
187         // for principal 'first'
188         match = _factory.matchManagedConnections(connections, second, info);
189         assertEquals(connection2, match);
190         match = _factory.matchManagedConnections(connections, first, info);
191         assertEquals(connection1, match);
192 
193         // make sure no errors were raised
194         assertEquals(0, listener.getErrors().size());
195 
196         // clean up
197         acceptor.close();
198         listener.destroy();
199         connection1.destroy();
200         connection2.destroy();
201     }
202 
203     /***
204      * Tests {@link ManagedConnectionFactory#matchManagedConnectionAcceptors}.
205      *
206      * @throws Exception for any error
207      */
208     public void testMatchManagedConnectionAcceptors() throws Exception {
209         ManagedConnectionAcceptor match = null;
210         ConnectionRequestInfo info = getAcceptorConnectionRequestInfo();
211 
212         List acceptors = new ArrayList();
213         match = _factory.matchManagedConnectionAcceptors(acceptors, info);
214         assertNull(match);
215 
216         // create an acceptor
217         ManagedConnectionAcceptor acceptor = createAcceptor(null);
218         acceptors.add(acceptor);
219 
220         // verify it matches
221         match = _factory.matchManagedConnectionAcceptors(acceptors, info);
222         assertEquals(acceptor, match);
223 
224         // clean up
225         acceptor.close();
226     }
227 
228     /***
229      * Sets up the test case.
230      *
231      * @throws Exception for any error
232      */
233     protected void setUp() throws Exception {
234         _factory = createManagedConnectionFactory();
235     }
236 
237     /***
238      * Creates a managed connection factory.
239      *
240      * @return the new managed connection factory
241      * @throws Exception for any error
242      */
243     protected abstract ManagedConnectionFactory
244         createManagedConnectionFactory() throws Exception;
245 
246     /***
247      * Returns the cached managed connection factory instance.
248      *
249      * @return the cached managed connection factory instance
250      */
251     protected ManagedConnectionFactory getManagedConnectionFactory() {
252         return _factory;
253     }
254 
255     /***
256      * Returns connection request info suitable for creating a managed
257      * connection.
258      *
259      * @return connection request info for creating a managed connection
260      * @throws Exception for any error
261      */
262     protected abstract ConnectionRequestInfo getManagedConnectionRequestInfo()
263         throws Exception;
264 
265     /***
266      * Returns connection request info suitable for creating a managed
267      * connection acceptor.
268      *
269      * @return connection request info for creating a managed connection
270      * acceptor
271      * @throws Exception for any error
272      */
273     protected abstract ConnectionRequestInfo getAcceptorConnectionRequestInfo()
274         throws Exception;
275 
276     /***
277      * Tests {@link ManagedConnectionFactory#createManagedConnection}.
278      *
279      * @param principal the principal to use. May be <code>null</code>
280      * @param invalidPrincipal an invalid principal. May be <code>null</code>
281      * @throws Exception for any error
282      */
283     protected void checkCreateManagedConnection(Principal principal,
284                                                 Principal invalidPrincipal)
285         throws Exception {
286 
287         // set up an acceptor to handle the connection request
288         Principal[] principals = new Principal[]{principal};
289         ManagedConnectionAcceptor acceptor = createAcceptor(principals);
290         TestAcceptorEventListener listener = new TestAcceptorEventListener(
291                 new TestInvocationHandler());
292         acceptor.accept(listener);
293 
294         // create the connection
295         ManagedConnection connection = createConnection(principal);
296         assertNotNull(connection);
297 
298         // delay to enable the listener to get notified
299         Thread.sleep(5000);
300 
301         // clean up client connection
302         connection.destroy();
303 
304         // try and create a connection for an invalid principal
305         try {
306             ManagedConnection invalid = createConnection(invalidPrincipal);
307             invalid.destroy();
308             fail("Expected connection creation to fail for invalid principal");
309         } catch (ResourceException expected) {
310             // the expected behaviour
311         }
312 
313         // verify that a single connection was accepted
314         assertEquals(1, listener.getConnections().size());
315 
316         // clean up the accepted connection
317         listener.destroy();
318 
319         // clean up the acceptor
320         acceptor.close();
321     }
322 
323     /***
324      * Helper to create a managed connection.
325      *
326      * @param principal the principal to use. May be <code>null</code>
327      * @throws Exception for any error
328      */
329     protected ManagedConnection createConnection(Principal principal)
330         throws Exception {
331         ConnectionRequestInfo info = getManagedConnectionRequestInfo();
332         return createConnection(principal, info);
333     }
334 
335     /***
336      * Helper to create a managed connection.
337      *
338      * @param principal the principal to use. May be <code>null</code>
339      * @param info the connection request info
340      * @throws Exception for any error
341      */
342     protected ManagedConnection createConnection(Principal principal,
343                                                  ConnectionRequestInfo info)
344         throws Exception {
345         ManagedConnection connection =
346                 _factory.createManagedConnection(principal, info);
347         connection.setInvocationHandler(new TestInvocationHandler());
348         return connection;
349     }
350 
351     /***
352      * Helper to create a managed connection acceptor.
353      *
354      * @param principals the principals to use. May be <code>null</code>
355      * @throws Exception for any error
356      */
357     protected ManagedConnectionAcceptor createAcceptor(Principal[] principals)
358         throws Exception {
359         ConnectionRequestInfo info = getAcceptorConnectionRequestInfo();
360         return createAcceptor(principals, info);
361     }
362 
363     /***
364      * Helper to create a managed connection acceptor.
365      *
366      * @param principals the principals to use. May be <code>null</code>
367      * @param info the connection request info
368      * @throws Exception for any error
369      */
370     protected ManagedConnectionAcceptor createAcceptor(
371             Principal[] principals, ConnectionRequestInfo info)
372         throws Exception {
373         Authenticator authenticator = new TestAuthenticator(principals);
374         return _factory.createManagedConnectionAcceptor(authenticator, info);
375     }
376 }