1 4 package org.ofbiz.minerva.pool.jdbc.xa; 5 6 import javax.sql.ConnectionEvent ; 7 import javax.sql.ConnectionEventListener ; 8 import javax.sql.XAConnection ; 9 import javax.sql.XADataSource ; 10 import javax.transaction.Status ; 11 import javax.transaction.Transaction ; 12 import javax.transaction.TransactionManager ; 13 import javax.transaction.xa.XAResource ; 14 import java.sql.Connection ; 15 import java.sql.SQLException ; 16 import java.util.Collections ; 17 import java.util.HashMap ; 18 import java.util.Map ; 19 20 import org.apache.log4j.Logger; 21 import org.ofbiz.minerva.pool.ObjectPool; 22 import org.ofbiz.minerva.pool.PoolObjectFactory; 23 import org.ofbiz.minerva.pool.jdbc.xa.wrapper.TransactionListener; 24 import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XAConnectionImpl; 25 import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XADataSourceImpl; 26 import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XAResourceImpl; 27 28 49 public class XAConnectionFactory extends PoolObjectFactory { 50 51 public static final int DEFAULT_ISOLATION = -1; 52 53 private XADataSource source; 54 private String userName; 55 private String password; 56 private int psCacheSize = 10; 57 private boolean releaseOnCommit = false; 58 private boolean saveStackTrace = false; 59 private int transactionIsolation = DEFAULT_ISOLATION; 60 private ConnectionEventListener listener, errorListener; 61 private TransactionListener transListener; 62 private ObjectPool pool; 63 private final Map wrapperTx = Collections.synchronizedMap(new HashMap ()); 64 private final Map rms = Collections.synchronizedMap(new HashMap ()); 65 private TransactionManager tm; 66 67 private static Logger log = Logger.getLogger(XAConnectionFactory.class); 68 69 73 public XAConnectionFactory() { 74 final boolean trace = log.isDebugEnabled(); 75 errorListener = new ConnectionEventListener () { 78 public void connectionErrorOccurred(ConnectionEvent evt) { 79 if (pool.isInvalidateOnError()) { 80 pool.markObjectAsInvalid(evt.getSource()); 81 } 82 } 83 84 public void connectionClosed(ConnectionEvent evt) { 85 } 86 }; 87 88 listener = new ConnectionEventListener () { 89 90 public void connectionErrorOccurred(ConnectionEvent evt) { 91 if (pool.isInvalidateOnError()) { 92 pool.markObjectAsInvalid(evt.getSource()); 93 } 94 } 96 97 public void connectionClosed(ConnectionEvent evt) { 98 closeConnection(evt, XAResource.TMSUCCESS); 99 } 100 101 private void closeConnection(ConnectionEvent evt, int status) { 102 XAConnection con = (XAConnection ) evt.getSource(); 103 try { 104 con.removeConnectionEventListener(listener); 105 } catch (IllegalArgumentException e) { 106 return; } 108 Transaction trans = null; 109 try { 110 if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) { 111 trans = tm.getTransaction(); 112 XAResource res = (XAResource ) rms.remove(con); 113 if (res != null) { 114 trans.delistResource(res, status); 115 if (trace) 116 log.debug("delisted resource from TM - " + res); 117 } else { 119 log.warn("no xares in rms for con " + con); 120 } } 122 } catch (Exception e) { 123 log.error("Unable to deregister with TransactionManager", e); 124 throw new RuntimeException ("Unable to deregister with TransactionManager: " + e); 125 } 126 127 if (!(con instanceof XAConnectionImpl)) { 128 pool.releaseObject(con); 130 } else { 131 XAConnectionImpl xaCon = (XAConnectionImpl) con; 132 if (!((XAResourceImpl) xaCon.getXAResource()).isTransaction()) { 133 if (trace) 137 log.debug("XAConnectionImpl: " + xaCon + " has no current tx!"); 138 try { 139 xaCon.rollback(); 140 } catch (SQLException e) { 141 pool.markObjectAsInvalid(con); 142 } 143 pool.releaseObject(con); 144 } else { 145 con.addConnectionEventListener(errorListener); 147 } 148 } 149 } 150 }; 151 transListener = new TransactionListener() { 152 public void transactionFinished(XAConnectionImpl con) { 153 con.clearTransactionListener(); 154 Object tx = wrapperTx.remove(con); 155 if (tx != null) 157 wrapperTx.remove(tx); 158 try { 159 con.removeConnectionEventListener(errorListener); 160 } catch (IllegalArgumentException e) { 161 if (!releaseOnCommit) { 163 return; 164 } else { 165 rms.remove(con); 166 pool.markObjectAsInvalid(con); 167 con.forceClientConnectionsClose(); 168 } 169 } 170 171 pool.releaseObject(con); 172 } 173 174 public void transactionFailed(XAConnectionImpl con) { 175 con.clearTransactionListener(); 176 Object tx = wrapperTx.remove(con); 177 if (tx != null) 178 wrapperTx.remove(tx); 179 pool.markObjectAsInvalid(con); 181 try { 182 con.removeConnectionEventListener(errorListener); 183 } catch (IllegalArgumentException e) { 184 if (!releaseOnCommit) { 185 return; 186 } else { 187 rms.remove(con); 188 con.forceClientConnectionsClose(); 189 } 190 } 191 pool.releaseObject(con); 192 } 193 }; 194 } 195 196 200 public void setUser(String userName) { 201 this.userName = userName; 202 } 203 204 207 public String getUser() { 208 return userName; 209 } 210 211 215 public void setPassword(String password) { 216 this.password = password; 217 } 218 219 222 public String getPassword() { 223 return password; 224 } 225 226 public boolean getReleaseOnCommit() { 227 return releaseOnCommit; 228 } 229 230 public void setReleaseOnCommit(boolean rel) { 231 releaseOnCommit = rel; 232 } 233 234 239 public void setPSCacheSize(int size) { 240 psCacheSize = size; 241 } 242 243 247 public int getPSCacheSize() { 248 return psCacheSize; 249 } 250 251 252 256 public int getTransactionIsolation() { 257 return transactionIsolation; 258 } 259 260 public void setTransactionIsolation(int iso) { 261 this.transactionIsolation = iso; 262 } 263 264 public void setTransactionIsolation(String iso) { 265 if (iso.equals("TRANSACTION_NONE")) { 266 this.transactionIsolation = Connection.TRANSACTION_NONE; 267 } else if (iso.equals("TRANSACTION_READ_COMMITTED")) { 268 this.transactionIsolation = Connection.TRANSACTION_READ_COMMITTED; 269 } else if (iso.equals("TRANSACTION_READ_UNCOMMITTED")) { 270 this.transactionIsolation = Connection.TRANSACTION_READ_UNCOMMITTED; 271 } else if (iso.equals("TRANSACTION_REPEATABLE_READ")) { 272 this.transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ; 273 } else if (iso.equals("TRANSACTION_SERIALIZABLE")) { 274 this.transactionIsolation = Connection.TRANSACTION_SERIALIZABLE; 275 } else { 276 throw new IllegalArgumentException ("Setting Isolation level to unknown state: " + iso); 277 } 278 } 279 280 286 public void setDataSource(XADataSource dataSource) { 287 source = dataSource; 288 } 289 290 293 public XADataSource getDataSource() { 294 return source; 295 } 296 297 300 public void setTransactionManager(TransactionManager tm) { 301 this.tm = tm; 302 } 303 304 307 public TransactionManager getTransactionManager() { 308 return this.tm; 309 } 310 311 312 317 public boolean getSaveStackTrace() { 318 return saveStackTrace; 319 } 320 321 public void setSaveStackTrace(boolean save) { 322 saveStackTrace = save; 323 } 324 325 328 public void poolStarted(ObjectPool pool) { 329 if (log.isDebugEnabled()) 330 log.debug("Starting"); 331 332 super.poolStarted(pool); 333 this.pool = pool; 334 if (source == null) 335 throw new IllegalStateException ("Must specify XADataSource to " + getClass().getName()); 336 if (source instanceof XADataSourceImpl) { 337 ((XADataSourceImpl) source).setSaveStackTrace(saveStackTrace); 338 } 339 340 351 } 352 353 356 public Object createObject(Object parameters) throws Exception { 357 358 log.debug("Opening new XAConnection"); 359 360 Object obj = null; 361 try { 362 if (parameters != null) { 363 String credentials[] = (String []) parameters; 364 if (credentials.length == 2) 365 obj = source.getXAConnection(credentials[0], credentials[1]); 366 } else if (userName != null && userName.length() > 0) 367 obj = source.getXAConnection(userName, password); 368 else 369 obj = source.getXAConnection(); 370 } catch (SQLException e) { 371 log.error("Can't get an XAConnection", e); 372 throw e; 373 } 374 return obj; 375 } 376 377 382 public Object prepareObject(Object pooledObject) { 383 boolean trace = log.isDebugEnabled(); 384 XAConnection con = (XAConnection ) pooledObject; 385 con.addConnectionEventListener(listener); 386 Transaction trans = null; 387 try { 388 if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) { 389 trans = tm.getTransaction(); 390 XAResource res = con.getXAResource(); 391 rms.put(con, res); 392 trans.enlistResource(res); 393 if (trace) 394 log.debug("Resource '" + res + "' enlisted for '" + con + "'."); 395 } else { 396 if (trace) 397 log.debug("No transaction right now."); 398 } 399 } catch (Exception e) { 400 e.printStackTrace(); 402 log.error("Unable to register with TransactionManager", e); 403 con.removeConnectionEventListener(listener); 404 throw new RuntimeException ("Unable to register with TransactionManager: " + e); 405 } 406 407 if (con instanceof XAConnectionImpl) { 408 ((XAConnectionImpl) con).setTransactionListener(transListener); 409 ((XAConnectionImpl) con).setPSCacheSize(psCacheSize); 410 if (transactionIsolation != DEFAULT_ISOLATION) { 411 try { 412 ((XAConnectionImpl) con).setTransactionIsolation(transactionIsolation); 413 } catch (SQLException sex) { 414 throw new RuntimeException ("Unable to setTransactionIsolation: " + sex.getMessage()); 415 } 416 } 417 418 if (trans != null) { 419 wrapperTx.put(con, trans); wrapperTx.put(trans, con); } 423 } 424 return con; 425 } 426 427 430 public void deleteObject(Object pooledObject) { 431 XAConnection con = (XAConnection ) pooledObject; 432 try { 433 con.close(); 434 } catch (SQLException e) { 435 } 436 } 437 438 443 public Object isUniqueRequest() { 444 try { 445 if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) { 446 Transaction trans = tm.getTransaction(); 447 return wrapperTx.get(trans); 449 } 450 } catch (Exception e) { 451 } 452 return null; 453 } 454 455 459 public boolean checkValidObject(Object source, Object parameters) { 460 boolean validObject = true; 461 if (parameters != null && source instanceof XAConnectionImpl) { 462 XAConnectionImpl con = (XAConnectionImpl) source; 463 String credentials[] = (String []) parameters; 464 if (credentials.length == 2) { 465 String user = con.getUser(); 466 String password = con.getPassword(); 467 boolean validUser = ((user == null) && (credentials[0] == null)) || ((user != null) && user.equals(credentials[0])); 468 boolean validPassword = ((password == null) && (credentials[1] == null)) || ((password != null) && password.equals(credentials[1])); 469 validObject = validUser && validPassword; 470 } 471 } 472 return validObject; 473 } 474 475 } 476 | Popular Tags |