1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.backsource.qcron;
21 import java.util.Date;
22 import javax.management.ObjectName;
23 import javax.management.MBeanServer;
24 import javax.management.MalformedObjectNameException;
25 import org.quartz.JobDetail;
26 import org.quartz.CronTrigger;
27
28 import org.backsource.jmx.ServiceMBeanSupport;
29 import org.backsource.jmx.ObjectNameFactory;
30 /***
31 * A "cron" row consisting of time to run command and command to run.
32 *
33 * <p>CronEntry is a wrapper above Quartz JobDetail and Trigger. Its purpose is
34 * twofold: to make it somewhat simpler to set up a cron jobb and to agument
35 * quartz with ways to call live objects to get the work done. If one likes
36 * to use the Quartz way of doing thing one may use the constructor that takes
37 * a JobDetail and a Trigger. See {@link org.backsource.qcron} for setup examples.</p>
38 *
39 * @author <a href="mailto:pra@tim.se">Peter Antman</a>
40 * @version $Revision: 1.1.1.1 $
41 * @jmx:mbean name="cron:name=CronEntry" extends="org.backsource.jmx.ServiceMBean"
42
43 */
44
45 public class CronEntry extends ServiceMBeanSupport
46 implements CronEntryMBean{
47 public static final javax.management.ObjectName OBJECT_NAME = ObjectNameFactory.create("cron:name=CronEntry");
48 protected ObjectName objectName = OBJECT_NAME;
49
50 protected MBeanServer server;
51 protected JobDetail jobDetail;
52 protected CronTrigger trigger;
53
54 protected String name;
55 protected String group;
56 protected boolean recover = false;
57 protected boolean volatility = false;
58 protected String cronExp;
59 protected ObjectName jobObjectName;
60
61 public CronEntry () {
62
63 }
64
65 /***
66 * Create a CronEntry by directly using the Quertz way of doing things.
67 */
68 public CronEntry (CronTrigger trigger, JobDetail detail){
69 this.trigger = trigger;
70 this.jobDetail = detail;
71 group = jobDetail.getGroup();
72 name = jobDetail.getName();
73 volatility = jobDetail.isVolatile();
74 recover = jobDetail.requestsRecovery();
75
76
77
78 cronExp = trigger.getCronExpression();
79 MBeanJob job = MBeanJob.getMBeanJob(detail.getJobDataMap());
80 if ( job != null) {
81 jobObjectName = job.getObjectName();
82 }
83
84 }
85
86 /***
87 * Creata cron entry wich will be triggered accordning to cron specification in cronExpr and wich will delegate callbacks to the MBean name, which must implement the Job interface (or have an equal method).
88 *
89 * <p>The gruop and name of the Trigger/Job will be taken from the delegate ObjectName. if this delegate will be used by more than one CronEntry the creator must set {@link setEntryGroup} and {@link setEntryName} manually after creation.</p>
90 *
91 * <p>This method will create a cron entry that will be run at times the cronExp specifyes and invokes the job found my invoking object name. It will be persisted, non-durable and non recovarable. The underlying trigger and job will have the same group and name.</p>
92 */
93 public CronEntry (String cronExpr, ObjectName delegate) throws CronException{
94
95
96 this.cronExp = cronExpr;
97 setJobObjectName(delegate);
98 setEntryGroup(delegate.getDomain());
99 setEntryName(delegate.toString());
100 setUpBeans();
101
102
103 }
104
105 private void setUpBeans() throws CronException {
106
107 log.debug("Creating job with name="+name);
108 jobDetail = new JobDetail(name,
109 group,
110 MBeanJob.class
111 );
112 log.debug("Created job " + jobDetail.toString());
113 MBeanJob job = new MBeanJob( jobDetail.getJobDataMap(),
114 jobObjectName);
115
116 trigger = new CronTrigger(name,
117 group,
118 name,
119 group
120 );
121 trigger.setStartTime(new Date());
122 setCronExp(cronExp);
123 setVolatility(volatility);
124 setRequestsRecovery(recover);
125 trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW );
126
127 }
128
129 protected ObjectName getObjectName(MBeanServer server, ObjectName name)
130 throws MalformedObjectNameException
131 {
132 this.server = server;
133 if ( name != null) {
134 this.objectName = name;
135 }
136
137 return this.objectName;
138 }
139
140 /***
141 * Set the cron expression to use for the trigger.
142 *
143 * @see org.quartz.CronTrigger
144 * @jmx:managed-attribute
145 */
146 public void setCronExp(String cronExp) throws CronException{
147 this.cronExp = cronExp;
148 if ( trigger != null){
149 try {
150 trigger.setCronExpression(cronExp);
151 } catch (java.text.ParseException e) {
152 throw new CronException("Could not parse cron expression: " +cronExp+": " +e,e);
153 }
154
155 }
156 }
157
158 /***
159 * Get the cron expression to use for the trigger.
160 * @jmx:managed-attribute
161 */
162 public String getCronExp() {
163 return cronExp;
164 }
165
166 /***
167 * Set the object name of an MBean which should be called when trigger triggers.
168 * @jmx:managed-attribute
169 */
170 public void setJobObjectName(ObjectName jobName) {
171 this.jobObjectName = jobName;
172 }
173 /***
174 * Get the object name of an MBean which should be called when trigger triggers.
175 * @jmx:managed-attribute
176 */
177 public ObjectName getJobObjectName() {
178 return jobObjectName;
179 }
180 /***
181 * Scheduler should try to recover job if it should have triggered while the
182 * server was down, default to false.
183 *<p>if set to true: volatile must be false.</p>
184 * @jmx:managed-attribute
185 */
186 public void setRequestsRecovery(boolean recover) {
187 this.recover = recover;
188 if ( jobDetail != null)
189 jobDetail.setRequestsRecovery(recover);
190 }
191 /***
192 * Should sceduler try to recover; for example if server was down when jib shoudl have triggered.
193 * @jmx:managed-attribute
194 */
195 public boolean getRequestsRecovery() {
196 return recover;
197 }
198 /***
199 * Save job to persistent state if false, default is false, saving to persisten state!
200 *
201 * @jmx:managed-attribute
202 */
203 public void setVolatility(boolean volatility) {
204 this.volatility = volatility;
205 if ( jobDetail != null) {
206 jobDetail.setVolatility(volatility);
207 trigger.setVolitility(volatility);
208 }
209 }
210 /***
211 * Will the entry be saved to persistent store.
212 * @jmx:managed-attribute
213 */
214 public boolean getVolatility() {
215 return volatility;
216 }
217 /***
218 *
219 * @jmx:managed-attribute
220 */
221 public String getEntryGroup() {
222 return group;
223 }
224 /***
225 * Set the group name of the entry (trigger/jobdetail).
226 * @jmx:managed-attribute
227 */
228 public void setEntryGroup(String group) {
229 this.group = group;
230 if ( jobDetail != null)
231 jobDetail.setGroup(group);
232 if ( trigger != null) {
233 trigger.setGroup(group);
234 trigger.setJobGroup(group);
235 }
236
237 }
238 /***
239 * Get the name of the entry (trigger/jobdetail).
240 * @jmx:managed-attribute
241 */
242 public String getEntryName() {
243 return name;
244 }
245 /***
246 * Set the name of the entry (trigger/jobdetail).
247 * @jmx:managed-attribute
248 */
249 public void setEntryName(String name) {
250 this.name = name;
251 if ( jobDetail != null)
252 jobDetail.setName(name);
253 if ( trigger != null) {
254 trigger.setName(name);
255 trigger.setJobName(name);
256 }
257 }
258 /***
259 * Get the underlying JobDetail.
260 * @jmx:managed-attribute
261 */
262 public JobDetail getJobDetail() {
263 return jobDetail;
264 }
265 /***
266 * Get the underlying CronTrigger.
267 * @jmx:managed-attribute
268 */
269 public CronTrigger getTrigger() {
270 return trigger;
271 }
272
273 /***
274 * Compare if all fields except the trigger and job is equal.
275 * @jmx:managed-attribute
276 */
277 public boolean equals(Object otherO) {
278 if ( otherO == null || !(otherO instanceof CronEntry)) {
279 return false;
280 }
281 CronEntry other = (CronEntry)otherO;
282 if (group.equals(other.getEntryGroup())
283 && name.equals(other.getEntryName())
284 && cronExp.equals(other.getCronExp())
285 && jobObjectName.equals( other.getJobObjectName())
286 && recover == other.getRequestsRecovery()
287 && volatility == other.getVolatility()
288 ) {
289 return true;
290 }
291 return false;
292 }
293 /***
294 * Get the instance of this MBean
295 * @jmx:managed-operation
296 */
297 public CronEntry instance() {
298 return this;
299 }
300
301 protected void startService() throws Exception {
302 setEntryGroup(objectName.getDomain());
303 setEntryName(objectName.toString());
304 setUpBeans();
305
306 }
307 }