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.servicemix.quartz;
018
019 import java.util.ArrayList;
020 import java.util.HashMap;
021 import java.util.List;
022 import java.util.Map;
023
024 import javax.jbi.management.DeploymentException;
025 import javax.jbi.messaging.ExchangeStatus;
026 import javax.jbi.messaging.InOnly;
027 import javax.jbi.messaging.MessageExchange;
028 import javax.jbi.messaging.MessagingException;
029 import javax.jbi.messaging.NormalizedMessage;
030
031 import org.apache.servicemix.common.EndpointSupport;
032 import org.apache.servicemix.common.endpoints.ConsumerEndpoint;
033 import org.apache.servicemix.quartz.support.DefaultQuartzMarshaler;
034 import org.apache.servicemix.quartz.support.JobDetailBean;
035 import org.apache.servicemix.quartz.support.QuartzMarshaler;
036 import org.apache.servicemix.quartz.support.ServiceMixJob;
037 import org.quartz.Calendar;
038 import org.quartz.JobDetail;
039 import org.quartz.JobExecutionContext;
040 import org.quartz.JobExecutionException;
041 import org.quartz.ObjectAlreadyExistsException;
042 import org.quartz.Scheduler;
043 import org.quartz.Trigger;
044 import org.springframework.scheduling.quartz.JobDetailAwareTrigger;
045
046 /**
047 * @org.apache.xbean.XBean element="endpoint"
048 */
049 public class QuartzEndpoint extends ConsumerEndpoint {
050
051 private Trigger trigger;
052 private List<Trigger> triggers;
053 private Map<String, Calendar> calendars;
054 private JobDetail jobDetail;
055 private QuartzMarshaler marshaler = new DefaultQuartzMarshaler();
056
057 /**
058 * @return the triggers
059 */
060 public List<Trigger> getTriggers() {
061 return triggers;
062 }
063
064 /**
065 * @param triggers the triggers to set
066 */
067 public void setTriggers(List<Trigger> triggers) {
068 this.triggers = triggers;
069 }
070
071 /**
072 * @return the trigger
073 */
074 public Trigger getTrigger() {
075 return trigger;
076 }
077
078 /**
079 * @param trigger the trigger to set
080 */
081 public void setTrigger(Trigger trigger) {
082 this.trigger = trigger;
083 }
084
085 /**
086 * @return the calendar
087 */
088 public Map<String, Calendar> getCalendars() {
089 return calendars;
090 }
091
092 /**
093 * @param calendar the calendar to set
094 */
095 public void setCalendars(Map<String, Calendar> calendars) {
096 this.calendars = calendars;
097 }
098
099 /**
100 * @return the job
101 */
102 public JobDetail getJobDetail() {
103 return jobDetail;
104 }
105
106 /**
107 * @param job the job to set
108 */
109 public void setJobDetail(JobDetail job) {
110 this.jobDetail = job;
111 }
112
113 public QuartzMarshaler getMarshaler() {
114 return marshaler;
115 }
116
117 public void setMarshaler(QuartzMarshaler marshaler) {
118 this.marshaler = marshaler;
119 }
120
121 @Override
122 public String getLocationURI() {
123 return null;
124 }
125
126 public void process(MessageExchange exchange) throws Exception {
127 if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
128 throw new IllegalStateException("Unexpected ACTIVE exchange: " + exchange);
129 }
130 }
131
132 public void onJobExecute(JobExecutionContext context) throws JobExecutionException {
133 if (logger.isDebugEnabled()) {
134 logger.debug("Firing Quartz Job with context: " + context);
135 }
136 try {
137 InOnly exchange = getExchangeFactory().createInOnlyExchange();
138 NormalizedMessage message = exchange.createMessage();
139 getMarshaler().populateNormalizedMessage(message, context);
140 exchange.setInMessage(message);
141 configureExchangeTarget(exchange);
142 send(exchange);
143 } catch (MessagingException e) {
144 throw new JobExecutionException(e);
145 }
146 }
147
148 public void validate() throws DeploymentException {
149 super.validate();
150 if (trigger instanceof JobDetailAwareTrigger) {
151 if (jobDetail != null) {
152 throw new DeploymentException("jobDetail can not be set on endpoint and trigger at the same time");
153 }
154 jobDetail = ((JobDetailAwareTrigger) trigger).getJobDetail();
155 }
156 if (jobDetail == null) {
157 JobDetailBean j = new JobDetailBean();
158 j.setName(EndpointSupport.getKey(this));
159 jobDetail = j;
160 }
161 if (triggers == null) {
162 triggers = new ArrayList<Trigger>();
163 }
164 if (trigger != null && triggers != null && triggers.size() > 0) {
165 throw new DeploymentException("trigger and triggers can not be set at the same time");
166 }
167 if (trigger != null) {
168 triggers.add(trigger);
169 }
170 if (calendars == null) {
171 calendars = new HashMap<String, Calendar>();
172 }
173 for (Trigger t : triggers) {
174 if (t.getCalendarName() != null && calendars.get(t.getCalendarName()) == null) {
175 throw new DeploymentException("Trigger references an unknown calendar " + t.getCalendarName());
176 }
177 t.setJobName(jobDetail.getName());
178 t.setJobGroup(jobDetail.getGroup());
179 }
180 }
181
182 public void start() throws Exception {
183 QuartzComponent component = (QuartzComponent) getServiceUnit().getComponent();
184 Scheduler scheduler = component.getScheduler();
185 jobDetail.getJobDataMap().put(ServiceMixJob.COMPONENT_NAME, component.getComponentName());
186 jobDetail.getJobDataMap().put(ServiceMixJob.ENDPOINT_NAME, EndpointSupport.getKey(this));
187 for (Map.Entry<String, Calendar> e : getCalendars().entrySet()) {
188 scheduler.addCalendar(e.getKey(), e.getValue(), true, true);
189 }
190 scheduler.addJob(getJobDetail(), true);
191 for (Trigger trg : getTriggers()) {
192 boolean triggerExists = scheduler.getTrigger(trg.getName(), trg.getGroup()) != null;
193 if (!triggerExists) {
194 try {
195 scheduler.scheduleJob(trg);
196 } catch (ObjectAlreadyExistsException ex) {
197 scheduler.rescheduleJob(trg.getName(), trg.getGroup(), trg);
198 }
199 } else {
200 scheduler.rescheduleJob(trg.getName(), trg.getGroup(), trg);
201 }
202 }
203 super.start();
204 }
205
206 public void stop() throws Exception {
207 super.stop();
208 Scheduler scheduler = ((QuartzComponent) getServiceUnit().getComponent()).getScheduler();
209 for (Trigger trg : getTriggers()) {
210 scheduler.unscheduleJob(trg.getName(), trg.getGroup());
211 }
212 scheduler.deleteJob(getJobDetail().getName(), getJobDetail().getGroup());
213 for (Map.Entry<String, Calendar> e : getCalendars().entrySet()) {
214 scheduler.deleteCalendar(e.getKey());
215 }
216 }
217
218 }