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