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