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