001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.scheduling.timer;
018:
019: import java.util.Timer;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: import org.springframework.beans.factory.DisposableBean;
025: import org.springframework.beans.factory.InitializingBean;
026: import org.springframework.scheduling.SchedulingTaskExecutor;
027: import org.springframework.util.Assert;
028:
029: /**
030: * {@link org.springframework.core.task.TaskExecutor} implementation that uses a
031: * single {@link Timer} for executing all tasks, effectively resulting in
032: * serialized asynchronous execution on a single thread.
033: *
034: * @author Juergen Hoeller
035: * @since 2.0
036: * @see java.util.Timer
037: */
038: public class TimerTaskExecutor implements SchedulingTaskExecutor,
039: InitializingBean, DisposableBean {
040:
041: /**
042: * The shared {@link Log} instance.
043: */
044: protected final Log logger = LogFactory.getLog(getClass());
045:
046: private Timer timer;
047:
048: private int delay = 0;
049:
050: private boolean usingAnInternalTimer = false;
051:
052: /**
053: * Create a new TimerTaskExecutor that needs to be further
054: * configured and initialized.
055: * @see #setTimer
056: * @see #afterPropertiesSet
057: */
058: public TimerTaskExecutor() {
059: }
060:
061: /**
062: * Create a new TimerTaskExecutor for the given {@link Timer}.
063: * @param timer the {@link Timer} to wrap
064: * @throws IllegalArgumentException if the supplied {@link Timer} is <code>null</code>
065: */
066: public TimerTaskExecutor(Timer timer) {
067: Assert.notNull(timer, "Timer must not be null");
068: this .timer = timer;
069: }
070:
071: /**
072: * Set the {@link Timer} to use for this {@link TimerTaskExecutor},
073: * for example a shared {@link Timer} instance defined by a
074: * {@link TimerFactoryBean}.
075: * <p>If not specified, a default {@link Timer} instance will be used.
076: * @param timer the {@link Timer} to use for this {@link TimerTaskExecutor} (may be <code>null</code>)
077: * @see TimerFactoryBean
078: */
079: public void setTimer(Timer timer) {
080: this .timer = timer;
081: }
082:
083: /**
084: * Set the delay to use for scheduling tasks passed into the
085: * <code>execute</code> method. Default is 0.
086: * @param delay the delay in milliseconds before the task is to be executed
087: */
088: public void setDelay(int delay) {
089: this .delay = delay;
090: }
091:
092: public void afterPropertiesSet() {
093: if (this .timer == null) {
094: logger.info("Initializing Timer");
095: this .timer = createTimer();
096: this .usingAnInternalTimer = true;
097: }
098: }
099:
100: /**
101: * Create a new {@link Timer} instance. Called by <code>afterPropertiesSet</code>
102: * if no {@link Timer} has been specified explicitly.
103: * <p>Default implementation creates a plain daemon {@link Timer}.
104: * <p>If overridden, subclasses must take care to ensure that a non-null
105: * {@link Timer} is returned from the execution of this method.
106: * @return a new {@link Timer} instance
107: * @see #afterPropertiesSet
108: * @see java.util.Timer#Timer(boolean)
109: */
110: protected Timer createTimer() {
111: return new Timer(true);
112: }
113:
114: /**
115: * Schedules the given {@link Runnable} on this executor's {@link Timer} instance,
116: * wrapping it in a {@link DelegatingTimerTask}.
117: * @param task the task to be executed
118: * @throws IllegalArgumentException if the supplied {@link Runnable task} is <code>null</code>,
119: * or if the {@link Timer} encapsulated by this instance has not been set, or
120: * if the {@link #setDelay(int) configured delay} is negative.
121: */
122: public void execute(Runnable task) {
123: Assert.notNull(this .timer, "timer is required");
124: this .timer.schedule(new DelegatingTimerTask(task), this .delay);
125: }
126:
127: /**
128: * This task executor prefers short-lived work units.
129: */
130: public boolean prefersShortLivedTasks() {
131: return true;
132: }
133:
134: /**
135: * Cancel the {@link Timer} on bean factory shutdown, stopping all scheduled tasks.
136: * @see java.util.Timer#cancel()
137: */
138: public void destroy() {
139: if (this .usingAnInternalTimer) {
140: logger.info("Cancelling Timer");
141: this.timer.cancel();
142: }
143: }
144:
145: }
|