001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.routepolicy.quartz;
018
019 import java.util.concurrent.TimeUnit;
020
021 import org.apache.camel.Route;
022 import org.apache.camel.ServiceStatus;
023 import org.apache.camel.impl.RoutePolicySupport;
024 import org.quartz.JobDetail;
025 import org.quartz.Scheduler;
026 import org.quartz.SchedulerException;
027 import org.quartz.Trigger;
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031 public abstract class ScheduledRoutePolicy extends RoutePolicySupport implements ScheduledRoutePolicyConstants {
032 private static final transient Logger LOG = LoggerFactory.getLogger(ScheduledRoutePolicy.class);
033 protected ScheduledRouteDetails scheduledRouteDetails;
034 private Scheduler scheduler;
035 private int routeStopGracePeriod;
036 private TimeUnit timeUnit;
037
038 protected abstract Trigger createTrigger(Action action, Route route) throws Exception;
039
040 protected void onJobExecute(Action action, Route route) throws Exception {
041 if (LOG.isDebugEnabled()) {
042 LOG.debug("Scheduled Event notification received. Performing requested operation " + action + " for route " + route.getId());
043 }
044 ServiceStatus routeStatus = route.getRouteContext().getCamelContext().getRouteStatus(route.getId());
045 if (action == Action.START) {
046 if (routeStatus == ServiceStatus.Stopped) {
047 startRoute(route);
048 } else if (routeStatus == ServiceStatus.Suspended) {
049 startConsumer(route.getConsumer());
050 }
051 } else if (action == Action.STOP) {
052 if ((routeStatus == ServiceStatus.Started) || (routeStatus == ServiceStatus.Suspended)) {
053 stopRoute(route, getRouteStopGracePeriod(), getTimeUnit());
054 }
055 } else if (action == Action.SUSPEND) {
056 if (routeStatus == ServiceStatus.Started) {
057 stopConsumer(route.getConsumer());
058 } else {
059 if (LOG.isWarnEnabled()) {
060 LOG.warn("Route is not in a started state and cannot be suspended. The current route state is " + routeStatus);
061 }
062 }
063 } else if (action == Action.RESUME) {
064 if (routeStatus == ServiceStatus.Started) {
065 startConsumer(route.getConsumer());
066 } else {
067 if (LOG.isWarnEnabled()) {
068 LOG.warn("Route is not in a started state and cannot be resumed. The current route state is " + routeStatus);
069 }
070 }
071 }
072 }
073
074 public void scheduleRoute(Action action) throws Exception {
075 Route route = scheduledRouteDetails.getRoute();
076
077 JobDetail jobDetail = createJobDetail(action, route);
078 Trigger trigger = createTrigger(action, route);
079 updateScheduledRouteDetails(action, jobDetail, trigger);
080
081 loadCallbackDataIntoSchedulerContext(jobDetail, action, route);
082 getScheduler().scheduleJob(jobDetail, trigger);
083
084 if (LOG.isDebugEnabled()) {
085 LOG.debug("Scheduled Trigger: " + trigger.getFullName() + " is operational");
086 }
087 }
088
089 public void pauseRouteTrigger(Action action) throws SchedulerException {
090 String triggerName = retrieveTriggerName(action);
091 String triggerGroup = retrieveTriggerGroup(action);
092
093 getScheduler().pauseTrigger(triggerName, triggerGroup);
094
095 if (LOG.isDebugEnabled()) {
096 LOG.debug("Scheduled Trigger: " + triggerGroup + "." + triggerName + " is paused");
097 }
098 }
099
100 public void resumeRouteTrigger(Action action) throws SchedulerException {
101 String triggerName = retrieveTriggerName(action);
102 String triggerGroup = retrieveTriggerGroup(action);
103
104 getScheduler().resumeTrigger(triggerName, triggerGroup);
105
106 if (LOG.isDebugEnabled()) {
107 LOG.debug("Scheduled Trigger: " + triggerGroup + "." + triggerName + " has been resumed");
108 }
109 }
110
111 public void deleteRouteJob(Action action) throws SchedulerException {
112 String jobDetailName = retrieveJobDetailName(action);
113 String jobDetailGroup = retrieveJobDetailGroup(action);
114
115 if (!getScheduler().isShutdown()) {
116 getScheduler().deleteJob(jobDetailName, jobDetailGroup);
117 }
118
119 if (LOG.isDebugEnabled()) {
120 LOG.debug("Scheduled Job: " + jobDetailGroup + "." + jobDetailName + " has been deleted");
121 }
122 }
123
124 protected JobDetail createJobDetail(Action action, Route route) throws Exception {
125 JobDetail jobDetail = null;
126
127 if (action == Action.START) {
128 jobDetail = new JobDetail(JOB_START + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
129 } else if (action == Action.STOP) {
130 jobDetail = new JobDetail(JOB_STOP + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
131 } else if (action == Action.SUSPEND) {
132 jobDetail = new JobDetail(JOB_SUSPEND + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
133 } else if (action == Action.RESUME) {
134 jobDetail = new JobDetail(JOB_RESUME + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
135 }
136
137 return jobDetail;
138 }
139
140 protected void updateScheduledRouteDetails(Action action, JobDetail jobDetail, Trigger trigger) throws Exception {
141 if (action == Action.START) {
142 scheduledRouteDetails.setStartJobDetail(jobDetail);
143 scheduledRouteDetails.setStartTrigger(trigger);
144 } else if (action == Action.STOP) {
145 scheduledRouteDetails.setStopJobDetail(jobDetail);
146 scheduledRouteDetails.setStopTrigger(trigger);
147 } else if (action == Action.SUSPEND) {
148 scheduledRouteDetails.setSuspendJobDetail(jobDetail);
149 scheduledRouteDetails.setSuspendTrigger(trigger);
150 } else if (action == Action.RESUME) {
151 scheduledRouteDetails.setResumeJobDetail(jobDetail);
152 scheduledRouteDetails.setResumeTrigger(trigger);
153 }
154 }
155
156 protected void loadCallbackDataIntoSchedulerContext(JobDetail jobDetail, Action action, Route route) throws SchedulerException {
157 getScheduler().getContext().put(jobDetail.getName(), new ScheduledJobState(action, route));
158 }
159
160 public String retrieveTriggerName(Action action) {
161 String triggerName = null;
162
163 if (action == Action.START) {
164 triggerName = scheduledRouteDetails.getStartTrigger().getName();
165 } else if (action == Action.STOP) {
166 triggerName = scheduledRouteDetails.getStopTrigger().getName();
167 } else if (action == Action.SUSPEND) {
168 triggerName = scheduledRouteDetails.getSuspendTrigger().getName();
169 } else if (action == Action.RESUME) {
170 triggerName = scheduledRouteDetails.getResumeTrigger().getName();
171 }
172
173 return triggerName;
174 }
175
176 public String retrieveTriggerGroup(Action action) {
177 String triggerGroup = null;
178
179 if (action == Action.START) {
180 triggerGroup = scheduledRouteDetails.getStartTrigger().getGroup();
181 } else if (action == Action.STOP) {
182 triggerGroup = scheduledRouteDetails.getStopTrigger().getGroup();
183 } else if (action == Action.SUSPEND) {
184 triggerGroup = scheduledRouteDetails.getSuspendTrigger().getGroup();
185 } else if (action == Action.RESUME) {
186 triggerGroup = scheduledRouteDetails.getResumeTrigger().getGroup();
187 }
188
189 return triggerGroup;
190 }
191
192 public String retrieveJobDetailName(Action action) {
193 String jobDetailName = null;
194
195 if (action == Action.START) {
196 jobDetailName = scheduledRouteDetails.getStartJobDetail().getName();
197 } else if (action == Action.STOP) {
198 jobDetailName = scheduledRouteDetails.getStopJobDetail().getName();
199 } else if (action == Action.SUSPEND) {
200 jobDetailName = scheduledRouteDetails.getSuspendJobDetail().getName();
201 } else if (action == Action.RESUME) {
202 jobDetailName = scheduledRouteDetails.getResumeJobDetail().getName();
203 }
204
205 return jobDetailName;
206 }
207
208 public String retrieveJobDetailGroup(Action action) {
209 String jobDetailGroup = null;
210
211 if (action == Action.START) {
212 jobDetailGroup = scheduledRouteDetails.getStartJobDetail().getGroup();
213 } else if (action == Action.STOP) {
214 jobDetailGroup = scheduledRouteDetails.getStopJobDetail().getGroup();
215 } else if (action == Action.SUSPEND) {
216 jobDetailGroup = scheduledRouteDetails.getSuspendJobDetail().getGroup();
217 } else if (action == Action.RESUME) {
218 jobDetailGroup = scheduledRouteDetails.getResumeJobDetail().getGroup();
219 }
220
221 return jobDetailGroup;
222 }
223
224 public ScheduledRouteDetails getScheduledRouteDetails() {
225 return scheduledRouteDetails;
226 }
227
228 public void setScheduledRouteDetails(ScheduledRouteDetails scheduledRouteDetails) {
229 this.scheduledRouteDetails = scheduledRouteDetails;
230 }
231
232 public void setScheduler(Scheduler scheduler) {
233 this.scheduler = scheduler;
234 }
235
236 public Scheduler getScheduler() {
237 return scheduler;
238 }
239
240 public void setRouteStopGracePeriod(int routeStopGracePeriod) {
241 this.routeStopGracePeriod = routeStopGracePeriod;
242 }
243
244 public int getRouteStopGracePeriod() {
245 return routeStopGracePeriod;
246 }
247
248 public void setTimeUnit(TimeUnit timeUnit) {
249 this.timeUnit = timeUnit;
250 }
251
252 public TimeUnit getTimeUnit() {
253 return timeUnit;
254 }
255
256 }