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(
129: "Unexpected ACTIVE exchange: " + exchange);
130: }
131: }
132:
133: public void onJobExecute(JobExecutionContext context)
134: throws JobExecutionException {
135: if (logger.isDebugEnabled()) {
136: logger.debug("Firing Quartz Job with context: " + context);
137: }
138: try {
139: InOnly exchange = getExchangeFactory()
140: .createInOnlyExchange();
141: NormalizedMessage message = exchange.createMessage();
142: getMarshaler().populateNormalizedMessage(message, context);
143: exchange.setInMessage(message);
144: configureExchangeTarget(exchange);
145: send(exchange);
146: } catch (MessagingException e) {
147: throw new JobExecutionException(e);
148: }
149: }
150:
151: public void validate() throws DeploymentException {
152: super .validate();
153: if (trigger instanceof JobDetailAwareTrigger) {
154: if (jobDetail != null) {
155: throw new DeploymentException(
156: "jobDetail can not be set on endpoint and trigger at the same time");
157: }
158: jobDetail = ((JobDetailAwareTrigger) trigger)
159: .getJobDetail();
160: }
161: if (jobDetail == null) {
162: JobDetailBean j = new JobDetailBean();
163: j.setName(EndpointSupport.getKey(this ));
164: jobDetail = j;
165: }
166: if (triggers == null) {
167: triggers = new ArrayList<Trigger>();
168: }
169: if (trigger != null && triggers != null && triggers.size() > 0) {
170: throw new DeploymentException(
171: "trigger and triggers can not be set at the same time");
172: }
173: if (trigger != null) {
174: triggers.add(trigger);
175: }
176: if (calendars == null) {
177: calendars = new HashMap<String, Calendar>();
178: }
179: for (Trigger t : triggers) {
180: if (t.getCalendarName() != null
181: && calendars.get(t.getCalendarName()) == null) {
182: throw new DeploymentException(
183: "Trigger references an unknown calendar "
184: + t.getCalendarName());
185: }
186: t.setJobName(jobDetail.getName());
187: t.setJobGroup(jobDetail.getGroup());
188: }
189: }
190:
191: public void start() throws Exception {
192: QuartzComponent component = (QuartzComponent) getServiceUnit()
193: .getComponent();
194: Scheduler scheduler = component.getScheduler();
195: jobDetail.getJobDataMap().put(ServiceMixJob.COMPONENT_NAME,
196: component.getComponentName());
197: jobDetail.getJobDataMap().put(ServiceMixJob.ENDPOINT_NAME,
198: EndpointSupport.getKey(this ));
199: for (Map.Entry<String, Calendar> e : getCalendars().entrySet()) {
200: scheduler.addCalendar(e.getKey(), e.getValue(), true, true);
201: }
202: scheduler.addJob(getJobDetail(), true);
203: for (Trigger trg : getTriggers()) {
204: boolean triggerExists = scheduler.getTrigger(trg.getName(),
205: trg.getGroup()) != null;
206: if (!triggerExists) {
207: try {
208: scheduler.scheduleJob(trg);
209: } catch (ObjectAlreadyExistsException ex) {
210: scheduler.rescheduleJob(trg.getName(), trg
211: .getGroup(), trg);
212: }
213: } else {
214: scheduler.rescheduleJob(trg.getName(), trg.getGroup(),
215: trg);
216: }
217: }
218: super .start();
219: }
220:
221: public void stop() throws Exception {
222: super .stop();
223: Scheduler scheduler = ((QuartzComponent) getServiceUnit()
224: .getComponent()).getScheduler();
225: for (Trigger trg : getTriggers()) {
226: scheduler.unscheduleJob(trg.getName(), trg.getGroup());
227: }
228: scheduler.deleteJob(getJobDetail().getName(), getJobDetail()
229: .getGroup());
230: for (Map.Entry<String, Calendar> e : getCalendars().entrySet()) {
231: scheduler.deleteCalendar(e.getKey());
232: }
233: }
234:
235: }
|