1 16 17 package org.springframework.jca.cci.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 24 import javax.resource.NotSupportedException ; 25 import javax.resource.ResourceException ; 26 import javax.resource.cci.Connection ; 27 import javax.resource.cci.ConnectionFactory ; 28 import javax.resource.cci.ConnectionSpec ; 29 30 import org.apache.commons.logging.Log; 31 import org.apache.commons.logging.LogFactory; 32 33 import org.springframework.beans.factory.DisposableBean; 34 import org.springframework.util.Assert; 35 36 54 public class SingleConnectionFactory extends DelegatingConnectionFactory implements DisposableBean { 55 56 protected final Log logger = LogFactory.getLog(getClass()); 57 58 59 private Connection target; 60 61 62 private Connection connection; 63 64 65 private final Object connectionMonitor = new Object (); 66 67 68 72 public SingleConnectionFactory() { 73 } 74 75 80 public SingleConnectionFactory(Connection target) { 81 Assert.notNull(target, "Target Connection must not be null"); 82 this.target = target; 83 this.connection = getCloseSuppressingConnectionProxy(target); 84 } 85 86 92 public SingleConnectionFactory(ConnectionFactory targetConnectionFactory) { 93 Assert.notNull(targetConnectionFactory, "Target ConnectionFactory must not be null"); 94 setTargetConnectionFactory(targetConnectionFactory); 95 } 96 97 100 public void afterPropertiesSet() { 101 if (this.connection == null && getTargetConnectionFactory() == null) { 102 throw new IllegalArgumentException ("Connection or targetConnectionFactory is required"); 103 } 104 } 105 106 107 public Connection getConnection() throws ResourceException { 108 synchronized (this.connectionMonitor) { 109 if (this.connection == null) { 110 initConnection(); 111 } 112 return this.connection; 113 } 114 } 115 116 public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException { 117 throw new NotSupportedException ( 118 "SingleConnectionFactory does not support custom ConnectionSpec"); 119 } 120 121 127 public void destroy() { 128 resetConnection(); 129 } 130 131 132 138 public void initConnection() throws ResourceException { 139 if (getTargetConnectionFactory() == null) { 140 throw new IllegalStateException ("targetConnectionFactory is required for lazily initializing a Connection"); 141 } 142 synchronized (this.connectionMonitor) { 143 if (this.target != null) { 144 closeConnection(this.target); 145 } 146 this.target = doCreateConnection(); 147 prepareConnection(this.target); 148 if (logger.isInfoEnabled()) { 149 logger.info("Established shared CCI Connection: " + this.target); 150 } 151 this.connection = getCloseSuppressingConnectionProxy(this.target); 152 } 153 } 154 155 158 public void resetConnection() { 159 synchronized (this.connectionMonitor) { 160 if (this.target != null) { 161 closeConnection(this.target); 162 } 163 this.target = null; 164 this.connection = null; 165 } 166 } 167 168 173 protected Connection doCreateConnection() throws ResourceException { 174 return getTargetConnectionFactory().getConnection(); 175 } 176 177 182 protected void prepareConnection(Connection con) throws ResourceException { 183 } 184 185 189 protected void closeConnection(Connection con) { 190 try { 191 con.close(); 192 } 193 catch (Throwable ex) { 194 logger.warn("Could not close shared CCI Connection", ex); 195 } 196 } 197 198 206 protected Connection getCloseSuppressingConnectionProxy(Connection target) { 207 return (Connection ) Proxy.newProxyInstance( 208 Connection .class.getClassLoader(), 209 new Class [] {Connection .class}, 210 new CloseSuppressingInvocationHandler(target)); 211 } 212 213 214 217 private static class CloseSuppressingInvocationHandler implements InvocationHandler { 218 219 private final Connection target; 220 221 private CloseSuppressingInvocationHandler(Connection target) { 222 this.target = target; 223 } 224 225 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 226 if (method.getName().equals("equals")) { 227 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); 229 } 230 else if (method.getName().equals("hashCode")) { 231 return new Integer (hashCode()); 233 } 234 else if (method.getName().equals("close")) { 235 return null; 237 } 238 try { 239 return method.invoke(this.target, args); 240 } 241 catch (InvocationTargetException ex) { 242 throw ex.getTargetException(); 243 } 244 } 245 } 246 247 } 248 | Popular Tags |