1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
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.scheduler.SchedulerEngine;
21  import com.liferay.portal.kernel.scheduler.SchedulerException;
22  import com.liferay.portal.kernel.scheduler.messaging.SchedulerRequest;
23  import com.liferay.portal.kernel.util.ServerDetector;
24  import com.liferay.portal.kernel.util.Time;
25  import com.liferay.portal.kernel.util.Validator;
26  import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
27  import com.liferay.portal.scheduler.job.MessageSenderJob;
28  import com.liferay.portal.service.QuartzLocalService;
29  import com.liferay.portal.util.PropsUtil;
30  import com.liferay.portal.util.PropsValues;
31  
32  import java.text.ParseException;
33  
34  import java.util.ArrayList;
35  import java.util.Date;
36  import java.util.List;
37  
38  import org.quartz.CronTrigger;
39  import org.quartz.JobDataMap;
40  import org.quartz.JobDetail;
41  import org.quartz.ObjectAlreadyExistsException;
42  import org.quartz.Scheduler;
43  import org.quartz.SimpleTrigger;
44  import org.quartz.Trigger;
45  import org.quartz.impl.StdSchedulerFactory;
46  
47  /**
48   * <a href="QuartzSchedulerEngineImpl.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Michael C. Han
51   * @author Bruno Farache
52   * @author Wesley Gong
53   */
54  public class QuartzSchedulerEngineImpl implements SchedulerEngine {
55  
56      public void afterPropertiesSet() {
57          try {
58              if (!PropsValues.SCHEDULER_ENABLED) {
59                  return;
60              }
61  
62              StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
63  
64              schedulerFactory.initialize(
65                  PropsUtil.getProperties("org.quartz.", false));
66  
67              quartzLocalService.checkQuartzTables();
68  
69              _scheduler = schedulerFactory.getScheduler();
70          }
71          catch (Exception e) {
72              _log.error("Unable to initialize engine", e);
73          }
74      }
75  
76      public List<SchedulerRequest> getScheduledJobs(String groupName)
77          throws SchedulerException {
78  
79          if (!PropsValues.SCHEDULER_ENABLED) {
80              return new ArrayList<SchedulerRequest>();
81          }
82  
83          try {
84              String[] jobNames = _scheduler.getJobNames(groupName);
85  
86              List<SchedulerRequest> requests = new ArrayList<SchedulerRequest>();
87  
88              for (String jobName : jobNames) {
89                  JobDetail jobDetail = _scheduler.getJobDetail(
90                      jobName, groupName);
91  
92                  if (jobDetail == null) {
93                      continue;
94                  }
95  
96                  JobDataMap jobDataMap = jobDetail.getJobDataMap();
97  
98                  String description = jobDataMap.getString(DESCRIPTION);
99                  String messageBody = jobDataMap.getString(MESSAGE_BODY);
100 
101                 SchedulerRequest schedulerRequest = null;
102 
103                 Trigger trigger = _scheduler.getTrigger(jobName, groupName);
104 
105                 if (CronTrigger.class.isAssignableFrom(trigger.getClass())) {
106                     CronTrigger cronTrigger = CronTrigger.class.cast(trigger);
107 
108                     schedulerRequest =
109                         SchedulerRequest.createRetrieveResponseRequest(
110                             jobName, groupName, cronTrigger.getCronExpression(),
111                             cronTrigger.getStartTime(),
112                             cronTrigger.getEndTime(), description, messageBody);
113                 }
114                 else if (SimpleTrigger.class.isAssignableFrom(
115                             trigger.getClass())) {
116 
117                     SimpleTrigger simpleTrigger = SimpleTrigger.class.cast(
118                         trigger);
119 
120                     schedulerRequest =
121                         SchedulerRequest.createRetrieveResponseRequest(
122                             jobName, groupName,
123                             simpleTrigger.getRepeatInterval(),
124                             simpleTrigger.getStartTime(),
125                             simpleTrigger.getEndTime(), description,
126                             messageBody);
127                 }
128 
129                 if (schedulerRequest != null) {
130                     requests.add(schedulerRequest);
131                 }
132             }
133 
134             return requests;
135         }
136         catch (org.quartz.SchedulerException se) {
137             throw new SchedulerException("Unable to retrieve job", se);
138         }
139     }
140 
141     public void schedule(
142             String groupName, long interval, Date startDate, Date endDate,
143             String description, String destination, String messageBody)
144         throws SchedulerException {
145 
146         schedule(
147             null, groupName, interval, startDate, endDate, description,
148             destination, messageBody);
149     }
150 
151     public void schedule(
152             String groupName, String cronText, Date startDate, Date endDate,
153             String description, String destination, String messageBody)
154         throws SchedulerException {
155 
156         schedule(
157             null, groupName, cronText, startDate, endDate, description,
158             destination, messageBody);
159     }
160 
161     public void schedule(
162             String jobName, String groupName, long interval, Date startDate,
163             Date endDate, String description, String destinationName,
164             String messageBody)
165         throws SchedulerException {
166 
167         if (!PropsValues.SCHEDULER_ENABLED) {
168             return;
169         }
170 
171         if (Validator.isNull(jobName)) {
172             jobName = PortalUUIDUtil.generate();
173         }
174 
175         try {
176             SimpleTrigger simpleTrigger = new SimpleTrigger(
177                 jobName, groupName, SimpleTrigger.REPEAT_INDEFINITELY,
178                 interval);
179 
180             simpleTrigger.setJobName(jobName);
181             simpleTrigger.setJobGroup(groupName);
182 
183             if (startDate == null) {
184                 if (ServerDetector.getServerId().equals(
185                         ServerDetector.TOMCAT_ID)) {
186 
187                     simpleTrigger.setStartTime(
188                         new Date(System.currentTimeMillis() + Time.MINUTE));
189                 }
190                 else {
191                     simpleTrigger.setStartTime(
192                         new Date(
193                         System.currentTimeMillis() + Time.MINUTE * 3));
194                 }
195             }
196             else {
197                 simpleTrigger.setStartTime(startDate);
198             }
199 
200             if (endDate != null) {
201                 simpleTrigger.setEndTime(endDate);
202             }
203 
204             schedule(
205                 groupName, simpleTrigger, description, destinationName,
206                 messageBody);
207         }
208         catch (RuntimeException re) {
209 
210             // ServerDetector will throw an exception when JobSchedulerImpl is
211             // initialized in a test environment
212 
213         }
214     }
215 
216     public void schedule(
217             String jobName, String groupName, String cronText, Date startDate,
218             Date endDate, String description, String destinationName,
219             String messageBody)
220         throws SchedulerException {
221 
222         if (!PropsValues.SCHEDULER_ENABLED) {
223             return;
224         }
225 
226         if (Validator.isNull(jobName)) {
227             jobName = PortalUUIDUtil.generate();
228         }
229 
230         try {
231             CronTrigger cronTrigger = new CronTrigger(
232                 jobName, groupName, jobName, groupName, cronText);
233 
234             if (startDate == null) {
235                 if (ServerDetector.getServerId().equals(
236                         ServerDetector.TOMCAT_ID)) {
237 
238                     cronTrigger.setStartTime(
239                         new Date(System.currentTimeMillis() + Time.MINUTE));
240                 }
241                 else {
242                     cronTrigger.setStartTime(
243                         new Date(System.currentTimeMillis() + Time.MINUTE * 3));
244                 }
245             }
246             else {
247                 cronTrigger.setStartTime(startDate);
248             }
249 
250             if (endDate != null) {
251                 cronTrigger.setEndTime(endDate);
252             }
253 
254             schedule(
255                 groupName, cronTrigger, description, destinationName,
256                 messageBody);
257         }
258         catch(ParseException pe) {
259             throw new SchedulerException("Unable to parse cron text", pe);
260         }
261         catch (RuntimeException re) {
262 
263             // ServerDetector will throw an exception when JobSchedulerImpl is
264             // initialized in a test environment
265 
266         }
267     }
268 
269     public void shutdown() throws SchedulerException {
270         if (!PropsValues.SCHEDULER_ENABLED) {
271             return;
272         }
273 
274         try {
275             _scheduler.shutdown(false);
276         }
277         catch (org.quartz.SchedulerException se) {
278             throw new SchedulerException("Unable to shutdown scheduler", se);
279         }
280     }
281 
282     public void start() throws SchedulerException {
283         if (!PropsValues.SCHEDULER_ENABLED) {
284             return;
285         }
286 
287         try {
288             _scheduler.start();
289         }
290         catch (org.quartz.SchedulerException se) {
291             throw new SchedulerException("Unable to start scheduler", se);
292         }
293     }
294 
295     public void unschedule(String jobName, String groupName)
296         throws SchedulerException {
297 
298         if (!PropsValues.SCHEDULER_ENABLED) {
299             return;
300         }
301 
302         try {
303             _scheduler.unscheduleJob(jobName, groupName);
304         }
305         catch (org.quartz.SchedulerException se) {
306             throw new SchedulerException(
307                 "Unable to unschedule job {jobName=" + jobName +
308                     ", groupName=" + groupName + "}",
309                 se);
310         }
311     }
312 
313     protected void schedule(
314             String groupName, Trigger trigger, String description,
315             String destination, String messageBody)
316         throws SchedulerException {
317 
318         try {
319             JobDetail jobDetail = new JobDetail(
320                 trigger.getJobName(), groupName, MessageSenderJob.class);
321 
322             JobDataMap jobDataMap = jobDetail.getJobDataMap();
323 
324             jobDataMap.put(DESCRIPTION, description);
325             jobDataMap.put(DESTINATION, destination);
326             jobDataMap.put(MESSAGE_BODY, messageBody);
327 
328             synchronized (this) {
329                 _scheduler.unscheduleJob(trigger.getJobName(), groupName);
330                 _scheduler.scheduleJob(jobDetail, trigger);
331             }
332         }
333         catch (ObjectAlreadyExistsException oare) {
334             if (_log.isInfoEnabled()) {
335                 _log.info("Message is already scheduled");
336             }
337         }
338         catch (org.quartz.SchedulerException se) {
339             throw new SchedulerException("Unable to scheduled job", se);
340         }
341     }
342 
343     @BeanReference(name = "com.liferay.portal.service.QuartzLocalService")
344     protected QuartzLocalService quartzLocalService;
345 
346     private Log _log = LogFactoryUtil.getLog(QuartzSchedulerEngineImpl.class);
347 
348     private Scheduler _scheduler;
349 
350 }