public final class ServletTimerImpl implements ServletTimer, Runnable { private static final Logger LOG = OSGiLogger.getLogger(ServletTimer.class, BundleLogger.getStaticLogger()); private static final int UUID_LENGTH = 40; private RunnableTimerTask timerTask; private final ApplicationSessionImpl appSession; private final String id; private final Serializable info; private final boolean repeatingTimer; private long scheduledExecutionTime; private long delay; private long period; private long numInvocations; private boolean fixedDelay; private long firstExecution; private TimerListener listener; /** * Constructor for non-repeating timer. * * @param info Information about the timer * @param delay Delay until execution * @param listener Listener that will get timeout events. */ public ServletTimerImpl( Serializable info, long delay, TimerListener listener, ApplicationSessionImpl appSession) { this(info, delay, false, 0, listener, appSession); } /** * Constructor for repeating times * * @param info Information about the timer * @param delay Delay until first execution * @param fixedDelay Whether fixed delay mode should be used * @param period Period between execution * @param listener Listener that will get timeout events. */ public ServletTimerImpl( Serializable info, long delay, boolean fixedDelay, long period, TimerListener listener, ApplicationSessionImpl appSession) { this.id = UUID.randomUUID(UUID_LENGTH); this.info = info; this.delay = delay; this.scheduledExecutionTime = delay + System.currentTimeMillis(); this.fixedDelay = fixedDelay; this.period = period; this.listener = listener; this.appSession = appSession; this.numInvocations = 0; this.firstExecution = 0; this.repeatingTimer = (period > 0); this.timerTask = new RunnableTimerTask(this); } public void cancel() { LOG.debug("removeServletTimer"); appSession.removeServletTimer(this); LOG.debug("cancel timerTask"); timerTask.cancel(); } public ApplicationSession getApplicationSession() { return appSession; } public String getId() { return id; } public Serializable getInfo() { return info; } public synchronized long getTimeRemaining() { return scheduledExecutionTime - System.currentTimeMillis(); } public synchronized long scheduledExecutionTime() { return this.scheduledExecutionTime; } public RunnableTimerTask getServletTimerTask() { return timerTask; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Info = ") .append(info) .append(System.getProperty("line.separator")) .append("Scheduled execution time = "); synchronized (this) { sb.append(scheduledExecutionTime); } sb.append(System.getProperty("line.separator")); sb.append("Time now = ") .append(System.currentTimeMillis()) .append(System.getProperty("line.separator")); sb.append("ApplicationSession = ") .append(appSession) .append(System.getProperty("line.separator")); sb.append("Delay = ").append(delay).append(System.getProperty("line.separator")); return sb.toString(); } /** Helper to calculate when next execution time is. */ private synchronized void estimateNextExecution() { if (fixedDelay) { scheduledExecutionTime = period + System.currentTimeMillis(); } else { if (firstExecution == 0) { // save timestamp of first execution firstExecution = scheduledExecutionTime; } long now = System.currentTimeMillis(); long executedTime = (numInvocations * period); numInvocations++; scheduledExecutionTime = firstExecution + executedTime; if (LOG.isDebugEnabled()) { LOG.debug("next execution estimated to run at " + scheduledExecutionTime); LOG.debug("current time is " + now); } } } public void run() { long run = System.currentTimeMillis(); // PORTAGE chgt de classLoader pour le currentThread // ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); try { // ClassLoader cl = listener.getClass().getClassLoader(); // Thread.currentThread().setContextClassLoader(cl); LOG.debug("Call timeout"); listener.timeout(this); } catch (Throwable e) { LOG.error("An unexpected exception happened in the timer callback", e); } finally { // Thread.currentThread().setContextClassLoader(oldClassLoader); if (repeatingTimer) { LOG.debug("Reset repeating servlet timer"); estimateNextExecution(); } else { LOG.debug("Cancel servlet timer"); // this non-repeating timer is now "ready" // and should not be included in the list of active timers // The application may already have canceled() the timer though cancel(); // dont bother about return value.... } } run = System.currentTimeMillis() - run; if (run > 500) { LOG.error( appSession.getId() + ": The servlet timer has taken more than 500 ms to be handled: " + run + " ms"); } } }
public final class TimerServiceImpl extends Timer implements TimerService { private static final Logger LOG = OSGiLogger.getLogger(TimerService.class, BundleLogger.getStaticLogger()); public ServletTimer createTimer( ServletContext context, long delay, boolean isPersistent, Serializable info) { throw new UnsupportedOperationException(); } public ServletTimer createTimer( ServletContext context, long delay, long period, boolean fixedDelay, boolean isPersistent, Serializable info) { throw new UnsupportedOperationException(); } public ServletTimer createTimer( ApplicationSession appSession, long delay, boolean isPersistent, Serializable info) { if (LOG.isDebugEnabled()) { LOG.debug( "Create timer for application " + appSession.getApplicationName() + " (delay=" + delay + ", persistent=" + isPersistent + ")"); } ApplicationSessionImpl applicationSessionImpl = (ApplicationSessionImpl) appSession; applicationSessionImpl.checkValid(); if (!applicationSessionImpl.hasTimerListener()) { throw new IllegalStateException( "No Timer listeners have been configured for this application "); } TimerListener listener = applicationSessionImpl.getServletContextInternal().getTimerListener(); ServletTimerImpl servletTimer = createTimerLocally(listener, delay, isPersistent, info, applicationSessionImpl); return servletTimer; } public ServletTimer createTimer( ApplicationSession appSession, long delay, long period, boolean fixedDelay, boolean isPersistent, Serializable info) { if (period < 1) { throw new IllegalArgumentException("Period should be greater than 0"); } if (LOG.isDebugEnabled()) { LOG.debug( "Create timer for application " + appSession.getApplicationName() + " (delay=" + delay + ", period=" + period + ", fixedDelay=" + fixedDelay + ", persistent=" + isPersistent + ")"); } ApplicationSessionImpl applicationSessionImpl = (ApplicationSessionImpl) appSession; applicationSessionImpl.checkValid(); if (applicationSessionImpl.getServletContextInternal().getTimerListener() == null) { throw new IllegalStateException( "No Timer listeners have been configured for this application "); } TimerListener timerListener = applicationSessionImpl.getServletContextInternal().getTimerListener(); ServletTimerImpl servletTimer = createTimerLocally( timerListener, delay, period, fixedDelay, isPersistent, info, applicationSessionImpl); return servletTimer; } /** * @param listener * @param delay * @param isPersistent * @param info * @param applicationSession * @return */ private ServletTimerImpl createTimerLocally( TimerListener listener, long delay, boolean isPersistent, Serializable info, ApplicationSessionImpl applicationSession) { ServletTimerImpl servletTimer = new ServletTimerImpl(info, delay, listener, applicationSession); super.schedule(servletTimer.getServletTimerTask(), delay); applicationSession.addServletTimer(servletTimer); if (isPersistent) { persist(servletTimer); } return servletTimer; } /** * @param listener * @param delay * @param period * @param fixedDelay * @param isPersistent * @param info * @param applicationSession * @return */ private ServletTimerImpl createTimerLocally( TimerListener listener, long delay, long period, boolean fixedDelay, boolean isPersistent, Serializable info, ApplicationSessionImpl applicationSession) { final ServletTimerImpl servletTimer = new ServletTimerImpl(info, delay, fixedDelay, period, listener, applicationSession); if (fixedDelay) { super.schedule(servletTimer.getServletTimerTask(), delay, period); } else { super.scheduleAtFixedRate(servletTimer.getServletTimerTask(), delay, period); } applicationSession.addServletTimer(servletTimer); if (isPersistent) { persist(servletTimer); } return servletTimer; } /** @param st */ private void persist(ServletTimerImpl st) { // TODO - implement persistance } public void stop() { super.cancel(); if (LOG.isDebugEnabled()) { LOG.debug("Stopped timer service " + this); } } public void start() { if (LOG.isDebugEnabled()) { LOG.debug("Started timer service " + this); } } }