Source Code Cross Referenced for JobInitializationPlugin.java in  » Project-Management » quartz » org » quartz » plugins » xml » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Project Management » quartz » org.quartz.plugins.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* 
002:         * Copyright 2004-2005 OpenSymphony 
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
005:         * use this file except in compliance with the License. You may obtain a copy 
006:         * 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, WITHOUT 
012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
013:         * License for the specific language governing permissions and limitations 
014:         * under the License.
015:         * 
016:         */
017:
018:        /*
019:         * Previously Copyright (c) 2001-2004 James House
020:         */
021:        package org.quartz.plugins.xml;
022:
023:        import java.io.File;
024:        import java.io.FileNotFoundException;
025:        import java.io.IOException;
026:        import java.io.InputStream;
027:        import java.net.URL;
028:        import java.net.URLDecoder;
029:        import java.util.Date;
030:        import java.util.HashMap;
031:        import java.util.HashSet;
032:        import java.util.Iterator;
033:        import java.util.Map;
034:        import java.util.Set;
035:        import java.util.StringTokenizer;
036:
037:        import javax.transaction.UserTransaction;
038:
039:        import org.quartz.JobDetail;
040:        import org.quartz.Scheduler;
041:        import org.quartz.SchedulerException;
042:        import org.quartz.SimpleTrigger;
043:        import org.quartz.jobs.FileScanJob;
044:        import org.quartz.jobs.FileScanListener;
045:        import org.quartz.plugins.SchedulerPluginWithUserTransactionSupport;
046:        import org.quartz.simpl.CascadingClassLoadHelper;
047:        import org.quartz.spi.ClassLoadHelper;
048:        import org.quartz.xml.JobSchedulingDataProcessor;
049:
050:        /**
051:         * This plugin loads XML file(s) to add jobs and schedule them with triggers
052:         * as the scheduler is initialized, and can optionally periodically scan the
053:         * file for changes.
054:         * 
055:         * <p>
056:         * The periodically scanning of files for changes is not currently supported in a 
057:         * clustered environment.
058:         * </p>
059:         * 
060:         * <p>
061:         * If using the JobInitializationPlugin with JobStoreCMT, be sure to set the
062:         * plugin property <em>wrapInUserTransaction</em> to true.  Also, if have a 
063:         * positive <em>scanInterval</em> be sure to set 
064:         * <em>org.quartz.scheduler.wrapJobExecutionInUserTransaction</em> to true.
065:         * </p>
066:         * 
067:         * @author James House
068:         * @author Pierre Awaragi
069:         */
070:        public class JobInitializationPlugin extends
071:                SchedulerPluginWithUserTransactionSupport implements 
072:                FileScanListener {
073:
074:            /*
075:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
076:             * 
077:             * Data members.
078:             * 
079:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
080:             */
081:            private static final int MAX_JOB_TRIGGER_NAME_LEN = 80;
082:            private static final String JOB_INITIALIZATION_PLUGIN_NAME = "JobInitializationPlugin";
083:            private static final String FILE_NAME_DELIMITERS = ",";
084:
085:            private boolean overWriteExistingJobs = false;
086:
087:            private boolean failOnFileNotFound = true;
088:
089:            private String fileNames = JobSchedulingDataProcessor.QUARTZ_XML_FILE_NAME;
090:
091:            // Populated by initialization
092:            private Map jobFiles = new HashMap();
093:
094:            private boolean useContextClassLoader = true;
095:
096:            private boolean validating = false;
097:
098:            private boolean validatingSchema = true;
099:
100:            private long scanInterval = 0;
101:
102:            boolean started = false;
103:
104:            protected ClassLoadHelper classLoadHelper = null;
105:
106:            private Set jobTriggerNameSet = new HashSet();
107:
108:            /*
109:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110:             * 
111:             * Constructors.
112:             * 
113:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114:             */
115:
116:            public JobInitializationPlugin() {
117:            }
118:
119:            /*
120:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121:             * 
122:             * Interface.
123:             * 
124:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125:             */
126:
127:            /**
128:             * The file name (and path) to the XML file that should be read.
129:             * @deprecated Use fileNames with just one file.
130:             */
131:            public String getFileName() {
132:                return fileNames;
133:            }
134:
135:            /**
136:             * The file name (and path) to the XML file that should be read.
137:             * @deprecated Use fileNames with just one file.
138:             */
139:            public void setFileName(String fileName) {
140:                getLog()
141:                        .warn(
142:                                "The \"filename\" plugin property is deprecated.  Please use \"filenames\" in the future.");
143:                this .fileNames = fileName;
144:            }
145:
146:            /**
147:             * Comma separated list of file names (with paths) to the XML files that should be read.
148:             */
149:            public String getFileNames() {
150:                return fileNames;
151:            }
152:
153:            /**
154:             * The file name (and path) to the XML file that should be read.
155:             */
156:            public void setFileNames(String fileNames) {
157:                this .fileNames = fileNames;
158:            }
159:
160:            /**
161:             * Whether or not jobs defined in the XML file should be overwrite existing
162:             * jobs with the same name.
163:             */
164:            public boolean isOverWriteExistingJobs() {
165:                return overWriteExistingJobs;
166:            }
167:
168:            /**
169:             * Whether or not jobs defined in the XML file should be overwrite existing
170:             * jobs with the same name.
171:             * 
172:             * @param overWriteExistingJobs
173:             */
174:            public void setOverWriteExistingJobs(boolean overWriteExistingJobs) {
175:                this .overWriteExistingJobs = overWriteExistingJobs;
176:            }
177:
178:            /**
179:             * The interval (in seconds) at which to scan for changes to the file.  
180:             * If the file has been changed, it is re-loaded and parsed.   The default 
181:             * value for the interval is 0, which disables scanning.
182:             * 
183:             * @return Returns the scanInterval.
184:             */
185:            public long getScanInterval() {
186:                return scanInterval / 1000;
187:            }
188:
189:            /**
190:             * The interval (in seconds) at which to scan for changes to the file.  
191:             * If the file has been changed, it is re-loaded and parsed.   The default 
192:             * value for the interval is 0, which disables scanning.
193:             * 
194:             * @param scanInterval The scanInterval to set.
195:             */
196:            public void setScanInterval(long scanInterval) {
197:                this .scanInterval = scanInterval * 1000;
198:            }
199:
200:            /**
201:             * Whether or not initialization of the plugin should fail (throw an
202:             * exception) if the file cannot be found. Default is <code>true</code>.
203:             */
204:            public boolean isFailOnFileNotFound() {
205:                return failOnFileNotFound;
206:            }
207:
208:            /**
209:             * Whether or not initialization of the plugin should fail (throw an
210:             * exception) if the file cannot be found. Default is <code>true</code>.
211:             */
212:            public void setFailOnFileNotFound(boolean failOnFileNotFound) {
213:                this .failOnFileNotFound = failOnFileNotFound;
214:            }
215:
216:            /**
217:             * Whether or not the context class loader should be used. Default is <code>true</code>.
218:             */
219:            public boolean isUseContextClassLoader() {
220:                return useContextClassLoader;
221:            }
222:
223:            /**
224:             * Whether or not context class loader should be used. Default is <code>true</code>.
225:             */
226:            public void setUseContextClassLoader(boolean useContextClassLoader) {
227:                this .useContextClassLoader = useContextClassLoader;
228:            }
229:
230:            /**
231:             * Whether or not the XML should be validated. Default is <code>false</code>.
232:             */
233:            public boolean isValidating() {
234:                return validating;
235:            }
236:
237:            /**
238:             * Whether or not the XML should be validated. Default is <code>false</code>.
239:             */
240:            public void setValidating(boolean validating) {
241:                this .validating = validating;
242:            }
243:
244:            /**
245:             * Whether or not the XML schema should be validated. Default is <code>true</code>.
246:             */
247:            public boolean isValidatingSchema() {
248:                return validatingSchema;
249:            }
250:
251:            /**
252:             * Whether or not the XML schema should be validated. Default is <code>true</code>.
253:             */
254:            public void setValidatingSchema(boolean validatingSchema) {
255:                this .validatingSchema = validatingSchema;
256:            }
257:
258:            /*
259:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
260:             * 
261:             * SchedulerPlugin Interface.
262:             * 
263:             * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
264:             */
265:
266:            /**
267:             * <p>
268:             * Called during creation of the <code>Scheduler</code> in order to give
269:             * the <code>SchedulerPlugin</code> a chance to initialize.
270:             * </p>
271:             * 
272:             * @throws org.quartz.SchedulerConfigException
273:             *           if there is an error initializing.
274:             */
275:            public void initialize(String name, final Scheduler scheduler)
276:                    throws SchedulerException {
277:                super .initialize(name, scheduler);
278:
279:                classLoadHelper = new CascadingClassLoadHelper();
280:                classLoadHelper.initialize();
281:
282:                getLog().info("Registering Quartz Job Initialization Plug-in.");
283:
284:                // Create JobFile objects
285:                StringTokenizer stok = new StringTokenizer(fileNames,
286:                        FILE_NAME_DELIMITERS);
287:                while (stok.hasMoreTokens()) {
288:                    JobFile jobFile = new JobFile(stok.nextToken());
289:                    jobFiles.put(jobFile.getFilePath(), jobFile);
290:                }
291:            }
292:
293:            public void start(UserTransaction userTransaction) {
294:                try {
295:                    if (jobFiles.isEmpty() == false) {
296:
297:                        if (scanInterval > 0) {
298:                            getScheduler().getContext().put(
299:                                    JOB_INITIALIZATION_PLUGIN_NAME + '_'
300:                                            + getName(), this );
301:                        }
302:
303:                        Iterator iterator = jobFiles.values().iterator();
304:                        while (iterator.hasNext()) {
305:                            JobFile jobFile = (JobFile) iterator.next();
306:
307:                            if (scanInterval > 0) {
308:                                String jobTriggerName = buildJobTriggerName(jobFile
309:                                        .getFileBasename());
310:
311:                                SimpleTrigger trig = new SimpleTrigger(
312:                                        jobTriggerName,
313:                                        JOB_INITIALIZATION_PLUGIN_NAME,
314:                                        new Date(), null,
315:                                        SimpleTrigger.REPEAT_INDEFINITELY,
316:                                        scanInterval);
317:                                trig.setVolatility(true);
318:
319:                                JobDetail job = new JobDetail(jobTriggerName,
320:                                        JOB_INITIALIZATION_PLUGIN_NAME,
321:                                        FileScanJob.class);
322:                                job.setVolatility(true);
323:                                job.getJobDataMap().put(FileScanJob.FILE_NAME,
324:                                        jobFile.getFilePath());
325:                                job.getJobDataMap().put(
326:                                        FileScanJob.FILE_SCAN_LISTENER_NAME,
327:                                        JOB_INITIALIZATION_PLUGIN_NAME + '_'
328:                                                + getName());
329:
330:                                getScheduler().scheduleJob(job, trig);
331:                            }
332:
333:                            processFile(jobFile);
334:                        }
335:                    }
336:                } catch (SchedulerException se) {
337:                    getLog()
338:                            .error(
339:                                    "Error starting background-task for watching jobs file.",
340:                                    se);
341:                } finally {
342:                    started = true;
343:                }
344:            }
345:
346:            /**
347:             * Helper method for generating unique job/trigger name for the  
348:             * file scanning jobs (one per FileJob).  The unique names are saved
349:             * in jobTriggerNameSet.
350:             */
351:            private String buildJobTriggerName(String fileBasename) {
352:                // Name w/o collisions will be prefix + _ + filename (with '.' of filename replaced with '_')
353:                // For example: JobInitializationPlugin_jobInitializer_myjobs_xml
354:                String jobTriggerName = JOB_INITIALIZATION_PLUGIN_NAME + '_'
355:                        + getName() + '_' + fileBasename.replace('.', '_');
356:
357:                // If name is too long (DB column is 80 chars), then truncate to max length
358:                if (jobTriggerName.length() > MAX_JOB_TRIGGER_NAME_LEN) {
359:                    jobTriggerName = jobTriggerName.substring(0,
360:                            MAX_JOB_TRIGGER_NAME_LEN);
361:                }
362:
363:                // Make sure this name is unique in case the same file name under different
364:                // directories is being checked, or had a naming collision due to length truncation.
365:                // If there is a conflict, keep incrementing a _# suffix on the name (being sure
366:                // not to get too long), until we find a unique name.
367:                int currentIndex = 1;
368:                while (jobTriggerNameSet.add(jobTriggerName) == false) {
369:                    // If not our first time through, then strip off old numeric suffix
370:                    if (currentIndex > 1) {
371:                        jobTriggerName = jobTriggerName.substring(0,
372:                                jobTriggerName.lastIndexOf('_'));
373:                    }
374:
375:                    String numericSuffix = "_" + currentIndex++;
376:
377:                    // If the numeric suffix would make the name too long, then make room for it.
378:                    if (jobTriggerName.length() > (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix
379:                            .length())) {
380:                        jobTriggerName = jobTriggerName.substring(0,
381:                                (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix
382:                                        .length()));
383:                    }
384:
385:                    jobTriggerName += numericSuffix;
386:                }
387:
388:                return jobTriggerName;
389:            }
390:
391:            /**
392:             * Overriden to ignore <em>wrapInUserTransaction</em> because shutdown()
393:             * does not interact with the <code>Scheduler</code>. 
394:             */
395:            public void shutdown() {
396:                // Since we have nothing to do, override base shutdown so don't
397:                // get extranious UserTransactions.
398:            }
399:
400:            private void processFile(JobFile jobFile) {
401:                if ((jobFile == null) || (jobFile.getFileFound() == false)) {
402:                    return;
403:                }
404:
405:                JobSchedulingDataProcessor processor = new JobSchedulingDataProcessor(
406:                        isUseContextClassLoader(), isValidating(),
407:                        isValidatingSchema());
408:
409:                try {
410:                    processor.processFileAndScheduleJobs(jobFile.getFilePath(),
411:                            jobFile.getFilePath(), // systemId 
412:                            getScheduler(), isOverWriteExistingJobs());
413:                } catch (Exception e) {
414:                    getLog().error("Error scheduling jobs: " + e.getMessage(),
415:                            e);
416:                }
417:            }
418:
419:            public void processFile(String filePath) {
420:                processFile((JobFile) jobFiles.get(filePath));
421:            }
422:
423:            /** 
424:             * @see org.quartz.jobs.FileScanListener#fileUpdated(java.lang.String)
425:             */
426:            public void fileUpdated(String fileName) {
427:                if (started) {
428:                    processFile(fileName);
429:                }
430:            }
431:
432:            class JobFile {
433:                private String fileName;
434:
435:                // These are set by initialize()
436:                private String filePath;
437:                private String fileBasename;
438:                private boolean fileFound;
439:
440:                protected JobFile(String fileName) throws SchedulerException {
441:                    this .fileName = fileName;
442:                    initialize();
443:                }
444:
445:                protected String getFileName() {
446:                    return fileName;
447:                }
448:
449:                protected boolean getFileFound() {
450:                    return fileFound;
451:                }
452:
453:                protected String getFilePath() {
454:                    return filePath;
455:                }
456:
457:                protected String getFileBasename() {
458:                    return fileBasename;
459:                }
460:
461:                private void initialize() throws SchedulerException {
462:                    InputStream f = null;
463:                    try {
464:                        String furl = null;
465:
466:                        File file = new File(getFileName()); // files in filesystem
467:                        if (!file.exists()) {
468:                            URL url = classLoadHelper
469:                                    .getResource(getFileName());
470:                            if (url != null) {
471:                                //     we need jdk 1.3 compatibility, so we abandon this code...
472:                                //                    try {
473:                                //                        furl = URLDecoder.decode(url.getPath(), "UTF-8");
474:                                //                    } catch (UnsupportedEncodingException e) {
475:                                //                        furl = url.getPath();
476:                                //                    }
477:                                furl = URLDecoder.decode(url.getPath());
478:                                file = new File(furl);
479:                                try {
480:                                    f = url.openStream();
481:                                } catch (IOException ignor) {
482:                                    // Swallow the exception
483:                                }
484:                            }
485:                        } else {
486:                            try {
487:                                f = new java.io.FileInputStream(file);
488:                            } catch (FileNotFoundException e) {
489:                                // ignore
490:                            }
491:                        }
492:
493:                        if (f == null) {
494:                            if (isFailOnFileNotFound()) {
495:                                throw new SchedulerException("File named '"
496:                                        + getFileName() + "' does not exist.");
497:                            } else {
498:                                getLog().warn(
499:                                        "File named '" + getFileName()
500:                                                + "' does not exist.");
501:                            }
502:                        } else {
503:                            fileFound = true;
504:                            filePath = (furl != null) ? furl : file
505:                                    .getAbsolutePath();
506:                            fileBasename = file.getName();
507:                        }
508:                    } finally {
509:                        try {
510:                            if (f != null) {
511:                                f.close();
512:                            }
513:                        } catch (IOException ioe) {
514:                            getLog().warn(
515:                                    "Error closing jobs file " + getFileName(),
516:                                    ioe);
517:                        }
518:                    }
519:                }
520:            }
521:        }
522:
523:        // EOF
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.