KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > infoglue > deliver > jobs > JobInitializationPlugin


1 /*
2  * Copyright James House (c) 2001-2004
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met: 1.
8  * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer. 2. Redistributions in
10  * binary form must reproduce the above copyright notice, this list of
11  * conditions and the following disclaimer in the documentation and/or other
12  * materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */

26 package org.infoglue.deliver.jobs;
27
28 import java.io.File JavaDoc;
29 import java.io.FileNotFoundException JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.net.URL JavaDoc;
32 import java.util.Date JavaDoc;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.infoglue.cms.util.CmsPropertyHandler;
37 import org.quartz.JobDetail;
38 import org.quartz.Scheduler;
39 import org.quartz.SchedulerConfigException;
40 import org.quartz.SchedulerException;
41 import org.quartz.SimpleTrigger;
42 import org.quartz.jobs.FileScanJob;
43 import org.quartz.jobs.FileScanListener;
44 import org.quartz.spi.SchedulerPlugin;
45 import org.quartz.xml.JobSchedulingDataProcessor;
46
47 /**
48 * This plugin loads an XML file to add jobs and schedule them with triggers
49  * as the scheduler is initialized, and can optionally periodically scan the
50  * file for changes.
51  *
52  * @author James House
53  * @author Pierre Awaragi
54  */

