001: /*
002: * Copyright 2002-2007 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.BeanNameAware;
025: import org.springframework.beans.factory.DisposableBean;
026: import org.springframework.beans.factory.FactoryBean;
027: import org.springframework.beans.factory.InitializingBean;
028: import org.springframework.core.JdkVersion;
029: import org.springframework.util.ObjectUtils;
030: import org.springframework.util.StringUtils;
031:
032: /**
033: * FactoryBean that sets up a {@link java.util.Timer} and exposes it for bean references.
034: *
035: * <p>Allows for registration of {@link ScheduledTimerTask ScheduledTimerTasks},
036: * automatically starting the {@link Timer} on initialization and cancelling it
037: * on destruction of the context. In scenarios that just require static registration
038: * of tasks at startup, there is no need to access the {@link Timer} instance itself
039: * in application code at all.
040: *
041: * <p>Note that the {@link Timer} mechanism uses a {@link java.util.TimerTask}
042: * instance that is shared between repeated executions, in contrast to Quartz
043: * which creates a new Job instance for each execution.
044: *
045: * @author Juergen Hoeller
046: * @since 19.02.2004
047: * @see ScheduledTimerTask
048: * @see java.util.Timer
049: * @see java.util.TimerTask
050: */
051: public class TimerFactoryBean implements FactoryBean, BeanNameAware,
052: InitializingBean, DisposableBean {
053:
054: protected final Log logger = LogFactory.getLog(getClass());
055:
056: private ScheduledTimerTask[] scheduledTimerTasks;
057:
058: private boolean daemon = false;
059:
060: private String beanName;
061:
062: private Timer timer;
063:
064: /**
065: * Register a list of ScheduledTimerTask objects with the Timer that
066: * this FactoryBean creates. Depending on each SchedulerTimerTask's
067: * settings, it will be registered via one of Timer's schedule methods.
068: * @see java.util.Timer#schedule(java.util.TimerTask, long)
069: * @see java.util.Timer#schedule(java.util.TimerTask, long, long)
070: * @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long)
071: */
072: public void setScheduledTimerTasks(
073: ScheduledTimerTask[] scheduledTimerTasks) {
074: this .scheduledTimerTasks = scheduledTimerTasks;
075: }
076:
077: /**
078: * Set whether the timer should use a daemon thread,
079: * just executing as long as the application itself is running.
080: * <p>Default is "false": The timer will automatically get cancelled on
081: * destruction of this FactoryBean. Hence, if the application shuts down,
082: * tasks will by default finish their execution. Specify "true" for eager
083: * shutdown of threads that execute tasks.
084: * @see java.util.Timer#Timer(boolean)
085: */
086: public void setDaemon(boolean daemon) {
087: this .daemon = daemon;
088: }
089:
090: public void setBeanName(String beanName) {
091: this .beanName = beanName;
092: }
093:
094: public void afterPropertiesSet() {
095: logger.info("Initializing Timer");
096: this .timer = createTimer(this .beanName, this .daemon);
097:
098: // Register specified ScheduledTimerTasks, if necessary.
099: if (!ObjectUtils.isEmpty(this .scheduledTimerTasks)) {
100: registerTasks(this .scheduledTimerTasks, this .timer);
101: }
102: }
103:
104: /**
105: * Create a new Timer instance. Called by <code>afterPropertiesSet</code>.
106: * Can be overridden in subclasses to provide custom Timer subclasses.
107: * <p>Uses the specified name as Timer thread name on JDK 1.5,
108: * simply falling back to a default Timer thread on JDK 1.4.
109: * @param name the desired name of the Timer's associated thread
110: * (applied on JDK 1.5 and higher; ignored on JDK 1.4)
111: * @param daemon whether to create a Timer that runs as daemon thread
112: * @return a new Timer instance
113: * @see #afterPropertiesSet()
114: * @see java.util.Timer#Timer(boolean)
115: */
116: protected Timer createTimer(String name, boolean daemon) {
117: Timer timer = createTimer(daemon);
118: if (timer != null) {
119: return timer;
120: }
121: if (StringUtils.hasText(name) && JdkVersion.isAtLeastJava15()) {
122: return new Timer(name, daemon);
123: } else {
124: return new Timer(daemon);
125: }
126: }
127:
128: /**
129: * Create a new Timer instance. Called by <code>afterPropertiesSet</code>.
130: * Can be overridden in subclasses to provide custom Timer subclasses.
131: * @deprecated as of Spring 2.0.1, in favor of {@link #createTimer(String, boolean)}
132: */
133: protected Timer createTimer(boolean daemon) {
134: return null;
135: }
136:
137: /**
138: * Register the specified {@link ScheduledTimerTask ScheduledTimerTasks}
139: * on the given {@link Timer}.
140: * @param tasks the specified ScheduledTimerTasks (never empty)
141: * @param timer the Timer to register the tasks on.
142: */
143: protected void registerTasks(ScheduledTimerTask[] tasks, Timer timer) {
144: for (int i = 0; i < tasks.length; i++) {
145: ScheduledTimerTask task = tasks[i];
146: if (task.isOneTimeTask()) {
147: timer.schedule(task.getTimerTask(), task.getDelay());
148: } else {
149: if (task.isFixedRate()) {
150: timer.scheduleAtFixedRate(task.getTimerTask(), task
151: .getDelay(), task.getPeriod());
152: } else {
153: timer.schedule(task.getTimerTask(),
154: task.getDelay(), task.getPeriod());
155: }
156: }
157: }
158: }
159:
160: public Object getObject() {
161: return this .timer;
162: }
163:
164: public Class getObjectType() {
165: return Timer.class;
166: }
167:
168: public boolean isSingleton() {
169: return true;
170: }
171:
172: /**
173: * Cancel the Timer on bean factory shutdown, stopping all scheduled tasks.
174: * @see java.util.Timer#cancel()
175: */
176: public void destroy() {
177: logger.info("Cancelling Timer");
178: this.timer.cancel();
179: }
180:
181: }
|