View Javadoc

1   /*
2    * $Id: QuartzMessageDispatcher.java 22396 2011-07-12 21:26:04Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.quartz;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.endpoint.OutboundEndpoint;
17  import org.mule.config.i18n.CoreMessages;
18  import org.mule.transport.AbstractMessageDispatcher;
19  import org.mule.transport.NullPayload;
20  import org.mule.transport.quartz.config.JobConfig;
21  import org.mule.transport.quartz.i18n.QuartzMessages;
22  import org.mule.transport.quartz.jobs.CustomJob;
23  import org.mule.transport.quartz.jobs.CustomJobConfig;
24  import org.mule.transport.quartz.jobs.CustomJobFromMessageConfig;
25  import org.mule.transport.quartz.jobs.ScheduledDispatchJobConfig;
26  
27  import java.util.Date;
28  
29  import org.quartz.CronTrigger;
30  import org.quartz.Job;
31  import org.quartz.JobDataMap;
32  import org.quartz.JobDetail;
33  import org.quartz.Scheduler;
34  import org.quartz.SimpleTrigger;
35  import org.quartz.Trigger;
36  
37  /**
38   * Can schedule a Job with the Quartz scheduler. The event must contain the Job to
39   * invoke or have it set as a property. Time trigger properties can be set on the
40   * event to control how and when the event is fired.
41   */
42  public class QuartzMessageDispatcher extends AbstractMessageDispatcher
43  {
44  
45      public QuartzMessageDispatcher(OutboundEndpoint endpoint)
46      {
47          super(endpoint);
48      }
49  
50      @Override
51      protected void doDispose()
52      {
53          // template method
54      }
55  
56      @Override
57      protected void doDispatch(MuleEvent event) throws Exception
58      {
59          JobConfig jobConfig = (JobConfig) endpoint.getProperty(QuartzConnector.PROPERTY_JOB_CONFIG);
60          if (jobConfig == null)
61          {
62              throw new IllegalArgumentException(CoreMessages.objectIsNull(QuartzConnector.PROPERTY_JOB_CONFIG).getMessage());
63          }
64  
65          JobDetail jobDetail = new JobDetail();
66          // make the job name unique per endpoint (MULE-753)
67          jobDetail.setName(endpoint.getEndpointURI().getAddress() + "-" + event.getId());
68  
69          JobDataMap jobDataMap = new JobDataMap();
70          jobDataMap.put(QuartzConnector.PROPERTY_JOB_DYNAMIC, Boolean.TRUE);
71          MuleMessage msg = event.getMessage();
72          // populate from invocation and outbound scopes only
73          for (String key : msg.getInvocationPropertyNames())
74          {
75              jobDataMap.put(key, msg.getInvocationProperty(key));
76          }
77          for (String key : msg.getOutboundPropertyNames())
78          {
79              jobDataMap.put(key, msg.getOutboundProperty(key));
80          }
81  
82          if (jobConfig instanceof ScheduledDispatchJobConfig) 
83          {
84              ScheduledDispatchJobConfig scheduledDispatchJobConfig = (ScheduledDispatchJobConfig) jobConfig;
85              String endpointRef = event.getMuleContext().getExpressionManager().parse(
86                  scheduledDispatchJobConfig.getEndpointRef(), event.getMessage());
87  
88              jobDataMap.put("endpointRef", endpointRef);
89          }
90          jobDetail.setJobDataMap(jobDataMap);
91  
92          Job job = null;
93          // work out what we're actually calling
94          Object payload = event.getMessage().getPayload();
95  
96          if(jobConfig instanceof CustomJobConfig)
97          {
98              job = ((CustomJobConfig) jobConfig).getJob();
99          }
100         else if(jobConfig instanceof CustomJobFromMessageConfig)
101         {
102             job = ((CustomJobFromMessageConfig) jobConfig).getJob(msg);
103             //rewrite the jobConfig to the real Jobconfig on the message
104             jobConfig = ((CustomJobFromMessageConfig) jobConfig).getJobConfig(msg);
105         }
106 
107         jobDataMap.put(QuartzConnector.PROPERTY_JOB_CONFIG, jobConfig);        
108         jobDetail.setJobClass(jobConfig.getJobClass());
109         // If there has been a job created or found then we default to a customJob configuration
110         if (job != null)
111         {
112             jobDataMap.put(QuartzConnector.PROPERTY_JOB_OBJECT, job);
113             jobDetail.setJobClass(CustomJob.class);
114         }
115        
116         // The payload will be ignored by the CustomJob - don't know why we need it here
117         //RM: The custom job may want the message and the Job type may not be delegating job
118         jobDataMap.put(QuartzConnector.PROPERTY_PAYLOAD, payload);
119 
120         Trigger trigger;
121         String cronExpression = jobDataMap.getString(QuartzConnector.PROPERTY_CRON_EXPRESSION);
122         String repeatInterval = jobDataMap.getString(QuartzConnector.PROPERTY_REPEAT_INTERVAL);
123         String repeatCount = jobDataMap.getString(QuartzConnector.PROPERTY_REPEAT_COUNT);
124         String startDelay = jobDataMap.getString(QuartzConnector.PROPERTY_START_DELAY);
125         String groupName = jobConfig.getGroupName();
126         String jobGroupName = jobConfig.getJobGroupName();
127 
128         if (groupName == null)
129         {
130             groupName = QuartzConnector.DEFAULT_GROUP_NAME;
131         }
132         if (jobGroupName == null)
133         {
134             jobGroupName = groupName;
135         }
136 
137         jobDetail.setGroup(groupName);
138 
139         if (cronExpression != null)
140         {
141             CronTrigger ctrigger = new CronTrigger();
142             ctrigger.setCronExpression(cronExpression);
143             trigger = ctrigger;
144         }
145         else if (repeatInterval != null)
146         {
147             SimpleTrigger strigger = new SimpleTrigger();
148             strigger.setRepeatInterval(Long.parseLong(repeatInterval));
149             if (repeatCount != null)
150             {
151                 strigger.setRepeatCount(Integer.parseInt(repeatCount));
152             }
153             else
154             {
155                 strigger.setRepeatCount(-1);
156             }
157             trigger = strigger;
158         }
159         else
160         {
161             throw new IllegalArgumentException(
162                 QuartzMessages.cronExpressionOrIntervalMustBeSet().getMessage());
163         }
164         trigger.setName(endpoint.getEndpointURI().toString() + "-" + event.getId());
165         trigger.setGroup(groupName);
166         trigger.setJobName(jobDetail.getName());
167         trigger.setJobGroup(jobGroupName);
168 
169         Scheduler scheduler = ((QuartzConnector) this.getConnector()).getQuartzScheduler();
170 
171         // Minimize the the time window capturing the start time and scheduling the job.
172         long start = System.currentTimeMillis();
173         if (startDelay != null)
174         {
175             start += Long.parseLong(startDelay);
176         }
177         trigger.setStartTime(new Date(start));
178 
179         scheduler.scheduleJob(jobDetail, trigger);
180     }
181 
182     @Override
183     protected MuleMessage doSend(MuleEvent event) throws Exception
184     {
185         doDispatch(event);
186         return new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
187     }
188 
189     @Override
190     protected void doConnect() throws Exception
191     {
192         // template method
193     }
194 
195     @Override
196     protected void doDisconnect() throws Exception
197     {
198         // template method
199     }
200 
201 }