55 public class JobInitializationPlugin implements SchedulerPlugin, FileScanListener {
56
57     /*
58      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59      *
60      * Data members.
61      *
62      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
63      */

64
65     private String JavaDoc name;
66
67     private Scheduler scheduler;
68
69     private boolean overWriteExistingJobs = false;
70
71     private boolean failOnFileNotFound = true;
72
73     private boolean fileFound = false;
74
75     private String JavaDoc fileName = JobSchedulingDataProcessor.QUARTZ_XML_FILE_NAME;
76     
77     private String JavaDoc filePath = null;
78     
79     private boolean useContextClassLoader = true;
80     
81     private boolean validating = true;
82     
83     private boolean validatingSchema = true;
84
85     private long scanInterval = 0;
86     
87     boolean initializing = true;
88     
89     boolean started = false;
90     
91     /*
92      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93      *
94      * Constructors.
95      *
96      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97      */

98
99     public JobInitializationPlugin() {
100     }
101
102     /*
103      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
104      *
105      * Interface.
106      *
107      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108      */

109
110     /**
111      * The file name (and path) to the XML file that should be read.
112      *
113      * @return
114      */

115     public String JavaDoc getFileName() {
116         return fileName;
117     }
118
119     /**
120      * The file name (and path) to the XML file that should be read.
121      *
122      * @param fileName
123      */

124     public void setFileName(String JavaDoc fileName) {
125         this.fileName = fileName;
126     }
127
128     /**
129      * Whether or not jobs defined in the XML file should be overwrite existing
130      * jobs with the same name.
131      *
132      * @return
133      */

134     public boolean isOverWriteExistingJobs() {
135         return overWriteExistingJobs;
136     }
137
138     /**
139      * Whether or not jobs defined in the XML file should be overwrite existing
140      * jobs with the same name.
141      *
142      * @param overWriteExistingJobs
143      */

144     public void setOverWriteExistingJobs(boolean overWriteExistingJobs) {
145         this.overWriteExistingJobs = overWriteExistingJobs;
146     }
147
148     /**
149      * The interval (in seconds) at which to scan for changes to the file.
150      * If the file has been changed, it is re-loaded and parsed. The default
151      * value for the interval is 0, which disables scanning.
152      *
153      * @return Returns the scanInterval.
154      */

155     public long getScanInterval() {
156         return scanInterval / 1000;
157     }
158
159     /**
160      * The interval (in seconds) at which to scan for changes to the file.
161      * If the file has been changed, it is re-loaded and parsed. The default
162      * value for the interval is 0, which disables scanning.
163      *
164      * @param scanInterval The scanInterval to set.
165      */

166     public void setScanInterval(long scanInterval) {
167         this.scanInterval = scanInterval * 1000;
168     }
169     
170     /**
171      * Whether or not initialization of the plugin should fail (throw an
172      * exception) if the file cannot be found. Default is <code>true</code>.
173      *
174      * @return
175      */

176     public boolean isFailOnFileNotFound() {
177         return failOnFileNotFound;
178     }
179
180     /**
181      * Whether or not initialization of the plugin should fail (throw an
182      * exception) if the file cannot be found. Default is <code>true</code>.
183      *
184      * @param overWriteExistingJobs
185      */

186     public void setFailOnFileNotFound(boolean failOnFileNotFound) {
187         this.failOnFileNotFound = failOnFileNotFound;
188     }
189     
190     /**
191      * Whether or not the context class loader should be used. Default is <code>true</code>.
192      *
193      * @return
194      */

195     public boolean isUseContextClassLoader() {
196         return useContextClassLoader;
197     }
198
199     /**
200      * Whether or not context class loader should be used. Default is <code>true</code>.
201      *
202      * @param useContextClassLoader
203      */

204     public void setUseContextClassLoader(boolean useContextClassLoader) {
205         this.useContextClassLoader = useContextClassLoader;
206     }
207     
208     /**
209      * Whether or not the XML should be validated. Default is <code>true</code>.
210      *
211      * @return
212      */

213     public boolean isValidating() {
214         return validating;
215     }
216
217     /**
218      * Whether or not the XML should be validated. Default is <code>true</code>.
219      *
220      * @param validating
221      */

222     public void setValidating(boolean validating) {
223         this.validating = validating;
224     }
225     
226     /**
227      * Whether or not the XML schema should be validated. Default is <code>true</code>.
228      *
229      * @return
230      */

231     public boolean isValidatingSchema() {
232         return validatingSchema;
233     }
234
235     /**
236      * Whether or not the XML schema should be validated. Default is <code>true</code>.
237      *
238      * @param validatingSchema
239      */

240     public void setValidatingSchema(boolean validatingSchema) {
241         this.validatingSchema = validatingSchema;
242     }
243
244     protected static Log getLog() {
245         return LogFactory.getLog(JobInitializationPlugin.class);
246     }
247
248     /*
249      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
250      *
251      * SchedulerPlugin Interface.
252      *
253      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
254      */

255
256     /**
257      * <p>
258      * Called during creation of the <code>Scheduler</code> in order to give
259      * the <code>SchedulerPlugin</code> a chance to initialize.
260      * </p>
261      *
262      * @throws SchedulerConfigException
263      * if there is an error initializing.
264      */

265     public void initialize(String JavaDoc name, final Scheduler scheduler)
266             throws SchedulerException {
267         
268         initializing = true;
269         try {
270             this.name = name;
271             this.scheduler = scheduler;
272     
273             getLog().info("Registering Quartz Job Initialization Plug-in.");
274             
275             findFile();
276         }
277         finally {
278             initializing = false;
279         }
280     }
281
282     private String JavaDoc getFilePath() throws SchedulerException {
283         if(this.filePath == null) {
284             findFile();
285         }
286         return this.filePath;
287     }
288     
289     /**
290      *
291      */

292     private void findFile() throws SchedulerException {
293         java.io.InputStream JavaDoc f = null;
294         
295         File JavaDoc file = new File JavaDoc(getFileName()); // files in filesystem
296
if (file == null || !file.exists()) {
297             // files in classpath
298
URL JavaDoc url = Thread.currentThread()
299                 .getContextClassLoader()
300                 .getResource(getFileName());
301             if(url != null) {
302                 file = new File JavaDoc(url.getPath());
303             }
304             if(file == null || !file.exists())
305             {
306                 String JavaDoc fileName = CmsPropertyHandler.getContextRootPath() + "WEB-INF" + File.separator + "classes" + File.separator + "jobs.xml";
307                 file = new File JavaDoc(fileName);
308             }
309         }
310         try {
311             f = new java.io.FileInputStream JavaDoc(file);
312         }catch (FileNotFoundException JavaDoc e) {
313             // ignore
314
}
315         
316         if (f == null && isFailOnFileNotFound()) {
317             throw new SchedulerException("File named '" + getFileName()
318                     + "' does not exist.");
319         } else if (f == null) {
320             getLog().warn("File named '" + getFileName() + "' does not exist.");
321         } else {
322             fileFound = true;
323             try {
324                 this.filePath = file.getPath();
325                 f.close();
326             } catch (IOException JavaDoc ioe) {
327                 getLog()
328                         .warn("Error closing file named '" + getFileName(), ioe);
329             }
330         }
331     }
332
333     public void start() {
334
335         if(scanInterval > 0) {
336             try{
337                 SimpleTrigger trig = new SimpleTrigger(
338                         "JobInitializationPlugin_"+name,
339                         "JobInitializationPlugin",
340                         new Date JavaDoc(), null,
341                         SimpleTrigger.REPEAT_INDEFINITELY, scanInterval);
342                 trig.setVolatility(true);
343                 JobDetail job = new JobDetail(
344                         "JobInitializationPlugin_"+name,
345                         "JobInitializationPlugin",
346                         FileScanJob.class);
347                 job.setVolatility(true);
348                 job.getJobDataMap().put(FileScanJob.FILE_NAME, getFilePath());
349                 job.getJobDataMap().put(FileScanJob.FILE_SCAN_LISTENER_NAME, "JobInitializationPlugin_"+name);
350                 
351                 scheduler.getContext().put("JobInitializationPlugin_"+name, this);
352                 scheduler.scheduleJob(job, trig);
353             }
354             catch(SchedulerException se) {
355                 getLog().error("Error starting background-task for watching jobs file.", se);
356             }
357         }
358         
359         try {
360             processFile();
361         }
362         finally {
363             started = true;
364         }
365     }
366
367     /**
368      * <p>
369      * Called in order to inform the <code>SchedulerPlugin</code> that it
370      * should free up all of it's resources because the scheduler is shutting
371      * down.
372      * </p>
373      */

374     public void shutdown() {
375         // nothing to do
376
}
377
378     
379     public void processFile() {
380         if (!fileFound) return;
381
382         JobSchedulingDataProcessor processor =
383             new JobSchedulingDataProcessor(isUseContextClassLoader(), isValidating(), isValidatingSchema());
384
385         try {
386             processor.processFileAndScheduleJobs(fileName, scheduler, true);
387         } catch (Exception JavaDoc e) {
388             getLog().error("Error scheduling jobs: " + e.getMessage(), e);
389         }
390     }
391
392     /**
393      * @see org.quartz.jobs.FileScanListener#fileUpdated(java.lang.String)
394      */

395     public void fileUpdated(String JavaDoc fileName) {
396         if(started)
397             processFile();
398     }
399     
400 }
401
402 // EOF
Popular Tags