001    package org.apache.turbine.services.schedule;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.List;
023    import java.util.Vector;
024    
025    import javax.servlet.ServletConfig;
026    
027    import org.apache.commons.configuration.Configuration;
028    
029    import org.apache.commons.lang.StringUtils;
030    
031    import org.apache.commons.logging.Log;
032    import org.apache.commons.logging.LogFactory;
033    
034    import org.apache.turbine.services.InitializationException;
035    import org.apache.turbine.util.TurbineException;
036    
037    /**
038     * Service for a cron like scheduler that uses the
039     * TurbineResources.properties file instead of the database.
040     * The methods that operate on jobs ( get,add,update,remove )
041     * only operate on the queue in memory and changes are not reflected
042     * to the properties file which was used to initilize the jobs.
043     * An example is given below.  The job names are the class names that
044     * extend ScheduledJob.
045     *
046     * <PRE>
047     *
048     * services.SchedulerService.scheduler.jobs=scheduledJobName,scheduledJobName2
049     *
050     * services.SchedulerService.scheduler.job.scheduledJobName.ID=1
051     * services.SchedulerService.scheduler.job.scheduledJobName.SECOND=-1
052     * services.SchedulerService.scheduler.job.scheduledJobName.MINUTE=-1
053     * services.SchedulerService.scheduler.job.scheduledJobName.HOUR=7
054     * services.SchedulerService.scheduler.job.scheduledJobName.WEEKDAY=-1
055     * services.SchedulerService.scheduler.job.scheduledJobName.DAY_OF_MONTH=-1
056     *
057     * services.SchedulerService.scheduler.job.scheduledJobName2.ID=1
058     * services.SchedulerService.scheduler.job.scheduledJobName2.SECOND=-1
059     * services.SchedulerService.scheduler.job.scheduledJobName2.MINUTE=-1
060     * services.SchedulerService.scheduler.job.scheduledJobName2.HOUR=7
061     * services.SchedulerService.scheduler.job.scheduledJobName2.WEEKDAY=-1
062     * services.SchedulerService.scheduler.job.scheduledJobName2.DAY_OF_MONTH=-1
063     *
064     * </PRE>
065     *
066     * Based on TamboraSchedulerService written by John Thorhauer.
067     *
068     * @author <a href="mailto:ekkerbj@netscpae.net">Jeff Brekke</a>
069     * @author <a href="mailto:john@zenplex.com">John Thorhauer</a>
070     * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
071     * @version $Id: TurbineNonPersistentSchedulerService.java 534527 2007-05-02 16:10:59Z tv $
072     */
073    public class TurbineNonPersistentSchedulerService
074            extends TurbineSchedulerService
075    {
076        /** Logging */
077        private static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME);
078    
079        /**
080         * Constructor.
081         *
082         * @exception TurbineException a generic exception.
083         */
084        public TurbineNonPersistentSchedulerService()
085                throws TurbineException
086        {
087            super();
088        }
089    
090        /**
091         * Called the first time the Service is used.<br>
092         *
093         * Load all the jobs from cold storage.  Add jobs to the queue
094         * (sorted in ascending order by runtime) and start the scheduler
095         * thread.
096         */
097        @SuppressWarnings("unchecked")
098        @Override
099        public void init()
100                throws InitializationException
101        {
102            Configuration conf = getConfiguration();
103    
104            try
105            {
106                scheduleQueue = new JobQueue();
107                mainLoop = new MainLoop();
108    
109                List<String> jobProps = conf.getList("scheduler.jobs");
110                List<JobEntry> jobs = new Vector<JobEntry>();
111                // If there are scheduler.jobs defined then set up a job vector
112                // for the scheduleQueue
113                if (!jobProps.isEmpty())
114                {
115                    for (int i = 0; i < jobProps.size(); i++)
116                    {
117                        String jobName = jobProps.get(i);
118                        String jobPrefix = "scheduler.job." + jobName;
119    
120                        String jobId = conf.getString(jobPrefix + ".ID", null);
121                        if (StringUtils.isEmpty(jobId))
122                        {
123                            throw new Exception(
124                                    "There is an error in the TurbineResources.properties file. \n"
125                                    + jobPrefix + ".ID is not found.\n");
126                        }
127    
128                        int sec = conf.getInt(jobPrefix + ".SECOND", -1);
129                        int min = conf.getInt(jobPrefix + ".MINUTE", -1);
130                        int hr = conf.getInt(jobPrefix + ".HOUR", -1);
131                        int wkday = conf.getInt(jobPrefix + ".WEEKDAY", -1);
132                        int dayOfMonth = conf.getInt(jobPrefix + ".DAY_OF_MONTH", -1);
133    
134                        JobEntry je = new JobEntry(
135                                sec,
136                                min,
137                                hr,
138                                wkday,
139                                dayOfMonth,
140                                jobName);
141                        je.setJobId(Integer.parseInt(jobId));
142                        jobs.add(je);
143    
144                    }
145                }
146    
147                if (jobs != null && jobs.size() > 0)
148                {
149                    scheduleQueue.batchLoad(jobs);
150                }
151    
152                setEnabled(getConfiguration().getBoolean("enabled", true));
153                restart();
154    
155                setInit(true);
156            }
157            catch (Exception e)
158            {
159                String errorMessage = "Could not initialize the scheduler service";
160                log.error(errorMessage, e);
161                throw new InitializationException(errorMessage, e);
162            }
163        }
164    
165        /**
166         * Called the first time the Service is used.<br>
167         *
168         * Load all the jobs from cold storage.  Add jobs to the queue
169         * (sorted in ascending order by runtime) and start the scheduler
170         * thread.
171         *
172         * @param config A ServletConfig.
173         * @deprecated use init() instead.
174         */
175        @Deprecated
176        @Override
177        public void init(ServletConfig config)
178                throws InitializationException
179        {
180            init();
181        }
182    
183        /**
184         * This method returns the job element from the internal queue.
185         *
186         * @param oid The int id for the job.
187         * @return A JobEntry.
188         * @exception TurbineException could not retrieve job
189         */
190        @Override
191        public JobEntry getJob(int oid)
192                throws TurbineException
193        {
194            JobEntry je = new JobEntry();
195            je.setJobId(oid);
196            return scheduleQueue.getJob(je);
197        }
198    
199        /**
200         * Add a new job to the queue.
201         *
202         * @param je A JobEntry with the job to add.
203         * @throws TurbineException job could not be added
204         */
205        @Override
206        public void addJob(JobEntry je)
207                throws TurbineException
208        {
209            updateJob(je);
210        }
211    
212        /**
213         * Remove a job from the queue.
214         *
215         * @param je A JobEntry with the job to remove.
216         */
217        @Override
218        public void removeJob(JobEntry je)
219        {
220            // Remove from the queue.
221            scheduleQueue.remove(je);
222            restart();
223        }
224    
225        /**
226         * Add/update a job
227         *
228         * @param je A JobEntry with the job to modify
229         * @throws TurbineException job could not be updated
230         */
231        @Override
232        public void updateJob(JobEntry je)
233                throws TurbineException
234        {
235            try
236            {
237                je.calcRunTime();
238    
239                // Update the queue.
240                scheduleQueue.modify(je);
241                restart();
242            }
243            catch (Exception e)
244            {
245                String errorMessage = "Problem updating Scheduled Job: " + je.getTask();
246                log.error(errorMessage, e);
247                throw new TurbineException(errorMessage, e);
248            }
249        }
250    }