1 23 package com.sun.enterprise.distributedtx; 24 25 import java.util.*; 26 import javax.transaction.*; 27 import com.sun.enterprise.*; 28 import com.sun.enterprise.resource.*; 29 import com.sun.enterprise.log.Log; 30 import com.sun.enterprise.util.Utility; 31 import com.sun.enterprise.util.i18n.StringManager; 32 33 import javax.transaction.xa.*; 34 35 import javax.persistence.EntityManagerFactory; 36 import javax.persistence.EntityManager; 37 38 import com.sun.jts.jta.TransactionManagerImpl; 39 import com.sun.jts.jta.TransactionImpl; 40 41 import java.util.logging.*; 43 import com.sun.logging.*; 44 46 60 public final class J2EETransaction extends TimerTask implements Transaction { 61 62 static Logger _logger=LogDomains.getLogger(LogDomains.JTA_LOGGER); 64 private static StringManager sm = StringManager.getManager(J2EETransaction.class); 67 68 69 70 private static long txIdCounter = 1; 73 74 private long txId; 75 private J2EEXid xid; 76 static J2EETransactionManagerOpt j2eeTM; 77 private Transaction jtsTx; 78 private ResourceHandle nonXAResource; 79 private ResourceHandle laoResource; 80 private int localTxStatus; 81 private Vector syncs = new Vector(); 82 private Vector interposedSyncs = new Vector(); 83 private boolean commitStarted = false; 84 private long startTime; 86 88 private boolean isTimedOut = false; 90 private boolean isTimerTask = false; 91 private int timeout; 92 private boolean imported = false; 94 95 private HashMap resourceTable; 96 private HashMap<Object , Object > userResourceMap; 97 98 private Object activeTxCache; 100 101 private Map<EntityManagerFactory, EntityManager> txEntityManagerMap; 103 104 private Map<EntityManagerFactory, EntityManager> extendedEntityManagerMap; 106 private String componentName = null; 107 private ArrayList<String > resourceNames = null; 108 109 static private boolean isTimerInitialized = false; 110 static private Timer timer = null; 111 112 static synchronized private void initializeTimer() { 113 if (isTimerInitialized) 114 return; 115 timer = new Timer(true); isTimerInitialized = true; 117 } 118 119 J2EETransaction() 121 { 122 this.txId = getNewTxId(); 123 this.xid = new J2EEXid(txId); 124 this.resourceTable = new HashMap(); 125 localTxStatus = Status.STATUS_ACTIVE; 126 startTime=System.currentTimeMillis(); 127 if (_logger.isLoggable(Level.FINE)) { 128 _logger.log(Level.FINE,"--Created new J2EETransaction, txId = "+txId); 129 } 130 } 131 132 133 J2EETransaction(int timeout) 135 { 136 this(); 137 if (!isTimerInitialized) 138 initializeTimer(); 139 timer.schedule(this,timeout * 1000); 140 isTimerTask = true; 141 this.timeout = timeout; 142 } 143 145 146 147 J2EETransaction(Transaction jtsTx) 148 { 149 this(); 150 this.jtsTx = jtsTx; 151 } 152 153 public void run() { 156 isTimedOut = true; 157 try { 158 setRollbackOnly(); 159 } catch (Exception e) { 160 e.printStackTrace(); 161 } 162 } 163 164 boolean isAssociatedTimeout() { 165 return isTimerTask; 166 } 167 168 int cancelTimerTask() { 170 cancel(); 171 return timeout; 172 } 173 174 boolean isTimedout() { 175 return isTimedOut; 176 } 177 179 180 181 private static synchronized long getNewTxId() { 182 long newTxId = txIdCounter++; 183 return newTxId; 184 } 185 186 public boolean equals(Object other) 187 { 188 if ( other == this ) 189 return true; 190 if ( other instanceof J2EETransaction ) { 191 J2EETransaction othertx = (J2EETransaction)other; 192 return ( txId == othertx.txId ); 193 } 194 return false; 195 } 196 197 public int hashCode() 198 { 199 return (int)txId; 200 } 201 202 203 Xid getLocalXid() 204 { 205 return xid; 206 } 207 208 public ResourceHandle getNonXAResource() 209 { 210 return nonXAResource; 211 } 212 213 void setNonXAResource(ResourceHandle h) 214 { 215 nonXAResource = h; 216 } 217 218 ResourceHandle getLAOResource() 219 { 220 return laoResource; 221 } 222 223 void setLAOResource(ResourceHandle h) 224 { 225 laoResource = h; 226 } 227 228 void setImportedTransaction() { 229 imported = true; 230 } 231 232 boolean isImportedTransaction() { 233 return imported; 234 } 235 236 synchronized void putUserResource(Object key, Object value) { 237 if (userResourceMap == null) 238 userResourceMap = new HashMap<Object , Object >(); 239 userResourceMap.put(key, value); 240 } 241 242 synchronized Object getUserResource(Object key) { 243 if (userResourceMap == null) 244 return null; 245 return userResourceMap.get(key); 246 } 247 248 void registerInterposedSynchronization(Synchronization sync) { 249 interposedSyncs.add(sync); 250 } 251 252 void setComponentName(String componentName) { 253 this.componentName = componentName; 254 } 255 256 String getComponentName() { 257 return componentName; 258 } 259 260 synchronized void addResourceName(String resourceName) { 261 if (resourceNames == null) 262 resourceNames = new ArrayList<String >(); 263 resourceNames.add(resourceName); 264 } 265 266 synchronized ArrayList<String > getResourceNames() { 267 return resourceNames; 268 } 269 270 271 public void addTxEntityManagerMapping(EntityManagerFactory emf, 272 EntityManager em) { 273 getTxEntityManagerMap().put(emf, em); 274 } 275 276 public EntityManager getTxEntityManager(EntityManagerFactory emf) { 277 return getTxEntityManagerMap().get(emf); 278 } 279 280 private Map<EntityManagerFactory, EntityManager> 281 getTxEntityManagerMap() { 282 if( txEntityManagerMap == null ) { 283 txEntityManagerMap = 284 new HashMap<EntityManagerFactory, EntityManager>(); 285 } 286 return txEntityManagerMap; 287 } 288 289 private void onTxCompletion(boolean status) { 290 for (Map.Entry<EntityManagerFactory, EntityManager> entry : 291 getTxEntityManagerMap().entrySet()) { 292 293 EntityManager em = entry.getValue(); 294 if (em.isOpen()) { 295 try { 296 em.close(); 297 } catch (Throwable th) { 298 if (_logger.isLoggable(Level.FINE)) { 299 _logger.log(Level.FINE, "Exception while closing em.", th); 300 } 301 } 302 } 303 } 304 } 305 306 public void addExtendedEntityManagerMapping(EntityManagerFactory emf, 307 EntityManager em) { 308 getExtendedEntityManagerMap().put(emf, em); 309 } 310 311 public void removeExtendedEntityManagerMapping(EntityManagerFactory emf) { 312 getExtendedEntityManagerMap().remove(emf); 313 } 314 315 public EntityManager getExtendedEntityManager(EntityManagerFactory emf) { 316 return getExtendedEntityManagerMap().get(emf); 317 } 318 319 private Map<EntityManagerFactory, EntityManager> 320 getExtendedEntityManagerMap() { 321 if( extendedEntityManagerMap == null ) { 322 extendedEntityManagerMap = 323 new HashMap<EntityManagerFactory, EntityManager>(); 324 } 325 return extendedEntityManagerMap; 326 } 327 328 boolean isLocalTx() 329 { 330 return (jtsTx==null); 331 } 332 333 void setJTSTx(Transaction jtsTx) throws RollbackException, SystemException 334 { 335 this.jtsTx = jtsTx; 336 337 if ( !commitStarted ) { 338 for ( int i=0; i<syncs.size(); i++ ) 340 jtsTx.registerSynchronization((Synchronization)syncs.elementAt(i)); 341 for ( int i=0; i<interposedSyncs.size(); i++ ) 342 ((TransactionImpl)jtsTx).registerInterposedSynchronization((Synchronization)interposedSyncs.elementAt(i)); 343 } 344 } 345 346 Transaction getJTSTx() 347 { 348 return jtsTx; 349 } 350 351 352 public void commit() throws RollbackException, 353 HeuristicMixedException, HeuristicRollbackException, 354 SecurityException , IllegalStateException , SystemException 355 { 356 if (isTimerTask) 359 cancel(); 360 if (_logger.isLoggable(Level.FINE)) { 362 _logger.log(Level.FINE,"--In J2EETransaction.commit, jtsTx="+jtsTx 363 +" nonXAResource="+ nonXAResource); 364 } 365 commitStarted = true; 366 367 if ( jtsTx != null ) { 368 try { 369 jtsTx.commit(); 370 } finally { 371 j2eeTM.clearThreadTx(); 372 onTxCompletion(true); 373 } 374 } 375 else { try { 377 if ( isTimedOut ) { 378 if ( nonXAResource != null ) 380 nonXAResource.getXAResource().rollback(xid); 381 localTxStatus = Status.STATUS_ROLLEDBACK; 382 throw new RollbackException(sm.getString("enterprise_distributedtx.rollback_timeout")); 383 } 384 if ( isRollbackOnly() ) { 385 if ( nonXAResource != null ) 387 nonXAResource.getXAResource().rollback(xid); 388 localTxStatus = Status.STATUS_ROLLEDBACK; 389 throw new RollbackException(sm.getString("enterprise_distributedtx.mark_rollback")); 390 } 391 for ( int i=0; i<syncs.size(); i++ ) { 393 try { 394 Synchronization sync = (Synchronization)syncs.elementAt(i); 395 sync.beforeCompletion(); 396 } catch ( RuntimeException ex ) { 397 setRollbackOnly(); 398 } catch (Exception ex) { } 399 } 400 for ( int i=0; i<interposedSyncs.size(); i++ ) { 401 try { 402 Synchronization sync = (Synchronization)interposedSyncs.elementAt(i); 403 sync.beforeCompletion(); 404 } catch ( RuntimeException ex ) { 405 setRollbackOnly(); 406 } catch (Exception ex) { } 407 } 408 if ( isRollbackOnly()) { 411 if(jtsTx == null) { 413 if ( nonXAResource != null ) 414 nonXAResource.getXAResource().rollback(xid); 415 localTxStatus = Status.STATUS_ROLLEDBACK; 416 throw new RollbackException(sm.getString("enterprise_distributedtx.mark_rollback")); 417 } else { 419 jtsTx.rollback(); 420 localTxStatus = Status.STATUS_ROLLEDBACK; 421 throw new RollbackException(sm.getString("enterprise_distributedtx.mark_rollback")); 422 } 423 } 424 if ( jtsTx != null ) { 427 jtsTx.commit(); 428 localTxStatus = Status.STATUS_COMMITTED; 430 } 435 else { 436 if ( nonXAResource != null ) 438 nonXAResource.getXAResource().commit(xid, true); 439 440 localTxStatus = Status.STATUS_COMMITTED; 442 } 443 } catch ( RollbackException ex ) { 444 localTxStatus = Status.STATUS_ROLLEDBACK; throw ex; 446 } catch ( SystemException ex ) { 447 localTxStatus = Status.STATUS_COMMITTING; 449 throw ex; 450 } catch ( Exception ex ) { 451 localTxStatus = Status.STATUS_ROLLEDBACK; SystemException exc = new SystemException(); 453 exc.initCause(ex); 454 throw exc; 455 } finally { 456 j2eeTM.clearThreadTx(); 457 for ( int i=0; i<interposedSyncs.size(); i++ ) { 458 try { 459 Synchronization sync = (Synchronization)interposedSyncs.elementAt(i); 460 sync.afterCompletion(localTxStatus); 461 } catch ( Exception ex ) {} 462 } 463 for ( int i=0; i<syncs.size(); i++ ) { 465 try { 466 Synchronization sync = (Synchronization)syncs.elementAt(i); 467 sync.afterCompletion(localTxStatus); 468 } catch ( Exception ex ) {} 469 } 470 onTxCompletion(true); 471 } 472 } 473 } 474 475 public void rollback() throws IllegalStateException , SystemException 476 { 477 if (isTimerTask) 480 cancel(); 481 if (_logger.isLoggable(Level.FINE)) { 483 _logger.log(Level.FINE,"--In J2EETransaction.rollback, jtsTx="+jtsTx 484 +" nonXAResource="+nonXAResource); 485 } 486 try { 487 if ( jtsTx != null ) 488 jtsTx.rollback(); 489 else { if ( nonXAResource != null ) 491 nonXAResource.getXAResource().rollback(xid); 492 493 localTxStatus = Status.STATUS_ROLLEDBACK; 495 } 496 } catch ( Exception ex ) { 497 localTxStatus = Status.STATUS_ROLLEDBACK; } finally { 499 j2eeTM.clearThreadTx(); 500 if ( jtsTx == null ) { 501 for ( int i=0; i<syncs.size(); i++ ) { 503 try { 504 Synchronization sync = (Synchronization)syncs.elementAt(i); 505 sync.afterCompletion(Status.STATUS_ROLLEDBACK); 506 } catch ( Exception ex ) {} 507 } 508 } 509 onTxCompletion(false); 510 } 511 } 512 513 public boolean delistResource(XAResource xaRes, int flag) 514 throws IllegalStateException , SystemException 515 { 516 if (_logger.isLoggable(Level.FINE)) { 518 _logger.log(Level.FINE,"--In J2EETransaction.delistResource, jtsTx=" 519 +jtsTx +" nonXAResource="+nonXAResource); 520 } 521 523 if ( jtsTx != null ) 524 return jtsTx.delistResource(xaRes, flag); 525 else 526 throw new IllegalStateException (sm.getString("enterprise_distributedtx.deleteresource_for_localtx")); 527 } 528 529 public boolean enlistResource(XAResource xaRes) 530 throws RollbackException, IllegalStateException , 531 SystemException 532 { 533 if (_logger.isLoggable(Level.FINE)) { 534 _logger.log(Level.FINE,"--In J2EETransaction.enlistResource, jtsTx=" 535 +jtsTx+" nonXAResource="+nonXAResource); 536 } 537 if ( jtsTx != null ) 538 return jtsTx.enlistResource(xaRes); 539 else if ( nonXAResource != null ) 540 throw new IllegalStateException (sm.getString("enterprise_distributedtx.already_has_nonxa")); 541 546 else { j2eeTM.startJTSTx(this); 548 return jtsTx.enlistResource(xaRes); 549 } 550 } 552 553 public int getStatus() throws SystemException 554 { 555 if ( jtsTx != null ) 556 return jtsTx.getStatus(); 557 else 558 return localTxStatus; 559 } 560 561 public void registerSynchronization(Synchronization sync) 562 throws RollbackException, IllegalStateException , 563 SystemException 564 { 565 if (_logger.isLoggable(Level.FINE)) { 567 _logger.log(Level.FINE,"--In J2EETransaction.registerSynchronization, jtsTx=" +jtsTx+" nonXAResource="+nonXAResource); 568 } 569 571 if ( jtsTx != null ) 572 jtsTx.registerSynchronization(sync); 573 else 574 syncs.add(sync); 575 } 576 577 public void setRollbackOnly() throws IllegalStateException , 578 SystemException 579 { 580 if ( jtsTx != null ) 581 jtsTx.setRollbackOnly(); 582 else 583 localTxStatus = Status.STATUS_MARKED_ROLLBACK; 584 } 585 586 private boolean isRollbackOnly() throws IllegalStateException , 587 SystemException 588 { 589 int status; 590 if ( jtsTx != null ) 591 status = jtsTx.getStatus(); 592 else 593 status = localTxStatus; 594 595 return (status == Status.STATUS_MARKED_ROLLBACK); 596 } 597 598 599 600 public String toString() 601 { 602 return "J2EETransaction: txId="+txId+" nonXAResource="+nonXAResource 603 +" jtsTx="+jtsTx+" localTxStatus="+localTxStatus 604 +" syncs="+syncs; 605 } 606 607 612 public String getTransactionId(){ 613 return xid.toString(); 614 } 615 616 619 public long getStartTime(){ 620 return startTime; 621 } 622 624 public void setResources(Set resources, String poolName) { 625 resourceTable.put(poolName, resources); 626 } 627 628 public Set getResources(String poolName) { 629 return (Set) resourceTable.get(poolName); 630 } 631 632 638 public Set getAllParticipatingPools() { 639 return (Set) resourceTable.keySet(); 640 } 641 642 private static final byte[] bqual = new byte[]{0}; 644 645 private class J2EEXid implements javax.transaction.xa.Xid { 647 private static final int formatId = 987654321; 648 private byte[] gtrId; 649 private String stringForm=null; 651 J2EEXid(long txId) { 653 gtrId = new byte[8]; 654 Utility.longToBytes(txId, gtrId, 0); 655 } 656 public int getFormatId() { 657 return formatId; 658 } 659 public byte[] getGlobalTransactionId() { 660 return gtrId; 661 } 662 public byte[] getBranchQualifier() { 663 return bqual; } 665 666 670 public String toString(){ 671 672 if( stringForm != null ) return stringForm; 675 676 char[] buff = new char[gtrId.length*2 + 3]; 679 int pos = 0; 680 682 684 int globalLen = gtrId.length ; 685 for( int i = 0; i < globalLen; i++ ) { 686 int currCharHigh = (gtrId[i]&0xf0) >> 4; 687 int currCharLow = gtrId[i]&0x0f; 688 buff[pos++] = (char)(currCharHigh + (currCharHigh > 9 ? 'A'-10 : '0')); 689 buff[pos++] = (char)(currCharLow + (currCharLow > 9 ? 'A'-10 : '0')); 690 } 691 692 buff[pos++] = '_'; 694 int currCharHigh = (0&0xf0) >> 4; 695 int currCharLow = 0&0x0f; 696 buff[pos++] = (char)(currCharHigh + (currCharHigh > 9 ? 'A'-10 : '0')); 697 buff[pos++] = (char)(currCharLow + (currCharLow > 9 ? 'A'-10 : '0')); 698 700 stringForm = new String (buff); 702 703 return stringForm; 704 } 705 } 707 708 public void setActiveTxCache(Object cache) { 709 this.activeTxCache = cache; 710 } 711 712 public Object getActiveTxCache() { 713 return this.activeTxCache; 714 } 715 716 } 717 | Popular Tags |