PageRenderTime 70ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/spring-jms/src/main/java/org/springframework/jms/connection/UserCredentialsConnectionFactoryAdapter.java

https://github.com/edwin-noh/spring-framework
Java | 300 lines | 123 code | 35 blank | 142 comment | 22 complexity | 57adc30fdd8743aef70edea99fe1bce1 MD5 | raw file
  1. /*
  2. * Copyright 2002-2010 the original author or authors.
  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. package org.springframework.jms.connection;
  17. import javax.jms.Connection;
  18. import javax.jms.ConnectionFactory;
  19. import javax.jms.JMSException;
  20. import javax.jms.QueueConnection;
  21. import javax.jms.QueueConnectionFactory;
  22. import javax.jms.TopicConnection;
  23. import javax.jms.TopicConnectionFactory;
  24. import org.springframework.beans.factory.InitializingBean;
  25. import org.springframework.core.NamedThreadLocal;
  26. import org.springframework.util.Assert;
  27. import org.springframework.util.StringUtils;
  28. /**
  29. * An adapter for a target JMS {@link javax.jms.ConnectionFactory}, applying the
  30. * given user credentials to every standard <code>createConnection()</code> call,
  31. * that is, implicitly invoking <code>createConnection(username, password)</code>
  32. * on the target. All other methods simply delegate to the corresponding methods
  33. * of the target ConnectionFactory.
  34. *
  35. * <p>Can be used to proxy a target JNDI ConnectionFactory that does not have user
  36. * credentials configured. Client code can work with the ConnectionFactory without
  37. * passing in username and password on every <code>createConnection()</code> call.
  38. *
  39. * <p>In the following example, client code can simply transparently work
  40. * with the preconfigured "myConnectionFactory", implicitly accessing
  41. * "myTargetConnectionFactory" with the specified user credentials.
  42. *
  43. * <pre class="code">
  44. * &lt;bean id="myTargetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
  45. * &lt;property name="jndiName" value="java:comp/env/jms/mycf"/&gt;
  46. * &lt;/bean&gt;
  47. *
  48. * &lt;bean id="myConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter"&gt;
  49. * &lt;property name="targetConnectionFactory" ref="myTargetConnectionFactory"/&gt;
  50. * &lt;property name="username" value="myusername"/&gt;
  51. * &lt;property name="password" value="mypassword"/&gt;
  52. * &lt;/bean></pre>
  53. *
  54. * <p>If the "username" is empty, this proxy will simply delegate to the standard
  55. * <code>createConnection()</code> method of the target ConnectionFactory.
  56. * This can be used to keep a UserCredentialsConnectionFactoryAdapter bean
  57. * definition just for the <i>option</i> of implicitly passing in user credentials
  58. * if the particular target ConnectionFactory requires it.
  59. *
  60. * @author Juergen Hoeller
  61. * @since 1.2
  62. * @see #createConnection
  63. * @see #createQueueConnection
  64. * @see #createTopicConnection
  65. */
  66. public class UserCredentialsConnectionFactoryAdapter
  67. implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, InitializingBean {
  68. private ConnectionFactory targetConnectionFactory;
  69. private String username;
  70. private String password;
  71. private final ThreadLocal<JmsUserCredentials> threadBoundCredentials =
  72. new NamedThreadLocal<JmsUserCredentials>("Current JMS user credentials");
  73. /**
  74. * Set the target ConnectionFactory that this ConnectionFactory should delegate to.
  75. */
  76. public void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) {
  77. Assert.notNull(targetConnectionFactory, "'targetConnectionFactory' must not be null");
  78. this.targetConnectionFactory = targetConnectionFactory;
  79. }
  80. /**
  81. * Set the username that this adapter should use for retrieving Connections.
  82. * Default is no specific user.
  83. */
  84. public void setUsername(String username) {
  85. this.username = username;
  86. }
  87. /**
  88. * Set the password that this adapter should use for retrieving Connections.
  89. * Default is no specific password.
  90. */
  91. public void setPassword(String password) {
  92. this.password = password;
  93. }
  94. public void afterPropertiesSet() {
  95. if (this.targetConnectionFactory == null) {
  96. throw new IllegalArgumentException("Property 'targetConnectionFactory' is required");
  97. }
  98. }
  99. /**
  100. * Set user credententials for this proxy and the current thread.
  101. * The given username and password will be applied to all subsequent
  102. * <code>createConnection()</code> calls on this ConnectionFactory proxy.
  103. * <p>This will override any statically specified user credentials,
  104. * that is, values of the "username" and "password" bean properties.
  105. * @param username the username to apply
  106. * @param password the password to apply
  107. * @see #removeCredentialsFromCurrentThread
  108. */
  109. public void setCredentialsForCurrentThread(String username, String password) {
  110. this.threadBoundCredentials.set(new JmsUserCredentials(username, password));
  111. }
  112. /**
  113. * Remove any user credentials for this proxy from the current thread.
  114. * Statically specified user credentials apply again afterwards.
  115. * @see #setCredentialsForCurrentThread
  116. */
  117. public void removeCredentialsFromCurrentThread() {
  118. this.threadBoundCredentials.remove();
  119. }
  120. /**
  121. * Determine whether there are currently thread-bound credentials,
  122. * using them if available, falling back to the statically specified
  123. * username and password (i.e. values of the bean properties) else.
  124. * @see #doCreateConnection
  125. */
  126. public final Connection createConnection() throws JMSException {
  127. JmsUserCredentials threadCredentials = this.threadBoundCredentials.get();
  128. if (threadCredentials != null) {
  129. return doCreateConnection(threadCredentials.username, threadCredentials.password);
  130. }
  131. else {
  132. return doCreateConnection(this.username, this.password);
  133. }
  134. }
  135. /**
  136. * Delegate the call straight to the target ConnectionFactory.
  137. */
  138. public Connection createConnection(String username, String password) throws JMSException {
  139. return doCreateConnection(username, password);
  140. }
  141. /**
  142. * This implementation delegates to the <code>createConnection(username, password)</code>
  143. * method of the target ConnectionFactory, passing in the specified user credentials.
  144. * If the specified username is empty, it will simply delegate to the standard
  145. * <code>createConnection()</code> method of the target ConnectionFactory.
  146. * @param username the username to use
  147. * @param password the password to use
  148. * @return the Connection
  149. * @see javax.jms.ConnectionFactory#createConnection(String, String)
  150. * @see javax.jms.ConnectionFactory#createConnection()
  151. */
  152. protected Connection doCreateConnection(String username, String password) throws JMSException {
  153. Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required");
  154. if (StringUtils.hasLength(username)) {
  155. return this.targetConnectionFactory.createConnection(username, password);
  156. }
  157. else {
  158. return this.targetConnectionFactory.createConnection();
  159. }
  160. }
  161. /**
  162. * Determine whether there are currently thread-bound credentials,
  163. * using them if available, falling back to the statically specified
  164. * username and password (i.e. values of the bean properties) else.
  165. * @see #doCreateQueueConnection
  166. */
  167. public final QueueConnection createQueueConnection() throws JMSException {
  168. JmsUserCredentials threadCredentials = this.threadBoundCredentials.get();
  169. if (threadCredentials != null) {
  170. return doCreateQueueConnection(threadCredentials.username, threadCredentials.password);
  171. }
  172. else {
  173. return doCreateQueueConnection(this.username, this.password);
  174. }
  175. }
  176. /**
  177. * Delegate the call straight to the target QueueConnectionFactory.
  178. */
  179. public QueueConnection createQueueConnection(String username, String password) throws JMSException {
  180. return doCreateQueueConnection(username, password);
  181. }
  182. /**
  183. * This implementation delegates to the <code>createQueueConnection(username, password)</code>
  184. * method of the target QueueConnectionFactory, passing in the specified user credentials.
  185. * If the specified username is empty, it will simply delegate to the standard
  186. * <code>createQueueConnection()</code> method of the target ConnectionFactory.
  187. * @param username the username to use
  188. * @param password the password to use
  189. * @return the Connection
  190. * @see javax.jms.QueueConnectionFactory#createQueueConnection(String, String)
  191. * @see javax.jms.QueueConnectionFactory#createQueueConnection()
  192. */
  193. protected QueueConnection doCreateQueueConnection(String username, String password) throws JMSException {
  194. Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required");
  195. if (!(this.targetConnectionFactory instanceof QueueConnectionFactory)) {
  196. throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory");
  197. }
  198. QueueConnectionFactory queueFactory = (QueueConnectionFactory) this.targetConnectionFactory;
  199. if (StringUtils.hasLength(username)) {
  200. return queueFactory.createQueueConnection(username, password);
  201. }
  202. else {
  203. return queueFactory.createQueueConnection();
  204. }
  205. }
  206. /**
  207. * Determine whether there are currently thread-bound credentials,
  208. * using them if available, falling back to the statically specified
  209. * username and password (i.e. values of the bean properties) else.
  210. * @see #doCreateTopicConnection
  211. */
  212. public final TopicConnection createTopicConnection() throws JMSException {
  213. JmsUserCredentials threadCredentials = this.threadBoundCredentials.get();
  214. if (threadCredentials != null) {
  215. return doCreateTopicConnection(threadCredentials.username, threadCredentials.password);
  216. }
  217. else {
  218. return doCreateTopicConnection(this.username, this.password);
  219. }
  220. }
  221. /**
  222. * Delegate the call straight to the target TopicConnectionFactory.
  223. */
  224. public TopicConnection createTopicConnection(String username, String password) throws JMSException {
  225. return doCreateTopicConnection(username, password);
  226. }
  227. /**
  228. * This implementation delegates to the <code>createTopicConnection(username, password)</code>
  229. * method of the target TopicConnectionFactory, passing in the specified user credentials.
  230. * If the specified username is empty, it will simply delegate to the standard
  231. * <code>createTopicConnection()</code> method of the target ConnectionFactory.
  232. * @param username the username to use
  233. * @param password the password to use
  234. * @return the Connection
  235. * @see javax.jms.TopicConnectionFactory#createTopicConnection(String, String)
  236. * @see javax.jms.TopicConnectionFactory#createTopicConnection()
  237. */
  238. protected TopicConnection doCreateTopicConnection(String username, String password) throws JMSException {
  239. Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required");
  240. if (!(this.targetConnectionFactory instanceof TopicConnectionFactory)) {
  241. throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory");
  242. }
  243. TopicConnectionFactory queueFactory = (TopicConnectionFactory) this.targetConnectionFactory;
  244. if (StringUtils.hasLength(username)) {
  245. return queueFactory.createTopicConnection(username, password);
  246. }
  247. else {
  248. return queueFactory.createTopicConnection();
  249. }
  250. }
  251. /**
  252. * Inner class used as ThreadLocal value.
  253. */
  254. private static class JmsUserCredentials {
  255. public final String username;
  256. public final String password;
  257. private JmsUserCredentials(String username, String password) {
  258. this.username = username;
  259. this.password = password;
  260. }
  261. public String toString() {
  262. return "JmsUserCredentials[username='" + this.username + "',password='" + this.password + "']";
  263. }
  264. }
  265. }