View Javadoc

1   /*
2    * Copyright (c) 2003 Peter Antman, Teknik i Media  <peter.antman@tim.se>
3    *
4    * $Id: CronEntry.java,v 1.1.1.1 2004/05/19 12:14:31 pra Exp $
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version
10   * 
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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     // reduntant info to help in equals
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        // To get equals to work, more has to be done!
77        
78        cronExp = trigger.getCronExpression();
79        MBeanJob job = MBeanJob.getMBeanJob(detail.getJobDataMap());
80        if ( job != null) {
81           jobObjectName = job.getObjectName();
82        } // end of if ()
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        // Set default.
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       // We use reduntant setters here, but what the..
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       } // end of if ()
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          } // end of try-catch
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       } // end of if ()
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       } // end of if ()
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       } // end of if ()
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 }// CronEntry