View Javadoc

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 2000-2001,2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: JmsConnectionFactory.java,v 1.19 2003/08/07 13:32:49 tanderson Exp $
44   *
45   * Date         Author  Changes
46   * 3/21/2000    jima    Created
47   */
48  package org.exolab.jms.client;
49  
50  import java.io.Externalizable;
51  import java.io.IOException;
52  import java.io.ObjectInput;
53  import java.io.ObjectOutput;
54  import java.lang.reflect.Constructor;
55  import java.lang.reflect.InvocationTargetException;
56  import java.util.Enumeration;
57  import java.util.Hashtable;
58  import java.util.Vector;
59  
60  import javax.jms.ConnectionFactory;
61  import javax.jms.ExceptionListener;
62  import javax.jms.JMSException;
63  import javax.naming.Reference;
64  import javax.naming.Referenceable;
65  import javax.naming.StringRefAddr;
66  
67  
68  /***
69   * This is simply a marker for connection factory classes.
70   *
71   * @version     $Revision: 1.19 $ $Date: 2003/08/07 13:32:49 $
72   * @author      <a href="mailto:jima@exoffice.com">Jim Alateras</a>
73   * @author      <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
74   * @see         org.exolab.jms.client.JmsQueueConnectionFactory
75   * @see         org.exolab.jms.client.JmsTopicConnectionFactory
76   */
77  public abstract class JmsConnectionFactory
78      implements ConnectionFactory, ExceptionListener, Externalizable,
79      Referenceable {
80  
81      /***
82       * Used for serialization
83       */
84      static final long serialVersionUID = 1;
85  
86      /***
87       * This variable maintains the name of the class that will facilitate
88       * communication with the JMS Server. This class must have a default
89       * constructor.
90       */
91      protected String _className = null;
92  
93      /***
94       * This is a list of environment variabels that are used to construct
95       * the object
96       */
97      protected Hashtable _env = null;
98  
99      /***
100      * The connection_ attribute is used to manage the list of connections
101      * created by the factory.
102      */
103     transient private Vector _connections = new Vector();
104 
105     /***
106      * This is a transient attribute that holds a reference to the JMS Server.
107      * Requests to the server are handled through this proxy.
108      */
109     transient private JmsServerStubIfc _proxy = null;
110 
111 
112     /***
113      * Need a default constructor for externalization
114      */
115     public JmsConnectionFactory() {
116     }
117 
118     /***
119      * Instantiate an instance of the connection factory with the name of the
120      * class that will facilitate communication with the JmsServer
121      *
122      * @param       name            name of the class
123      * @param       envc            properties for contructing
124      */
125     protected JmsConnectionFactory(String name, Hashtable env) {
126         _className = name;
127         _env = env;
128     }
129 
130     /***
131      * Return a reference to the server proxy. If the proxy has not yet
132      * been created then create it prior to returning.
133      *
134      * @return a reference to the server proxy
135      * @throws JMSException if the proxy cannot be created
136      */
137     public JmsServerStubIfc getProxy() throws JMSException {
138         if (_proxy == null) {
139             try {
140                 Class[] argTypes = {Hashtable.class};
141                 Object[] args = {_env};
142 
143                 Class factoryClass = Class.forName(_className);
144                 Constructor constructor =
145                     factoryClass.getDeclaredConstructor(argTypes);
146                 _proxy = (JmsServerStubIfc) constructor.newInstance(args);
147                 _proxy.setExceptionListener(this);
148             } catch (InvocationTargetException exception) {
149                 if (exception.getTargetException() != null) {
150                     throw new JMSException("Failed to create proxy: " +
151                         exception.getTargetException());
152                 } else {
153                     throw new JMSException("Failed to create proxy: " +
154                         exception);
155                 }
156             } catch (Exception exception) {
157                 throw new JMSException("Failed to create proxy: " +
158                     exception);
159             }
160         }
161 
162         return _proxy;
163     }
164 
165     /***
166      * Add the specified connection to the list of managed sessions
167      *
168      * @param       connection          connection to register
169      */
170     protected void addConnection(JmsConnection connection) {
171         _connections.addElement(connection);
172     }
173 
174     /***
175      * Remove the specified connection from the list of managed connections..
176      * If it doesn't exist then fail silently
177      *
178      * @param       connection          connection to remove
179      */
180     protected void removeConnection(JmsConnection connection) {
181         _connections.removeElement(connection);
182     }
183 
184     /***
185      * Test whether the specified connection is managed by this factory
186      *
187      * @param       connection      connection to test against
188      * @return      boolean         true if managed
189      */
190     protected boolean isManaged(JmsConnection connection) {
191         return _connections.contains(connection);
192     }
193 
194     /***
195      * Return an enumeration of all connections managed by this factory
196      *
197      * @return      Enumeration
198      */
199     protected Enumeration getConnections() {
200         return _connections.elements();
201     }
202 
203     // implementation of Externalizable.writeExternal
204     public void writeExternal(ObjectOutput stream) throws IOException {
205         stream.writeLong(serialVersionUID);
206         stream.writeObject(_className);
207         stream.writeObject(_env);
208     }
209 
210     // implementation of Externalizable.readExternal
211     public void readExternal(ObjectInput stream)
212         throws IOException, ClassNotFoundException {
213         long version = stream.readLong();
214         if (version == serialVersionUID) {
215             _className = (String) stream.readObject();
216             _env = (Hashtable) stream.readObject();
217         } else {
218             throw new IOException("JmsConnectionFactory with version " +
219                 version + " is not supported.");
220         }
221     }
222 
223     // implementation of ExceptionListener.onException
224     public void onException(JMSException exception) {
225         // iterate through the list of connection and call
226         // notifyExceptionListener
227         Enumeration iter = _connections.elements();
228         while (iter.hasMoreElements()) {
229             JmsConnection connection = (JmsConnection) iter.nextElement();
230             connection.notifyExceptionListener(exception);
231         }
232 
233         // local clean up
234         _connections.clear();
235         _proxy = null;
236     }
237 
238     // implementation of Referenceable.getReference
239     public Reference getReference() {
240         Reference reference = new Reference(
241             this.getClass().getName(),
242             new StringRefAddr("serverClass", _className),
243             JmsConnectionFactoryBuilder.class.getName(), null);
244 
245         // all properties are strings so add them to the reference
246         Enumeration iter = _env.keys();
247         while (iter.hasMoreElements()) {
248             String key = (String) iter.nextElement();
249             reference.add(new StringRefAddr(key, (String) _env.get(key)));
250         }
251 
252         return reference;
253     }
254 
255 } //-- JmsConnectionFactory