001
014
015 package com.liferay.portal.scheduler.quartz;
016
017 import com.liferay.portal.kernel.bean.BeanReference;
018 import com.liferay.portal.kernel.dao.db.DB;
019 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020 import com.liferay.portal.kernel.json.JSONFactoryUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.messaging.Message;
024 import com.liferay.portal.kernel.scheduler.IntervalTrigger;
025 import com.liferay.portal.kernel.scheduler.JobState;
026 import com.liferay.portal.kernel.scheduler.JobStateSerializeUtil;
027 import com.liferay.portal.kernel.scheduler.SchedulerEngine;
028 import com.liferay.portal.kernel.scheduler.SchedulerException;
029 import com.liferay.portal.kernel.scheduler.StorageType;
030 import com.liferay.portal.kernel.scheduler.TriggerFactoryUtil;
031 import com.liferay.portal.kernel.scheduler.TriggerState;
032 import com.liferay.portal.kernel.scheduler.TriggerType;
033 import com.liferay.portal.kernel.scheduler.messaging.SchedulerResponse;
034 import com.liferay.portal.kernel.util.CharPool;
035 import com.liferay.portal.kernel.util.ServerDetector;
036 import com.liferay.portal.kernel.util.StringPool;
037 import com.liferay.portal.kernel.util.Time;
038 import com.liferay.portal.scheduler.job.MessageSenderJob;
039 import com.liferay.portal.service.QuartzLocalService;
040 import com.liferay.portal.util.PropsUtil;
041 import com.liferay.portal.util.PropsValues;
042
043 import java.text.ParseException;
044
045 import java.util.ArrayList;
046 import java.util.Date;
047 import java.util.List;
048 import java.util.Map;
049 import java.util.Properties;
050
051 import org.quartz.CronTrigger;
052 import org.quartz.JobDataMap;
053 import org.quartz.JobDetail;
054 import org.quartz.ObjectAlreadyExistsException;
055 import org.quartz.Scheduler;
056 import org.quartz.SimpleTrigger;
057 import org.quartz.Trigger;
058 import org.quartz.impl.StdSchedulerFactory;
059
060
067 public class QuartzSchedulerEngine implements SchedulerEngine {
068
069 public void afterPropertiesSet() {
070 if (!PropsValues.SCHEDULER_ENABLED) {
071 return;
072 }
073
074 try {
075 quartzLocalService.checkQuartzTables();
076
077 _persistedScheduler = initializeScheduler(
078 "persisted.scheduler.", true);
079
080 _memoryScheduler = initializeScheduler("memory.scheduler.", false);
081 }
082 catch (Exception e) {
083 _log.error("Unable to initialize engine", e);
084 }
085 }
086
087 public void delete(String groupName) throws SchedulerException {
088 if (!PropsValues.SCHEDULER_ENABLED) {
089 return;
090 }
091
092 try {
093 Scheduler scheduler = getScheduler(groupName);
094
095 delete(scheduler, groupName);
096 }
097 catch (Exception e) {
098 throw new SchedulerException(
099 "Unable to delete jobs in group " + groupName, e);
100 }
101 }
102
103 public void delete(String jobName, String groupName)
104 throws SchedulerException {
105
106 if (!PropsValues.SCHEDULER_ENABLED) {
107 return;
108 }
109
110 try {
111 Scheduler scheduler = getScheduler(groupName);
112
113 delete(scheduler, jobName, groupName);
114 }
115 catch (Exception e) {
116 throw new SchedulerException(
117 "Unable to delete job {jobName=" + jobName + ", groupName=" +
118 groupName + "}",
119 e);
120 }
121 }
122
123 public void destroy() {
124 try {
125 shutdown();
126 }
127 catch (SchedulerException se) {
128 if (_log.isWarnEnabled()) {
129 _log.warn("Unable to shutdown", se);
130 }
131 }
132 }
133
134 public SchedulerResponse getScheduledJob(String jobName, String groupName)
135 throws SchedulerException {
136
137 if (!PropsValues.SCHEDULER_ENABLED) {
138 return null;
139 }
140
141 try {
142 Scheduler scheduler = getScheduler(groupName);
143
144 return getScheduledJob(scheduler, jobName, groupName);
145 }
146 catch (Exception e) {
147 throw new SchedulerException(
148 "Unable to get job {jobName=" + jobName + ", groupName=" +
149 groupName + "}",
150 e);
151 }
152 }
153
154 public List<SchedulerResponse> getScheduledJobs()
155 throws SchedulerException {
156
157 if (!PropsValues.SCHEDULER_ENABLED) {
158 return null;
159 }
160
161 try {
162 String[] groupNames = _persistedScheduler.getJobGroupNames();
163
164 List<SchedulerResponse> schedulerResponses =
165 new ArrayList<SchedulerResponse>();
166
167 for (String groupName : groupNames) {
168 schedulerResponses.addAll(
169 getScheduledJobs(_persistedScheduler, groupName));
170 }
171
172 groupNames = _memoryScheduler.getJobGroupNames();
173
174 for (String groupName : groupNames) {
175 schedulerResponses.addAll(
176 getScheduledJobs(_memoryScheduler, groupName));
177 }
178
179 return schedulerResponses;
180 }
181 catch (Exception e) {
182 throw new SchedulerException("Unable to get jobs", e);
183 }
184 }
185
186 public List<SchedulerResponse> getScheduledJobs(String groupName)
187 throws SchedulerException {
188
189 if (!PropsValues.SCHEDULER_ENABLED) {
190 return null;
191 }
192
193 try {
194 Scheduler scheduler = getScheduler(groupName);
195
196 return getScheduledJobs(scheduler, groupName);
197 }
198 catch (Exception e) {
199 throw new SchedulerException(
200 "Unable to get jobs in group " + groupName, e);
201 }
202 }
203
204 public void pause(String groupName) throws SchedulerException {
205 if (!PropsValues.SCHEDULER_ENABLED) {
206 return;
207 }
208
209 try {
210 Scheduler scheduler = getScheduler(groupName);
211
212 pause(scheduler, groupName);
213 }
214 catch (Exception e) {
215 throw new SchedulerException(
216 "Unable to pause jobs in group " + groupName, e);
217 }
218 }
219
220 public void pause(String jobName, String groupName)
221 throws SchedulerException {
222
223 if (!PropsValues.SCHEDULER_ENABLED) {
224 return;
225 }
226
227 try {
228 Scheduler scheduler = getScheduler(groupName);
229
230 pause(scheduler, jobName, groupName);
231 }
232 catch (Exception e) {
233 throw new SchedulerException(
234 "Unable to pause job {jobName=" + jobName + ", groupName=" +
235 groupName + "}",
236 e);
237 }
238 }
239
240 public void resume(String groupName) throws SchedulerException {
241 if (!PropsValues.SCHEDULER_ENABLED) {
242 return;
243 }
244
245 try {
246 Scheduler scheduler = getScheduler(groupName);
247
248 resume(scheduler, groupName);
249 }
250 catch (Exception e) {
251 throw new SchedulerException(
252 "Unable to resume jobs in group " + groupName, e);
253 }
254 }
255
256 public void resume(String jobName, String groupName)
257 throws SchedulerException {
258
259 if (!PropsValues.SCHEDULER_ENABLED) {
260 return;
261 }
262
263 try {
264 Scheduler scheduler = getScheduler(groupName);
265
266 resume(scheduler, jobName, groupName);
267 }
268 catch (Exception e) {
269 throw new SchedulerException(
270 "Unable to resume job {jobName=" + jobName + ", groupName=" +
271 groupName + "}",
272 e);
273 }
274 }
275
276 public void schedule(
277 com.liferay.portal.kernel.scheduler.Trigger trigger,
278 String description, String destination, Message message)
279 throws SchedulerException {
280
281 if (!PropsValues.SCHEDULER_ENABLED) {
282 return;
283 }
284
285 try {
286 Scheduler scheduler = getScheduler(trigger.getGroupName());
287
288 StorageType storageType = getStorageType(trigger.getGroupName());
289
290 trigger = TriggerFactoryUtil.buildTrigger(
291 trigger.getTriggerType(), trigger.getJobName(),
292 getOriginalGroupName(trigger.getGroupName()),
293 trigger.getStartDate(), trigger.getEndDate(),
294 trigger.getTriggerContent());
295
296 Trigger quartzTrigger = getQuartzTrigger(trigger);
297
298 if (quartzTrigger == null) {
299 return;
300 }
301
302 description = fixMaxLength(description, DESCRIPTION_MAX_LENGTH);
303
304 if (message == null) {
305 message = new Message();
306 }
307 else {
308 message = message.clone();
309 }
310
311 message.put(RECEIVER_KEY, quartzTrigger.getFullJobName());
312
313 schedule(
314 scheduler, storageType, quartzTrigger, description, destination,
315 message);
316 }
317 catch (RuntimeException re) {
318
319
320
321
322 }
323 catch (Exception e) {
324 throw new SchedulerException("Unable to schedule job", e);
325 }
326 }
327
328 public void shutdown() throws SchedulerException {
329 if (!PropsValues.SCHEDULER_ENABLED) {
330 return;
331 }
332
333 try {
334 if (!_persistedScheduler.isShutdown()) {
335 _persistedScheduler.shutdown(false);
336 }
337
338 if (!_memoryScheduler.isShutdown()) {
339 _memoryScheduler.shutdown(false);
340 }
341 }
342 catch (Exception e) {
343 throw new SchedulerException("Unable to shutdown scheduler", e);
344 }
345 }
346
347 public void start() throws SchedulerException {
348 if (!PropsValues.SCHEDULER_ENABLED) {
349 return;
350 }
351
352 try {
353 _persistedScheduler.start();
354
355 initJobState();
356
357 _memoryScheduler.start();
358 }
359 catch (Exception e) {
360 throw new SchedulerException("Unable to start scheduler", e);
361 }
362 }
363
364 public void suppressError(String jobName, String groupName)
365 throws SchedulerException {
366
367 if (!PropsValues.SCHEDULER_ENABLED) {
368 return;
369 }
370
371 try {
372 Scheduler scheduler = getScheduler(groupName);
373
374 suppressError(jobName, groupName, scheduler);
375 }
376 catch (Exception e) {
377 throw new SchedulerException(
378 "Unable to suppress error for job {jobName=" + jobName +
379 ", groupName=" + groupName + "}",
380 e);
381 }
382 }
383
384 public void unschedule(String groupName) throws SchedulerException {
385 if (!PropsValues.SCHEDULER_ENABLED) {
386 return;
387 }
388
389 try {
390 Scheduler scheduler = getScheduler(groupName);
391
392 unschedule(groupName, scheduler);
393 }
394 catch (Exception e) {
395 throw new SchedulerException(
396 "Unable to unschedule jobs in group " + groupName, e);
397 }
398 }
399
400 public void unschedule(String jobName, String groupName)
401 throws SchedulerException {
402
403 if (!PropsValues.SCHEDULER_ENABLED) {
404 return;
405 }
406
407 try {
408 Scheduler scheduler = getScheduler(groupName);
409
410 unschedule(jobName, groupName, scheduler);
411 }
412 catch (Exception e) {
413 throw new SchedulerException(
414 "Unable to unschedule job {jobName=" + jobName +
415 ", groupName=" + groupName + "}",
416 e);
417 }
418 }
419
420 public void update(com.liferay.portal.kernel.scheduler.Trigger trigger)
421 throws SchedulerException {
422
423 if (!PropsValues.SCHEDULER_ENABLED) {
424 return;
425 }
426
427 try {
428 Scheduler scheduler = getScheduler(trigger.getGroupName());
429
430 trigger = TriggerFactoryUtil.buildTrigger(
431 trigger.getTriggerType(), trigger.getJobName(),
432 getOriginalGroupName(trigger.getGroupName()),
433 trigger.getStartDate(), trigger.getEndDate(),
434 trigger.getTriggerContent());
435
436 update(scheduler, trigger);
437 }
438 catch (Exception e) {
439 throw new SchedulerException("Unable to update trigger", e);
440 }
441 }
442
443 protected void delete(Scheduler scheduler, String groupName)
444 throws Exception {
445
446 groupName = fixMaxLength(
447 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
448
449 String[] jobNames = scheduler.getJobNames(groupName);
450
451 for (String jobName : jobNames) {
452 delete(scheduler, jobName, groupName);
453 }
454 }
455
456 protected void delete(Scheduler scheduler, String jobName, String groupName)
457 throws Exception {
458
459 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
460 groupName = fixMaxLength(
461 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
462
463 scheduler.deleteJob(jobName, groupName);
464 }
465
466 protected String fixMaxLength(String argument, int maxLength) {
467 if (argument == null) {
468 return null;
469 }
470
471 if (argument.length() > maxLength) {
472 argument = argument.substring(0, maxLength);
473 }
474
475 return argument;
476 }
477
478 protected String getFullName(String jobName, String groupName) {
479 return groupName.concat(StringPool.PERIOD).concat(jobName);
480 }
481
482 protected JobState getJobState(JobDataMap jobDataMap) {
483 Map<String, Object> jobStateMap = (Map<String, Object>)jobDataMap.get(
484 JOB_STATE);
485
486 return JobStateSerializeUtil.deserialize(jobStateMap);
487 }
488
489 protected Message getMessage(JobDataMap jobDataMap) {
490 String messageJSON = (String)jobDataMap.get(MESSAGE);
491
492 return (Message)JSONFactoryUtil.deserialize(messageJSON);
493 }
494
495 protected String getOriginalGroupName(String groupName) {
496 int pos = groupName.indexOf(CharPool.POUND);
497
498 return groupName.substring(pos + 1);
499 }
500
501 protected Trigger getQuartzTrigger(
502 com.liferay.portal.kernel.scheduler.Trigger trigger)
503 throws SchedulerException {
504
505 if (trigger == null) {
506 return null;
507 }
508
509 String jobName = fixMaxLength(
510 trigger.getJobName(), JOB_NAME_MAX_LENGTH);
511 String groupName = fixMaxLength(
512 trigger.getGroupName(), GROUP_NAME_MAX_LENGTH);
513
514 Trigger quartzTrigger = null;
515
516 TriggerType triggerType = trigger.getTriggerType();
517
518 if (triggerType.equals(TriggerType.CRON)) {
519 try {
520 quartzTrigger = new CronTrigger(
521 jobName, groupName, (String)trigger.getTriggerContent());
522 }
523 catch (ParseException pe) {
524 throw new SchedulerException(
525 "Unable to parse cron text " + trigger.getTriggerContent());
526 }
527 }
528 else if (triggerType.equals(TriggerType.SIMPLE)) {
529 long interval = (Long)trigger.getTriggerContent();
530
531 if (interval <= 0) {
532 if (_log.isDebugEnabled()) {
533 _log.debug(
534 "Not scheduling " + trigger.getJobName() +
535 " because interval is less than or equal to 0");
536 }
537
538 return null;
539 }
540
541 quartzTrigger = new SimpleTrigger(
542 jobName, groupName, SimpleTrigger.REPEAT_INDEFINITELY,
543 interval);
544 }
545 else {
546 throw new SchedulerException(
547 "Unknown trigger type " + trigger.getTriggerType());
548 }
549
550 quartzTrigger.setJobName(jobName);
551 quartzTrigger.setJobGroup(groupName);
552
553 Date startDate = trigger.getStartDate();
554
555 if (startDate == null) {
556 if (ServerDetector.getServerId().equals(ServerDetector.TOMCAT_ID)) {
557 quartzTrigger.setStartTime(
558 new Date(System.currentTimeMillis() + Time.MINUTE));
559 }
560 else {
561 quartzTrigger.setStartTime(
562 new Date(System.currentTimeMillis() + Time.MINUTE * 3));
563 }
564 }
565 else {
566 quartzTrigger.setStartTime(startDate);
567 }
568
569 Date endDate = trigger.getEndDate();
570
571 if (endDate != null) {
572 quartzTrigger.setEndTime(endDate);
573 }
574
575 return quartzTrigger;
576 }
577
578 protected SchedulerResponse getScheduledJob(
579 Scheduler scheduler, String jobName, String groupName)
580 throws Exception {
581
582 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
583 groupName = fixMaxLength(
584 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
585
586 JobDetail jobDetail = scheduler.getJobDetail(
587 jobName, groupName);
588
589 if (jobDetail == null) {
590 return null;
591 }
592
593 JobDataMap jobDataMap = jobDetail.getJobDataMap();
594
595 String description = jobDataMap.getString(DESCRIPTION);
596 String destinationName = jobDataMap.getString(DESTINATION_NAME);
597 Message message = getMessage(jobDataMap);
598 StorageType storageType = StorageType.valueOf(
599 jobDataMap.getString(STORAGE_TYPE));
600
601 SchedulerResponse schedulerResponse = null;
602
603 Trigger trigger = scheduler.getTrigger(jobName, groupName);
604
605 JobState jobState = getJobState(jobDataMap);
606
607 message.put(JOB_STATE, jobState);
608
609 if (trigger == null) {
610 schedulerResponse = new SchedulerResponse();
611
612 schedulerResponse.setDescription(description);
613 schedulerResponse.setDestinationName(destinationName);
614 schedulerResponse.setGroupName(groupName);
615 schedulerResponse.setJobName(jobName);
616 schedulerResponse.setMessage(message);
617 schedulerResponse.setStorageType(storageType);
618 }
619 else {
620 message.put(END_TIME, trigger.getEndTime());
621 message.put(FINAL_FIRE_TIME, trigger.getFinalFireTime());
622 message.put(NEXT_FIRE_TIME, trigger.getNextFireTime());
623 message.put(PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
624 message.put(START_TIME, trigger.getStartTime());
625
626 if (CronTrigger.class.isAssignableFrom(trigger.getClass())) {
627
628 CronTrigger cronTrigger = CronTrigger.class.cast(trigger);
629
630 schedulerResponse = new SchedulerResponse();
631
632 schedulerResponse.setDescription(description);
633 schedulerResponse.setDestinationName(destinationName);
634 schedulerResponse.setMessage(message);
635 schedulerResponse.setStorageType(storageType);
636 schedulerResponse.setTrigger(
637 new com.liferay.portal.kernel.scheduler.CronTrigger(
638 jobName, groupName, cronTrigger.getStartTime(),
639 cronTrigger.getEndTime(),
640 cronTrigger.getCronExpression()));
641 }
642 else if (SimpleTrigger.class.isAssignableFrom(
643 trigger.getClass())) {
644
645 SimpleTrigger simpleTrigger = SimpleTrigger.class.cast(
646 trigger);
647
648 schedulerResponse = new SchedulerResponse();
649
650 schedulerResponse.setDescription(description);
651 schedulerResponse.setDestinationName(destinationName);
652 schedulerResponse.setMessage(message);
653 schedulerResponse.setStorageType(storageType);
654 schedulerResponse.setTrigger(
655 new IntervalTrigger(
656 jobName, groupName, simpleTrigger.getStartTime(),
657 simpleTrigger.getEndTime(),
658 simpleTrigger.getRepeatInterval()));
659 }
660 }
661
662 return schedulerResponse;
663 }
664
665 protected List<SchedulerResponse> getScheduledJobs(
666 Scheduler scheduler, String groupName)
667 throws Exception {
668
669 groupName = fixMaxLength(
670 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
671
672 List<SchedulerResponse> schedulerResponses =
673 new ArrayList<SchedulerResponse>();
674
675 String[] jobNames = scheduler.getJobNames(groupName);
676
677 for (String jobName : jobNames) {
678 SchedulerResponse schedulerResponse = getScheduledJob(
679 scheduler, jobName, groupName);
680
681 if (schedulerResponse != null) {
682 schedulerResponses.add(schedulerResponse);
683 }
684 }
685
686 return schedulerResponses;
687 }
688
689 protected Scheduler getScheduler(String groupName) throws Exception {
690 if (groupName.startsWith(StorageType.PERSISTED.toString())) {
691 return _persistedScheduler;
692 }
693 else {
694 return _memoryScheduler;
695 }
696 }
697
698 protected StorageType getStorageType(String groupName) {
699 int pos = groupName.indexOf(CharPool.POUND);
700
701 String storageTypeString = groupName.substring(0, pos);
702
703 return StorageType.valueOf(storageTypeString);
704 }
705
706 protected Scheduler initializeScheduler(
707 String propertiesPrefix, boolean useQuartzCluster)
708 throws Exception {
709
710 StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
711
712 Properties properties = PropsUtil.getProperties(propertiesPrefix, true);
713
714 if (useQuartzCluster && PropsValues.CLUSTER_LINK_ENABLED) {
715 DB db = DBFactoryUtil.getDB();
716
717 String dbType = db.getType();
718
719 if (dbType.equals(DB.TYPE_HYPERSONIC)) {
720 _log.error("Unable to cluster scheduler on Hypersonic");
721 }
722 else {
723 properties.put(
724 "org.quartz.jobStore.isClustered", Boolean.TRUE.toString());
725 }
726 }
727
728 schedulerFactory.initialize(properties);
729
730 return schedulerFactory.getScheduler();
731 }
732
733 protected void initJobState() throws Exception {
734 String [] groupNames = _persistedScheduler.getJobGroupNames();
735
736 for (String groupName : groupNames) {
737 String[] jobNames = _persistedScheduler.getJobNames(groupName);
738
739 for (String jobName : jobNames) {
740 Trigger trigger = _persistedScheduler.getTrigger(
741 jobName, groupName);
742
743 if (trigger != null) {
744 continue;
745 }
746
747 JobDetail jobDetail = _persistedScheduler.getJobDetail(
748 jobName, groupName);
749
750 JobDataMap jobDataMap = jobDetail.getJobDataMap();
751
752 JobState jobState = getJobState(jobDataMap);
753
754 jobState.setTriggerState(TriggerState.COMPLETE);
755
756 jobDataMap.put(
757 JOB_STATE, JobStateSerializeUtil.serialize(jobState));
758
759 _persistedScheduler.addJob(jobDetail, true);
760 }
761 }
762 }
763
764 protected void pause(Scheduler scheduler, String groupName)
765 throws Exception {
766
767 groupName = fixMaxLength(
768 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
769
770 String[] jobNames = scheduler.getJobNames(groupName);
771
772 for (String jobName : jobNames) {
773 updateJobState(
774 scheduler, jobName, groupName, TriggerState.PAUSED, false);
775 }
776
777 scheduler.pauseJobGroup(groupName);
778 }
779
780 protected void pause(Scheduler scheduler, String jobName, String groupName)
781 throws Exception {
782
783 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
784 groupName = fixMaxLength(
785 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
786
787 updateJobState(
788 scheduler, jobName, groupName, TriggerState.PAUSED, false);
789
790 scheduler.pauseJob(jobName, groupName);
791 }
792
793 protected void resume(Scheduler scheduler, String groupName)
794 throws Exception {
795
796 groupName = fixMaxLength(
797 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
798
799 String[] jobNames = scheduler.getJobNames(groupName);
800
801 for (String jobName : jobNames) {
802 updateJobState(
803 scheduler, jobName, groupName, TriggerState.NORMAL, false);
804 }
805
806 scheduler.resumeJobGroup(groupName);
807 }
808
809 protected void resume(Scheduler scheduler, String jobName, String groupName)
810 throws Exception {
811
812 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
813 groupName = fixMaxLength(
814 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
815
816 updateJobState(
817 scheduler, jobName, groupName, TriggerState.NORMAL, false);
818
819 scheduler.resumeJob(jobName, groupName);
820 }
821
822 protected void schedule(
823 Scheduler scheduler, StorageType storageType, Trigger trigger,
824 String description, String destinationName, Message message)
825 throws Exception {
826
827 try {
828 String jobName = trigger.getName();
829 String groupName = trigger.getGroup();
830
831 JobDetail jobDetail = new JobDetail(
832 jobName, groupName, MessageSenderJob.class);
833
834 JobDataMap jobDataMap = jobDetail.getJobDataMap();
835
836 jobDataMap.put(DESCRIPTION, description);
837 jobDataMap.put(DESTINATION_NAME, destinationName);
838 jobDataMap.put(MESSAGE, JSONFactoryUtil.serialize(message));
839 jobDataMap.put(STORAGE_TYPE, storageType.toString());
840
841 JobState jobState = new JobState(
842 TriggerState.NORMAL, message.getInteger(EXCEPTIONS_MAX_SIZE));
843
844 jobDataMap.put(
845 JOB_STATE, JobStateSerializeUtil.serialize(jobState));
846
847 if (scheduler == _persistedScheduler) {
848 jobDetail.setDurability(true);
849 }
850
851 synchronized (this) {
852 scheduler.deleteJob(jobName, groupName);
853 scheduler.scheduleJob(jobDetail, trigger);
854 }
855 }
856 catch (ObjectAlreadyExistsException oare) {
857 if (_log.isInfoEnabled()) {
858 _log.info("Message is already scheduled");
859 }
860 }
861 }
862
863 protected void suppressError(
864 String jobName, String groupName, Scheduler scheduler)
865 throws Exception {
866
867 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
868 groupName = fixMaxLength(
869 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
870
871 updateJobState(scheduler, jobName, groupName, null, true);
872 }
873
874 protected void unschedule(String groupName, Scheduler scheduler)
875 throws Exception {
876
877 groupName = fixMaxLength(
878 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
879
880 String[] jobNames = scheduler.getJobNames(groupName);
881
882 for (String jobName : jobNames) {
883 unschedule(jobName, groupName, scheduler);
884 }
885 }
886
887 protected void unschedule(
888 String jobName, String groupName, Scheduler scheduler)
889 throws Exception {
890
891 jobName = fixMaxLength(jobName, JOB_NAME_MAX_LENGTH);
892 groupName = fixMaxLength(
893 getOriginalGroupName(groupName), GROUP_NAME_MAX_LENGTH);
894
895 JobDetail jobDetail = scheduler.getJobDetail(jobName, groupName);
896
897 if (jobDetail == null) {
898 return;
899 }
900
901 if (scheduler == _memoryScheduler) {
902 scheduler.unscheduleJob(jobName, groupName);
903
904 return;
905 }
906
907 JobDataMap jobDataMap = jobDetail.getJobDataMap();
908
909 JobState jobState = getJobState(jobDataMap);
910
911 Trigger trigger = scheduler.getTrigger(jobName, groupName);
912
913 jobState.setTriggerDate(END_TIME, new Date());
914 jobState.setTriggerDate(FINAL_FIRE_TIME, trigger.getPreviousFireTime());
915 jobState.setTriggerDate(NEXT_FIRE_TIME, null);
916 jobState.setTriggerDate(
917 PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
918 jobState.setTriggerDate(START_TIME, trigger.getStartTime());
919
920 jobState.setTriggerState(TriggerState.UNSCHEDULED);
921
922 jobState.clearExceptions();
923
924 jobDataMap.put(JOB_STATE, JobStateSerializeUtil.serialize(jobState));
925
926 scheduler.unscheduleJob(jobName, groupName);
927
928 scheduler.addJob(jobDetail, true);
929 }
930
931 protected void update(
932 Scheduler scheduler,
933 com.liferay.portal.kernel.scheduler.Trigger trigger)
934 throws Exception {
935
936 Trigger quartzTrigger = getQuartzTrigger(trigger);
937
938 if (quartzTrigger == null) {
939 return;
940 }
941
942 String jobName = quartzTrigger.getJobName();
943 String groupName = quartzTrigger.getGroup();
944
945 if (scheduler.getTrigger(jobName, groupName) != null) {
946 scheduler.rescheduleJob(jobName, groupName, quartzTrigger);
947 }
948 else {
949 JobDetail jobDetail = scheduler.getJobDetail(jobName, groupName);
950
951 if (jobDetail == null) {
952 return;
953 }
954
955 updateJobState(
956 scheduler, jobName, groupName, TriggerState.NORMAL, true);
957
958 synchronized (this) {
959 scheduler.deleteJob(jobName, groupName);
960 scheduler.scheduleJob(jobDetail, quartzTrigger);
961 }
962 }
963 }
964
965 protected void updateJobState(
966 Scheduler scheduler, String jobName, String groupName,
967 TriggerState triggerState, boolean suppressError)
968 throws Exception {
969
970 JobDetail jobDetail = scheduler.getJobDetail(jobName, groupName);
971
972 JobDataMap jobDataMap = jobDetail.getJobDataMap();
973
974 JobState jobState = getJobState(jobDataMap);
975
976 if (triggerState != null) {
977 jobState.setTriggerState(triggerState);
978 }
979
980 if (suppressError) {
981 jobState.clearExceptions();
982 }
983
984 jobDataMap.put(JOB_STATE, JobStateSerializeUtil.serialize(jobState));
985
986 scheduler.addJob(jobDetail, true);
987 }
988
989 @BeanReference(name = "com.liferay.portal.service.QuartzLocalService")
990 protected QuartzLocalService quartzLocalService;
991
992 private static Log _log = LogFactoryUtil.getLog(
993 QuartzSchedulerEngine.class);
994
995 private Scheduler _memoryScheduler;
996 private Scheduler _persistedScheduler;
997
998 }