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 LOG.debug("Scheduled Event notification received. Performing action: {} on route: {}", action, route.getId());
042
043 ServiceStatus routeStatus = route.getRouteContext().getCamelContext().getRouteStatus(route.getId());
044 if (action == Action.START) {
045 if (routeStatus == ServiceStatus.Stopped) {
046 startRoute(route);
047 } else if (routeStatus == ServiceStatus.Suspended) {
048 startConsumer(route.getConsumer());
049 }
050 } else if (action == Action.STOP) {
051 if ((routeStatus == ServiceStatus.Started) || (routeStatus == ServiceStatus.Suspended)) {
052 stopRoute(route, getRouteStopGracePeriod(), getTimeUnit());
053 }
054 } else if (action == Action.SUSPEND) {
055 if (routeStatus == ServiceStatus.Started) {
056 stopConsumer(route.getConsumer());
057 } else {
058 LOG.warn("Route is not in a started state and cannot be suspended. The current route state is {}", routeStatus);
059 }
060 } else if (action == Action.RESUME) {
061 if (routeStatus == ServiceStatus.Started) {
062 startConsumer(route.getConsumer());
063 } else {
064 LOG.warn("Route is not in a started state and cannot be resumed. The current route state is {}", routeStatus);
065 }
066 }
067 }
068
069 public void scheduleRoute(Action action) throws Exception {
070 Route route = scheduledRouteDetails.getRoute();
071
072 JobDetail jobDetail = createJobDetail(action, route);
073 Trigger trigger = createTrigger(action, route);
074 updateScheduledRouteDetails(action, jobDetail, trigger);
075
076 loadCallbackDataIntoSchedulerContext(jobDetail, action, route);
077 getScheduler().scheduleJob(jobDetail, trigger);
078
079 if (LOG.isInfoEnabled()) {
080 LOG.info("Scheduled trigger: {} for action: {} on route: ", new Object[]{trigger.getFullName(), action, route.getId()});
081 }
082 }
083
084 public void pauseRouteTrigger(Action action) throws SchedulerException {
085 String triggerName = retrieveTriggerName(action);
086 String triggerGroup = retrieveTriggerGroup(action);
087
088 getScheduler().pauseTrigger(triggerName, triggerGroup);
089
090 LOG.debug("Scheduled trigger: {}.{} is paused", triggerGroup, triggerName);
091 }
092
093 public void resumeRouteTrigger(Action action) throws SchedulerException {
094 String triggerName = retrieveTriggerName(action);
095 String triggerGroup = retrieveTriggerGroup(action);
096
097 getScheduler().resumeTrigger(triggerName, triggerGroup);
098
099 LOG.debug("Scheduled trigger: {}.{} is resumed", triggerGroup, triggerName);
100 }
101
102 public void deleteRouteJob(Action action) throws SchedulerException {
103 String jobDetailName = retrieveJobDetailName(action);
104 String jobDetailGroup = retrieveJobDetailGroup(action);
105
106 if (!getScheduler().isShutdown()) {
107 getScheduler().deleteJob(jobDetailName, jobDetailGroup);
108 }
109
110 LOG.debug("Scheduled Job: {}.{} is deleted", jobDetailGroup, jobDetailName);
111 }
112
113 protected JobDetail createJobDetail(Action action, Route route) throws Exception {
114 JobDetail jobDetail = null;
115
116 if (action == Action.START) {
117 jobDetail = new JobDetail(JOB_START + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
118 } else if (action == Action.STOP) {
119 jobDetail = new JobDetail(JOB_STOP + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
120 } else if (action == Action.SUSPEND) {
121 jobDetail = new JobDetail(JOB_SUSPEND + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
122 } else if (action == Action.RESUME) {
123 jobDetail = new JobDetail(JOB_RESUME + route.getId(), JOB_GROUP + route.getId(), ScheduledJob.class);
124 }
125
126 return jobDetail;
127 }
128
129 protected void updateScheduledRouteDetails(Action action, JobDetail jobDetail, Trigger trigger) throws Exception {
130 if (action == Action.START) {
131 scheduledRouteDetails.setStartJobDetail(jobDetail);
132 scheduledRouteDetails.setStartTrigger(trigger);
133 } else if (action == Action.STOP) {
134 scheduledRouteDetails.setStopJobDetail(jobDetail);
135 scheduledRouteDetails.setStopTrigger(trigger);
136 } else if (action == Action.SUSPEND) {
137 scheduledRouteDetails.setSuspendJobDetail(jobDetail);
138 scheduledRouteDetails.setSuspendTrigger(trigger);
139 } else if (action == Action.RESUME) {
140 scheduledRouteDetails.setResumeJobDetail(jobDetail);
141 scheduledRouteDetails.setResumeTrigger(trigger);
142 }
143 }
144
145 protected void loadCallbackDataIntoSchedulerContext(JobDetail jobDetail, Action action, Route route) throws SchedulerException {
146 getScheduler().getContext().put(jobDetail.getName(), new ScheduledJobState(action, route));
147 }
148
149 public String retrieveTriggerName(Action action) {
150 String triggerName = null;
151
152 if (action == Action.START) {
153 triggerName = scheduledRouteDetails.getStartTrigger().getName();
154 } else if (action == Action.STOP) {
155 triggerName = scheduledRouteDetails.getStopTrigger().getName();
156 } else if (action == Action.SUSPEND) {
157 triggerName = scheduledRouteDetails.getSuspendTrigger().getName();
158 } else if (action == Action.RESUME) {
159 triggerName = scheduledRouteDetails.getResumeTrigger().getName();
160 }
161
162 return triggerName;
163 }
164
165 public String retrieveTriggerGroup(Action action) {
166 String triggerGroup = null;
167
168 if (action == Action.START) {
169 triggerGroup = scheduledRouteDetails.getStartTrigger().getGroup();
170 } else if (action == Action.STOP) {
171 triggerGroup = scheduledRouteDetails.getStopTrigger().getGroup();
172 } else if (action == Action.SUSPEND) {
173 triggerGroup = scheduledRouteDetails.getSuspendTrigger().getGroup();
174 } else if (action == Action.RESUME) {
175 triggerGroup = scheduledRouteDetails.getResumeTrigger().getGroup();
176 }
177
178 return triggerGroup;
179 }
180
181 public String retrieveJobDetailName(Action action) {
182 String jobDetailName = null;
183
184 if (action == Action.START) {
185 jobDetailName = scheduledRouteDetails.getStartJobDetail().getName();
186 } else if (action == Action.STOP) {
187 jobDetailName = scheduledRouteDetails.getStopJobDetail().getName();
188 } else if (action == Action.SUSPEND) {
189 jobDetailName = scheduledRouteDetails.getSuspendJobDetail().getName();
190 } else if (action == Action.RESUME) {
191 jobDetailName = scheduledRouteDetails.getResumeJobDetail().getName();
192 }
193
194 return jobDetailName;
195 }
196
197 public String retrieveJobDetailGroup(Action action) {
198 String jobDetailGroup = null;
199
200 if (action == Action.START) {
201 jobDetailGroup = scheduledRouteDetails.getStartJobDetail().getGroup();
202 } else if (action == Action.STOP) {
203 jobDetailGroup = scheduledRouteDetails.getStopJobDetail().getGroup();
204 } else if (action == Action.SUSPEND) {
205 jobDetailGroup = scheduledRouteDetails.getSuspendJobDetail().getGroup();
206 } else if (action == Action.RESUME) {
207 jobDetailGroup = scheduledRouteDetails.getResumeJobDetail().getGroup();
208 }
209
210 return jobDetailGroup;
211 }
212
213 public ScheduledRouteDetails getScheduledRouteDetails() {
214 return scheduledRouteDetails;
215 }
216
217 public void setScheduledRouteDetails(ScheduledRouteDetails scheduledRouteDetails) {
218 this.scheduledRouteDetails = scheduledRouteDetails;
219 }
220
221 public void setScheduler(Scheduler scheduler) {
222 this.scheduler = scheduler;
223 }
224
225 public Scheduler getScheduler() {
226 return scheduler;
227 }
228
229 public void setRouteStopGracePeriod(int routeStopGracePeriod) {
230 this.routeStopGracePeriod = routeStopGracePeriod;
231 }
232
233 public int getRouteStopGracePeriod() {
234 return routeStopGracePeriod;
235 }
236
237 public void setTimeUnit(TimeUnit timeUnit) {
238 this.timeUnit = timeUnit;
239 }
240
241 public TimeUnit getTimeUnit() {
242 return timeUnit;
243 }
244
245 }