1 29 30 package com.caucho.jca; 31 32 import com.caucho.log.Log; 33 import com.caucho.transaction.TransactionImpl; 34 import com.caucho.transaction.TransactionManagerImpl; 35 import com.caucho.util.L10N; 36 37 import javax.resource.spi.ConnectionRequestInfo ; 38 import javax.resource.spi.ManagedConnectionFactory ; 39 import javax.security.auth.Subject ; 40 import javax.transaction.*; 41 import javax.transaction.xa.Xid ; 42 import java.util.ArrayList ; 43 import java.util.logging.Level ; 44 import java.util.logging.Logger ; 45 46 49 public class UserTransactionImpl implements UserTransaction { 50 private static final Logger log = Log.open(UserTransactionImpl.class); 51 private static final L10N L = new L10N(UserTransactionImpl.class); 52 53 private TransactionManagerImpl _transactionManager; 54 55 private ArrayList <UserPoolItem> _resources = new ArrayList <UserPoolItem>(); 56 private ArrayList <PoolItem> _poolItems = new ArrayList <PoolItem>(); 57 private ArrayList <BeginResource> _beginResources 58 = new ArrayList <BeginResource>(); 59 private ArrayList <CloseResource> _closeResources 60 = new ArrayList <CloseResource>(); 61 62 private int _xaDepth; 63 64 67 public UserTransactionImpl(TransactionManagerImpl tm) 68 { 69 _transactionManager = tm; 70 } 71 72 75 public void setTransactionTimeout(int seconds) 76 throws SystemException 77 { 78 _transactionManager.setTransactionTimeout(seconds); 79 } 80 81 84 public int getStatus() 85 throws SystemException 86 { 87 return _transactionManager.getStatus(); 88 } 89 90 93 void enlistResource(UserPoolItem resource) 94 throws SystemException, RollbackException 95 { 96 if (_resources.contains(resource)) 97 return; 98 99 Transaction xa = _transactionManager.getTransaction(); 100 if (xa != null) { 101 PoolItem poolItem = resource.getXAPoolItem(); 102 103 enlistPoolItem(xa, poolItem); 104 } 105 106 _resources.add(resource); 107 } 108 109 private void enlistPoolItem(Transaction xa, PoolItem poolItem) 110 throws SystemException, RollbackException 111 { 112 if (poolItem == null) 113 return; 114 else if (! poolItem.supportsTransaction()) { 115 return; 117 } 118 119 if (_poolItems.contains(poolItem)) 121 return; 122 123 poolItem.setTransaction(this); 124 125 if (xa instanceof TransactionImpl) { 126 TransactionImpl xaImpl = (TransactionImpl) xa; 127 128 if (xaImpl.allowLocalTransactionOptimization()) 130 poolItem.enableLocalTransactionOptimization(true); 131 } 132 133 if (poolItem.getXid() == null) 134 xa.enlistResource(poolItem); 135 136 _poolItems.add(poolItem); 137 } 138 139 142 void delistPoolItem(PoolItem poolItem, int flags) 143 throws SystemException, RollbackException 144 { 145 Transaction xa = _transactionManager.getTransaction(); 146 147 try { 148 if (xa != null) 149 xa.delistResource(poolItem, flags); 150 } finally { 151 _poolItems.remove(poolItem); 152 } 153 } 154 155 158 void delistResource(UserPoolItem resource) 159 { 160 _resources.remove(resource); 161 } 162 163 166 public void enlistBeginResource(BeginResource resource) 167 { 168 _beginResources.add(resource); 169 170 try { 171 Transaction xa = _transactionManager.getTransaction(); 172 if (xa != null) 173 resource.begin(xa); 174 } catch (Exception e) { 175 throw new RuntimeException (e); 176 } 177 } 178 179 182 public void enlistCloseResource(CloseResource resource) 183 { 184 _closeResources.add(resource); 185 } 186 187 191 UserPoolItem allocate(ManagedConnectionFactory mcf, 192 Subject subject, 193 ConnectionRequestInfo info) 194 { 195 if (_xaDepth == 0) 196 return null; 197 198 ArrayList <PoolItem> poolItems = _poolItems; 199 int length = poolItems.size(); 200 201 for (int i = 0; i < length; i++) { 202 PoolItem poolItem = poolItems.get(i); 203 204 UserPoolItem item = poolItem.allocateXA(mcf, subject, info); 205 206 if (item != null) 207 return item; 208 } 209 210 return null; 211 } 212 213 217 PoolItem findJoin(PoolItem item) 218 { 219 if (_xaDepth == 0) 220 return null; 221 222 ArrayList <PoolItem> poolItems = _poolItems; 223 int length = poolItems.size(); 224 225 for (int i = 0; i < length; i++) { 226 PoolItem poolItem = poolItems.get(i); 227 228 if (poolItem.isJoin(item)) 229 return poolItem; 230 } 231 232 return null; 233 } 234 235 238 public Xid getXid() 239 throws SystemException, RollbackException 240 { 241 TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); 242 243 if (xa != null) 244 return xa.getXid(); 245 else 246 return null; 247 } 248 249 252 public int getEnlistedResourceCount() 253 throws SystemException, RollbackException 254 { 255 TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); 256 257 if (xa != null) 258 return xa.getEnlistedResourceCount(); 259 else 260 return 0; 261 } 262 263 266 public void begin() 267 throws NotSupportedException, SystemException 268 { 269 _transactionManager.begin(); 270 _xaDepth++; 271 boolean isOkay = false; 272 273 try { 274 TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); 275 xa.setUserTransaction(this); 276 277 _poolItems.clear(); 278 279 int length = _resources.size(); 281 282 for (int i = 0; i < length; i++) { 283 UserPoolItem userPoolItem = _resources.get(i); 284 285 for (int j = _poolItems.size() - 1; j >= 0; j--) { 286 PoolItem poolItem = _poolItems.get(j); 287 288 if (poolItem.share(userPoolItem)) { 289 break; 290 } 291 } 292 293 PoolItem xaPoolItem = userPoolItem.getXAPoolItem(); 294 if (! _poolItems.contains(xaPoolItem)) 295 _poolItems.add(xaPoolItem); 296 } 297 298 for (int i = 0; i < _poolItems.size(); i++) { 299 PoolItem poolItem = _poolItems.get(i); 300 301 poolItem.enableLocalTransactionOptimization(_poolItems.size() == 1); 302 303 try { 304 xa.enlistResource(poolItem); 305 } catch (Exception e) { 306 throw new SystemException(e); 307 } 308 } 309 310 for (int i = 0; i < _beginResources.size(); i++) { 312 try { 313 BeginResource resource = _beginResources.get(i); 314 315 resource.begin(xa); 316 } catch (Throwable e) { 317 log.log(Level.WARNING, e.toString(), e); 318 } 319 } 320 321 isOkay = true; 322 } finally { 323 if (! isOkay) { 324 log.warning("Rolling back transaction from failed begin()"); 325 326 _xaDepth--; 328 329 ArrayList <PoolItem> recoveryList = new ArrayList <PoolItem>(_poolItems); 330 _poolItems.clear(); 331 _resources.clear(); 332 333 for (int i = 0; i < recoveryList.size(); i++) { 334 try { 335 PoolItem item = recoveryList.get(i); 336 337 item.abortConnection(); 338 339 item.destroy(); 340 } catch (Throwable e) { 341 log.log(Level.FINE, e.toString(), e); 342 } 343 } 344 345 _transactionManager.rollback(); 346 } 347 } 348 } 349 350 353 public UserTransactionSuspendState suspend() 354 { 355 if (_xaDepth == 0) 356 throw new IllegalStateException (L.l("suspend may only be called in a transaction.")); 357 358 _xaDepth--; 359 360 UserTransactionSuspendState state; 361 state = new UserTransactionSuspendState(_poolItems); 362 _poolItems.clear(); 363 364 return state; 365 } 366 367 370 public void resume(UserTransactionSuspendState state) 371 { 372 376 377 _xaDepth++; 378 379 _poolItems.addAll(state.getPoolItems()); 380 } 381 382 385 public void setRollbackOnly() 386 throws IllegalStateException , SystemException 387 { 388 _transactionManager.setRollbackOnly(); 389 } 390 391 394 public void commit() 395 throws IllegalStateException , RollbackException, HeuristicMixedException, 396 HeuristicRollbackException, SecurityException , SystemException 397 { 398 try { 399 403 404 _transactionManager.commit(); 405 } finally { 406 _poolItems.clear(); 407 if (_xaDepth > 0) 408 _xaDepth--; 409 } 410 } 411 412 415 public void rollback() 416 throws IllegalStateException , SecurityException , SystemException 417 { 418 try { 419 _transactionManager.rollback(); 420 } finally { 421 _poolItems.clear(); 422 if (_xaDepth > 0) 423 _xaDepth--; 424 } 425 } 426 427 430 public void abortTransaction() 431 throws IllegalStateException 432 { 433 IllegalStateException exn = null; 434 435 boolean inTransaction = _xaDepth > 0; 436 _xaDepth = 0; 437 438 if (! inTransaction && _poolItems.size() > 0) { 439 Exception e = new IllegalStateException ("user transaction pool broken"); 440 log.log(Level.WARNING, e.toString(), e); 441 } 442 443 _poolItems.clear(); 444 445 if (inTransaction) { 446 try { 447 TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); 448 449 exn = new IllegalStateException (L.l("Transactions must have a commit() or rollback() in a finally block.")); 450 451 log.warning("Rolling back dangling transaction. All transactions must have a commit() or rollback() in a finally block."); 452 453 _transactionManager.rollback(); 454 } catch (Throwable e) { 455 log.log(Level.WARNING, e.toString()); 456 } 457 458 } 459 460 _beginResources.clear(); 461 462 while (_closeResources.size() > 0) { 463 try { 464 CloseResource resource; 465 466 resource = _closeResources.remove(_closeResources.size() - 1); 467 resource.close(); 468 } catch (Throwable e) { 469 log.log(Level.WARNING, e.toString(), e); 470 } 471 } 472 473 if (_resources.size() > 0) { 474 log.warning("Closing dangling connections. All connections must have a close() in a finally block."); 475 } 476 while (_resources.size() > 0) { 477 UserPoolItem userPoolItem = _resources.remove(_resources.size() - 1); 478 479 try { 480 IllegalStateException stackTrace = userPoolItem.getAllocationStackTrace(); 481 482 if (stackTrace != null) 483 log.log(Level.WARNING, stackTrace.getMessage(), stackTrace); 484 else { 485 userPoolItem.setSaveAllocationStackTrace(true); 487 } 488 489 if (exn == null) 490 exn = new IllegalStateException (L.l("Connection {0} was not closed. Connections must have a close() in a finally block.", 491 userPoolItem.getUserConnection())); 492 493 userPoolItem.abortConnection(); 494 } catch (Throwable e) { 495 log.log(Level.WARNING, e.toString(), e); 496 } 497 } 498 499 _poolItems.clear(); 500 501 try { 502 _transactionManager.setTransactionTimeout(0); 503 } catch (Throwable e) { 504 log.log(Level.WARNING, e.toString(), e); 505 } 506 507 if (exn != null) 508 throw exn; 509 } 510 } 511 512 | Popular Tags |