1 16 17 package org.springframework.jms.connection; 18 19 import java.lang.reflect.InvocationHandler ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.ArrayList ; 24 import java.util.List ; 25 26 import javax.jms.Connection ; 27 import javax.jms.ConnectionFactory ; 28 import javax.jms.JMSException ; 29 import javax.jms.QueueConnection ; 30 import javax.jms.QueueConnectionFactory ; 31 import javax.jms.QueueSession ; 32 import javax.jms.Session ; 33 import javax.jms.TopicConnection ; 34 import javax.jms.TopicConnectionFactory ; 35 import javax.jms.TopicSession ; 36 import javax.jms.TransactionInProgressException ; 37 38 import org.springframework.util.Assert; 39 40 79 public class TransactionAwareConnectionFactoryProxy 80 implements ConnectionFactory , QueueConnectionFactory , TopicConnectionFactory { 81 82 private boolean synchedLocalTransactionAllowed = false; 83 84 private ConnectionFactory targetConnectionFactory; 85 86 87 90 public TransactionAwareConnectionFactoryProxy() { 91 } 92 93 97 public TransactionAwareConnectionFactoryProxy(ConnectionFactory targetConnectionFactory) { 98 setTargetConnectionFactory(targetConnectionFactory); 99 } 100 101 102 105 public final void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) { 106 Assert.notNull(targetConnectionFactory, "targetConnectionFactory must not be nul"); 107 this.targetConnectionFactory = targetConnectionFactory; 108 } 109 110 113 protected ConnectionFactory getTargetConnectionFactory() { 114 return this.targetConnectionFactory; 115 } 116 117 128 public void setSynchedLocalTransactionAllowed(boolean synchedLocalTransactionAllowed) { 129 this.synchedLocalTransactionAllowed = synchedLocalTransactionAllowed; 130 } 131 132 136 protected boolean isSynchedLocalTransactionAllowed() { 137 return this.synchedLocalTransactionAllowed; 138 } 139 140 141 public Connection createConnection() throws JMSException { 142 Connection targetConnection = this.targetConnectionFactory.createConnection(); 143 return getTransactionAwareConnectionProxy(targetConnection); 144 } 145 146 public Connection createConnection(String username, String password) throws JMSException { 147 Connection targetConnection = this.targetConnectionFactory.createConnection(username, password); 148 return getTransactionAwareConnectionProxy(targetConnection); 149 } 150 151 public QueueConnection createQueueConnection() throws JMSException { 152 if (!(this.targetConnectionFactory instanceof QueueConnectionFactory )) { 153 throw new javax.jms.IllegalStateException ("'targetConnectionFactory' is no QueueConnectionFactory"); 154 } 155 QueueConnection targetConnection = 156 ((QueueConnectionFactory ) this.targetConnectionFactory).createQueueConnection(); 157 return (QueueConnection ) getTransactionAwareConnectionProxy(targetConnection); 158 } 159 160 public QueueConnection createQueueConnection(String username, String password) throws JMSException { 161 if (!(this.targetConnectionFactory instanceof QueueConnectionFactory )) { 162 throw new javax.jms.IllegalStateException ("'targetConnectionFactory' is no QueueConnectionFactory"); 163 } 164 QueueConnection targetConnection = 165 ((QueueConnectionFactory ) this.targetConnectionFactory).createQueueConnection(username, password); 166 return (QueueConnection ) getTransactionAwareConnectionProxy(targetConnection); 167 } 168 169 public TopicConnection createTopicConnection() throws JMSException { 170 if (!(this.targetConnectionFactory instanceof TopicConnectionFactory )) { 171 throw new javax.jms.IllegalStateException ("'targetConnectionFactory' is no TopicConnectionFactory"); 172 } 173 TopicConnection targetConnection = 174 ((TopicConnectionFactory ) this.targetConnectionFactory).createTopicConnection(); 175 return (TopicConnection ) getTransactionAwareConnectionProxy(targetConnection); 176 } 177 178 public TopicConnection createTopicConnection(String username, String password) throws JMSException { 179 if (!(this.targetConnectionFactory instanceof TopicConnectionFactory )) { 180 throw new javax.jms.IllegalStateException ("'targetConnectionFactory' is no TopicConnectionFactory"); 181 } 182 TopicConnection targetConnection = 183 ((TopicConnectionFactory ) this.targetConnectionFactory).createTopicConnection(username, password); 184 return (TopicConnection ) getTransactionAwareConnectionProxy(targetConnection); 185 } 186 187 188 194 private Connection getTransactionAwareConnectionProxy(Connection target) { 195 List classes = new ArrayList (3); 196 classes.add(Connection .class); 197 if (target instanceof QueueConnection ) { 198 classes.add(QueueConnection .class); 199 } 200 if (target instanceof TopicConnection ) { 201 classes.add(TopicConnection .class); 202 } 203 return (Connection ) Proxy.newProxyInstance( 204 getClass().getClassLoader(), 205 (Class []) classes.toArray(new Class [classes.size()]), 206 new TransactionAwareConnectionInvocationHandler(target)); 207 } 208 209 210 213 private class TransactionAwareConnectionInvocationHandler implements InvocationHandler { 214 215 private final Connection target; 216 217 public TransactionAwareConnectionInvocationHandler(Connection target) { 218 this.target = target; 219 } 220 221 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 222 224 if (Session .class.equals(method.getReturnType())) { 225 Session session = ConnectionFactoryUtils.getTransactionalSession( 226 getTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed()); 227 if (session != null) { 228 return getCloseSuppressingSessionProxy(session); 229 } 230 } 231 else if (QueueSession .class.equals(method.getReturnType())) { 232 QueueSession session = ConnectionFactoryUtils.getTransactionalQueueSession( 233 (QueueConnectionFactory ) getTargetConnectionFactory(), (QueueConnection ) this.target, 234 isSynchedLocalTransactionAllowed()); 235 if (session != null) { 236 return getCloseSuppressingSessionProxy(session); 237 } 238 } 239 else if (TopicSession .class.equals(method.getReturnType())) { 240 TopicSession session = ConnectionFactoryUtils.getTransactionalTopicSession( 241 (TopicConnectionFactory ) getTargetConnectionFactory(), (TopicConnection ) this.target, 242 isSynchedLocalTransactionAllowed()); 243 if (session != null) { 244 return getCloseSuppressingSessionProxy(session); 245 } 246 } 247 else if (method.getName().equals("equals")) { 248 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); 250 } 251 else if (method.getName().equals("hashCode")) { 252 return new Integer (hashCode()); 254 } 255 256 try { 258 return method.invoke(this.target, args); 259 } 260 catch (InvocationTargetException ex) { 261 throw ex.getTargetException(); 262 } 263 } 264 265 private Session getCloseSuppressingSessionProxy(Session target) { 266 List classes = new ArrayList (3); 267 classes.add(SessionProxy.class); 268 if (target instanceof QueueSession ) { 269 classes.add(QueueSession .class); 270 } 271 if (target instanceof TopicSession ) { 272 classes.add(TopicSession .class); 273 } 274 return (Session ) Proxy.newProxyInstance( 275 SessionProxy.class.getClassLoader(), 276 (Class []) classes.toArray(new Class [classes.size()]), 277 new CloseSuppressingSessionInvocationHandler(target)); 278 } 279 } 280 281 282 285 private static class CloseSuppressingSessionInvocationHandler implements InvocationHandler { 286 287 private final Session target; 288 289 public CloseSuppressingSessionInvocationHandler(Session target) { 290 this.target = target; 291 } 292 293 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 294 296 if (method.getName().equals("getTargetSession")) { 297 return this.target; 299 } 300 else if (method.getName().equals("equals")) { 301 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); 303 } 304 else if (method.getName().equals("hashCode")) { 305 return new Integer (hashCode()); 307 } 308 else if (method.getName().equals("commit")) { 309 throw new TransactionInProgressException ("Commit call not allowed within a managed transaction"); 310 } 311 else if (method.getName().equals("rollback")) { 312 throw new TransactionInProgressException ("Rollback call not allowed within a managed transaction"); 313 } 314 else if (method.getName().equals("close")) { 315 return null; 317 } 318 319 try { 321 return method.invoke(this.target, args); 322 } 323 catch (InvocationTargetException ex) { 324 throw ex.getTargetException(); 325 } 326 } 327 } 328 329 } 330 | Popular Tags |