1 25 26 package org.objectweb.jonas_ejb.container; 27 28 import java.rmi.NoSuchObjectException ; 29 import java.rmi.RemoteException ; 30 import java.util.ArrayList ; 31 import java.util.Collections ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 35 import javax.ejb.EJBException ; 36 import javax.ejb.NoSuchObjectLocalException ; 37 import javax.ejb.RemoveException ; 38 import javax.ejb.SessionSynchronization ; 39 import javax.ejb.TransactionRolledbackLocalException ; 40 import javax.transaction.InvalidTransactionException ; 41 import javax.transaction.RollbackException ; 42 import javax.transaction.SystemException ; 43 import javax.transaction.Transaction ; 44 45 import org.objectweb.transaction.jta.ResourceManagerEvent; 46 import org.objectweb.util.monolog.api.BasicLevel; 47 48 53 public class JStatefulSwitch extends JSessionSwitch { 54 55 private int sessionId; 56 57 private JStatefulContext bctx = null; 58 59 private Transaction currTx = null; 60 61 private boolean mustCommit = false; 62 63 private boolean expired = false; 64 65 private Transaction beanTx = null; 67 private long lastaccesstime; 68 69 private boolean passivated = false; 70 71 81 private List connectionList = Collections.synchronizedList(new ArrayList ()); 82 83 88 public JStatefulSwitch(JStatefulFactory bf) throws RemoteException { 89 super(bf); 90 if (TraceEjb.isDebugIc()) { 91 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 92 } 93 } 94 95 public int getSessionId() { 96 return sessionId; 97 } 98 99 102 public boolean canPassivate() { 103 if (currTx != null || beanTx != null) { 104 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Victim is busy"); 105 return false; 106 } 107 return (! passivated); 108 } 109 110 113 public boolean isPassivated() { 114 return passivated; 115 } 116 117 120 public boolean passivate() { 121 if (currTx != null || beanTx != null) { 122 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Cannot passivate: busy"); 123 return false; 124 } 125 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Instance will be passivated"); 126 passivated = ((JStatefulFactory)bf).passivateStateful(this); 127 if (passivated) { 128 bctx.setInstance(null); 130 } 131 return passivated; 132 } 133 134 137 public void activate() { 138 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Instance will be activated"); 139 ((JStatefulFactory)bf).activateStateful(this); 140 } 141 142 146 public void pushConnectionList() { 147 if (TraceEjb.isDebugTx()) { 148 TraceEjb.tx.log(BasicLevel.DEBUG, "pushed connectionList =" + connectionList); 149 } 150 bf.getTransactionManager().pushThreadLocalRMEventList(connectionList); 151 } 152 153 156 public void popConnectionList() { 157 connectionList = bf.getTransactionManager().popThreadLocalRMEventList(); 158 if (TraceEjb.isDebugTx()) { 159 TraceEjb.tx.log(BasicLevel.DEBUG, "poped connectionList =" + connectionList); 160 } 161 } 162 163 166 public void setConnectionList(List cl) { 167 connectionList = cl; 168 if (TraceEjb.isDebugTx()) { 169 TraceEjb.tx.log(BasicLevel.DEBUG, "init connectionList =" + connectionList); 170 } 171 } 172 173 176 public void enlistConnections(Transaction tx) { 177 if (tx != null && connectionList != null) { 178 try { 179 for (Iterator it = connectionList.iterator(); it.hasNext();) { 180 ResourceManagerEvent rme = (ResourceManagerEvent) it.next(); 181 if (rme != null) { 182 rme.enlistConnection(tx); 183 } else { 184 TraceEjb.tx.log(BasicLevel.WARN, "Null ResourceManagerEvent in Connection List"); 185 } 186 } 187 } catch (SystemException e) { 188 TraceEjb.tx.log(BasicLevel.ERROR, "cannot enlist connection", e); 189 } 190 } 191 pushConnectionList(); 194 } 195 196 199 public void delistConnections(Transaction tx) { 200 popConnectionList(); 201 } 202 203 207 211 public synchronized void timeoutExpired(Object arg) { 212 if (TraceEjb.isVerbose()) { 213 TraceEjb.logger.log(BasicLevel.WARN, "stateful session timeout expired"); 214 } 215 mytimer = null; 216 if (currTx != null) { 218 expired = true; 219 } else { 220 if (bctx != null) { 221 try { 222 bctx.setRemoved(); 223 } catch (RemoteException e) { 224 if (TraceEjb.isVerbose()) { 225 TraceEjb.logger.log(BasicLevel.WARN, "timeout expired", e); 226 } 227 } catch (RemoveException e) { 228 if (TraceEjb.isVerbose()) { 229 TraceEjb.logger.log(BasicLevel.WARN, "timeout expired", e); 230 } 231 } 232 } 233 noLongerUsed(); 234 } 235 } 236 237 241 244 public JStatefulContext getStatefulContext() { 245 if (sessionId == -1) { 246 throw new EJBException ("This Session has been removed"); 247 } 248 if (bctx == null) { 249 throw new EJBException ("Already passivated"); 250 } 251 return bctx; 252 } 253 254 259 public JSessionContext getICtx(Transaction tx) { 260 if (TraceEjb.isDebugIc()) { 261 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 262 } 263 264 if (sessionId == -1) { 268 throw new NoSuchObjectLocalException ("This Session has been removed"); 269 } 270 271 if (passivated) { activate(); 274 } 275 checkTx(tx); 277 278 lastaccesstime = System.currentTimeMillis(); 279 return bctx; 280 } 281 282 287 public void bindICtx(Transaction tx, JStatefulContext bctx) { 288 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 289 sessionId = ((JStatefulFactory)bf).getNewSessionId(this); 290 this.bctx = bctx; 291 bctx.initSessionContext(this); 292 checkTx(tx); 294 lastaccesstime = System.currentTimeMillis(); 295 } 296 297 301 public void releaseICtx(Transaction tx) { 302 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 303 304 if (bctx == null) { 306 return; 307 } 308 309 if (bctx.isMarkedRemoved()) { 310 stopTimer(); 311 noLongerUsed(); 312 } 313 } 314 315 320 public void discardICtx(Transaction tx) { 321 if (TraceEjb.isDebugIc()) { 322 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 323 } 324 325 if (bctx == null) { 327 return; 328 } 329 330 stopTimer(); 331 noLongerUsed(); 332 } 333 334 338 public void noLongerUsed() { 339 if (TraceEjb.isDebugIc()) { 340 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 341 } 342 343 if (remote != null) { 345 try { 346 remote.unexportObject(); 347 } catch (NoSuchObjectException e) { 348 TraceEjb.logger.log(BasicLevel.ERROR, "unexportObject failed", e); 349 } 350 } 351 352 if (beanTx != null) { 355 TraceEjb.tx.log(BasicLevel.WARN, "transaction not ended. forget it"); 356 beanTx = null; 357 } 358 359 bf.removeEJB(this); 362 363 ((JStatefulFactory)bf).removeStateful(sessionId); 366 bctx = null; 367 sessionId = -1; 368 } 369 370 373 public void txCompleted() { 374 if (TraceEjb.isDebugIc()) { 375 TraceEjb.interp.log(BasicLevel.DEBUG, ""); 376 } 377 currTx = null; 378 if (expired) { 379 timeoutExpired(null); } 381 } 382 383 387 public boolean isInTransaction() { 388 return (currTx != null && !mustCommit); 389 } 390 391 394 public void setMustCommit(boolean mc) { 395 mustCommit = mc; 396 } 397 398 403 public void saveBeanTx() { 404 if (bf.isTxBeanManaged()) { 405 if (TraceEjb.isDebugTx()) { 406 TraceEjb.tx.log(BasicLevel.DEBUG, ""); 407 } 408 try { 409 beanTx = bf.getTransactionManager().suspend(); 410 } catch (SystemException e) { 411 TraceEjb.logger.log(BasicLevel.ERROR, "cannot suspend transaction:", e); 412 } 413 } 414 } 415 416 419 public long getLastAccessTime() { 420 return lastaccesstime; 421 } 422 423 427 433 private void checkTx(Transaction tx) { 434 435 if (bf.isSessionSynchro() == false) { 437 if (bf.isTxBeanManaged() && beanTx != null) { 441 if (TraceEjb.isDebugTx()) { 442 TraceEjb.tx.log(BasicLevel.DEBUG, "resuming Bean Managed Tx"); 443 } 444 try { 445 bf.getTransactionManager().resume(beanTx); 446 } catch (SystemException e) { 447 TraceEjb.logger.log(BasicLevel.ERROR, "cannot resume transaction", e); 448 } catch (InvalidTransactionException e) { 449 TraceEjb.logger.log(BasicLevel.ERROR, "Cannot resume transaction", e); 450 } 451 } else { 452 if (TraceEjb.isDebugTx()) { 453 TraceEjb.tx.log(BasicLevel.DEBUG, "no checkTx"); 454 } 455 } 456 return; 457 } 458 459 if (tx == null) { 460 if (TraceEjb.isDebugTx()) { 461 TraceEjb.tx.log(BasicLevel.DEBUG, "(No Tx)"); 462 } 463 if (currTx != null) { 464 TraceEjb.logger.log(BasicLevel.ERROR, "synchronized session called outside transaction context"); 467 throw new EJBException ("Synchronized session called outside transaction context"); 468 } 469 } else { 470 if (TraceEjb.isDebugTx()) { 471 TraceEjb.tx.log(BasicLevel.DEBUG, ""); 472 } 473 if (currTx == null) { 474 try { 476 tx.registerSynchronization(bctx); 477 SessionSynchronization ssbean = (SessionSynchronization ) bctx.getInstance(); 478 ssbean.afterBegin(); 479 } catch (RollbackException e) { 480 throw new TransactionRolledbackLocalException ("Session rolled back"); 481 } catch (SystemException e) { 482 throw new EJBException ("checkTx error", e); 483 } catch (RemoteException e) { 484 throw new EJBException ("checkTx error", e); 485 } 486 currTx = tx; 487 } else { 488 if (tx.equals(currTx) == false) { 491 TraceEjb.logger.log(BasicLevel.ERROR, "synchronized session called in another transaction context"); 492 throw new EJBException ("Synchronized session called in another transaction context"); 493 } 494 } 495 } 496 } 497 } 498 | Popular Tags |