1 21 package oracle.toplink.essentials.transaction; 23 24 import java.util.*; 25 import javax.naming.*; 26 import oracle.toplink.essentials.sessions.ExternalTransactionController; 27 import oracle.toplink.essentials.logging.SessionLog; 28 import oracle.toplink.essentials.exceptions.TransactionException; 29 import oracle.toplink.essentials.exceptions.DatabaseException; 30 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl; 31 import oracle.toplink.essentials.internal.sessions.AbstractSession; 32 33 47 public abstract class AbstractTransactionController implements ExternalTransactionController { 48 49 50 protected Hashtable unitsOfWork; 51 52 53 protected AbstractSession session; 54 55 56 protected SynchronizationListenerFactory listenerFactory; 57 58 59 protected ThreadLocal activeUnitOfWorkThreadLocal; 60 61 65 public AbstractTransactionController() { 66 this.unitsOfWork = new Hashtable(); 67 this.activeUnitOfWorkThreadLocal = new ThreadLocal (); 68 } 69 70 79 public void bindToCurrentTransaction(UnitOfWorkImpl unitOfWork, AbstractSession session) { 80 Object status = getTransactionStatus(); 81 logTxStateTrace(unitOfWork, "TX_bind", status); 82 try { 83 Object txn = getTransaction(); 84 if (txn == null) { 85 unitOfWork.beginTransaction(); 87 txn = getTransaction(); 88 } 89 90 if (txn == null) { 92 throw TransactionException.externalTransactionNotActive(); 93 } 94 95 AbstractSynchronizationListener listener = getListenerFactory().newSynchronizationListener(unitOfWork, session, txn, this); 97 98 registerSynchronization_impl(listener, txn); 99 unitOfWork.setSynchronized(true); 100 101 } catch (Exception exception) { 102 throw TransactionException.errorBindingToExternalTransaction(exception); 103 } 104 } 105 106 112 public void beginTransaction(AbstractSession session) { 113 try { 114 Object status = getTransactionStatus(); 115 logTxStateTrace(session, "TX_begin", status); 116 117 if (canBeginTransaction_impl(status)) { 120 logTxTrace(session, "TX_beginningTxn", null); 121 beginTransaction_impl(); 122 session.setWasJTSTransactionInternallyStarted(true); 123 } 124 } catch (Exception exception) { 125 throw TransactionException.errorBeginningExternalTransaction(exception); 126 } 127 } 128 129 135 public void commitTransaction(AbstractSession session) { 136 try { 137 Object status = getTransactionStatus(); 138 logTxStateTrace(session, "TX_commit", status); 139 140 if (canCommitTransaction_impl(status)) { 141 logTxTrace(session, "TX_committingTxn", null); 142 143 session.setWasJTSTransactionInternallyStarted(false); 144 commitTransaction_impl(); 145 } 146 } catch (Exception exception) { 147 throw TransactionException.errorCommittingExternalTransaction(exception); 148 } 149 } 150 151 157 public void rollbackTransaction(AbstractSession session) { 158 try { 159 Object status = getTransactionStatus(); 160 logTxStateTrace(session, "TX_rollback", status); 161 162 session.setWasJTSTransactionInternallyStarted(false); 163 164 if ((canRollbackTransaction_impl(status)) && (getTransaction() != null)) { 166 logTxTrace(session, "TX_rollingBackTxn", null); 167 rollbackTransaction_impl(); 168 } 169 } catch (Exception exception) { 170 throw TransactionException.errorRollingBackExternalTransaction(exception); 171 } 172 } 173 174 178 public void markTransactionForRollback() { 179 try { 180 markTransactionForRollback_impl(); 181 } catch (Exception exception) { 182 throw TransactionException.errorMarkingTransactionForRollback(exception); 183 } 184 } 185 186 191 public Object getTransaction() { 192 try { 193 return getTransaction_impl(); 194 } catch (Exception exception) { 195 throw TransactionException.errorGettingExternalTransaction(exception); 196 } 197 } 198 199 205 public Object getTransactionKey(Object transaction) { 206 try { 207 return getTransactionKey_impl(transaction); 208 } catch (Exception exception) { 209 throw TransactionException.errorGettingExternalTransaction(exception); 210 } 211 } 212 213 218 public Object getTransactionStatus() { 219 try { 220 return getTransactionStatus_impl(); 221 } catch (Exception exception) { 222 throw TransactionException.errorGettingExternalTransactionStatus(exception); 223 } 224 } 225 226 231 public boolean noTransactionOrRolledBackOrCommited() { 232 try { 233 Object status = getTransactionStatus(); 234 return canBeginTransaction_impl(status) || canMergeUnitOfWork_impl(status) || isRolledBack_impl(status); 235 } catch (Exception exception) { 236 throw TransactionException.errorGettingExternalTransactionStatus(exception); 237 } 238 } 239 240 244 public abstract boolean isRolledBack_impl(Object status); 245 246 252 public boolean hasActiveUnitOfWork() { 253 return this.lookupActiveUnitOfWork() != null; 254 } 255 256 262 public UnitOfWorkImpl getActiveUnitOfWork() { 263 Object transaction = getTransaction(); 264 if (transaction == null) { 265 return null; 266 } 267 268 UnitOfWorkImpl activeUnitOfWork = lookupActiveUnitOfWork(transaction); 269 if (activeUnitOfWork == null) { 270 activeUnitOfWork = (UnitOfWorkImpl) getSession().acquireUnitOfWork(); 272 Object transactionKey = getTransactionKey(transaction); 273 addUnitOfWork(transactionKey, activeUnitOfWork); 274 activeUnitOfWork.setTransaction(transaction); 275 this.activeUnitOfWorkThreadLocal.set(activeUnitOfWork); 276 } 277 return activeUnitOfWork; 278 } 279 280 286 public UnitOfWorkImpl lookupActiveUnitOfWork() { 287 return lookupActiveUnitOfWork(getTransaction()); 288 } 289 290 296 public UnitOfWorkImpl lookupActiveUnitOfWork(Object transaction) { 297 if (transaction == null) { 298 return null; 299 } 300 Object transactionKey = getTransactionKey(transaction); 301 302 UnitOfWorkImpl activeUnitOfWork = (UnitOfWorkImpl)this.activeUnitOfWorkThreadLocal.get(); 305 if (activeUnitOfWork != null) { 306 if (transaction == activeUnitOfWork.getTransaction()) { 307 return activeUnitOfWork; 308 } 309 } 310 activeUnitOfWork = (UnitOfWorkImpl)getUnitsOfWork().get(transactionKey); 311 if (activeUnitOfWork != null) { 312 activeUnitOfWork.setTransaction(transaction); 313 } 314 this.activeUnitOfWorkThreadLocal.set(activeUnitOfWork); 315 return activeUnitOfWork; 316 } 317 318 322 public void addUnitOfWork(Object transaction, UnitOfWorkImpl activeUnitOfWork) { 323 this.activeUnitOfWorkThreadLocal.set(null); 324 getUnitsOfWork().put(transaction, activeUnitOfWork); 325 } 326 327 331 public void removeUnitOfWork(Object transaction) { 332 if (transaction != null) { 333 getUnitsOfWork().remove(transaction); 334 } 335 this.activeUnitOfWorkThreadLocal.set(null); 336 } 337 338 342 public AbstractSession getSession() { 343 return session; 344 } 345 346 350 public void setSession(AbstractSession session) { 351 this.session = session; 352 } 353 354 359 public Hashtable getUnitsOfWork() { 360 return unitsOfWork; 361 } 362 363 367 protected void setUnitsOfWork(Hashtable unitsOfWork) { 368 this.unitsOfWork = unitsOfWork; 369 } 370 371 375 public SynchronizationListenerFactory getListenerFactory() { 376 return listenerFactory; 377 } 378 379 384 public void setListenerFactory(SynchronizationListenerFactory factory) { 385 listenerFactory = factory; 386 } 387 388 393 public void registerSynchronizationListener(UnitOfWorkImpl uow, AbstractSession session) throws DatabaseException { 394 this.bindToCurrentTransaction(uow, session); 395 } 396 397 410 public Object jndiLookup(String jndiName) { 411 Context context = null; 412 Object jndiObject = null; 413 try { 414 context = new InitialContext(); 415 jndiObject = context.lookup(jndiName); 416 } catch (NamingException ex) { 417 throw TransactionException.jndiLookupException(jndiName, ex); 418 } finally { 419 try { 420 context.close(); 421 } catch (Exception ex2) { 422 } 423 } 424 return jndiObject; 425 } 426 427 431 public void logTxTrace(AbstractSession session, String msgInd, Object [] args) { 432 session.log(SessionLog.FINER, SessionLog.TRANSACTION, msgInd, args); 433 } 434 435 439 public void logTxStateTrace(AbstractSession session, String msgInd, Object status) { 440 if (session.shouldLog(SessionLog.FINER, SessionLog.TRANSACTION)) { 441 String statusString = statusToString_impl(status); 442 Object [] args = { statusString }; 443 session.log(SessionLog.FINER, SessionLog.TRANSACTION, msgInd, args); 444 } 445 } 446 447 451 459 protected abstract void registerSynchronization_impl(AbstractSynchronizationListener listener, Object txn) throws Exception ; 460 461 468 protected abstract Object getTransaction_impl() throws Exception ; 469 470 479 protected abstract Object getTransactionKey_impl(Object transaction) throws Exception ; 480 481 488 protected abstract Object getTransactionStatus_impl() throws Exception ; 489 490 495 protected abstract void beginTransaction_impl() throws Exception ; 496 497 502 protected abstract void commitTransaction_impl() throws Exception ; 503 504 509 protected abstract void rollbackTransaction_impl() throws Exception ; 510 511 516 protected abstract void markTransactionForRollback_impl() throws Exception ; 517 518 527 protected abstract boolean canBeginTransaction_impl(Object status); 528 529 538 protected abstract boolean canCommitTransaction_impl(Object status); 539 540 549 protected abstract boolean canRollbackTransaction_impl(Object status); 550 551 561 protected abstract boolean canIssueSQLToDatabase_impl(Object status); 562 563 573 protected abstract boolean canMergeUnitOfWork_impl(Object status); 574 575 579 protected abstract String statusToString_impl(Object status); 580 } 581 | Popular Tags |