00001
00026 package org.objectweb.jonas_ejb.container;
00027
00028 import java.io.Serializable;
00029 import java.util.Date;
00030
00031 import javax.ejb.EJBException;
00032 import javax.ejb.NoSuchObjectLocalException;
00033 import javax.ejb.Timer;
00034 import javax.ejb.TimerHandle;
00035 import javax.transaction.RollbackException;
00036 import javax.transaction.Status;
00037 import javax.transaction.Synchronization;
00038 import javax.transaction.SystemException;
00039 import javax.transaction.Transaction;
00040 import javax.transaction.TransactionManager;
00041
00042 import org.objectweb.jonas_timer.TimerEvent;
00043 import org.objectweb.jonas_timer.TimerEventListener;
00044 import org.objectweb.jonas_timer.TimerManager;
00045 import org.objectweb.jonas_timer.TraceTimer;
00046 import org.objectweb.util.monolog.api.BasicLevel;
00047
00054 public class JTimer implements Timer, TimerEventListener, Synchronization {
00055
00059 private boolean oneshot;
00060
00064 private long period;
00065
00069 private long initial;
00070
00074 private JTimerService timerservice;
00075
00079 private Serializable info;
00080
00084 private TimerManager tim = TimerManager.getInstance();
00085
00089 private TimerEvent te1 = null;
00090
00094 private TimerEvent te2 = null;
00095
00099 private long starttime;
00100
00104 private long endtime;
00105
00109 private boolean createdInTx = false;
00110
00114 private boolean cancelledInTx = false;
00115
00119 private boolean cancelled = false;
00120
00124 private TimerHandle myHandle = null;
00125
00129 public JTimer(JTimerService timerservice, long initial, long period, Serializable info) {
00130 TraceTimer.logger.log(BasicLevel.DEBUG, "New JTimer initial = " + initial + ", period = " + period);
00131 this.timerservice = timerservice;
00132 this.info = info;
00133 this.period = period;
00134 this.initial = initial;
00135 oneshot = (period == 0);
00136
00137 }
00138
00142 public long getStartTime() {
00143 return starttime;
00144 }
00145
00149 public long getInitial() {
00150 return initial;
00151 }
00152
00156 public long getPeriod() {
00157 return period;
00158 }
00159
00163 public JTimerService getTimerService() {
00164 return timerservice;
00165 }
00166
00170 public void startTimer() {
00171
00172
00173 TransactionManager tm = timerservice.getTransactionManager();
00174 try {
00175 Transaction tx = tm.getTransaction();
00176 if (tx != null) {
00177 tx.registerSynchronization(this);
00178 createdInTx = true;
00179 }
00180 } catch (SystemException e) {
00181 TraceTimer.logger.log(BasicLevel.ERROR, "Cannot get Transaction");
00182 } catch (IllegalStateException e) {
00183 TraceTimer.logger.log(BasicLevel.ERROR, "Cannot register synchronization:" + e);
00184 } catch (RollbackException e) {
00185 TraceTimer.logger.log(BasicLevel.ERROR, "transaction already rolled back");
00186 }
00187
00188
00189 starttime = System.currentTimeMillis();
00190 endtime = starttime + initial;
00191
00192
00193 te1 = tim.addTimerMs(this, initial, null, false);
00194 }
00195
00199 public void stopTimer() {
00200 TraceTimer.logger.log(BasicLevel.DEBUG, "Stop JTimer");
00201 cancelled = true;
00202 if (te1 != null) {
00203 te1.unset();
00204 te1 = null;
00205 }
00206 if (te2 != null) {
00207 te2.unset();
00208 te2 = null;
00209 }
00210 }
00211
00212
00213
00214
00215
00222 public boolean equals(Object obj) {
00223 if (obj instanceof JTimer) {
00224 JTimer timer2 = (JTimer) obj;
00225 if (timer2.getInitial() != getInitial()) {
00226 TraceTimer.logger.log(BasicLevel.DEBUG, "different initial duration");
00227 return false;
00228 }
00229 if (timer2.getPeriod() != getPeriod()) {
00230 TraceTimer.logger.log(BasicLevel.DEBUG, "different period");
00231 return false;
00232 }
00233 if (timer2.getTimerService() != getTimerService()) {
00234 TraceTimer.logger.log(BasicLevel.DEBUG, "different timerservice");
00235 return false;
00236 }
00237 TraceTimer.logger.log(BasicLevel.DEBUG, "timers are equal");
00238 return true;
00239 } else {
00240 TraceTimer.logger.log(BasicLevel.DEBUG, "not a Timer");
00241 return false;
00242 }
00243 }
00244
00249 public int hashCode() {
00250 return (int) (getPeriod() / 1000);
00251 }
00252
00253
00254
00255
00256
00260 public void timeoutExpired(Object arg) {
00261 TraceTimer.logger.log(BasicLevel.DEBUG, "JTimer expires");
00262
00263 timerservice.notify(this);
00264 if (cancelled) {
00265 TraceTimer.logger.log(BasicLevel.DEBUG, "JTimer cancelled during timeout");
00266 return;
00267 }
00268 if (te2 == null) {
00269 te1 = null;
00270 if (oneshot) {
00271 timerservice.remove(this);
00272 cancelled = true;
00273 } else {
00274
00275 TraceTimer.logger.log(BasicLevel.DEBUG, "Start periodic jonas timer");
00276 endtime = System.currentTimeMillis() + period;
00277 te2 = tim.addTimerMs(this, period, null, true);
00278 }
00279 } else {
00280
00281 endtime = System.currentTimeMillis() + period;
00282 }
00283 }
00284
00285
00286
00287
00288
00299 public void cancel() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00300 if (cancelled || cancelledInTx) {
00301 TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00302 throw new NoSuchObjectLocalException("Timer already cancelled");
00303 }
00304 TraceTimer.logger.log(BasicLevel.DEBUG, "");
00305
00306
00307 TransactionManager tm = timerservice.getTransactionManager();
00308 try {
00309 Transaction tx = tm.getTransaction();
00310 if (tx != null) {
00311
00312 tx.registerSynchronization(this);
00313 cancelledInTx = true;
00314 } else {
00315 doCancel();
00316 }
00317 } catch (SystemException e) {
00318 TraceTimer.logger.log(BasicLevel.ERROR, "Cannot get Transaction");
00319 } catch (IllegalStateException e) {
00320 TraceTimer.logger.log(BasicLevel.ERROR, "Cannot register synchronization:" + e);
00321 } catch (RollbackException e) {
00322 TraceTimer.logger.log(BasicLevel.ERROR, "transaction already rolled back");
00323 }
00324 }
00325
00326 private void doCancel() {
00327 stopTimer();
00328 timerservice.remove(this);
00329 }
00330
00343 public long getTimeRemaining() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00344 if (cancelled || cancelledInTx) {
00345 TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00346 throw new NoSuchObjectLocalException("Timer cancelled or expired");
00347 }
00348 TraceTimer.logger.log(BasicLevel.DEBUG, "");
00349 return endtime - System.currentTimeMillis();
00350 }
00351
00364 public Date getNextTimeout() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00365 if (cancelled || cancelledInTx) {
00366 TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00367 throw new NoSuchObjectLocalException("Timer cancelled or expired");
00368 }
00369 TraceTimer.logger.log(BasicLevel.DEBUG, "");
00370 return new Date(endtime);
00371 }
00372
00384 public Serializable getInfo() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00385 if (cancelled || cancelledInTx) {
00386 TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00387 throw new NoSuchObjectLocalException("Timer cancelled or expired");
00388 }
00389 TraceTimer.logger.log(BasicLevel.DEBUG, "");
00390 return info;
00391 }
00392
00404 public TimerHandle getHandle() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00405 if (cancelled || cancelledInTx) {
00406 TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00407 throw new NoSuchObjectLocalException("Timer cancelled or expired");
00408 }
00409 TraceTimer.logger.log(BasicLevel.DEBUG, "");
00410 if (myHandle == null) {
00411 myHandle = new JTimerHandle(initial, period, info, timerservice.getEjbName(),
00412 timerservice.getContainer(), timerservice.getPK());
00413 }
00414 return myHandle;
00415 }
00416
00417
00418
00419
00420
00427 public void afterCompletion(int status) {
00428 TraceEjb.tx.log(BasicLevel.DEBUG, "");
00429
00430
00431 if (createdInTx) {
00432 if (status != Status.STATUS_COMMITTED && !cancelled) {
00433 doCancel();
00434 }
00435 createdInTx = false;
00436 }
00437
00438
00439 if (cancelledInTx) {
00440 if (status == Status.STATUS_COMMITTED && !cancelled) {
00441 doCancel();
00442 }
00443 cancelledInTx = false;
00444 }
00445 }
00446
00447
00448
00449
00450 public void beforeCompletion() {
00451
00452 }
00453
00454 }