1 package org.enhydra.dods.xa; 2 3 import java.sql.SQLException ; 4 import java.util.Hashtable ; 5 import java.util.Vector ; 6 7 import javax.transaction.xa.XAException ; 8 import javax.transaction.xa.XAResource ; 9 import javax.transaction.xa.Xid ; 10 11 import org.enhydra.dods.DODS; 12 import org.enhydra.dods.cache.DOCache; 13 14 import com.lutris.appserver.server.sql.AbstractDBTransactionFactory; 15 import com.lutris.appserver.server.sql.CachedDBTransaction; 16 import com.lutris.appserver.server.sql.CoreDO; 17 import com.lutris.appserver.server.sql.DBConnection; 18 import com.lutris.appserver.server.sql.DBQuery; 19 import com.lutris.appserver.server.sql.DBTransaction; 20 import com.lutris.appserver.server.sql.Transaction; 21 import com.lutris.logging.Logger; 22 23 27 28 public class XATransaction implements CachedDBTransaction, XAResource { 29 30 static final String rMessage = "rollback not allowed here"; 31 32 static final String eMessage = "release not allowed here"; 33 34 static final String cMessage = "commit not allowed here"; 35 36 private Hashtable dodsTransactions = null; 37 38 CachedDBTransaction wrapped; 39 CachedDBTransaction internal; 40 CachedDBTransaction current; 41 42 protected javax.transaction.Transaction contextTx; 43 44 protected Xid identity; 45 46 protected int flags; 47 48 private int classicUsageReaction; 49 50 private int intTimeout; 51 52 private boolean distributed = false; 53 54 55 60 public XATransaction(javax.transaction.Transaction ctTx, 61 AbstractDBTransactionFactory adbtf, 62 DBConnection conn, 63 int classicUsageFlag , 64 int defaultTimeout, 65 Hashtable dodsTransTable) throws SQLException { 66 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##constructor:"+this); 67 this.classicUsageReaction = classicUsageFlag; 68 this.intTimeout = defaultTimeout; 69 this.contextTx = ctTx; 70 this.dodsTransactions = dodsTransTable; 71 try { 72 this.current = (CachedDBTransaction)adbtf.getTransaction(conn); 73 this.internal= this.current; 74 } catch (SQLException e) { 75 DODS.getLogChannel().write(Logger.ERROR,"XATransaction Error : Faild to allocate internal transaction. "); 76 throw e; 77 } 78 synchronized(dodsTransactions) { 79 if(dodsTransactions.containsKey(this.contextTx)) { 80 wrapped = (CachedDBTransaction)dodsTransactions.get(this.contextTx); 81 }else{ 82 this.wrapped = this.current; 83 dodsTransactions.put(this.contextTx,this.wrapped); 84 } 85 } 86 distributed = false; 87 } 88 89 private CachedDBTransaction deattacht() { 90 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##deattacht"); 91 synchronized(dodsTransactions) { 92 DBTransaction dbt= (DBTransaction)dodsTransactions.get(this.contextTx); 93 if ((dbt!=null)&&(dbt==this.wrapped)){ 94 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##deattacht-release:"+this); 95 this.wrapped.release(); 96 this.wrapped = null; 97 if(this.internal!=null) { 98 this.internal.release(); 99 this.internal=null; 100 } 101 dodsTransactions.remove(this.contextTx); 102 this.contextTx=null; 103 distributed = false; 104 }else { 105 DODS.getLogChannel().write(Logger.ERROR,"XATransaction##deattacht"); 106 } 107 } 108 return null; 109 } 110 111 public int getTransactionTimeout() { 112 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##getTransactionTimeout"); 113 return intTimeout; 114 } 115 116 public boolean setTransactionTimeout(int arg0) { 117 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##setTransactionTimeout"); 118 intTimeout = arg0; 119 return true; 120 } 121 122 public boolean isSameRM(XAResource arg0) throws XAException { 123 DODS.getLogChannel().write(Logger.DEBUG, "XATransaction##isSameRM"+this); 124 if (arg0 instanceof XATransaction) { 125 if( ((XATransaction)arg0).getWrapped()==this.wrapped) { 126 DODS.getLogChannel().write(Logger.DEBUG, "XATransaction##isSameRM-true:"+this); 127 return true; 128 } 129 } 130 return false; 131 } 132 133 public Xid [] recover(int arg0) throws XAException { 134 DODS.getLogChannel().write(Logger.DEBUG, "XATransaction##recover"); 135 return new Xid [0]; 136 } 137 138 public int prepare(Xid arg0) throws XAException { 139 DODS.getLogChannel().write(Logger.DEBUG, "XATransaction##prepare:" + arg0); 140 if (identityTest(arg0)) { 141 try { 142 this.wrapped.write(); 143 } catch (SQLException e) { 144 DODS.getLogChannel().write(Logger.ERROR, 145 "XATransaction##prepare:"+this, e); 146 throw new XAException (XAException.XAER_RMERR); 147 } 148 if (this.wrapped.wasReadOnly()) { 149 deattacht(); 150 return XA_RDONLY; 151 } else { 152 return XA_OK; 153 } 154 } else { 155 throw new XAException (XAException.XAER_NOTA); 156 } 157 } 158 159 public void forget(Xid arg0) throws XAException { 160 DODS.getLogChannel().write(Logger.DEBUG, "XATransaction##forget"); 161 if(distributed) { 162 163 }else { 164 String msg ="XAResource.forget(..) outside of 'XAResource.start(..)' "+ 165 ", 'XAResource.end(..)' scope."; 166 DODS.getLogChannel().write(Logger.ERROR,msg); 167 throw new XAException (msg); 168 } 169 } 170 171 public void rollback(Xid arg0) throws XAException { 172 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##rollback:" + arg0); 173 if (identityTest(arg0)){ 174 try { 175 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##rollback-rollback:"); 176 this.wrapped.rollback(); 177 } catch (SQLException e) { 178 DODS.getLogChannel().write(Logger.ERROR,"XATransaction##rollback",e); 179 throw new XAException (XAException.XAER_RMERR); 180 }finally { 181 deattacht(); 182 } 183 } else { 184 throw new XAException (XAException.XAER_NOTA); 185 } 186 } 187 188 public void end(Xid arg0, int arg1) throws XAException { 189 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##end:" + arg0); 190 if(distributed) { 191 distributed = false; 192 }else { 193 throw new XAException ("Distributed JTA XAResource.end on local (non JTA) Transaction."); 194 } 195 } 196 197 public void start(Xid xaId, int flg) throws XAException { 198 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##start:" + xaId); 199 200 this.identity = xaId; 201 this.flags = flg; 202 if ( (this.internal!=this.wrapped) && (this.internal!=null) ) { 203 this.internal.release(); 204 } 205 this.internal = null; 206 this.current = this.wrapped; 207 distributed = true; 208 } 209 210 public void commit(Xid arg0, boolean arg1) throws XAException { 211 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##commit:" + arg0); 212 if (identityTest(arg0)) { 213 try { 214 this.wrapped.commit(); 215 } catch (SQLException e) { 216 DODS.getLogChannel().write(Logger.ERROR, "XATransaction##commit",e); 217 throw new XAException (XAException.XAER_RMERR); 218 }finally { 219 deattacht(); 220 } 221 } else { 222 throw new XAException (XAException.XAER_NOTA); 223 } 224 } 225 226 private boolean identityTest(Xid arg0) { 227 return arg0.getGlobalTransactionId() 228 .equals(identity.getGlobalTransactionId()); 229 } 230 231 public void update(Transaction transaction) { 232 this.current.update(transaction); 233 } 234 235 public void delete(Transaction transaction) { 236 this.current.delete(transaction); 237 } 238 239 public void insert(Transaction transaction) { 240 this.current.insert(transaction); 241 } 242 243 public void commit() throws SQLException { 244 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##commit() distributed="+distributed); 245 if(distributed) { 246 switch (classicUsageReaction) { 247 case XATransactionFactory.XA_THROW_ERROR: 248 throw new Error (cMessage); 249 case XATransactionFactory.XA_THROW_EXCEPTION: 250 throw new SQLException (cMessage); 251 case XATransactionFactory.XA_WARN: 252 DODS.getLogChannel().write(Logger.DEBUG, cMessage); 253 break; 254 case XATransactionFactory.XA_WARN_WITH_TRACE: 255 DODS.getLogChannel().write(Logger.DEBUG, 256 cMessage, 257 new Throwable ()); 258 case XATransactionFactory.XA_INGORE: 259 } 260 }else { 261 this.internal.commit(); 262 } 263 } 264 265 266 267 public void rollback() throws SQLException { 268 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##rollback() distributed="+distributed); 269 270 if(distributed) { 271 switch (classicUsageReaction) { 272 case XATransactionFactory.XA_THROW_ERROR: 273 throw new Error (rMessage); 274 case XATransactionFactory.XA_THROW_EXCEPTION: 275 throw new SQLException (rMessage); 276 case XATransactionFactory.XA_WARN: 277 DODS.getLogChannel().write(Logger.DEBUG, rMessage); 278 break; 279 case XATransactionFactory.XA_WARN_WITH_TRACE: 280 DODS.getLogChannel().write(Logger.DEBUG, 281 rMessage, 282 new Throwable ()); 283 case XATransactionFactory.XA_INGORE: 284 } 285 }else { 286 this.internal.rollback(); 287 288 } 289 } 290 291 292 public void release() { 293 DODS.getLogChannel().write(Logger.DEBUG,"XATransaction##release() distributed="+distributed); 294 if(distributed) { 295 switch (classicUsageReaction) { 296 case XATransactionFactory.XA_THROW_ERROR: 297 throw new Error (eMessage); 298 case XATransactionFactory.XA_THROW_EXCEPTION: 299 case XATransactionFactory.XA_WARN: 300 DODS.getLogChannel().write(Logger.DEBUG, eMessage); 301 break; 302 case XATransactionFactory.XA_WARN_WITH_TRACE: 303 DODS.getLogChannel().write(Logger.DEBUG, 304 eMessage, 305 new Throwable ()); 306 case XATransactionFactory.XA_INGORE: 307 } 308 }else { 309 this.internal.release(); 310 this.internal=null; 311 } 312 } 313 314 315 public boolean handleException(SQLException e) { 316 return this.current.handleException(e); 317 } 318 319 public Transaction getDO(Transaction transaction) { 320 return this.current.getDO(transaction); 321 } 322 323 public Transaction getDO(Transaction transaction, int action) { 324 return this.current.getDO(transaction, action); 325 } 326 327 public String getDatabaseName() { 328 return this.current.getDatabaseName(); 329 } 330 331 public void setDatabaseName(String dbName) { 332 this.current.setDatabaseName(dbName); 333 } 334 335 public void write() throws SQLException { 336 this.current.write(); 337 } 338 339 public void lockDO(Transaction cdo) throws SQLException { 340 this.current.lockDO(cdo); 341 } 342 343 public DBQuery createQuery() throws SQLException { 344 return this.current.createQuery(); 345 } 346 347 public boolean preventCacheQueries() { 348 return this.current.preventCacheQueries(); 349 } 350 351 public boolean isReleased() { 352 return this.current.isReleased(); 353 } 354 355 public CoreDO[] getDOs() { 356 return this.current.getDOs(); 357 } 358 359 public void saveDirtyDOs() { 360 this.current.saveDirtyDOs(); 361 } 362 363 public DOCache getTransactionCache() { 364 return this.current.getTransactionCache(); 365 } 366 367 public Vector getDeletedDOs() { 368 return this.current.getDeletedDOs(); 369 } 370 371 public void addDeletedDO(CoreDO DO) { 372 this.current.addDeletedDO(DO); 373 } 374 375 public void resetDeletedDOs() { 376 this.current.resetDeletedDOs(); 377 } 378 379 public void dontAggregateDOModifications() { 380 this.current.dontAggregateDOModifications(); 381 } 382 383 public boolean getAutoWrite() { 384 return this.current.getAutoWrite(); 385 } 386 387 public boolean isFirstWrite() { 388 return this.current.isFirstWrite(); 389 } 390 391 public void setFirstWrite(boolean newfw) { 392 this.current.setFirstWrite(newfw); 393 } 394 395 public boolean wasReadOnly() { 396 return this.current.wasReadOnly(); 397 } 398 399 402 public CachedDBTransaction getWrapped() { 403 return wrapped; 404 } 405 408 public void setWrapped(CachedDBTransaction wrapped) { 409 this.wrapped = wrapped; 410 } 411 412 public boolean equals(Object trans) { 413 if (trans instanceof XAUserTransaction) { 414 XAUserTransaction xaUserTrans = (XAUserTransaction)trans; 415 return xaUserTrans.equals(this); 416 } 417 else if (trans instanceof XATransaction) { 418 XATransaction xaTrans = (XATransaction)trans; 419 return current.equals(xaTrans.current); 420 } 421 else if (trans instanceof DBTransaction) { 422 DBTransaction dbTrans = (DBTransaction)trans; 423 return current.equals(dbTrans); 424 } 425 return false; 426 } 427 428 } 429 | Popular Tags |