001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.scheduler;
016    
017    import com.liferay.portal.kernel.audit.AuditMessage;
018    import com.liferay.portal.kernel.audit.AuditRouterUtil;
019    import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler;
020    import com.liferay.portal.kernel.cal.DayAndPosition;
021    import com.liferay.portal.kernel.cal.Duration;
022    import com.liferay.portal.kernel.cal.Recurrence;
023    import com.liferay.portal.kernel.cal.RecurrenceSerializer;
024    import com.liferay.portal.kernel.json.JSONFactoryUtil;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.messaging.Destination;
028    import com.liferay.portal.kernel.messaging.DestinationNames;
029    import com.liferay.portal.kernel.messaging.InvokerMessageListener;
030    import com.liferay.portal.kernel.messaging.Message;
031    import com.liferay.portal.kernel.messaging.MessageBus;
032    import com.liferay.portal.kernel.messaging.MessageBusUtil;
033    import com.liferay.portal.kernel.messaging.MessageListener;
034    import com.liferay.portal.kernel.scheduler.messaging.SchedulerEventMessageListenerWrapper;
035    import com.liferay.portal.kernel.scheduler.messaging.SchedulerResponse;
036    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
037    import com.liferay.portal.kernel.util.InetAddressUtil;
038    import com.liferay.portal.kernel.util.ObjectValuePair;
039    import com.liferay.portal.kernel.util.ParamUtil;
040    import com.liferay.portal.kernel.util.PortalLifecycle;
041    import com.liferay.portal.kernel.util.ProxyUtil;
042    import com.liferay.portal.kernel.util.StringPool;
043    import com.liferay.portal.model.CompanyConstants;
044    import com.liferay.portal.util.PortalUtil;
045    
046    import java.util.ArrayList;
047    import java.util.Calendar;
048    import java.util.Date;
049    import java.util.List;
050    import java.util.Set;
051    
052    import javax.portlet.PortletRequest;
053    
054    /**
055     * @author Bruno Farache
056     * @author Shuyang Zhou
057     * @author Tina Tian
058     */
059    public class SchedulerEngineUtil {
060    
061            public static void addScriptingJob(
062                            Trigger trigger, StorageType storageType, String description,
063                            String language, String script, int exceptionsMaxSize)
064                    throws SchedulerException {
065    
066                    _instance._addScriptingJob(
067                            trigger, storageType, description, language, script,
068                            exceptionsMaxSize);
069            }
070    
071            public static void auditSchedulerJobs(
072                            Message message, TriggerState triggerState)
073                    throws SchedulerException {
074    
075                    _instance._auditSchedulerJobs(message, triggerState);
076            }
077    
078            public static void delete(
079                            SchedulerEntry schedulerEntry, StorageType storageType)
080                    throws SchedulerException {
081    
082                    _instance._delete(schedulerEntry, storageType);
083            }
084    
085            public static void delete(String groupName, StorageType storageType)
086                    throws SchedulerException {
087    
088                    _instance._delete(groupName, storageType);
089            }
090    
091            public static void delete(
092                            String jobName, String groupName, StorageType storageType)
093                    throws SchedulerException {
094    
095                    _instance._delete(jobName, groupName, storageType);
096            }
097    
098            public static String getCronText(
099                    Calendar calendar, boolean timeZoneSensitive) {
100    
101                    return _instance._getCronText(calendar, timeZoneSensitive);
102            }
103    
104            public static String getCronText(
105                    PortletRequest portletRequest, Calendar calendar,
106                    boolean timeZoneSensitive, int recurrenceType) {
107    
108                    return _instance._getCronText(
109                            portletRequest, calendar, timeZoneSensitive, recurrenceType);
110            }
111    
112            public static Date getEndTime(SchedulerResponse schedulerResponse) {
113                    return _instance._getEndTime(schedulerResponse);
114            }
115    
116            public static Date getEndTime(
117                            String jobName, String groupName, StorageType storageType)
118                    throws SchedulerException {
119    
120                    return _instance._getEndTime(jobName, groupName, storageType);
121            }
122    
123            public static Date getFinalFireTime(SchedulerResponse schedulerResponse) {
124                    return _instance._getFinalFireTime(schedulerResponse);
125            }
126    
127            public static Date getFinalFireTime(
128                            String jobName, String groupName, StorageType storageType)
129                    throws SchedulerException {
130    
131                    return _instance._getFinalFireTime(jobName, groupName, storageType);
132            }
133    
134            public static ObjectValuePair<Exception, Date>[] getJobExceptions(
135                    SchedulerResponse schedulerResponse) {
136    
137                    return _instance._getJobExceptions(schedulerResponse);
138            }
139    
140            public static ObjectValuePair<Exception, Date>[] getJobExceptions(
141                            String jobName, String groupName, StorageType storageType)
142                    throws SchedulerException {
143    
144                    return _instance._getJobExceptions(jobName, groupName, storageType);
145            }
146    
147            public static TriggerState getJobState(
148                    SchedulerResponse schedulerResponse) {
149    
150                    return _instance._getJobState(schedulerResponse);
151            }
152    
153            public static TriggerState getJobState(
154                            String jobName, String groupName, StorageType storageType)
155                    throws SchedulerException {
156    
157                    return _instance._getJobState(jobName, groupName, storageType);
158            }
159    
160            public static Date getNextFireTime(SchedulerResponse schedulerResponse) {
161                    return _instance._getNextFireTime(schedulerResponse);
162            }
163    
164            public static Date getNextFireTime(
165                            String jobName, String groupName, StorageType storageType)
166                    throws SchedulerException {
167    
168                    return _instance._getNextFireTime(jobName, groupName, storageType);
169            }
170    
171            public static Date getPreviousFireTime(
172                    SchedulerResponse schedulerResponse) {
173    
174                    return _instance._getPreviousFireTime(schedulerResponse);
175            }
176    
177            public static Date getPreviousFireTime(
178                            String jobName, String groupName, StorageType storageType)
179                    throws SchedulerException {
180    
181                    return _instance._getPreviousFireTime(jobName, groupName, storageType);
182            }
183    
184            public static SchedulerResponse getScheduledJob(
185                            String jobName, String groupName, StorageType storageType)
186                    throws SchedulerException {
187    
188                    return _instance._getScheduledJob(jobName, groupName, storageType);
189            }
190    
191            public static List<SchedulerResponse> getScheduledJobs()
192                    throws SchedulerException {
193    
194                    return _instance._getScheduledJobs();
195            }
196    
197            public static List<SchedulerResponse> getScheduledJobs(
198                            StorageType storageType)
199                    throws SchedulerException {
200    
201                    return _instance._getScheduledJobs(storageType);
202            }
203    
204            public static List<SchedulerResponse> getScheduledJobs(
205                            String groupName, StorageType storageType)
206                    throws SchedulerException {
207    
208                    return _instance._getScheduledJobs(groupName, storageType);
209            }
210    
211            public static Date getStartTime(SchedulerResponse schedulerResponse) {
212                    return _instance._getStartTime(schedulerResponse);
213            }
214    
215            public static Date getStartTime(
216                            String jobName, String groupName, StorageType storageType)
217                    throws SchedulerException {
218    
219                    return _instance._getStartTime(jobName, groupName, storageType);
220            }
221    
222            public static void initialize() throws SchedulerException {
223                    _instance._initialize();
224    
225                    SchedulerLifecycle schedulerLifecycle = new SchedulerLifecycle();
226    
227                    schedulerLifecycle.registerPortalLifecycle(PortalLifecycle.METHOD_INIT);
228            }
229    
230            public static String namespaceGroupName(
231                    String groupName, StorageType storageType) {
232    
233                    return _instance._namespaceGroupName(groupName, storageType);
234            }
235    
236            public static void pause(String groupName, StorageType storageType)
237                    throws SchedulerException {
238    
239                    _instance._pause(groupName, storageType);
240            }
241    
242            public static void pause(
243                            String jobName, String groupName, StorageType storageType)
244                    throws SchedulerException {
245    
246                    _instance._pause(jobName, groupName, storageType);
247            }
248    
249            public static void resume(String groupName, StorageType storageType)
250                    throws SchedulerException {
251    
252                    _instance._resume(groupName, storageType);
253            }
254    
255            public static void resume(
256                            String jobName, String groupName, StorageType storageType)
257                    throws SchedulerException {
258    
259                    _instance._resume(jobName, groupName, storageType);
260            }
261    
262            public static void schedule(
263                            SchedulerEntry schedulerEntry, StorageType storageType,
264                            ClassLoader classLoader, int exceptionsMaxSize)
265                    throws SchedulerException {
266    
267                    _instance._schedule(
268                            schedulerEntry, storageType, classLoader, exceptionsMaxSize);
269            }
270    
271            public static void schedule(
272                            Trigger trigger, StorageType storageType, String description,
273                            String destinationName, Message message, int exceptionsMaxSize)
274                    throws SchedulerException {
275    
276                    _instance._schedule(
277                            trigger, storageType, description, destinationName, message,
278                            exceptionsMaxSize);
279            }
280    
281            public static void schedule(
282                            Trigger trigger, StorageType storageType, String description,
283                            String destinationName, Object payload, int exceptionsMaxSize)
284                    throws SchedulerException {
285    
286                    _instance._schedule(
287                            trigger, storageType, description, destinationName, payload,
288                            exceptionsMaxSize);
289            }
290    
291            public static void shutdown() throws SchedulerException {
292                    _instance._shutdown();
293            }
294    
295            public static void start() throws SchedulerException {
296                    _instance._start();
297            }
298    
299            public static void suppressError(
300                            String jobName, String groupName, StorageType storageType)
301                    throws SchedulerException {
302    
303                    _instance._suppressError(jobName, groupName, storageType);
304            }
305    
306            public static void unschedule(
307                            SchedulerEntry schedulerEntry, StorageType storageType)
308                    throws SchedulerException {
309    
310                    _instance._unschedule(schedulerEntry, storageType);
311            }
312    
313            public static void unschedule(String groupName, StorageType storageType)
314                    throws SchedulerException {
315    
316                    _instance._unschedule(groupName, storageType);
317            }
318    
319            public static void unschedule(
320                            String jobName, String groupName, StorageType storageType)
321                    throws SchedulerException {
322    
323                    _instance._unschedule(jobName, groupName, storageType);
324            }
325    
326            public static void update(
327                            String jobName, String groupName, StorageType storageType,
328                            String description, String language, String script,
329                            int exceptionsMaxSize)
330                    throws SchedulerException {
331    
332                    _instance._update(
333                            jobName, groupName, storageType, description, language, script,
334                            exceptionsMaxSize);
335            }
336    
337            public static void update(Trigger trigger, StorageType storageType)
338                    throws SchedulerException {
339    
340                    _instance._update(trigger, storageType);
341            }
342    
343            public static void updateMemorySchedulerClusterMaster()
344                    throws SchedulerException {
345    
346                    _instance._updateMemorySchedulerClusterMaster();
347            }
348    
349            public void setSchedulerEngine(SchedulerEngine schedulerEngine) {
350                    _instance._schedulerEngine = schedulerEngine;
351    
352                    if (schedulerEngine instanceof SchedulerEngineClusterManager) {
353                            _instance._schedulerEngineClusterManager =
354                                    (SchedulerEngineClusterManager)schedulerEngine;
355                    }
356            }
357    
358            private void _addScriptingJob(
359                            Trigger trigger, StorageType storageType, String description,
360                            String language, String script, int exceptionsMaxSize)
361                    throws SchedulerException {
362    
363                    Message message = new Message();
364    
365                    message.put(SchedulerEngine.LANGUAGE, language);
366                    message.put(SchedulerEngine.SCRIPT, script);
367    
368                    _schedule(
369                            trigger, storageType, description,
370                            DestinationNames.SCHEDULER_SCRIPTING, message, exceptionsMaxSize);
371            }
372    
373            private void _addWeeklyDayPos(
374                    PortletRequest portletRequest, List<DayAndPosition> list, int day) {
375    
376                    if (ParamUtil.getBoolean(portletRequest, "weeklyDayPos" + day)) {
377                            list.add(new DayAndPosition(day, 0));
378                    }
379            }
380    
381            private void _auditSchedulerJobs(Message message, TriggerState triggerState)
382                    throws SchedulerException {
383    
384                    try {
385                            AuditMessage auditMessage = new AuditMessage(
386                                    SchedulerEngine.AUDIT_ACTION, CompanyConstants.SYSTEM, 0,
387                                    StringPool.BLANK, SchedulerEngine.class.getName(), "0",
388                                    triggerState.toString(), new Date(),
389                                    JSONFactoryUtil.createJSONObject(
390                                            JSONFactoryUtil.serialize(message)));
391    
392                            auditMessage.setServerName(InetAddressUtil.getLocalHostName());
393                            auditMessage.setServerPort(PortalUtil.getPortalPort(false));
394    
395                            AuditRouterUtil.route(auditMessage);
396                    }
397                    catch (Exception e) {
398                            throw new SchedulerException(e);
399                    }
400            }
401    
402            private void _delete(SchedulerEntry schedulerEntry, StorageType storageType)
403                    throws SchedulerException {
404    
405                    Trigger trigger = schedulerEntry.getTrigger();
406    
407                    _delete(trigger.getJobName(), trigger.getGroupName(), storageType);
408            }
409    
410            private void _delete(String groupName, StorageType storageType)
411                    throws SchedulerException {
412    
413                    _unregisterMessageListener(groupName, storageType);
414    
415                    _schedulerEngine.delete(_namespaceGroupName(groupName, storageType));
416            }
417    
418            private void _delete(
419                            String jobName, String groupName, StorageType storageType)
420                    throws SchedulerException {
421    
422                    _unregisterMessageListener(jobName, groupName, storageType);
423    
424                    _schedulerEngine.delete(
425                            jobName, _namespaceGroupName(groupName, storageType));
426            }
427    
428            private String _getCronText(Calendar calendar, boolean timeZoneSensitive) {
429                    return _getCronText(
430                            null, calendar, timeZoneSensitive, Recurrence.NO_RECURRENCE);
431            }
432    
433            private String _getCronText(
434                    PortletRequest portletRequest, Calendar calendar,
435                    boolean timeZoneSensitive, int recurrenceType) {
436    
437                    Calendar recurrenceCalendar = null;
438    
439                    if (timeZoneSensitive) {
440                            recurrenceCalendar = CalendarFactoryUtil.getCalendar();
441    
442                            recurrenceCalendar.setTime(calendar.getTime());
443                    }
444                    else {
445                            recurrenceCalendar = (Calendar)calendar.clone();
446                    }
447    
448                    Recurrence recurrence = new Recurrence(
449                            recurrenceCalendar, new Duration(1, 0, 0, 0), recurrenceType);
450    
451                    recurrence.setWeekStart(Calendar.SUNDAY);
452    
453                    if (recurrenceType == Recurrence.DAILY) {
454                            int dailyType = ParamUtil.getInteger(portletRequest, "dailyType");
455    
456                            if (dailyType == 0) {
457                                    int dailyInterval = ParamUtil.getInteger(
458                                            portletRequest, "dailyInterval", 1);
459    
460                                    recurrence.setInterval(dailyInterval);
461                            }
462                            else {
463                                    DayAndPosition[] dayPos = {
464                                            new DayAndPosition(Calendar.MONDAY, 0),
465                                            new DayAndPosition(Calendar.TUESDAY, 0),
466                                            new DayAndPosition(Calendar.WEDNESDAY, 0),
467                                            new DayAndPosition(Calendar.THURSDAY, 0),
468                                            new DayAndPosition(Calendar.FRIDAY, 0)};
469    
470                                    recurrence.setByDay(dayPos);
471                            }
472                    }
473                    else if (recurrenceType == Recurrence.WEEKLY) {
474                            int weeklyInterval = ParamUtil.getInteger(
475                                    portletRequest, "weeklyInterval", 1);
476    
477                            recurrence.setInterval(weeklyInterval);
478    
479                            List<DayAndPosition> dayPos = new ArrayList<DayAndPosition>();
480    
481                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.SUNDAY);
482                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.MONDAY);
483                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.TUESDAY);
484                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.WEDNESDAY);
485                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.THURSDAY);
486                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.FRIDAY);
487                            _addWeeklyDayPos(portletRequest, dayPos, Calendar.SATURDAY);
488    
489                            if (dayPos.size() == 0) {
490                                    dayPos.add(new DayAndPosition(Calendar.MONDAY, 0));
491                            }
492    
493                            recurrence.setByDay(dayPos.toArray(new DayAndPosition[0]));
494                    }
495                    else if (recurrenceType == Recurrence.MONTHLY) {
496                            int monthlyType = ParamUtil.getInteger(
497                                    portletRequest, "monthlyType");
498    
499                            if (monthlyType == 0) {
500                                    int monthlyDay = ParamUtil.getInteger(
501                                            portletRequest, "monthlyDay0", 1);
502    
503                                    recurrence.setByMonthDay(new int[] {monthlyDay});
504    
505                                    int monthlyInterval = ParamUtil.getInteger(
506                                            portletRequest, "monthlyInterval0", 1);
507    
508                                    recurrence.setInterval(monthlyInterval);
509                            }
510                            else {
511                                    int monthlyPos = ParamUtil.getInteger(
512                                            portletRequest, "monthlyPos");
513                                    int monthlyDay = ParamUtil.getInteger(
514                                            portletRequest, "monthlyDay1");
515    
516                                    DayAndPosition[] dayPos = {
517                                            new DayAndPosition(monthlyDay, monthlyPos)};
518    
519                                    recurrence.setByDay(dayPos);
520    
521                                    int monthlyInterval = ParamUtil.getInteger(
522                                            portletRequest, "monthlyInterval1", 1);
523    
524                                    recurrence.setInterval(monthlyInterval);
525                            }
526                    }
527                    else if (recurrenceType == Recurrence.YEARLY) {
528                            int yearlyType = ParamUtil.getInteger(portletRequest, "yearlyType");
529    
530                            if (yearlyType == 0) {
531                                    int yearlyMonth = ParamUtil.getInteger(
532                                            portletRequest, "yearlyMonth0");
533                                    int yearlyDay = ParamUtil.getInteger(
534                                            portletRequest, "yearlyDay0", 1);
535    
536                                    recurrence.setByMonth(new int[] {yearlyMonth});
537                                    recurrence.setByMonthDay(new int[] {yearlyDay});
538    
539                                    int yearlyInterval = ParamUtil.getInteger(
540                                            portletRequest, "yearlyInterval0", 1);
541    
542                                    recurrence.setInterval(yearlyInterval);
543                            }
544                            else {
545                                    int yearlyPos = ParamUtil.getInteger(
546                                            portletRequest, "yearlyPos");
547                                    int yearlyDay = ParamUtil.getInteger(
548                                            portletRequest, "yearlyDay1");
549                                    int yearlyMonth = ParamUtil.getInteger(
550                                            portletRequest, "yearlyMonth1");
551    
552                                    DayAndPosition[] dayPos = {
553                                            new DayAndPosition(yearlyDay, yearlyPos)};
554    
555                                    recurrence.setByDay(dayPos);
556    
557                                    recurrence.setByMonth(new int[] {yearlyMonth});
558    
559                                    int yearlyInterval = ParamUtil.getInteger(
560                                            portletRequest, "yearlyInterval1", 1);
561    
562                                    recurrence.setInterval(yearlyInterval);
563                            }
564                    }
565    
566                    return RecurrenceSerializer.toCronText(recurrence);
567            }
568    
569            private Date _getEndTime(SchedulerResponse schedulerResponse) {
570                    Message message = schedulerResponse.getMessage();
571    
572                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
573    
574                    TriggerState triggerState = jobState.getTriggerState();
575    
576                    if ((triggerState.equals(TriggerState.NORMAL)) ||
577                            (triggerState.equals(TriggerState.PAUSED))) {
578    
579                            return (Date)message.get(SchedulerEngine.END_TIME);
580                    }
581                    else {
582                            return jobState.getTriggerDate(SchedulerEngine.END_TIME);
583                    }
584            }
585    
586            private Date _getEndTime(
587                            String jobName, String groupName, StorageType storageType)
588                    throws SchedulerException {
589    
590                    SchedulerResponse schedulerResponse = _getScheduledJob(
591                            jobName, groupName, storageType);
592    
593                    if (schedulerResponse != null) {
594                            return _getEndTime(schedulerResponse);
595                    }
596    
597                    return null;
598            }
599    
600            private Date _getFinalFireTime(SchedulerResponse schedulerResponse) {
601                    Message message = schedulerResponse.getMessage();
602    
603                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
604    
605                    TriggerState triggerState = jobState.getTriggerState();
606    
607                    if ((triggerState.equals(TriggerState.NORMAL)) ||
608                            (triggerState.equals(TriggerState.PAUSED))) {
609    
610                            return (Date)message.get(SchedulerEngine.FINAL_FIRE_TIME);
611                    }
612                    else {
613                            return jobState.getTriggerDate(SchedulerEngine.FINAL_FIRE_TIME);
614                    }
615            }
616    
617            private Date _getFinalFireTime(
618                            String jobName, String groupName, StorageType storageType)
619                    throws SchedulerException {
620    
621                    SchedulerResponse schedulerResponse = _getScheduledJob(
622                            jobName, groupName, storageType);
623    
624                    if (schedulerResponse != null) {
625                            return _getFinalFireTime(schedulerResponse);
626                    }
627    
628                    return null;
629            }
630    
631            private ObjectValuePair<Exception, Date>[] _getJobExceptions(
632                    SchedulerResponse schedulerResponse) {
633    
634                    Message message = schedulerResponse.getMessage();
635    
636                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
637    
638                    return jobState.getExceptions();
639            }
640    
641            private ObjectValuePair<Exception, Date>[] _getJobExceptions(
642                            String jobName, String groupName, StorageType storageType)
643                    throws SchedulerException {
644    
645                    SchedulerResponse schedulerResponse = _getScheduledJob(
646                            jobName, groupName, storageType);
647    
648                    if (schedulerResponse != null) {
649                            return _getJobExceptions(schedulerResponse);
650                    }
651    
652                    return null;
653            }
654    
655            private TriggerState _getJobState(SchedulerResponse schedulerResponse) {
656                    Message message = schedulerResponse.getMessage();
657    
658                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
659    
660                    return jobState.getTriggerState();
661            }
662    
663            private TriggerState _getJobState(
664                            String jobName, String groupName, StorageType storageType)
665                    throws SchedulerException {
666    
667                    SchedulerResponse schedulerResponse = _getScheduledJob(
668                            jobName, groupName, storageType);
669    
670                    if (schedulerResponse != null) {
671                            return _getJobState(schedulerResponse);
672                    }
673    
674                    return null;
675            }
676    
677            private Date _getNextFireTime(SchedulerResponse schedulerResponse) {
678                    Message message = schedulerResponse.getMessage();
679    
680                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
681    
682                    TriggerState triggerState = jobState.getTriggerState();
683    
684                    if ((triggerState.equals(TriggerState.NORMAL)) ||
685                            (triggerState.equals(TriggerState.PAUSED))) {
686    
687                            return (Date)message.get(SchedulerEngine.NEXT_FIRE_TIME);
688                    }
689                    else {
690                            return jobState.getTriggerDate(SchedulerEngine.NEXT_FIRE_TIME);
691                    }
692            }
693    
694            private Date _getNextFireTime(
695                            String jobName, String groupName, StorageType storageType)
696                    throws SchedulerException {
697    
698                    SchedulerResponse schedulerResponse = _getScheduledJob(
699                            jobName, groupName, storageType);
700    
701                    if (schedulerResponse != null) {
702                            return _getNextFireTime(schedulerResponse);
703                    }
704    
705                    return null;
706            }
707    
708            private Date _getPreviousFireTime(SchedulerResponse schedulerResponse) {
709                    Message message = schedulerResponse.getMessage();
710    
711                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
712    
713                    TriggerState triggerState = jobState.getTriggerState();
714    
715                    if ((triggerState.equals(TriggerState.NORMAL)) ||
716                            (triggerState.equals(TriggerState.PAUSED))) {
717    
718                            return (Date)message.get(SchedulerEngine.PREVIOUS_FIRE_TIME);
719                    }
720                    else {
721                            return jobState.getTriggerDate(SchedulerEngine.PREVIOUS_FIRE_TIME);
722                    }
723            }
724    
725            private Date _getPreviousFireTime(
726                            String jobName, String groupName, StorageType storageType)
727                    throws SchedulerException {
728    
729                    SchedulerResponse schedulerResponse = _getScheduledJob(
730                            jobName, groupName, storageType);
731    
732                    if (schedulerResponse != null) {
733                            return _getPreviousFireTime(schedulerResponse);
734                    }
735    
736                    return null;
737            }
738    
739            private SchedulerResponse _getScheduledJob(
740                            String jobName, String groupName, StorageType storageType)
741                    throws SchedulerException {
742    
743                    return _schedulerEngine.getScheduledJob(
744                            jobName, _namespaceGroupName(groupName, storageType));
745            }
746    
747            private List<SchedulerResponse> _getScheduledJobs()
748                    throws SchedulerException {
749    
750                    return _schedulerEngine.getScheduledJobs();
751            }
752    
753            private List<SchedulerResponse> _getScheduledJobs(StorageType storageType)
754                    throws SchedulerException {
755    
756                    List<SchedulerResponse> schedulerResponses =
757                            new ArrayList<SchedulerResponse>();
758    
759                    for (SchedulerResponse schedulerResponse :
760                                    _schedulerEngine.getScheduledJobs()) {
761    
762                            if (storageType.equals(schedulerResponse.getStorageType())) {
763                                    schedulerResponses.add(schedulerResponse);
764                            }
765                    }
766    
767                    return schedulerResponses;
768            }
769    
770            private List<SchedulerResponse> _getScheduledJobs(
771                            String groupName, StorageType storageType)
772                    throws SchedulerException {
773    
774                    return _schedulerEngine.getScheduledJobs(
775                            _namespaceGroupName(groupName, storageType));
776            }
777    
778            private MessageListener _getSchedulerEventListener(
779                            SchedulerEntry schedulerEntry, ClassLoader classLoader)
780                    throws SchedulerException {
781    
782                    try {
783                            MessageListener schedulerEventListener =
784                                    (MessageListener)classLoader.loadClass(
785                                            schedulerEntry.getEventListenerClass()).newInstance();
786    
787                            return (MessageListener)ProxyUtil.newProxyInstance(
788                                    classLoader, new Class[] {MessageListener.class},
789                                    new ClassLoaderBeanHandler(
790                                            schedulerEventListener, classLoader));
791                    }
792                    catch (Exception e) {
793                            throw new SchedulerException(e);
794                    }
795            }
796    
797            private Date _getStartTime(SchedulerResponse schedulerResponse) {
798                    Message message = schedulerResponse.getMessage();
799    
800                    JobState jobState = (JobState)message.get(SchedulerEngine.JOB_STATE);
801    
802                    TriggerState triggerState = jobState.getTriggerState();
803    
804                    if ((triggerState.equals(TriggerState.NORMAL)) ||
805                            (triggerState.equals(TriggerState.PAUSED))) {
806    
807                            return (Date)message.get(SchedulerEngine.START_TIME);
808                    }
809                    else {
810                            return jobState.getTriggerDate(SchedulerEngine.START_TIME);
811                    }
812            }
813    
814            private Date _getStartTime(
815                            String jobName, String groupName, StorageType storageType)
816                    throws SchedulerException {
817    
818                    SchedulerResponse schedulerResponse = _getScheduledJob(
819                            jobName, groupName, storageType);
820    
821                    if (schedulerResponse != null) {
822                            return _getStartTime(schedulerResponse);
823                    }
824    
825                    return null;
826            }
827    
828            private void _initialize() throws SchedulerException {
829                    if (_schedulerEngineClusterManager != null) {
830                            _schedulerEngineClusterManager.initialize();
831                    }
832            }
833    
834            private String _namespaceGroupName(
835                    String groupName, StorageType storageType) {
836    
837                    return storageType.toString().concat(StringPool.POUND).concat(
838                            groupName);
839            }
840    
841            private void _pause(String groupName, StorageType storageType)
842                    throws SchedulerException {
843    
844                    _schedulerEngine.pause(_namespaceGroupName(groupName, storageType));
845            }
846    
847            private void _pause(
848                            String jobName, String groupName, StorageType storageType)
849                    throws SchedulerException {
850    
851                    _schedulerEngine.pause(
852                            jobName, _namespaceGroupName(groupName, storageType));
853            }
854    
855            private void _resume(String groupName, StorageType storageType)
856                    throws SchedulerException {
857    
858                    _schedulerEngine.resume(_namespaceGroupName(groupName, storageType));
859            }
860    
861            private void _resume(
862                            String jobName, String groupName, StorageType storageType)
863                    throws SchedulerException {
864    
865                    _schedulerEngine.resume(
866                            jobName, _namespaceGroupName(groupName, storageType));
867            }
868    
869            private void _schedule(
870                            SchedulerEntry schedulerEntry, StorageType storageType,
871                            ClassLoader classLoader, int exceptionsMaxSize)
872                    throws SchedulerException {
873    
874                    SchedulerEventMessageListenerWrapper schedulerEventListenerWrapper =
875                            new SchedulerEventMessageListenerWrapper();
876    
877                    schedulerEventListenerWrapper.setClassName(
878                            schedulerEntry.getEventListenerClass());
879                    schedulerEventListenerWrapper.setMessageListener(
880                            _getSchedulerEventListener(schedulerEntry, classLoader));
881    
882                    schedulerEventListenerWrapper.afterPropertiesSet();
883    
884                    schedulerEntry.setEventListener(schedulerEventListenerWrapper);
885    
886                    MessageBusUtil.registerMessageListener(
887                            DestinationNames.SCHEDULER_DISPATCH, schedulerEventListenerWrapper);
888    
889                    Message message = new Message();
890    
891                    message.put(
892                            SchedulerEngine.CONTEXT_PATH, schedulerEntry.getContextPath());
893                    message.put(
894                            SchedulerEngine.MESSAGE_LISTENER_UUID,
895                            schedulerEventListenerWrapper.getMessageListenerUUID());
896    
897                    _schedule(
898                            schedulerEntry.getTrigger(), storageType,
899                            schedulerEntry.getDescription(),
900                            DestinationNames.SCHEDULER_DISPATCH, message, exceptionsMaxSize);
901            }
902    
903            private void _schedule(
904                            Trigger trigger, StorageType storageType, String description,
905                            String destinationName, Message message, int exceptionsMaxSize)
906                    throws SchedulerException {
907    
908                    if (message == null) {
909                            message = new Message();
910                    }
911    
912                    message.put(SchedulerEngine.EXCEPTIONS_MAX_SIZE, exceptionsMaxSize);
913    
914                    trigger = TriggerFactoryUtil.buildTrigger(
915                            trigger.getTriggerType(), trigger.getJobName(),
916                            _namespaceGroupName(trigger.getGroupName(), storageType),
917                            trigger.getStartDate(), trigger.getEndDate(),
918                            trigger.getTriggerContent());
919    
920                    _schedulerEngine.schedule(
921                            trigger, description, destinationName, message);
922            }
923    
924            private void _schedule(
925                            Trigger trigger, StorageType storageType, String description,
926                            String destinationName, Object payload, int exceptionsMaxSize)
927                    throws SchedulerException {
928    
929                    Message message = new Message();
930    
931                    message.setPayload(payload);
932    
933                    _schedule(
934                            trigger, storageType, description, destinationName, message,
935                            exceptionsMaxSize);
936            }
937    
938            private void _shutdown() throws SchedulerException {
939                    _schedulerEngine.shutdown();
940            }
941    
942            private void _start() throws SchedulerException {
943                    _schedulerEngine.start();
944            }
945    
946            private void _suppressError(
947                            String jobName, String groupName, StorageType storageType)
948                    throws SchedulerException {
949    
950                    _schedulerEngine.suppressError(
951                            jobName, _namespaceGroupName(groupName, storageType));
952            }
953    
954            private void _unregisterMessageListener(
955                    SchedulerResponse schedulerResponse) {
956    
957                    if (schedulerResponse == null) {
958                            return;
959                    }
960    
961                    String destinationName = schedulerResponse.getDestinationName();
962    
963                    if (!destinationName.equals(DestinationNames.SCHEDULER_DISPATCH)) {
964                            return;
965                    }
966    
967                    Message message = schedulerResponse.getMessage();
968    
969                    String messageListenerUUID = message.getString(
970                            SchedulerEngine.MESSAGE_LISTENER_UUID);
971    
972                    if (messageListenerUUID == null) {
973                            return;
974                    }
975    
976                    MessageBus messageBus = MessageBusUtil.getMessageBus();
977    
978                    Destination destination = messageBus.getDestination(
979                            DestinationNames.SCHEDULER_DISPATCH);
980    
981                    Set<MessageListener> messageListeners =
982                            destination.getMessageListeners();
983    
984                    for (MessageListener messageListener : messageListeners) {
985                            InvokerMessageListener invokerMessageListener =
986                                    (InvokerMessageListener)messageListener;
987    
988                            SchedulerEventMessageListenerWrapper schedulerMessageListener =
989                                    (SchedulerEventMessageListenerWrapper)
990                                            invokerMessageListener.getMessageListener();
991    
992                            if (messageListenerUUID.equals(
993                                            schedulerMessageListener.getMessageListenerUUID())) {
994    
995                                    MessageBusUtil.unregisterMessageListener(
996                                            DestinationNames.SCHEDULER_DISPATCH,
997                                            schedulerMessageListener);
998    
999                                    return;
1000                            }
1001                    }
1002            }
1003    
1004            private void _unregisterMessageListener(
1005                            String groupName, StorageType storageType)
1006                    throws SchedulerException {
1007    
1008                    List<SchedulerResponse> schedulerResponses = _getScheduledJobs(
1009                            groupName, storageType);
1010    
1011                    for (SchedulerResponse schedulerResponse : schedulerResponses) {
1012                            _unregisterMessageListener(schedulerResponse);
1013                    }
1014            }
1015    
1016            private void _unregisterMessageListener(
1017                            String jobName, String groupName, StorageType storageType)
1018                    throws SchedulerException {
1019    
1020                    SchedulerResponse schedulerResponse = _getScheduledJob(
1021                            jobName, groupName, storageType);
1022    
1023                    _unregisterMessageListener(schedulerResponse);
1024            }
1025    
1026            private void _unschedule(
1027                            SchedulerEntry schedulerEntry, StorageType storageType)
1028                    throws SchedulerException {
1029    
1030                    Trigger trigger = schedulerEntry.getTrigger();
1031    
1032                    _unschedule(trigger.getJobName(), trigger.getGroupName(), storageType);
1033            }
1034    
1035            private void _unschedule(String groupName, StorageType storageType)
1036                    throws SchedulerException {
1037    
1038                    _unregisterMessageListener(groupName, storageType);
1039    
1040                    _schedulerEngine.unschedule(
1041                            _namespaceGroupName(groupName, storageType));
1042            }
1043    
1044            private void _unschedule(
1045                            String jobName, String groupName, StorageType storageType)
1046                    throws SchedulerException {
1047    
1048                    _unregisterMessageListener(jobName, groupName, storageType);
1049    
1050                    _schedulerEngine.unschedule(
1051                            jobName, _namespaceGroupName(groupName, storageType));
1052            }
1053    
1054            private void _update(
1055                            String jobName, String groupName, StorageType storageType,
1056                            String description, String language, String script,
1057                            int exceptionsMaxSize)
1058                    throws SchedulerException {
1059    
1060                    SchedulerResponse schedulerResponse = _getScheduledJob(
1061                            jobName, groupName, storageType);
1062    
1063                    if (schedulerResponse == null) {
1064                            return;
1065                    }
1066    
1067                    Trigger trigger = schedulerResponse.getTrigger();
1068    
1069                    if (trigger == null) {
1070                            return;
1071                    }
1072    
1073                    Message message = schedulerResponse.getMessage();
1074    
1075                    if (message == null) {
1076                            return;
1077                    }
1078    
1079                    _unregisterMessageListener(schedulerResponse);
1080    
1081                    _addScriptingJob(
1082                            trigger, storageType, description, language, script,
1083                            exceptionsMaxSize);
1084            }
1085    
1086            private void _update(Trigger trigger, StorageType storageType)
1087                    throws SchedulerException {
1088    
1089                    trigger = TriggerFactoryUtil.buildTrigger(
1090                            trigger.getTriggerType(), trigger.getJobName(),
1091                            _namespaceGroupName(trigger.getGroupName(), storageType),
1092                            trigger.getStartDate(), trigger.getEndDate(),
1093                            trigger.getTriggerContent());
1094    
1095                    _schedulerEngine.update(trigger);
1096            }
1097    
1098            private void _updateMemorySchedulerClusterMaster()
1099                    throws SchedulerException {
1100    
1101                    if (_schedulerEngineClusterManager == null) {
1102                            _log.error(
1103                                    "Unable to update memory scheduler cluster master because " +
1104                                            "the portal is not using a clustered scheduler engine");
1105    
1106                            return;
1107                    }
1108    
1109                    _schedulerEngineClusterManager.updateMemorySchedulerClusterMaster();
1110            }
1111    
1112            private static Log _log = LogFactoryUtil.getLog(SchedulerEngineUtil.class);
1113    
1114            private static SchedulerEngineUtil _instance = new SchedulerEngineUtil();
1115    
1116            private SchedulerEngine _schedulerEngine;
1117            private SchedulerEngineClusterManager _schedulerEngineClusterManager;
1118    
1119    }