001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.components.varscheduler;
018    
019    import java.util.Date;
020    import java.util.Timer;
021    import java.util.TimerTask;
022    
023    /**
024     * Class to handle scheduling tasks.
025     * <p>
026     * This class is thread-safe
027     * <p>
028     * 
029     * @author George Gastaldi (gastaldi)
030     */
031    public class Scheduler {
032    
033        private Timer timer;
034    
035        /**
036         * Creates a new Scheduler.
037         */
038        public Scheduler() {
039            this.timer = new Timer();
040        }
041    
042        /**
043         * Creates a new Daemon Scheduler
044         * 
045         * @param daemon
046         *            Thread must be executed as "daemon".
047         */
048        public Scheduler(boolean daemon) {
049            this.timer = new Timer(daemon);
050        }
051    
052        /**
053         * Cancels the scheduler task
054         */
055        public void cancel() {
056            timer.cancel();
057        }
058    
059        /**
060         * Schedules a task
061         * 
062         * @param task
063         *            scheduled tasl
064         * @param iterator
065         *            iterator for schedulingque descreve o agendamento
066         * @throws IllegalStateException
067         *             if task scheduled or canceled
068         */
069        public void schedule(SchedulerTask task, ScheduleIterator iterator) {
070            Date time = iterator.nextExecution();
071            if (time == null) {
072                task.cancel();
073            } else {
074                synchronized (task.lock) {
075                    if (task.state != SchedulerTask.VIRGIN) {
076                        throw new IllegalStateException("Task already scheduled or cancelled");
077                    }
078                    task.state = SchedulerTask.SCHEDULED;
079                    task.timerTask = new SchedulerTimerTask(task, iterator);
080                    timer.schedule(task.timerTask, time);
081                }
082            }
083        }
084    
085        private void reschedule(SchedulerTask task, ScheduleIterator iterator) {
086            Date time = iterator.nextExecution();
087            if (time == null) {
088                task.cancel();
089            } else {
090                synchronized (task.lock) {
091                    if (task.state != SchedulerTask.CANCELLED) {
092                        task.timerTask = new SchedulerTimerTask(task, iterator);
093                        timer.schedule(task.timerTask, time);
094                    }
095                }
096            }
097        }
098    
099        /**
100         * Internal TimerTask instance
101         */
102        class SchedulerTimerTask extends TimerTask {
103            private SchedulerTask task;
104    
105            private ScheduleIterator iterator;
106    
107            public SchedulerTimerTask(SchedulerTask task, ScheduleIterator iterator) {
108                this.task = task;
109                this.iterator = iterator;
110            }
111    
112            public void run() {
113                task.run();
114                reschedule(task, iterator);
115            }
116        }
117    
118    }