001 /**
002 * Jetrix TetriNET Server
003 * Copyright (C) 2001-2004 Emmanuel Bourg
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License
007 * as published by the Free Software Foundation; either version 2
008 * of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018 */
019
020 package net.jetrix.services;
021
022 import java.util.Calendar;
023 import java.util.Date;
024 import java.util.Timer;
025 import java.util.TimerTask;
026 import java.util.logging.Level;
027
028 import org.jcrontab.data.CalendarBuilder;
029 import org.jcrontab.data.CrontabEntryBean;
030 import org.jcrontab.data.CrontabEntryException;
031 import org.jcrontab.data.CrontabParser;
032
033 /**
034 * A service running a task at a fixed date. Services extending this service
035 * expect a <tt>pattern</tt> parameter setting the execution time, this pattern
036 * uses the cron format of Unix systems extended with a 6th field for the year
037 * (see http://www.nncron.ru/nncronlt/help/EN/working/cron-format.htm).
038 *
039 * @author Emmanuel Bourg
040 * @version $Revision: 794 $, $Date: 2009-02-17 20:08:39 +0100 (Tue, 17 Feb 2009) $
041 * @since 0.2
042 */
043 public abstract class CronService extends AbstractService
044 {
045 protected String pattern;
046 private Timer timer;
047 private CrontabEntryBean cron;
048
049 public void setPattern(String pattern)
050 {
051 this.pattern = pattern;
052 }
053
054 /**
055 * Initialization performed before the timer is started.
056 */
057 protected void init() { }
058
059 public void start()
060 {
061 if (!isRunning())
062 {
063 init();
064
065 // parse the cron pattern
066 CrontabParser parser = new CrontabParser();
067 try
068 {
069 cron = parser.marshall(pattern);
070 cron.setBSeconds(new boolean[60]);
071 }
072 catch (CrontabEntryException e)
073 {
074 log.log(Level.SEVERE, "Unable to start the service", e);
075 return;
076 }
077
078 // start the timer
079 timer = new Timer();
080 scheduleNext();
081 }
082 }
083
084 public synchronized void stop()
085 {
086 // stop the timer
087 if (isRunning())
088 {
089 timer.cancel();
090 timer = null;
091 }
092 }
093
094 public boolean isRunning()
095 {
096 return timer != null;
097 }
098
099 /**
100 * Do the task
101 */
102 protected abstract void run();
103
104 /**
105 * Schedule the next execution of the task.
106 */
107 private synchronized void scheduleNext()
108 {
109 if (timer != null)
110 {
111 timer.cancel();
112 }
113 else
114 {
115 return;
116 }
117
118 TimerTask task = new TimerTask()
119 {
120 public void run()
121 {
122 CronService.this.run();
123 scheduleNext();
124 }
125 };
126
127 timer = new Timer();
128 timer.schedule(task, getNextExecutionDate());
129 }
130
131 /**
132 * Return the next time the task has to be executed.
133 */
134 private Date getNextExecutionDate()
135 {
136 Calendar calendar = Calendar.getInstance();
137 calendar.add(Calendar.SECOND, 1);
138 Date date = new CalendarBuilder().buildCalendar(cron, calendar.getTime());
139
140 log.fine("Next execution of '" + getName() + "' on " + date);
141
142 return date;
143 }
144 }