1 4 package org.oddjob.quartz; 5 6 import java.io.IOException ; 7 import java.io.ObjectInputStream ; 8 import java.io.ObjectOutputStream ; 9 import java.io.Serializable ; 10 import java.util.Date ; 11 12 import org.oddjob.Iconic; 13 import org.oddjob.Resetable; 14 import org.oddjob.Stateful; 15 import org.oddjob.arooa.registry.ComponentRegistry; 16 import org.oddjob.framework.BasePrimary; 17 import org.oddjob.images.IconEvent; 18 import org.oddjob.images.IconListener; 19 import org.oddjob.state.JobState; 20 import org.oddjob.state.JobStateEvent; 21 import org.oddjob.state.JobStateListener; 22 import org.oddjob.util.OddjobConfigException; 23 import org.oddjob.util.OddjobConstantException; 24 import org.quartz.JobDataMap; 25 import org.quartz.JobDetail; 26 import org.quartz.Scheduler; 27 import org.quartz.SchedulerException; 28 import org.quartz.SimpleTrigger; 29 30 40 public class TriggerSchedule extends BasePrimary 41 implements Serializable , Stateful, QuartzSchedule, JobStateListener { 42 private static final long serialVersionUID = 20051121; 43 44 45 private static final String GROUP_NAME = Scheduler.DEFAULT_GROUP; 46 47 49 private JobToken jobToken; 50 51 private transient ComponentRegistry componentRegistry; 52 53 58 private transient Stateful on; 59 60 private JobToken onToken; 61 62 63 68 private String state; 69 70 71 private JobState jobState; 72 73 74 private Date lastTime; 75 76 77 private transient Scheduler scheduler; 78 79 80 private String id; 81 82 83 private transient JobStateListener jobListener; 84 85 private transient IconListener iconListener; 86 87 public TriggerSchedule() { 88 completeConstruction(); 89 } 90 91 private void completeConstruction() { 92 jobListener = new JobStateListener() { 93 public void jobStateChange(JobStateEvent event) { 94 stateHandler.fireEvent(new JobStateEvent( 95 TriggerSchedule.this, event.getJobState(), 96 event.getTime(), event.getException())); 97 } 98 }; 99 100 iconListener = new IconListener() { 101 public void iconEvent(IconEvent e) { 102 iconHelper.changeIcon(e.getIconId()); 103 } 104 }; 105 } 106 107 113 public void setId(String id) { 114 if (this.id != null) { 115 throw new OddjobConfigException("Id can't be changed."); 116 } 117 this.id = id; 118 } 119 120 125 private String triggerName() { 126 return id + "-Trigger"; 127 } 128 129 132 public void scheduleWith(Scheduler scheduler) throws SchedulerException { 133 if (jobToken == null) { 134 throw new NullPointerException ("Job to schedule must be specified."); 135 } 136 if (onToken == null) { 137 throw new NullPointerException ("Job to trigger on must be specified."); 138 } 139 140 this.scheduler = scheduler; 141 142 JobDetail jobDetail = scheduler.getJobDetail(toString(), Scheduler.DEFAULT_GROUP); 144 OddjobData ojd = null; 145 if (jobDetail != null) { 146 JobDataMap jobDataMap = jobDetail.getJobDataMap(); 147 if (jobDataMap != null) { 148 ojd = (OddjobData) jobDataMap.get(OddjobData.ODDJOB_DATA); 149 } 150 } 151 if (ojd != null) { 152 lastTime = ojd.getLast(); 153 } 154 155 if (jobState == null) { 156 if (state == null) { 157 jobState = JobState.COMPLETE; 158 } 159 else { 160 jobState = JobState.stateFor(state); 161 } 162 } 163 if (jobState == null) { 164 throw new OddjobConfigException("State is invalid."); 165 } 166 167 on = (Stateful) JobToken.retrieve(componentRegistry, onToken); 168 on.addJobStateListener(this); 169 } 170 171 174 public void jobStateChange(JobStateEvent event) { 175 logger().debug("Trigger has state [" + event.getJobState() + "]"); 176 if (event.getJobState() == jobState) { 177 if (event.getTime().equals(lastTime)) { 179 logger().debug("Already had this event."); 180 return; 181 } 182 lastTime = event.getTime(); 183 184 SimpleTrigger trigger = new SimpleTrigger(triggerName(), 185 GROUP_NAME, 186 new Date (), 187 null, 188 0, 189 0L); 190 try { 191 JobDetail jobDetail = scheduler.getJobDetail(toString(), Scheduler.DEFAULT_GROUP); 192 if (jobDetail == null) { 193 194 OddjobData ojd = new OddjobData(); 195 ojd.setJob(new Execute()); 196 ojd.setLast(lastTime); 197 198 JobDataMap jobDataMap = new JobDataMap(); 199 200 jobDataMap.put(OddjobData.ODDJOB_DATA, ojd); 201 202 jobDetail = new JobDetail(toString(), 203 Scheduler.DEFAULT_GROUP, 204 RunnableQuartzJob.class); 205 206 jobDetail.setJobDataMap(jobDataMap); 207 scheduler.scheduleJob(jobDetail, trigger); 208 } 209 else { 210 JobDataMap jobDataMap = jobDetail.getJobDataMap(); 211 OddjobData ojd = (OddjobData) jobDataMap.get(OddjobData.ODDJOB_DATA); 212 ojd.setLast(lastTime); 214 trigger.setJobName(jobDetail.getName()); 215 trigger.setJobGroup(jobDetail.getGroup()); 216 scheduler.rescheduleJob(trigger.getName(), jobDetail.getGroup(), trigger); 217 } 218 } catch (SchedulerException e) { 219 logger().error("Failed to schedule.", e); 220 } 221 } 222 } 223 224 228 public void unscheduleFrom(Scheduler scheduler) throws SchedulerException { 229 scheduler.unscheduleJob(triggerName(), GROUP_NAME); 230 } 231 232 public String getState() { 233 return state; 234 } 235 236 public void setState(String state) { 237 this.state = state; 238 } 239 240 public void setComponentRegistry(ComponentRegistry componentRegistry) { 241 this.componentRegistry = componentRegistry; 242 } 243 244 public void setJob(Runnable job) { 245 if (job == null) { 246 throw new OddjobConfigException("No job to schedule specified!"); 247 } 248 if (this.jobToken != null) { 249 throw new OddjobConstantException("[" + this 250 + "] job can't be changed."); 251 } 252 253 this.jobToken = JobToken.create(componentRegistry, job); 254 } 255 256 public void onDestroy() { 257 on.removeJobStateListener(this); 258 } 259 260 261 public String toString() { 262 if (getName() == null) { 263 return "Trigger [" + jobToken + "] on [" + on + "] [" + jobState + "]"; 264 } 265 return getName(); 266 } 267 268 public void setOn(Stateful triggerOn) { 269 this.onToken = JobToken.create(componentRegistry, triggerOn); 270 } 271 272 private void writeObject(ObjectOutputStream os) 273 throws IOException { 274 os.defaultWriteObject(); 275 } 276 277 private void readObject(ObjectInputStream is) 278 throws IOException , ClassNotFoundException { 279 is.defaultReadObject(); 280 completeConstruction(); 281 } 282 283 285 class Execute implements Runnable { 286 synchronized public void run() { 287 logger().debug("Executing at [" + new Date ()+ "]"); 288 Runnable job = (Runnable ) JobToken.retrieve(componentRegistry, jobToken); 289 if (job == null) { 290 setJobStateException( 291 new NullPointerException ("Failed to find job for [" + jobToken + "]")); 292 } 293 294 if (job instanceof Resetable) { 295 ((Resetable) job).hardReset(); 296 } 297 298 if (job instanceof Stateful) { 299 ((Stateful) job).addJobStateListener(jobListener); 300 } 301 if (job instanceof Iconic) { 302 ((Iconic) job).addIconListener(iconListener); 303 } 304 305 try { 306 job.run(); 307 } 308 catch (Throwable t) { 309 setJobStateException(t); 310 } 311 finally { 312 if (job instanceof Stateful) { 313 ((Stateful) job).removeJobStateListener(jobListener); 314 } 315 if (job instanceof Iconic) { 316 ((Iconic) job).removeIconListener(iconListener); 317 } 318 } 319 } 320 } 321 } 322 | Popular Tags |