001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.client;
022
023 import java.net.InetAddress;
024 import java.net.UnknownHostException;
025 import java.util.Hashtable;
026 import java.util.UUID;
027
028 import javax.jms.*;
029 import javax.naming.Context;
030 import javax.naming.Name;
031 import javax.naming.NamingException;
032 import javax.naming.RefAddr;
033 import javax.naming.Reference;
034 import javax.naming.Referenceable;
035 import javax.naming.StringRefAddr;
036 import javax.naming.spi.ObjectFactory;
037
038 import org.apache.qpid.jms.ConnectionURL;
039 import org.apache.qpid.url.AMQBindingURL;
040 import org.apache.qpid.url.URLSyntaxException;
041
042
043 public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory,
044 ObjectFactory, Referenceable, XATopicConnectionFactory,
045 XAQueueConnectionFactory, XAConnectionFactory
046 {
047 private String _host;
048 private int _port;
049 private String _defaultUsername;
050 private String _defaultPassword;
051 private String _virtualPath;
052
053 private ConnectionURL _connectionDetails;
054 private SSLConfiguration _sslConfig;
055
056 public AMQConnectionFactory()
057 {
058 }
059
060 /**
061 * This is the Only constructor used!
062 * It is used form the context and from the JNDI objects.
063 */
064 public AMQConnectionFactory(String url) throws URLSyntaxException
065 {
066 _connectionDetails = new AMQConnectionURL(url);
067 }
068
069 /**
070 * This constructor is never used!
071 */
072 public AMQConnectionFactory(ConnectionURL url)
073 {
074 _connectionDetails = url;
075 }
076
077 /**
078 * This constructor is never used!
079 */
080 public AMQConnectionFactory(String broker, String username, String password, String clientName, String virtualHost)
081 throws URLSyntaxException
082 {
083 this(new AMQConnectionURL(
084 ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" + clientName + "/" + virtualHost + "?brokerlist='" + broker + "'"));
085 }
086
087 /**
088 * This constructor is never used!
089 */
090 public AMQConnectionFactory(String host, int port, String virtualPath)
091 {
092 this(host, port, "guest", "guest", virtualPath);
093 }
094
095 /**
096 * This constructor is never used!
097 */
098 public AMQConnectionFactory(String host, int port, String defaultUsername, String defaultPassword,
099 String virtualPath)
100 {
101 _host = host;
102 _port = port;
103 _defaultUsername = defaultUsername;
104 _defaultPassword = defaultPassword;
105 _virtualPath = virtualPath;
106
107 //todo when setting Host/Port has been resolved then we can use this otherwise those methods won't work with the following line.
108 // _connectionDetails = new AMQConnectionURL(
109 // ConnectionURL.AMQ_PROTOCOL + "://" +
110 // _defaultUsername + ":" + _defaultPassword + "@" +
111 // virtualPath + "?brokerlist='tcp://" + host + ":" + port + "'");
112 }
113
114 /**
115 * @return The _defaultPassword.
116 */
117 public final String getDefaultPassword(String password)
118 {
119 if (_connectionDetails != null)
120 {
121 return _connectionDetails.getPassword();
122 }
123 else
124 {
125 return _defaultPassword;
126 }
127 }
128
129 /**
130 * @param password The _defaultPassword to set.
131 */
132 public final void setDefaultPassword(String password)
133 {
134 if (_connectionDetails != null)
135 {
136 _connectionDetails.setPassword(password);
137 }
138 _defaultPassword = password;
139 }
140
141 /**
142 * Getter for SSLConfiguration
143 *
144 * @return SSLConfiguration if set, otherwise null
145 */
146 public final SSLConfiguration getSSLConfiguration()
147 {
148 return _sslConfig;
149 }
150
151 /**
152 * Setter for SSLConfiguration
153 *
154 * @param sslConfig config to store
155 */
156 public final void setSSLConfiguration(SSLConfiguration sslConfig)
157 {
158 _sslConfig = sslConfig;
159 }
160
161 /**
162 * @return The _defaultPassword.
163 */
164 public final String getDefaultUsername(String password)
165 {
166 if (_connectionDetails != null)
167 {
168 return _connectionDetails.getUsername();
169 }
170 else
171 {
172 return _defaultUsername;
173 }
174 }
175
176 /**
177 * @param username The _defaultUsername to set.
178 */
179 public final void setDefaultUsername(String username)
180 {
181 if (_connectionDetails != null)
182 {
183 _connectionDetails.setUsername(username);
184 }
185 _defaultUsername = username;
186 }
187
188 /**
189 * @return The _host .
190 */
191 public final String getHost()
192 {
193 //todo this doesn't make sense in a multi broker URL as we have no current as that is done by AMQConnection
194 return _host;
195 }
196
197 /**
198 * @param host The _host to set.
199 */
200 public final void setHost(String host)
201 {
202 //todo if _connectionDetails is set then run _connectionDetails.addBrokerDetails()
203 // Should perhaps have this method changed to setBroker(host,port)
204 _host = host;
205 }
206
207 /**
208 * @return _port The _port to set.
209 */
210 public final int getPort()
211 {
212 //todo see getHost
213 return _port;
214 }
215
216 /**
217 * @param port The port to set.
218 */
219 public final void setPort(int port)
220 {
221 //todo see setHost
222 _port = port;
223 }
224
225 /**
226 * @return he _virtualPath.
227 */
228 public final String getVirtualPath()
229 {
230 if (_connectionDetails != null)
231 {
232 return _connectionDetails.getVirtualHost();
233 }
234 else
235 {
236 return _virtualPath;
237 }
238 }
239
240 /**
241 * @param path The _virtualPath to set.
242 */
243 public final void setVirtualPath(String path)
244 {
245 if (_connectionDetails != null)
246 {
247 _connectionDetails.setVirtualHost(path);
248 }
249
250 _virtualPath = path;
251 }
252
253 public static String getUniqueClientID()
254 {
255 try
256 {
257 InetAddress addr = InetAddress.getLocalHost();
258 return addr.getHostName() + System.currentTimeMillis();
259 }
260 catch (UnknownHostException e)
261 {
262 return "UnknownHost" + UUID.randomUUID();
263 }
264 }
265
266 public Connection createConnection() throws JMSException
267 {
268 try
269 {
270 if (_connectionDetails != null)
271 {
272 if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
273 {
274 _connectionDetails.setClientName(getUniqueClientID());
275 }
276 return new AMQConnection(_connectionDetails, _sslConfig);
277 }
278 else
279 {
280 return new AMQConnection(_host, _port, _defaultUsername, _defaultPassword, getUniqueClientID(),
281 _virtualPath);
282 }
283 }
284 catch (Exception e)
285 {
286 JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
287 jmse.setLinkedException(e);
288 throw jmse;
289 }
290
291
292 }
293
294 public Connection createConnection(String userName, String password) throws JMSException
295 {
296 return createConnection(userName, password, null);
297 }
298
299 public Connection createConnection(String userName, String password, String id) throws JMSException
300 {
301 try
302 {
303 if (_connectionDetails != null)
304 {
305 _connectionDetails.setUsername(userName);
306 _connectionDetails.setPassword(password);
307
308 if (id != null && !id.equals(""))
309 {
310 _connectionDetails.setClientName(id);
311 }
312 else if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
313 {
314 _connectionDetails.setClientName(getUniqueClientID());
315 }
316 return new AMQConnection(_connectionDetails, _sslConfig);
317 }
318 else
319 {
320 return new AMQConnection(_host, _port, userName, password, (id != null ? id : getUniqueClientID()), _virtualPath);
321 }
322 }
323 catch (Exception e)
324 {
325 JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
326 jmse.setLinkedException(e);
327 throw jmse;
328 }
329 }
330
331 public QueueConnection createQueueConnection() throws JMSException
332 {
333 return (QueueConnection) createConnection();
334 }
335
336 public QueueConnection createQueueConnection(String username, String password) throws JMSException
337 {
338 return (QueueConnection) createConnection(username, password);
339 }
340
341 public TopicConnection createTopicConnection() throws JMSException
342 {
343 return (TopicConnection) createConnection();
344 }
345
346 public TopicConnection createTopicConnection(String username, String password) throws JMSException
347 {
348 return (TopicConnection) createConnection(username, password);
349 }
350
351
352 public ConnectionURL getConnectionURL()
353 {
354 return _connectionDetails;
355 }
356
357 /**
358 * JNDI interface to create objects from References.
359 *
360 * @param obj The Reference from JNDI
361 * @param name
362 * @param ctx
363 * @param env
364 *
365 * @return AMQConnection,AMQTopic,AMQQueue, or AMQConnectionFactory.
366 *
367 * @throws Exception
368 */
369 public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception
370 {
371 if (obj instanceof Reference)
372 {
373 Reference ref = (Reference) obj;
374
375 if (ref.getClassName().equals(AMQConnection.class.getName()))
376 {
377 RefAddr addr = ref.get(AMQConnection.class.getName());
378
379 if (addr != null)
380 {
381 return new AMQConnection((String) addr.getContent());
382 }
383 }
384
385 if (ref.getClassName().equals(AMQQueue.class.getName()))
386 {
387 RefAddr addr = ref.get(AMQQueue.class.getName());
388
389 if (addr != null)
390 {
391 return new AMQQueue(new AMQBindingURL((String) addr.getContent()));
392 }
393 }
394
395 if (ref.getClassName().equals(AMQTopic.class.getName()))
396 {
397 RefAddr addr = ref.get(AMQTopic.class.getName());
398
399 if (addr != null)
400 {
401 return new AMQTopic(new AMQBindingURL((String) addr.getContent()));
402 }
403 }
404
405 if (ref.getClassName().equals(AMQConnectionFactory.class.getName()))
406 {
407 RefAddr addr = ref.get(AMQConnectionFactory.class.getName());
408
409 if (addr != null)
410 {
411 return new AMQConnectionFactory((String) addr.getContent());
412 }
413 }
414
415 }
416 return null;
417 }
418
419
420 public Reference getReference() throws NamingException
421 {
422 return new Reference(
423 AMQConnectionFactory.class.getName(),
424 new StringRefAddr(AMQConnectionFactory.class.getName(), _connectionDetails.getURL()),
425 AMQConnectionFactory.class.getName(), null); // factory location
426 }
427
428 // ---------------------------------------------------------------------------------------------------
429 // the following methods are provided for XA compatibility
430 // Those methods are only supported by 0_10 and above
431 // ---------------------------------------------------------------------------------------------------
432
433 /**
434 * Creates a XAConnection with the default user identity.
435 * <p> The XAConnection is created in stopped mode. No messages
436 * will be delivered until the <code>Connection.start</code> method
437 * is explicitly called.
438 *
439 * @return A newly created XAConnection
440 * @throws JMSException If creating the XAConnection fails due to some internal error.
441 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
442 */
443 public XAConnection createXAConnection() throws JMSException
444 {
445 try
446 {
447 return new XAConnectionImpl(_connectionDetails, _sslConfig);
448 }
449 catch (Exception e)
450 {
451 JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
452 jmse.setLinkedException(e);
453 throw jmse;
454 }
455 }
456
457 /**
458 * Creates a XAConnection with the specified user identity.
459 * <p> The XAConnection is created in stopped mode. No messages
460 * will be delivered until the <code>Connection.start</code> method
461 * is explicitly called.
462 *
463 * @param username the caller's user name
464 * @param password the caller's password
465 * @return A newly created XAConnection.
466 * @throws JMSException If creating the XAConnection fails due to some internal error.
467 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
468 */
469 public XAConnection createXAConnection(String username, String password) throws JMSException
470 {
471 if (_connectionDetails != null)
472 {
473 _connectionDetails.setUsername(username);
474 _connectionDetails.setPassword(password);
475
476 if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
477 {
478 _connectionDetails.setClientName(getUniqueClientID());
479 }
480 }
481 else
482 {
483 throw new JMSException("A URL must be specified to access XA connections");
484 }
485 return createXAConnection();
486 }
487
488
489 /**
490 * Creates a XATopicConnection with the default user identity.
491 * <p> The XATopicConnection is created in stopped mode. No messages
492 * will be delivered until the <code>Connection.start</code> method
493 * is explicitly called.
494 *
495 * @return A newly created XATopicConnection
496 * @throws JMSException If creating the XATopicConnection fails due to some internal error.
497 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
498 */
499 public XATopicConnection createXATopicConnection() throws JMSException
500 {
501 return (XATopicConnection) createXAConnection();
502 }
503
504 /**
505 * Creates a XATopicConnection with the specified user identity.
506 * <p> The XATopicConnection is created in stopped mode. No messages
507 * will be delivered until the <code>Connection.start</code> method
508 * is explicitly called.
509 *
510 * @param username the caller's user name
511 * @param password the caller's password
512 * @return A newly created XATopicConnection.
513 * @throws JMSException If creating the XATopicConnection fails due to some internal error.
514 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
515 */
516 public XATopicConnection createXATopicConnection(String username, String password) throws JMSException
517 {
518 return (XATopicConnection) createXAConnection(username, password);
519 }
520
521 /**
522 * Creates a XAQueueConnection with the default user identity.
523 * <p> The XAQueueConnection is created in stopped mode. No messages
524 * will be delivered until the <code>Connection.start</code> method
525 * is explicitly called.
526 *
527 * @return A newly created XAQueueConnection
528 * @throws JMSException If creating the XAQueueConnection fails due to some internal error.
529 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
530 */
531 public XAQueueConnection createXAQueueConnection() throws JMSException
532 {
533 return (XAQueueConnection) createXAConnection();
534 }
535
536 /**
537 * Creates a XAQueueConnection with the specified user identity.
538 * <p> The XAQueueConnection is created in stopped mode. No messages
539 * will be delivered until the <code>Connection.start</code> method
540 * is explicitly called.
541 *
542 * @param username the caller's user name
543 * @param password the caller's password
544 * @return A newly created XAQueueConnection.
545 * @throws JMSException If creating the XAQueueConnection fails due to some internal error.
546 * @throws JMSSecurityException If client authentication fails due to an invalid user name or password.
547 */
548 public XAQueueConnection createXAQueueConnection(String username, String password) throws JMSException
549 {
550 return (XAQueueConnection) createXAConnection(username, password);
551 }
552 }
|