View Javadoc

1   /*
2    * $Id: QuartzMessageDispatcher.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.providers.quartz;
12  
13  import org.mule.MuleManager;
14  import org.mule.providers.AbstractMessageDispatcher;
15  import org.mule.providers.quartz.i18n.QuartzMessages;
16  import org.mule.providers.quartz.jobs.DelegatingJob;
17  import org.mule.umo.UMOEvent;
18  import org.mule.umo.UMOMessage;
19  import org.mule.umo.endpoint.UMOImmutableEndpoint;
20  import org.mule.umo.provider.DispatchException;
21  import org.mule.util.ClassUtils;
22  
23  import java.util.Date;
24  import java.util.Iterator;
25  
26  import org.quartz.CronTrigger;
27  import org.quartz.Job;
28  import org.quartz.JobDataMap;
29  import org.quartz.JobDetail;
30  import org.quartz.Scheduler;
31  import org.quartz.SimpleTrigger;
32  import org.quartz.Trigger;
33  
34  /**
35   * Can schedule a Job with the Quartz scheduler. The event must contain the Job to
36   * invoke or have it set as a property. Time triggger properties can be set on the
37   * event to control how and when the event is fired.
38   */
39  public class QuartzMessageDispatcher extends AbstractMessageDispatcher
40  {
41  
42      public QuartzMessageDispatcher(UMOImmutableEndpoint endpoint)
43      {
44          super(endpoint);
45      }
46  
47      protected void doDispose()
48      {
49          // template method
50      }
51  
52      protected void doDispatch(UMOEvent event) throws Exception
53      {
54          JobDetail jobDetail = new JobDetail();
55          // make the job name unique per endpoint (MULE-753)
56          jobDetail.setName(event.getEndpoint().getEndpointURI().toString() + "-" + event.getId());
57  
58          JobDataMap jobDataMap = new JobDataMap();
59          UMOMessage msg = event.getMessage();
60          for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
61          {
62              String propertyKey = (String)iterator.next();
63              jobDataMap.put(propertyKey, msg.getProperty(propertyKey));
64          }
65          jobDetail.setJobDataMap(jobDataMap);
66  
67          Job job;
68          // work out what we're actually calling
69          Object payload = event.getTransformedMessage();
70  
71          String jobClass = jobDataMap.getString(QuartzConnector.PROPERTY_JOB_CLASS);
72          // If the payload is a Job instance, then we are going to save it in
73          // the jobDataMap under the key "jobObject". The actual Job that will 
74          // execute will be the DelegatingJob
75          if (payload instanceof Job)
76          {
77              job = (Job)payload;
78              jobDataMap.put(QuartzConnector.PROPERTY_JOB_OBJECT, job);
79              jobDetail.setJobClass(DelegatingJob.class);
80          }
81          // If the payload is not a Job instance, but the jobClass has been set
82          // on the Message under the property "jobClass", then set the execution 
83          // Job to be that class.
84          else if (jobClass != null)
85          {
86              jobDetail.setJobClass(ClassUtils.loadClass(jobClass, getClass()));
87          }
88          // Otherwise, we have to find the job some other way
89          else
90          {
91              // See if the Message has the job stored under "jobObject"
92              Object tempJob = jobDataMap.get(QuartzConnector.PROPERTY_JOB_OBJECT);
93              if (tempJob == null)
94              {
95                  // See if the Message has the job stored under "jobRef"
96                  tempJob = jobDataMap.get(QuartzConnector.PROPERTY_JOB_REF);
97                  if (tempJob == null)
98                  {
99                      // Now we'll give up
100                     throw new DispatchException(QuartzMessages.invalidPayloadType(), 
101                         event.getMessage(), event.getEndpoint());
102                 }
103                 else
104                 {
105                     tempJob = MuleManager.getInstance().getContainerContext().getComponent(tempJob);
106                     if (!(tempJob instanceof Job))
107                     {
108                         throw new DispatchException(QuartzMessages.invalidJobObject(), 
109                             event.getMessage(), event.getEndpoint());
110                     }
111                 }
112             }
113             else if (!(tempJob instanceof Job))
114             {
115                 throw new DispatchException(QuartzMessages.invalidJobObject(), 
116                     event.getMessage(), event.getEndpoint());
117             }
118             // If we have a job at this point, then the execution Job
119             // will be the DelegatingJob
120             jobDetail.setJobClass(DelegatingJob.class);
121         }
122 
123         // The payload will be ignored by the DelegatingJob - don't know why
124         // we need it here
125         jobDataMap.put(QuartzConnector.PROPERTY_PAYLOAD, payload);
126 
127         Trigger trigger = null;
128         String cronExpression = jobDataMap.getString(QuartzConnector.PROPERTY_CRON_EXPRESSION);
129         String repeatInterval = jobDataMap.getString(QuartzConnector.PROPERTY_REPEAT_INTERVAL);
130         String repeatCount = jobDataMap.getString(QuartzConnector.PROPERTY_REPEAT_COUNT);
131         String startDelay = jobDataMap.getString(QuartzConnector.PROPERTY_START_DELAY);
132         String groupName = jobDataMap.getString(QuartzConnector.PROPERTY_GROUP_NAME);
133         String jobGroupName = jobDataMap.getString(QuartzConnector.PROPERTY_JOB_GROUP_NAME);
134 
135         if (groupName == null)
136         {
137             groupName = QuartzConnector.DEFAULT_GROUP_NAME;
138         }
139         if (jobGroupName == null)
140         {
141             jobGroupName = groupName;
142         }
143 
144         jobDetail.setGroup(groupName);
145 
146         if (cronExpression != null)
147         {
148             CronTrigger ctrigger = new CronTrigger();
149             ctrigger.setCronExpression(cronExpression);
150             trigger = ctrigger;
151         }
152         else if (repeatInterval != null)
153         {
154             SimpleTrigger strigger = new SimpleTrigger();
155             strigger.setRepeatInterval(Long.parseLong(repeatInterval));
156             if (repeatCount != null)
157             {
158                 strigger.setRepeatCount(Integer.parseInt(repeatCount));
159             }
160             else
161             {
162                 strigger.setRepeatCount(-1);
163             }
164             trigger = strigger;
165         }
166         else
167         {
168             throw new IllegalArgumentException(
169                 QuartzMessages.cronExpressionOrIntervalMustBeSet().getMessage());
170         }
171         long start = System.currentTimeMillis();
172         if (startDelay != null)
173         {
174             start += Long.parseLong(startDelay);
175         }
176         trigger.setStartTime(new Date(start));
177         trigger.setName(event.getEndpoint().getEndpointURI().toString() + "-" + event.getId());
178         trigger.setGroup(groupName);
179         trigger.setJobName(jobDetail.getName());
180         trigger.setJobGroup(jobGroupName);
181 
182         Scheduler scheduler = ((QuartzConnector)this.getConnector()).getQuartzScheduler();
183         scheduler.scheduleJob(jobDetail, trigger);
184     }
185 
186     protected UMOMessage doSend(UMOEvent event) throws Exception
187     {
188         doDispatch(event);
189         return null;
190     }
191 
192     protected void doConnect() throws Exception
193     {
194         // template method
195     }
196 
197     protected void doDisconnect() throws Exception
198     {
199         // template method
200     }
201 
202     /**
203      * Make a specific request to the underlying transport
204      * 
205      * @param endpoint the endpoint to use when connecting to the resource
206      * @param timeout the maximum time the operation should block before returning.
207      *            The call should return immediately if there is data available. If
208      *            no data becomes available before the timeout elapses, null will be
209      *            returned
210      * @return the result of the request wrapped in a UMOMessage object. Null will be
211      *         returned if no data was avaialable
212      * @throws Exception if the call to the underlying protocal cuases an exception
213      */
214     protected UMOMessage doReceive(long timeout) throws Exception
215     {
216         throw new UnsupportedOperationException("doReceive");
217     }
218 
219 }