/* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that Software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of * any nuclear facility. */ import java.io.Serializable; /** * * @author Matthew Bohm */ public class SimpleTask implements Runnable, Serializable { private String taskId; private Thread thread; //thread in which to run task. task is in progress if thread != null private boolean paused, cancelled; //indicates task has been paused or cancelled by client and not yet restarted private boolean indeterminate, doomed, failed; //indicates whether progress is indeterminate or if task is doomed to fail or failed private int percentage, interval = 1200, sleepDelay = 800, indeterminatePercentage = 0; /** Creates a new instance of SimpleTask */ public SimpleTask(String taskId, int interval, int sleepDelay, boolean indeterminate) { if (taskId == null) { throw new NullPointerException(); } this.taskId = taskId; if (interval >= 0) { this.interval = interval; } if (sleepDelay > 0) { this.sleepDelay = sleepDelay; } this.indeterminate = indeterminate; } public String getTaskId() { return taskId; } public int getInterval() { return interval; } public int getPercentage() { return percentage; } public boolean isFailed() { return failed; } public int getStatus() { int percentageSnapshot = percentage; if (failed) { return -1; } else if (cancelled) { return 4; } else if (paused) { return 2; } else if (percentageSnapshot >= 100) { return 5; } else if (thread == null) { return 0; } else { return 1; } } public synchronized String getPercentageText() { StringBuffer sb = new StringBuffer(); int percentageSnapshot = percentage; if (!indeterminate || percentage == 0) { sb.append(percentageSnapshot); sb.append("%
"); } if (failed) { sb.append("(failed)"); } else if (cancelled) { sb.append("(cancelled)"); } else if (paused) { sb.append("(paused)"); } else if (percentageSnapshot >= 100) { sb.append("(complete)"); } else if (percentageSnapshot == -1) { sb.append("(time remaining unknown)"); } else if (thread == null) { sb.append("(not started)"); } else { //sb.append("(in progress)"); } return sb.toString(); } public synchronized void start(boolean doomed) { if (thread != null && (paused || cancelled)) { //task is taking a while to actually pause or cancel //give it a few chances for (int i = 0; i < 3; i++) { try { Thread.sleep(sleepDelay + 300); } catch (InterruptedException e) { e.printStackTrace(); } if (thread == null) { break; } } if (thread != null) { System.err.println("Could not restart task " + taskId + ": task is taking too long to pause or cancel"); } } if (thread != null) { System.err.println("Could not start task " + taskId + ": task already in progress"); return; } if (indeterminate && percentage == 0) { //never started before percentage = -1; } //if task is already complete, failed, or has been cancelled, restart task from the beginnning if (percentage >= 100 || cancelled || failed) { if (indeterminate) { percentage = -1; indeterminatePercentage = 0; } else { percentage = 0; } } //we're about to (re)start the task, so set pause and cancelled to false paused = false; cancelled = false; failed = false; this.doomed = doomed; //(re)start the task thread = new Thread(this); thread.start(); } public synchronized void pause() { paused = true; } public synchronized void cancel() { cancelled = true; } public void run() { while(!failed && !paused && !cancelled && percentage < 100) { try { Thread.sleep(sleepDelay); } catch (InterruptedException e) { e.printStackTrace(); } if (!paused && !cancelled) { //operation could have been paused or cancelled during sleep if (indeterminate) { indeterminatePercentage++; if (doomed) { if (indeterminatePercentage > 24) { failed = true; } } else if (indeterminatePercentage > 44) { percentage = 100; } } else { percentage++; if (doomed && percentage > 24) { failed = true; } } } } //task is complete or has been paused/cancelled, so thread's execution will discontinue //release reference to the thread thread = null; } }