KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > components > jms > SonicMQVendorAdapter


1 /*
2  * Copyright 2001, 2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.components.jms;
18
19 import org.apache.axis.MessageContext;
20 import org.apache.axis.client.Call;
21 import org.apache.axis.transport.jms.JMSConnector;
22 import org.apache.axis.transport.jms.JMSConnectorFactory;
23 import org.apache.axis.transport.jms.JMSURLHelper;
24
25 import progress.message.client.ENetworkFailure;
26 import progress.message.client.EUserAlreadyConnected;
27 import progress.message.jclient.ErrorCodes;
28
29 import javax.jms.ConnectionFactory JavaDoc;
30 import javax.jms.JMSException JavaDoc;
31 import javax.jms.QueueConnectionFactory JavaDoc;
32 import javax.jms.TopicConnectionFactory JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Iterator JavaDoc;
35
36 /**
37  * Defines SonicMQ specific constants for connnection factory creation.
38  * Overrides methods in BeanVendorAdapter to fill in MQ classnames
39  *
40  * @author Jaime Meritt (jmeritt@sonicsoftware.com)
41  * @author Ray Chun (rchun@sonicsoftware.com)
42  */

43 public class SonicMQVendorAdapter extends BeanVendorAdapter
44 {
45     private final static String JavaDoc QCF_CLASS =
46         "progress.message.jclient.QueueConnectionFactory";
47
48     private final static String JavaDoc TCF_CLASS =
49         "progress.message.jclient.TopicConnectionFactory";
50
51     /**
52      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
53      * be used as a key in the environment map passed into calls to
54      * <code>createConnector</code> in <code>JMSConnectorFactory</code>.
55      * This is a required property.
56      * The value must be a <code>java.lang.String</code>
57      * See the SonicMQ documentation for information on this property
58      */

59     public final static String JavaDoc BROKER_URL = "brokerURL";
60
61     /**
62      * <code>SonicConnectionFactory</code> parameter valid for either domains. This should
63      * be used as a key in the environment map passed into calls to
64      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
65      * This is a required property for secure brokers.
66      * The value must be a <code>java.lang.String</code>
67      * See the SonicMQ documentation for information on this property
68      */

69     public final static String JavaDoc DEFAULT_USERNAME = "defaultUser";
70
71     /**
72      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
73      * be used as a key in the environment map passed into calls to
74      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
75      * This is a required property for secure brokers.
76      * The value must be a <code>java.lang.String</code>
77      * See the SonicMQ documentation for information on this property
78      */

79     public final static String JavaDoc DEFAULT_PASSWORD = "defaultPassword";
80     /**
81      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
82      * be used as a key in the environment map passed into calls to
83      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
84      * The value must be a <code>java.lang.Long</code>
85      * See the SonicMQ documentation for information on this property
86      */

87     public final static String JavaDoc PING_INTERVAL = "pingIntervalLong";
88     /**
89      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
90      * be used as a key in the environment map passed into calls to
91      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
92      * The value must be a <code>java.lang.Integer</code>
93      * See the SonicMQ documentation for information on this property
94      */

95     public final static String JavaDoc RECONNECT_INTERVAL = "reconnectIntervalInteger";
96     /**
97      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
98      * be used as a key in the environment map passed into calls to
99      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
100      * The value must be a <code>java.lang.Integer</code>
101      * See the SonicMQ documentation for information on this property
102      */

103     public final static String JavaDoc RECONNECT_TIMEOUT = "reconnectTimeoutInteger";
104     /**
105      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
106      * be used as a key in the environment map passed into calls to
107      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
108      * The value must be a <code>java.lang.String</code>
109      * See the SonicMQ documentation for information on this property
110      */

111     public final static String JavaDoc CONNECT_ID = "connectID";
112     /**
113      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
114      * be used as a key in the environment map passed into calls to
115      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
116      * The value must be a <code>java.lang.String</code>
117      * See the SonicMQ documentation for information on this property
118      */

119     public final static String JavaDoc CONNECTION_URLS = "connectionURLs";
120     /**
121      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
122      * be used as a key in the environment map passed into calls to
123      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
124      * The value must be a <code>java.lang.Boolean</code>
125      * See the SonicMQ documentation for information on this property
126      */

127     public final static String JavaDoc LOAD_BALANCING = "loadBalancingBoolean";
128     /**
129      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
130      * be used as a key in the environment map passed into calls to
131      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
132      * The value must be a <code>java.lang.Long</code>
133      * See the SonicMQ documentation for information on this property
134      */

135     public final static String JavaDoc MONITOR_INTERVAL = "monitorInterval";
136     /**
137      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
138      * be used as a key in the environment map passed into calls to
139      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
140      * The value must be a <code>java.lang.Boolean</code>
141      * See the SonicMQ documentation for information on this property
142      */

143     public final static String JavaDoc PERSISTENT_DELIVERY = "persistentDeliveryBoolean";
144     /**
145      * <code>SonicConnectionFactory</code> parameter valid for either domain. This should
146      * be used as a key in the environment map passed into calls to
147      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
148      * The value must be a <code>java.lang.Boolean</code>
149      * See the SonicMQ documentation for information on this property
150      */

151     public final static String JavaDoc SEQUENTIAL = "sequentialBoolean";
152
153     /**
154      * <code>SonicConnectionFactory</code> parameter valid for the PTP domain. This should
155      * be used as a key in the environment map passed into calls to
156      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
157      * The value must be a <code>java.lang.Integer</code>
158      * See the SonicMQ documentation for information on this property
159      */

160     public final static String JavaDoc PREFETCH_COUNT = "prefetchCountInteger";
161     /**
162      * <code>SonicConnectionFactory</code> parameter valid for the PTP domain. This should
163      * be used as a key in the environment map passed into calls to
164      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
165      * The value must be a <code>java.lang.Integer</code>
166      * See the SonicMQ documentation for information on this property
167      */

168     public final static String JavaDoc PREFETCH_THRESHOLD = "prefetchThresholdInteger";
169     /**
170      * <code>SonicConnectionFactory</code> parameter valid for the PubSub domain. This should
171      * be used as a key in the environment map passed into calls to
172      * <code>createConnector</code> in <code>JMSConnectorFactory</code>
173      * The value must be a <code>java.lang.Boolean</code>
174      * See the SonicMQ documentation for information on this property
175      */

176     public final static String JavaDoc SELECTOR_AT_BROKER = "selectorAtBroker";
177
178     public QueueConnectionFactory JavaDoc getQueueConnectionFactory(HashMap JavaDoc cfConfig)
179         throws Exception JavaDoc
180     {
181         cfConfig = (HashMap JavaDoc)cfConfig.clone();
182         cfConfig.put(CONNECTION_FACTORY_CLASS, QCF_CLASS);
183         return super.getQueueConnectionFactory(cfConfig);
184     }
185
186     public TopicConnectionFactory JavaDoc getTopicConnectionFactory(HashMap JavaDoc cfConfig)
187         throws Exception JavaDoc
188     {
189         cfConfig = (HashMap JavaDoc)cfConfig.clone();
190         cfConfig.put(CONNECTION_FACTORY_CLASS, TCF_CLASS);
191         return super.getTopicConnectionFactory(cfConfig);
192     }
193
194     /**
195      * Extract Sonic-specific properties from the JMS URL
196      *
197      * @param jmsurl The JMS URL representing the target endpoint address
198      * @param cfProps The set of connection factory configuration properties
199      */

200     public void addVendorConnectionFactoryProperties(JMSURLHelper jmsurl, HashMap JavaDoc cfProps)
201     {
202         if (jmsurl.getPropertyValue(BROKER_URL) != null)
203             cfProps.put(BROKER_URL, jmsurl.getPropertyValue(BROKER_URL));
204
205         if (jmsurl.getPropertyValue(DEFAULT_USERNAME) != null)
206             cfProps.put(DEFAULT_USERNAME, jmsurl.getPropertyValue(DEFAULT_USERNAME));
207
208         if (jmsurl.getPropertyValue(DEFAULT_PASSWORD) != null)
209             cfProps.put(DEFAULT_PASSWORD, jmsurl.getPropertyValue(DEFAULT_PASSWORD));
210
211         if (jmsurl.getPropertyValue(PING_INTERVAL) != null)
212             cfProps.put(PING_INTERVAL, jmsurl.getPropertyValue(PING_INTERVAL));
213
214         if (jmsurl.getPropertyValue(RECONNECT_INTERVAL) != null)
215             cfProps.put(RECONNECT_INTERVAL, jmsurl.getPropertyValue(RECONNECT_INTERVAL));
216
217         if (jmsurl.getPropertyValue(RECONNECT_TIMEOUT) != null)
218             cfProps.put(RECONNECT_TIMEOUT, jmsurl.getPropertyValue(RECONNECT_TIMEOUT));
219
220         if (jmsurl.getPropertyValue(CONNECT_ID) != null)
221             cfProps.put(CONNECT_ID, jmsurl.getPropertyValue(CONNECT_ID));
222
223         if (jmsurl.getPropertyValue(CONNECTION_URLS) != null)
224             cfProps.put(CONNECTION_URLS, jmsurl.getPropertyValue(CONNECTION_URLS));
225
226         if (jmsurl.getPropertyValue(LOAD_BALANCING) != null)
227             cfProps.put(LOAD_BALANCING, jmsurl.getPropertyValue(LOAD_BALANCING));
228
229         if (jmsurl.getPropertyValue(MONITOR_INTERVAL) != null)
230             cfProps.put(MONITOR_INTERVAL, jmsurl.getPropertyValue(MONITOR_INTERVAL));
231
232         if (jmsurl.getPropertyValue(PERSISTENT_DELIVERY) != null)
233             cfProps.put(PERSISTENT_DELIVERY, jmsurl.getPropertyValue(PERSISTENT_DELIVERY));
234
235         if (jmsurl.getPropertyValue(SEQUENTIAL) != null)
236             cfProps.put(SEQUENTIAL, jmsurl.getPropertyValue(SEQUENTIAL));
237
238         if (jmsurl.getPropertyValue(PREFETCH_COUNT) != null)
239             cfProps.put(PREFETCH_COUNT, jmsurl.getPropertyValue(PREFETCH_COUNT));
240
241         if (jmsurl.getPropertyValue(PREFETCH_THRESHOLD) != null)
242             cfProps.put(PREFETCH_THRESHOLD, jmsurl.getPropertyValue(PREFETCH_THRESHOLD));
243
244         if (jmsurl.getPropertyValue(SELECTOR_AT_BROKER) != null)
245             cfProps.put(SELECTOR_AT_BROKER, jmsurl.getPropertyValue(SELECTOR_AT_BROKER));
246     }
247
248     /**
249      * Check that the attributes of the candidate connection factory match the
250      * requested connection factory properties.
251      *
252      * @param cf the candidate connection factory
253      * @param jmsurl the JMS URL associated with the candidate connection factory
254      * @param cfProps the properties associated with the current request
255      * @return true or false
256      */

257     public boolean isMatchingConnectionFactory(javax.jms.ConnectionFactory JavaDoc cf,
258                                                JMSURLHelper jmsurl,
259                                                HashMap JavaDoc cfProps)
260     {
261         String JavaDoc brokerURL = null;
262         String JavaDoc connectionURLs = null;
263         boolean loadBalancing = false;
264         boolean sequential = false;
265
266         if (cf instanceof progress.message.jclient.QueueConnectionFactory)
267         {
268             progress.message.jclient.QueueConnectionFactory qcf =
269                 (progress.message.jclient.QueueConnectionFactory)cf;
270
271             // get existing queue connection factory properties
272
brokerURL = qcf.getBrokerURL();
273             connectionURLs = qcf.getConnectionURLs();
274             loadBalancing = qcf.getLoadBalancing();
275             sequential = qcf.getSequential();
276         }
277         else if (cf instanceof progress.message.jclient.TopicConnectionFactory)
278         {
279             progress.message.jclient.TopicConnectionFactory tcf =
280                 (progress.message.jclient.TopicConnectionFactory)cf;
281
282             // get existing topic connection factory properties
283
brokerURL = tcf.getBrokerURL();
284             connectionURLs = tcf.getConnectionURLs();
285             loadBalancing = tcf.getLoadBalancing();
286             sequential = tcf.getSequential();
287         }
288
289         // compare broker url
290
String JavaDoc propertyBrokerURL = (String JavaDoc)cfProps.get(BROKER_URL);
291         if (!brokerURL.equals(propertyBrokerURL))
292             return false;
293
294         // compare connection url list
295
String JavaDoc propertyConnectionURLs = (String JavaDoc)cfProps.get(CONNECTION_URLS);
296         if ((connectionURLs != null) && (propertyConnectionURLs != null))
297         {
298             if (!connectionURLs.equalsIgnoreCase(propertyConnectionURLs))
299                 return false;
300
301             // check sequential if connection urls have been set
302
String JavaDoc tmpSequential = (String JavaDoc)cfProps.get(SEQUENTIAL);
303             boolean propertySequential = true;
304             if (tmpSequential != null)
305                 propertySequential = Boolean.getBoolean(tmpSequential);
306             if (sequential != propertySequential)
307                 return false;
308         }
309         else if ((connectionURLs != null) || (propertyConnectionURLs != null))
310             return false;
311
312         // compare load balancing flag
313
String JavaDoc tmpLoadBalancing = (String JavaDoc)cfProps.get(LOAD_BALANCING);
314         boolean propertyLoadBalancing = false;
315         if (tmpLoadBalancing != null)
316             propertyLoadBalancing = Boolean.getBoolean(tmpLoadBalancing);
317         if (loadBalancing != propertyLoadBalancing)
318             return false;
319
320         return true;
321     }
322
323     public boolean isRecoverable(Throwable JavaDoc thrown, int action)
324     {
325         //the super class cannot be trusted for on exception because it always
326
//returns false
327
if(action != ON_EXCEPTION_ACTION && !super.isRecoverable(thrown, action))
328             return false;
329
330         if(!(thrown instanceof JMSException JavaDoc))
331             return true;
332
333         JMSException JavaDoc jmse = (JMSException JavaDoc)thrown;
334         switch(action)
335         {
336             case CONNECT_ACTION:
337                 if(isNetworkFailure(jmse))
338                     return false;
339                 break;
340             case SUBSCRIBE_ACTION:
341
342                 if(isQueueMissing(jmse) || isAnotherSubscriberConnected(jmse))
343                     return false;
344                 break;
345
346             case ON_EXCEPTION_ACTION:
347                 if(isConnectionDropped(jmse))
348                     return false;
349                 break;
350
351         }
352
353         return true;
354     }
355
356     public boolean isConnectionDropped(JMSException JavaDoc jmse)
357     {
358         return ErrorCodes.testException(jmse, ErrorCodes.ERR_CONNECTION_DROPPED);
359     }
360
361     private boolean isQueueMissing(JMSException JavaDoc jmse)
362     {
363         String JavaDoc message = jmse.getMessage();
364         if(message != null && message.startsWith("Queue not found"))
365         {
366             return true;
367         }
368         return false;
369     }
370
371     private boolean isAnotherSubscriberConnected(JMSException JavaDoc jmse)
372     {
373         Exception JavaDoc linkedException = jmse.getLinkedException();
374         if(linkedException != null &&
375            linkedException instanceof EUserAlreadyConnected)
376         {
377             return true;
378         }
379         return false;
380     }
381
382     private boolean isNetworkFailure(JMSException JavaDoc jmse)
383     {
384         Exception JavaDoc linkedException = jmse.getLinkedException();
385         if(linkedException != null &&
386            linkedException instanceof ENetworkFailure)
387         {
388             return true;
389         }
390         return false;
391     }
392 }
Popular Tags