1 package org.oddjob.jobs; 2 3 4 import java.beans.PropertyChangeListener ; 5 import java.beans.PropertyChangeSupport ; 6 import java.io.IOException ; 7 import java.io.ObjectInputStream ; 8 import java.io.ObjectOutputStream ; 9 import java.io.Serializable ; 10 11 import org.apache.log4j.Logger; 12 import org.apache.log4j.MDC; 13 import org.oddjob.Iconic; 14 import org.oddjob.Resetable; 15 import org.oddjob.Stateful; 16 import org.oddjob.arooa.ArooaContext; 17 import org.oddjob.arooa.ArooaConstants; 18 import org.oddjob.arooa.Lifecycle; 19 import org.oddjob.arooa.Location; 20 import org.oddjob.arooa.RuntimeConfiguration; 21 import org.oddjob.images.IconHelper; 22 import org.oddjob.images.IconListener; 23 import org.oddjob.images.IconTip; 24 import org.oddjob.logging.Log4jArchiver; 25 import org.oddjob.state.JobState; 26 import org.oddjob.state.JobStateEvent; 27 import org.oddjob.state.JobStateHandler; 28 import org.oddjob.state.JobStateListener; 29 import org.oddjob.state.StateTransform; 30 import org.oddjob.structural.StatefulChildHelper; 31 import org.oddjob.structural.StructuralListener; 32 import org.oddjob.util.Lock; 33 import org.oddjob.util.OddjobLockedException; 34 import org.xml.sax.Locator ; 35 36 42 43 public abstract class AbstractJob 44 implements Serializable , 45 Runnable , Resetable, Stateful, Iconic { 46 private static final long serialVersionUID = 20041005; 47 48 49 private static int instanceCount; 50 51 52 private transient String logger; 53 private transient Logger theLogger; 54 55 56 private transient Location location; 57 58 59 private transient RuntimeConfiguration wrapper; 60 61 64 protected transient PropertyChangeSupport changes; 65 66 69 protected IconHelper iconHelper = new IconHelper(this); 70 71 75 protected transient StatefulChildHelper childHelper; 76 77 80 protected JobStateHandler stateHandler = new JobStateHandler(this); 81 82 87 private String name; 88 89 94 protected transient volatile boolean stop; 95 96 100 protected transient volatile boolean destroyed; 101 102 107 protected transient Lock lock; 108 109 public AbstractJob() { 110 completeConstruction(); 111 } 112 113 117 private void completeConstruction() { 118 changes = new PropertyChangeSupport (this); 119 childHelper = new StatefulChildHelper(this); 120 lock = new Lock(); 121 } 122 123 128 public Logger logger() { 129 if (theLogger == null) { 130 int count = 0; 131 synchronized (AbstractJob.class) { 132 count = instanceCount++; 133 } 134 theLogger = Logger.getLogger(this.getClass().getName() 135 + "." + count); 136 } 137 return theLogger; 138 } 139 140 public void setContext(ArooaContext context) { 141 Locator locator = context.getLocator(); 142 if (locator != null) { 143 Location location = new Location(locator.getSystemId(), 144 locator.getLineNumber(), 145 locator.getColumnNumber()); 146 this.location = location; 147 } 148 this.wrapper = (RuntimeConfiguration) context.get(ArooaConstants.CURRENTLY_CONFIGURING); 149 } 150 151 public Location getLocation() { 152 return this.location; 153 } 154 155 protected RuntimeConfiguration getRuntimeConfigurable() { 156 return wrapper; 157 } 158 159 165 protected void setJobStateException(Throwable ex) { 166 stateHandler.setJobStateException(ex); 167 iconHelper.changeIcon(IconHelper.EXCEPTION); 168 } 169 170 175 protected void sleep(long waitTime) { 176 if (destroyed) { 177 throw new IllegalStateException ("[" + this + "] destroyed"); 178 } 179 iconHelper.changeIcon(IconHelper.SLEEPING); 180 logger().debug("[" + this + "] Sleeping for [" + waitTime + "] milli seconds." ); 181 try { 182 synchronized (this) { 183 wait(waitTime); 184 } 185 } catch (InterruptedException e) { 186 logger().debug("Sleep interupted."); 187 } 188 iconHelper.changeIcon(IconHelper.EXECUTING); 189 } 190 191 196 public void stop() { 197 if (destroyed) { 198 throw new IllegalStateException ("[" + this + "] destroyed"); 199 } 200 if (stateHandler.getJobState() != JobState.EXECUTING) { 201 return; 202 } 203 iconHelper.changeIcon(IconHelper.STOPPING); 204 childHelper.stopChildren(); 205 stop = true; 206 synchronized (this) { 207 notifyAll(); 208 } 209 logger().debug("Thread [" + Thread.currentThread().getName() 210 + "] requested [" + getName() + "] stop."); 211 } 212 213 219 abstract protected int execute() throws Throwable ; 220 221 225 public final void run() throws OddjobLockedException { 226 lock.accquire("Job executing."); 227 String oldMDC = (String )MDC.get(Log4jArchiver.MDC); 228 try { 229 MDC.put(Log4jArchiver.MDC, getLogger()); 230 if (!stateHandler.requestJobStateExecuting()) { 231 logger().debug("Can't execute job [" + this + "] because state is [" 232 + stateHandler.getJobState() + "]"); 233 return; 234 } 235 iconHelper.changeIcon(IconHelper.EXECUTING); 236 237 if (wrapper != null) { 239 try { 240 logger().debug("Configuring job [" + this + "]"); 241 wrapper.configure(); 242 } catch (Exception e) { 243 logger().error("Configruation exception for job: " 244 + this + ", location: " + getLocation(), e); 245 setJobStateException(e); 246 return; 247 } 248 } 249 logger().debug("Executing job [" + this + "]"); 250 251 int result = -1; 252 try { 253 result = execute(); 254 } 255 catch (Throwable e) { 256 logger().info("Job Exception in [" + this + "]", e); 257 setJobStateException(e); 258 return; 259 } 260 261 logger().debug("Finished job [" + this + "], result " + result); 262 263 if (result == 0) { 264 iconHelper.changeIcon(IconHelper.COMPLETE); 265 stateHandler.setJobStateComplete(); 266 } 267 else { 268 iconHelper.changeIcon(IconHelper.NOT_COMPLETE); 269 stateHandler.setJobStateNotComplete(); 270 } 271 } 272 finally { 273 if (oldMDC != null) { 274 MDC.put(Log4jArchiver.MDC, oldMDC); 275 } 276 else { 277 MDC.remove(Log4jArchiver.MDC); 278 } 279 lock.release(); 280 } 281 } 282 283 288 synchronized public void setName(String name) { 289 if (destroyed) { 290 throw new IllegalStateException ("[" + this + "] destroyed"); 291 } 292 String old = this.name; 293 this.name = name; 294 changes.firePropertyChange("name", old, name); 295 } 296 297 302 synchronized public String getName() { 303 if (name == null && wrapper != null) { 304 return wrapper.getAttribute("name"); 305 } 306 return name; 307 } 308 309 318 319 public JobStateEvent lastJobStateEvent() { 320 return stateHandler.getLastEvent(); 321 } 322 323 326 327 public void addJobStateListener(JobStateListener listener) { 328 if (destroyed) { 329 throw new IllegalStateException ("[" + this + "] destroyed"); 330 } 331 stateHandler.addJobStateListener(listener); 332 } 333 334 337 338 public void removeJobStateListener(JobStateListener listener){ 339 stateHandler.removeJobStateListener(listener); 340 } 341 342 347 public void addPropertyChangeListener(PropertyChangeListener l) { 348 if (destroyed) { 349 throw new IllegalStateException ("[" + this + "] destroyed"); 350 } 351 changes.addPropertyChangeListener(l); 352 } 353 354 359 public void removePropertyChangeListener(PropertyChangeListener l) { 360 changes.removePropertyChangeListener(l); 361 } 362 363 369 protected boolean reset(StateTransform transform) { 370 371 if (transform.canReset(stateHandler.getJobState())) { 372 iconHelper.changeIcon(IconHelper.READY); 373 stop = false; 374 stateHandler.setJobStateReady(); 375 return true; 376 } 377 else { 378 return false; 379 } 380 } 381 382 385 public void softReset() { 386 lock.accquire("Soft reset in progress."); 387 try { 388 logger().debug("Thread [" + Thread.currentThread().getName() 389 + "] soft reset for [" + getName() + "]."); 390 childHelper.softResetChildren(); 391 reset(StateTransform.SOFT_RESET); 392 } 393 finally { 394 lock.release(); 395 } 396 } 397 398 401 public void hardReset() { 402 lock.accquire("Hard reset in progress."); 403 try { 404 logger().debug("Thread [" + Thread.currentThread().getName() 405 + "] hard reset for [" + getName() + "]."); 406 childHelper.hardResetChildren(); 407 reset(StateTransform.HARD_RESET); 408 } 409 finally { 410 lock.release(); 411 } 412 } 413 414 418 public IconTip iconForId(String iconId) { 419 return iconHelper.iconForId(iconId); 420 } 421 422 428 public void addIconListener(IconListener listener) { 429 if (destroyed) { 430 throw new IllegalStateException ("[" + this + "] destroyed"); 431 } 432 iconHelper.addIconListener(listener); 433 } 434 435 441 public void removeIconListener(IconListener listener) { 442 iconHelper.removeIconListener(listener); 443 } 444 445 451 public void addStructuralListener(StructuralListener listener) { 452 if (destroyed) { 453 throw new IllegalStateException ("[" + this + "] destroyed"); 454 } 455 childHelper.addStructuralListener(listener); 456 } 457 458 463 public void removeStructuralListener(StructuralListener listener) { 464 childHelper.removeStructuralListener(listener); 465 } 466 467 470 public String toString() { 471 if (name == null) { 472 return getClass().getName(); 473 } 474 else { 475 return name; 476 } 477 } 478 479 482 public void destroy() { 483 if (destroyed) { 484 throw new IllegalStateException ("[" + this + "] destroyed"); 485 } 486 Lifecycle.destroy(childHelper.getChildren()); 487 childHelper.removeAllChildren(); 488 destroyed = true; 489 logger().debug("Destroyed [" + this + "]"); 490 } 491 492 495 private void writeObject(ObjectOutputStream s) 496 throws IOException { 497 if (destroyed) { 498 throw new IllegalStateException ("[" + this + "] destroyed"); 499 } 500 s.defaultWriteObject(); 501 } 502 503 506 private void readObject(ObjectInputStream s) 507 throws IOException , ClassNotFoundException { 508 s.defaultReadObject(); 509 stateHandler.setSource(this); 510 iconHelper.setSource(this); 511 completeConstruction(); 512 } 513 514 517 public String getLogger() { 518 return logger().getName(); 519 } 520 521 524 public void setLogger(String logger) { 525 this.logger = logger; 526 if (theLogger != null) { 527 theLogger.debug("Logger being replaced by [" + logger + "]"); 528 } 529 theLogger = Logger.getLogger(logger); 530 } 531 } 532 | Popular Tags |