1 package org.apache.ojb.broker.accesslayer; 2 3 17 18 import org.apache.commons.pool.BasePoolableObjectFactory; 19 import org.apache.commons.pool.ObjectPool; 20 import org.apache.commons.pool.PoolableObjectFactory; 21 import org.apache.commons.pool.impl.GenericObjectPool; 22 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor; 23 import org.apache.ojb.broker.util.logging.Logger; 24 import org.apache.ojb.broker.util.logging.LoggerFactory; 25 import org.apache.ojb.broker.OJBRuntimeException; 26 27 import java.sql.Connection ; 28 import java.sql.ResultSet ; 29 import java.sql.SQLException ; 30 import java.sql.PreparedStatement ; 31 import java.util.Collection ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.Map ; 35 import java.util.NoSuchElementException ; 36 37 45 public class ConnectionFactoryPooledImpl extends ConnectionFactoryAbstractImpl 46 { 47 48 private Logger log = LoggerFactory.getLogger(ConnectionFactoryPooledImpl.class); 49 50 private Map poolMap = new HashMap (); 51 52 private final Object poolSynch = new Object (); 53 54 public void releaseJdbcConnection(JdbcConnectionDescriptor jcd, Connection con) 55 throws LookupException 56 { 57 final ObjectPool op = (ObjectPool) poolMap.get(jcd.getPBKey()); 58 try 59 { 60 70 op.returnObject(con); 71 } 72 catch (Exception e) 73 { 74 throw new LookupException(e); 75 } 76 } 77 78 public Connection checkOutJdbcConnection(JdbcConnectionDescriptor jcd) throws LookupException 79 { 80 ObjectPool op = (ObjectPool) poolMap.get(jcd.getPBKey()); 81 if (op == null) 82 { 83 synchronized (poolSynch) 84 { 85 log.info("Create new connection pool:" + jcd); 86 op = createConnectionPool(jcd); 87 poolMap.put(jcd.getPBKey(), op); 88 } 89 } 90 final Connection conn; 91 try 92 { 93 conn = (Connection ) op.borrowObject(); 94 } 95 catch (NoSuchElementException e) 96 { 97 int active = 0; 98 int idle = 0; 99 try 100 { 101 active = op.getNumActive(); 102 idle = op.getNumIdle(); 103 } 104 catch(Exception ignore){} 105 throw new LookupException("Could not borrow connection from pool, seems ObjectPool is exhausted." + 106 " Active/Idle instances in pool=" + active + "/" + idle 107 + ". "+ JdbcConnectionDescriptor.class.getName() + ": " + jcd, e); 108 } 109 catch (Exception e) 110 { 111 int active = 0; 112 int idle = 0; 113 try 114 { 115 active = op.getNumActive(); 116 idle = op.getNumIdle(); 117 } 118 catch(Exception ignore){} 119 throw new LookupException("Could not borrow connection from pool." + 120 " Active/Idle instances in pool=" + active + "/" + idle 121 + ". "+ JdbcConnectionDescriptor.class.getName() + ": " + jcd, e); 122 } 123 return conn; 124 } 125 126 130 public ObjectPool createConnectionPool(JdbcConnectionDescriptor jcd) 131 { 132 if (log.isDebugEnabled()) log.debug("createPool was called"); 133 PoolableObjectFactory pof = new ConPoolFactory(this, jcd); 134 GenericObjectPool.Config conf = jcd.getConnectionPoolDescriptor().getObjectPoolConfig(); 135 return (ObjectPool)new GenericObjectPool(pof, conf); 136 } 137 138 141 public void releaseAllResources() 142 { 143 synchronized (poolSynch) 144 { 145 Collection pools = poolMap.values(); 146 poolMap = new HashMap (poolMap.size()); 147 ObjectPool op = null; 148 for (Iterator iterator = pools.iterator(); iterator.hasNext();) 149 { 150 try 151 { 152 op = ((ObjectPool) iterator.next()); 153 op.close(); 154 } 155 catch (Exception e) 156 { 157 log.error("Exception occured while closing pool " + op, e); 158 } 159 } 160 } 161 super.releaseAllResources(); 162 } 163 164 168 172 class ConPoolFactory extends BasePoolableObjectFactory 173 { 174 final private JdbcConnectionDescriptor jcd; 175 final private ConnectionFactoryPooledImpl cf; 176 private int failedValidationQuery; 177 178 public ConPoolFactory(ConnectionFactoryPooledImpl cf, JdbcConnectionDescriptor jcd) 179 { 180 this.cf = cf; 181 this.jcd = jcd; 182 } 183 184 public boolean validateObject(Object obj) 185 { 186 boolean isValid = false; 187 if (obj != null) 188 { 189 final Connection con = (Connection ) obj; 190 try 191 { 192 isValid = !con.isClosed(); 193 } 194 catch (SQLException e) 195 { 196 log.warn("Connection validation failed: " + e.getMessage()); 197 if (log.isDebugEnabled()) log.debug(e); 198 isValid = false; 199 } 200 if (isValid) 201 { 202 final String validationQuery; 203 validationQuery = jcd.getConnectionPoolDescriptor().getValidationQuery(); 204 if (validationQuery != null) 205 { 206 isValid = validateConnection(con, validationQuery); 207 } 208 } 209 } 210 return isValid; 211 } 212 213 private boolean validateConnection(Connection conn, String query) 214 { 215 PreparedStatement stmt = null; 216 ResultSet rset = null; 217 boolean isValid = false; 218 if (failedValidationQuery > 100) 219 { 220 --failedValidationQuery; 221 throw new OJBRuntimeException("Validation of connection "+conn+" using validation query '"+ 222 query + "' failed more than 100 times."); 223 } 224 try 225 { 226 stmt = conn.prepareStatement(query); 227 stmt.setMaxRows(1); 228 stmt.setFetchSize(1); 229 rset = stmt.executeQuery(); 230 if (rset.next()) 231 { 232 failedValidationQuery = 0; 233 isValid = true; 234 } 235 else 236 { 237 ++failedValidationQuery; 238 log.warn("Validation query '" + query + 239 "' result set does not match, discard connection"); 240 isValid = false; 241 } 242 } 243 catch (SQLException e) 244 { 245 ++failedValidationQuery; 246 log.warn("Validation query for connection failed, discard connection. Query was '" + 247 query + "', Message was " + e.getMessage()); 248 if (log.isDebugEnabled()) log.debug(e); 249 } 250 finally 251 { 252 try 253 { 254 if(rset != null) rset.close(); 255 } 256 catch (SQLException t) 257 { 258 if (log.isDebugEnabled()) log.debug("ResultSet already closed.", t); 259 } 260 try 261 { 262 if(stmt != null) stmt.close(); 263 } 264 catch (SQLException t) 265 { 266 if (log.isDebugEnabled()) log.debug("Statement already closed.", t); 267 } 268 } 269 return isValid; 270 } 271 272 public Object makeObject() throws Exception 273 { 274 if (log.isDebugEnabled()) log.debug("makeObject called"); 275 return cf.newConnectionFromDriverManager(jcd); 276 } 277 278 public void destroyObject(Object obj) 279 throws Exception 280 { 281 log.info("Destroy object was called, try to close connection: " + obj); 282 try 283 { 284 ((Connection ) obj).close(); 285 } 286 catch (SQLException ignore) 287 { 288 } 290 } 291 } 292 293 } 294 | Popular Tags |