1
14
15 package com.liferay.portal.scheduler.quartz;
16
17 import com.liferay.portal.kernel.annotation.BeanReference;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.messaging.Message;
21 import com.liferay.portal.kernel.scheduler.IntervalTrigger;
22 import com.liferay.portal.kernel.scheduler.SchedulerEngine;
23 import com.liferay.portal.kernel.scheduler.SchedulerException;
24 import com.liferay.portal.kernel.scheduler.TriggerType;
25 import com.liferay.portal.kernel.scheduler.messaging.SchedulerRequest;
26 import com.liferay.portal.kernel.util.ServerDetector;
27 import com.liferay.portal.kernel.util.StringPool;
28 import com.liferay.portal.kernel.util.Time;
29 import com.liferay.portal.scheduler.job.MessageSenderJob;
30 import com.liferay.portal.service.QuartzLocalService;
31 import com.liferay.portal.util.PropsUtil;
32 import com.liferay.portal.util.PropsValues;
33
34 import java.text.ParseException;
35
36 import java.util.ArrayList;
37 import java.util.Date;
38 import java.util.List;
39
40 import org.quartz.CronTrigger;
41 import org.quartz.JobDataMap;
42 import org.quartz.JobDetail;
43 import org.quartz.ObjectAlreadyExistsException;
44 import org.quartz.Scheduler;
45 import org.quartz.SimpleTrigger;
46 import org.quartz.Trigger;
47 import org.quartz.impl.StdSchedulerFactory;
48
49
57 public class QuartzSchedulerEngineImpl implements SchedulerEngine {
58
59 public void afterPropertiesSet() {
60 try {
61 if (!PropsValues.SCHEDULER_ENABLED) {
62 return;
63 }
64
65 StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
66
67 schedulerFactory.initialize(
68 PropsUtil.getProperties("org.quartz.", false));
69
70 quartzLocalService.checkQuartzTables();
71
72 _scheduler = schedulerFactory.getScheduler();
73 }
74 catch (Exception e) {
75 _log.error("Unable to initialize engine", e);
76 }
77 }
78
79 public List<SchedulerRequest> getScheduledJobs(String groupName)
80 throws SchedulerException {
81
82 if (!PropsValues.SCHEDULER_ENABLED) {
83 return new ArrayList<SchedulerRequest>();
84 }
85
86 try {
87 String[] jobNames = _scheduler.getJobNames(groupName);
88
89 List<SchedulerRequest> requests = new ArrayList<SchedulerRequest>();
90
91 for (String jobName : jobNames) {
92 JobDetail jobDetail = _scheduler.getJobDetail(
93 jobName, groupName);
94
95 if (jobDetail == null) {
96 continue;
97 }
98
99 JobDataMap jobDataMap = jobDetail.getJobDataMap();
100
101 String description = jobDataMap.getString(DESCRIPTION);
102 Message message = (Message)jobDataMap.get(MESSAGE);
103
104 SchedulerRequest schedulerRequest = null;
105
106 Trigger trigger = _scheduler.getTrigger(jobName, groupName);
107
108 if (CronTrigger.class.isAssignableFrom(trigger.getClass())) {
109 CronTrigger cronTrigger = CronTrigger.class.cast(trigger);
110
111 schedulerRequest =
112 SchedulerRequest.createRetrieveResponseRequest(
113 new com.liferay.portal.kernel.scheduler.CronTrigger(
114 jobName, groupName, cronTrigger.getStartTime(),
115 cronTrigger.getEndTime(),
116 cronTrigger.getCronExpression()),
117 description, message);
118 }
119 else if (SimpleTrigger.class.isAssignableFrom(
120 trigger.getClass())) {
121
122 SimpleTrigger simpleTrigger = SimpleTrigger.class.cast(
123 trigger);
124
125 schedulerRequest =
126 SchedulerRequest.createRetrieveResponseRequest(
127 new IntervalTrigger(
128 jobName, groupName,
129 simpleTrigger.getStartTime(),
130 simpleTrigger.getEndTime(),
131 simpleTrigger.getRepeatInterval()), description,
132 message);
133 }
134
135 if (schedulerRequest != null) {
136 requests.add(schedulerRequest);
137 }
138 }
139
140 return requests;
141 }
142 catch (org.quartz.SchedulerException se) {
143 throw new SchedulerException("Unable to retrieve job", se);
144 }
145 }
146
147 public void schedule(
148 com.liferay.portal.kernel.scheduler.Trigger trigger,
149 String description, String destination, Message message)
150 throws SchedulerException {
151
152 if (!PropsValues.SCHEDULER_ENABLED) {
153 return;
154 }
155
156 try {
157 String jobName = trigger.getJobName();
158 String groupName = trigger.getGroupName();
159
160 if (jobName.length() > JOB_NAME_MAX_LENGTH) {
161 jobName = jobName.substring(0, JOB_NAME_MAX_LENGTH);
162 }
163
164 if (groupName.length() > GROUP_NAME_MAX_LENGTH) {
165 groupName = groupName.substring(0, GROUP_NAME_MAX_LENGTH);
166 }
167
168 Trigger quartzTrigger = null;
169
170 if (trigger.getTriggerType() == TriggerType.CRON) {
171 try {
172 quartzTrigger = new CronTrigger(
173 jobName, groupName,
174 (String)trigger.getTriggerContent());
175 }
176 catch (ParseException pe) {
177 throw new SchedulerException(
178 "Unable to parse cron text " +
179 trigger.getTriggerContent());
180 }
181 }
182 else if (trigger.getTriggerType() == TriggerType.SIMPLE) {
183 long interval = (Long)trigger.getTriggerContent();
184
185 if (interval <= 0) {
186 if (_log.isDebugEnabled()) {
187 _log.debug(
188 "Not scheduling " + trigger.getJobName() +
189 " because interval is less than or equal to 0");
190 }
191
192 return;
193 }
194
195 quartzTrigger = new SimpleTrigger(
196 jobName, groupName, SimpleTrigger.REPEAT_INDEFINITELY,
197 interval);
198 }
199 else {
200 throw new SchedulerException(
201 "Unknown trigger type " + trigger.getTriggerType());
202 }
203
204 quartzTrigger.setJobName(jobName);
205 quartzTrigger.setJobGroup(groupName);
206
207 Date startDate = trigger.getStartDate();
208
209 if (startDate == null) {
210 if (ServerDetector.getServerId().equals(
211 ServerDetector.TOMCAT_ID)) {
212
213 quartzTrigger.setStartTime(
214 new Date(System.currentTimeMillis() + Time.MINUTE));
215 }
216 else {
217 quartzTrigger.setStartTime(
218 new Date(
219 System.currentTimeMillis() + Time.MINUTE * 3));
220 }
221 }
222 else {
223 quartzTrigger.setStartTime(startDate);
224 }
225
226 Date endDate = trigger.getEndDate();
227
228 if (endDate != null) {
229 quartzTrigger.setEndTime(endDate);
230 }
231
232 if ((description != null) &&
233 (description.length() > DESCRIPTION_MAX_LENGTH)) {
234
235 description = description.substring(0, DESCRIPTION_MAX_LENGTH);
236 }
237
238 if (message == null){
239 message = new Message();
240 }
241
242 message.put(
243 RECEIVER_KEY,
244 jobName.concat(StringPool.COLON).concat(groupName));
245
246 schedule(quartzTrigger, description, destination, message);
247 }
248 catch (RuntimeException re) {
249
250
253 }
254 }
255
256 public void shutdown() throws SchedulerException {
257 if (!PropsValues.SCHEDULER_ENABLED) {
258 return;
259 }
260
261 try {
262 _scheduler.shutdown(false);
263 }
264 catch (org.quartz.SchedulerException se) {
265 throw new SchedulerException("Unable to shutdown scheduler", se);
266 }
267 }
268
269 public void start() throws SchedulerException {
270 if (!PropsValues.SCHEDULER_ENABLED) {
271 return;
272 }
273
274 try {
275 _scheduler.start();
276 }
277 catch (org.quartz.SchedulerException se) {
278 throw new SchedulerException("Unable to start scheduler", se);
279 }
280 }
281
282 public void unschedule(
283 com.liferay.portal.kernel.scheduler.Trigger trigger)
284 throws SchedulerException {
285
286 if (!PropsValues.SCHEDULER_ENABLED) {
287 return;
288 }
289
290 String jobName = trigger.getJobName();
291 String groupName = trigger.getGroupName();
292
293 try {
294 _scheduler.unscheduleJob(jobName, groupName);
295 }
296 catch (org.quartz.SchedulerException se) {
297 throw new SchedulerException(
298 "Unable to unschedule job {jobName=" + jobName +
299 ", groupName=" + groupName + "}",
300 se);
301 }
302 }
303
304 protected void schedule(
305 Trigger trigger, String description,
306 String destination, Message message)
307 throws SchedulerException {
308
309 try {
310 String jobName = trigger.getName();
311 String groupName = trigger.getGroup();
312
313 JobDetail jobDetail = new JobDetail(
314 jobName, groupName, MessageSenderJob.class);
315
316 JobDataMap jobDataMap = jobDetail.getJobDataMap();
317
318 jobDataMap.put(DESCRIPTION, description);
319 jobDataMap.put(DESTINATION, destination);
320 jobDataMap.put(MESSAGE, message);
321
322 synchronized (this) {
323 _scheduler.unscheduleJob(jobName, groupName);
324 _scheduler.scheduleJob(jobDetail, trigger);
325 }
326 }
327 catch (ObjectAlreadyExistsException oare) {
328 if (_log.isInfoEnabled()) {
329 _log.info("Message is already scheduled");
330 }
331 }
332 catch (org.quartz.SchedulerException se) {
333 throw new SchedulerException("Unable to scheduled job", se);
334 }
335 }
336
337 @BeanReference(name = "com.liferay.portal.service.QuartzLocalService")
338 protected QuartzLocalService quartzLocalService;
339
340 private Log _log = LogFactoryUtil.getLog(QuartzSchedulerEngineImpl.class);
341
342 private Scheduler _scheduler;
343
344 }