UIMA-6114 Reformatted the new experiments code

git-svn-id: https://svn.apache.org/repos/asf/uima/uima-ducc/trunk@1865251 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
index c27625c..3db02a6 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
@@ -33,98 +33,93 @@
 import org.eclipse.jetty.server.Handler;
 
 public class DuccPlugins {
-	
-	private static DuccLogger logger = DuccLogger.getLogger(DuccPlugins.class);
-	private static DuccId jobid = null;
-	
-	private static DuccPlugins instance = new DuccPlugins();
-	
-	public static DuccPlugins getInstance() {
-		return instance;
-	}
-	
-	private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager.getInstance();
 
-	/**
-	 * The restore methods are called during boot of the web server.
-	 * This is an opportunity to have local mods plug-in for
-	 * processing that may be desirable relative to each Job,
-	 * Reservation, and Service during the restoration from history.
-	 */
-	
-	public void restore(IDuccWorkJob job) {
-		String location = "restore";
-		try {
-			if(job != null) {
-				String user = job.getStandardInfo().getUser();
-				String directory = job.getStandardInfo().getLogDirectory();
-				logger.info(location, jobid, "user", user, "directory", directory);
-				experimentsRegistryManager.initialize(user, directory);
-			}
-		}
-		catch(Throwable t) {
-			logger.error(location, jobid, t);
-		}
-	}
-	
-	public void restore(IDuccWorkReservation reservation) {
-		String location = "restore";
-		try {
-			//loc mods here
-		}
-		catch(Throwable t) {
-			logger.error(location, jobid, t);
-		}
-	}
-	
-	public void restore(IDuccWorkService service) {
-		String location = "restore";
-		try {
-			// Also process managed reservations in case the experiment has only these.
-		    if(service != null && service.getServiceDeploymentType() == ServiceDeploymentType.other) {
-		        String user = service.getStandardInfo().getUser();
-		        String directory = service.getStandardInfo().getLogDirectory();
-		        experimentsRegistryManager.initialize(user, directory);
-		    }
-		}
-		catch(Throwable t) {
-			logger.error(location, jobid, t);
-		}
-	}
-	
-	/**
-	 * The update method is called for each Orchestrator publication.
-	 * This is an opportunity to have local mods plug-in for
-	 * processing that may be desirable relative to each Job,
-	 * Reservation, and Service within the published map.
-	 */
-	
-	public void update(IDuccWorkMap dwm) {
-		String location = "update";
-		try {
-			experimentsRegistryManager.update(dwm);
-		}
-		catch(Throwable t) {
-			logger.error(location, jobid, t);
-		}
-	}
-	
-	/**
-	 * The gethandlers method is called during boot of the web server.
-	 * This is an opportunity to have local mods plug-in for
-	 * processing that may be desirable relative to http/s requests.
-	 */
-	
-	public ArrayList<Handler> gethandlers(DuccWebServer duccWebServer) {
-		String location = "gethandlers";
-		ArrayList<Handler> handlersList = new ArrayList<Handler> ();
-		try {
-			HandlerExperimentsServlets handlerExperimentsServlets = new HandlerExperimentsServlets(duccWebServer);
-			handlersList.add(handlerExperimentsServlets);
-		}
-		catch(Throwable t) {
-			logger.error(location, jobid, t);
-		}
-		return handlersList;
-	}
+  private static DuccLogger logger = DuccLogger.getLogger(DuccPlugins.class);
+
+  private static DuccId jobid = null;
+
+  private static DuccPlugins instance = new DuccPlugins();
+
+  public static DuccPlugins getInstance() {
+    return instance;
+  }
+
+  private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager
+          .getInstance();
+
+  /**
+   * The restore methods are called during boot of the web server. This is an opportunity to have
+   * local mods plug-in for processing that may be desirable relative to each Job, Reservation, and
+   * Service during the restoration from history.
+   */
+
+  public void restore(IDuccWorkJob job) {
+    String location = "restore";
+    try {
+      if (job != null) {
+        String user = job.getStandardInfo().getUser();
+        String directory = job.getStandardInfo().getLogDirectory();
+        logger.info(location, jobid, "user", user, "directory", directory);
+        experimentsRegistryManager.initialize(user, directory);
+      }
+    } catch (Throwable t) {
+      logger.error(location, jobid, t);
+    }
+  }
+
+  public void restore(IDuccWorkReservation reservation) {
+    String location = "restore";
+    try {
+      // loc mods here
+    } catch (Throwable t) {
+      logger.error(location, jobid, t);
+    }
+  }
+
+  public void restore(IDuccWorkService service) {
+    String location = "restore";
+    try {
+      // Also process managed reservations in case the experiment has only these.
+      if (service != null && service.getServiceDeploymentType() == ServiceDeploymentType.other) {
+        String user = service.getStandardInfo().getUser();
+        String directory = service.getStandardInfo().getLogDirectory();
+        experimentsRegistryManager.initialize(user, directory);
+      }
+    } catch (Throwable t) {
+      logger.error(location, jobid, t);
+    }
+  }
+
+  /**
+   * The update method is called for each Orchestrator publication. This is an opportunity to have
+   * local mods plug-in for processing that may be desirable relative to each Job, Reservation, and
+   * Service within the published map.
+   */
+
+  public void update(IDuccWorkMap dwm) {
+    String location = "update";
+    try {
+      experimentsRegistryManager.update(dwm);
+    } catch (Throwable t) {
+      logger.error(location, jobid, t);
+    }
+  }
+
+  /**
+   * The gethandlers method is called during boot of the web server. This is an opportunity to have
+   * local mods plug-in for processing that may be desirable relative to http/s requests.
+   */
+
+  public ArrayList<Handler> gethandlers(DuccWebServer duccWebServer) {
+    String location = "gethandlers";
+    ArrayList<Handler> handlersList = new ArrayList<Handler>();
+    try {
+      HandlerExperimentsServlets handlerExperimentsServlets = new HandlerExperimentsServlets(
+              duccWebServer);
+      handlersList.add(handlerExperimentsServlets);
+    } catch (Throwable t) {
+      logger.error(location, jobid, t);
+    }
+    return handlersList;
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsAbstract.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsAbstract.java
index 0881f0c..78d9be3 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsAbstract.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsAbstract.java
@@ -42,366 +42,359 @@
 public abstract class HandlerExperimentsAbstract extends AbstractHandler {
 
   // NOTE - this variable used to hold the class name before WsLog was simplified
-	private static DuccLogger cName = DuccLogger.getLogger(HandlerExperimentsAbstract.class);
-	
-	private static DuccData duccData = DuccData.getInstance();
+  private static DuccLogger cName = DuccLogger.getLogger(HandlerExperimentsAbstract.class);
 
-	public final String duccContext = DuccLocalConstants.duccContext;
+  private static DuccData duccData = DuccData.getInstance();
 
-	protected DuccWebServer duccWebServer = null;
+  public final String duccContext = DuccLocalConstants.duccContext;
 
-	public void init(DuccWebServer duccWebServer) {
-		this.duccWebServer = duccWebServer;
-	}
+  protected DuccWebServer duccWebServer = null;
 
-	public boolean isIgnorable(Throwable t) {
-		return HandlersUtilities.isIgnorable(t);
-	}
+  public void init(DuccWebServer duccWebServer) {
+    this.duccWebServer = duccWebServer;
+  }
 
-	public String getFmtDuration(IDuccWorkJob job, HttpServletRequest request, long now) {
-		String retVal = "";
-		StringBuffer tb = new StringBuffer();
-		if(job.isCompleted()) {
-			String duration = getDuration(request,job);
-			String decoratedDuration = decorateDuration(request,job, duration);
-			tb.append("<span>");
-			tb.append(decoratedDuration);
-			tb.append("</span>");
-			retVal = tb.toString();
-		}
-		else {
-			String duration = getDuration(request,job,now);
-			String decoratedDuration = decorateDuration(request,job, duration);
-			tb.append("<span class=\"health_green\""+">");
-			tb.append(decoratedDuration);
-			tb.append("</span>");
-			String projection = getProjection(request,job);
-			tb.append(projection);
-			retVal = tb.toString();
-		}
-		return retVal;
-	}
+  public boolean isIgnorable(Throwable t) {
+    return HandlersUtilities.isIgnorable(t);
+  }
 
-	public String getLink(IDuccWorkJob job) {
-		String retVal = "";
-		String parm = job.getDuccId().toString();
-		String displayId =  "j"+parm;
-		String link = "<a href=\"job.details.html?id="+parm+"\">"+displayId+"</a>";
-		retVal = link;
-		return retVal;
-	}
+  public String getFmtDuration(IDuccWorkJob job, HttpServletRequest request, long now) {
+    String retVal = "";
+    StringBuffer tb = new StringBuffer();
+    if (job.isCompleted()) {
+      String duration = getDuration(request, job);
+      String decoratedDuration = decorateDuration(request, job, duration);
+      tb.append("<span>");
+      tb.append(decoratedDuration);
+      tb.append("</span>");
+      retVal = tb.toString();
+    } else {
+      String duration = getDuration(request, job, now);
+      String decoratedDuration = decorateDuration(request, job, duration);
+      tb.append("<span class=\"health_green\"" + ">");
+      tb.append(decoratedDuration);
+      tb.append("</span>");
+      String projection = getProjection(request, job);
+      tb.append(projection);
+      retVal = tb.toString();
+    }
+    return retVal;
+  }
 
-	public String getTotal(IDuccWorkJob job) {
-		String retVal = "";
-		String total = job.getSchedulingInfo().getWorkItemsTotal();
-		retVal = total;
-		return retVal;
-	}
+  public String getLink(IDuccWorkJob job) {
+    String retVal = "";
+    String parm = job.getDuccId().toString();
+    String displayId = "j" + parm;
+    String link = "<a href=\"job.details.html?id=" + parm + "\">" + displayId + "</a>";
+    retVal = link;
+    return retVal;
+  }
 
-	public String getDone(IDuccWorkJob job) {
-		String retVal = "";
-		String done = job.getSchedulingInfo().getWorkItemsCompleted();
-		IDuccPerWorkItemStatistics perWorkItemStatistics = job.getSchedulingInfo().getPerWorkItemStatistics();
-		if (perWorkItemStatistics != null) {
-			double max = Math.round(perWorkItemStatistics.getMax()/100.0)/10.0;
-			double min = Math.round(perWorkItemStatistics.getMin()/100.0)/10.0;
-			double avg = Math.round(perWorkItemStatistics.getMean()/100.0)/10.0;
-			double dev = Math.round(perWorkItemStatistics.getStandardDeviation()/100.0)/10.0;
-			done = "<span title=\""+"seconds-per-work-item "+"Max:"+max+" "+"Min:"+min+" "+"Avg:"+avg+" "+"Dev:"+dev+"\""+">"+done+"</span>";
-		}
-		retVal = done;
-		return retVal;
-	}
+  public String getTotal(IDuccWorkJob job) {
+    String retVal = "";
+    String total = job.getSchedulingInfo().getWorkItemsTotal();
+    retVal = total;
+    return retVal;
+  }
 
-	public String getDispatch(IDuccWorkJob job) {
-		String retVal = "";
-		if(duccData.isLive(job.getDuccId())) {
-			int unassigned = job.getSchedulingInfo().getCasQueuedMap().size();
-			try {
-				int dispatched = Integer.parseInt(job.getSchedulingInfo().getWorkItemsDispatched())-unassigned;
-				retVal = ""+dispatched;
-			}
-			catch(Exception e) {
-			}
-		}
-		else {
-			retVal = "0";
-		}
-		return retVal;
-	}
+  public String getDone(IDuccWorkJob job) {
+    String retVal = "";
+    String done = job.getSchedulingInfo().getWorkItemsCompleted();
+    IDuccPerWorkItemStatistics perWorkItemStatistics = job.getSchedulingInfo()
+            .getPerWorkItemStatistics();
+    if (perWorkItemStatistics != null) {
+      double max = Math.round(perWorkItemStatistics.getMax() / 100.0) / 10.0;
+      double min = Math.round(perWorkItemStatistics.getMin() / 100.0) / 10.0;
+      double avg = Math.round(perWorkItemStatistics.getMean() / 100.0) / 10.0;
+      double dev = Math.round(perWorkItemStatistics.getStandardDeviation() / 100.0) / 10.0;
+      done = "<span title=\"" + "seconds-per-work-item " + "Max:" + max + " " + "Min:" + min + " "
+              + "Avg:" + avg + " " + "Dev:" + dev + "\"" + ">" + done + "</span>";
+    }
+    retVal = done;
+    return retVal;
+  }
 
-	public String getError(IDuccWorkJob job) {
-		String retVal = "";
-		retVal = buildErrorLink(job);
-		return retVal;
-	}
+  public String getDispatch(IDuccWorkJob job) {
+    String retVal = "";
+    if (duccData.isLive(job.getDuccId())) {
+      int unassigned = job.getSchedulingInfo().getCasQueuedMap().size();
+      try {
+        int dispatched = Integer.parseInt(job.getSchedulingInfo().getWorkItemsDispatched())
+                - unassigned;
+        retVal = "" + dispatched;
+      } catch (Exception e) {
+      }
+    } else {
+      retVal = "0";
+    }
+    return retVal;
+  }
 
-	public String getRetry(IDuccWorkJob job) {
-		String retVal = "";
-		retVal = job.getSchedulingInfo().getWorkItemsRetry();
-		return retVal;
-	}
+  public String getError(IDuccWorkJob job) {
+    String retVal = "";
+    retVal = buildErrorLink(job);
+    return retVal;
+  }
 
-	public String getPreempt(IDuccWorkJob job) {
-		String retVal = "";
-		retVal = job.getSchedulingInfo().getWorkItemsPreempt();
-		return retVal;
-	}
+  public String getRetry(IDuccWorkJob job) {
+    String retVal = "";
+    retVal = job.getSchedulingInfo().getWorkItemsRetry();
+    return retVal;
+  }
 
-	public String buildErrorLink(IDuccWorkJob job) {
-		return(buildErrorLink(job,null));
-	}
+  public String getPreempt(IDuccWorkJob job) {
+    String retVal = "";
+    retVal = job.getSchedulingInfo().getWorkItemsPreempt();
+    return retVal;
+  }
 
-	public final String duccLogData			  = duccContext+"/log-data";
+  public String buildErrorLink(IDuccWorkJob job) {
+    return (buildErrorLink(job, null));
+  }
 
-	public String buildErrorLink(IDuccWorkJob job, String name) {
-		String retVal = job.getSchedulingInfo().getWorkItemsError();
-		if(!retVal.equals("0")) {
-			String errorCount = retVal;
-			if(name == null) {
-				name = errorCount;
-			}
-			String logfile = job.getUserLogDir() + "jd.err.log";
-			String href = "<a href=\""+duccLogData+"?"+"fname="+logfile+"\" onclick=\"var newWin = window.open(this.href,'child','height=800,width=1200,scrollbars');  newWin.focus(); return false;\">"+name+"</a>";
-			retVal = href;
-		}
-		return retVal;
-	}
+  public final String duccLogData = duccContext + "/log-data";
 
-	public String getDuration(HttpServletRequest request, IDuccWork dw) {
-		String mName = "getDuration";
-		String retVal = "";
-		try {
-			String v2 = dw.getStandardInfo().getDateOfCompletion();
-			String v1 = dw.getStandardInfo().getDateOfSubmission();
-			WsLog.trace(cName, mName, "v2:"+v2+" v1:"+v1);
-			retVal = getDuration(dw.getDuccId(),v2,v1);
-		}
-		catch(Exception e) {
-			//
-		}
-		catch(Throwable t) {
-			//
-		}
-		return retVal;
-	}
+  public String buildErrorLink(IDuccWorkJob job, String name) {
+    String retVal = job.getSchedulingInfo().getWorkItemsError();
+    if (!retVal.equals("0")) {
+      String errorCount = retVal;
+      if (name == null) {
+        name = errorCount;
+      }
+      String logfile = job.getUserLogDir() + "jd.err.log";
+      String href = "<a href=\"" + duccLogData + "?" + "fname=" + logfile
+              + "\" onclick=\"var newWin = window.open(this.href,'child','height=800,width=1200,scrollbars');  newWin.focus(); return false;\">"
+              + name + "</a>";
+      retVal = href;
+    }
+    return retVal;
+  }
 
-	public String getDuration(HttpServletRequest request, IDuccWork dw, long now) {
-		String retVal = "";
-		try {
-			String v2 = ""+now;
-			String v1 = dw.getStandardInfo().getDateOfSubmission();
-			retVal = getDuration(dw.getDuccId(),v2,v1);
-		}
-		catch(Exception e) {
-		}
-		catch(Throwable t) {
-		}
-		return retVal;
-	}
+  public String getDuration(HttpServletRequest request, IDuccWork dw) {
+    String mName = "getDuration";
+    String retVal = "";
+    try {
+      String v2 = dw.getStandardInfo().getDateOfCompletion();
+      String v1 = dw.getStandardInfo().getDateOfSubmission();
+      WsLog.trace(cName, mName, "v2:" + v2 + " v1:" + v1);
+      retVal = getDuration(dw.getDuccId(), v2, v1);
+    } catch (Exception e) {
+      //
+    } catch (Throwable t) {
+      //
+    }
+    return retVal;
+  }
 
-	public String getDuration(DuccId jobId, String millisV2, String millisV1) {
-		String retVal = "";
-		try {
-			long d2 = Long.parseLong(millisV2);
-			long d1 = Long.parseLong(millisV1);
-			long diff = d2 - d1;
-			retVal = FormatHelper.duration(diff,Precision.Whole);
-		}
-		catch(Exception e) {
-			//
-		}
-		catch(Throwable t) {
-			//
-		}
-		return retVal;
-	}
+  public String getDuration(HttpServletRequest request, IDuccWork dw, long now) {
+    String retVal = "";
+    try {
+      String v2 = "" + now;
+      String v1 = dw.getStandardInfo().getDateOfSubmission();
+      retVal = getDuration(dw.getDuccId(), v2, v1);
+    } catch (Exception e) {
+    } catch (Throwable t) {
+    }
+    return retVal;
+  }
 
-	public String decorateDuration(HttpServletRequest request, IDuccWorkJob job, String duration) {
-		String mName = "decorateDuration";
-		String retVal = duration;
-		try {
-			StringBuffer title = new StringBuffer();
-			double avgMillisPerWorkItem = getAvgMillisPerWorkItem(request, job);
-			if(avgMillisPerWorkItem > 0) {
-				if(avgMillisPerWorkItem < 500) {
-					avgMillisPerWorkItem = 500;
-				}
-			}
-			int iAvgMillisPerWorkItem = (int)avgMillisPerWorkItem;
-			if(iAvgMillisPerWorkItem > 0) {
-				if(title.length() > 0) {
-					title.append("; ");
-				}
-				title.append("Time (ddd:hh:mm:ss) elapsed for job, average processing time per work item="+FormatHelper.duration(iAvgMillisPerWorkItem,Precision.Whole));
-			}
-			String cVal = getCompletion(request,job);
-			if(cVal != null) {
-				if(cVal.length() > 0) {
-					if(title.length() > 0) {
-						title.append("; ");
-					}
-					title.append("End="+cVal);
-				}
-			}
-			if(title.length() > 0) {
-				retVal = "<span "+"title=\""+title+"\""+">"+duration+"</span>";
-			}
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-		return retVal;
-	}
+  public String getDuration(DuccId jobId, String millisV2, String millisV1) {
+    String retVal = "";
+    try {
+      long d2 = Long.parseLong(millisV2);
+      long d1 = Long.parseLong(millisV1);
+      long diff = d2 - d1;
+      retVal = FormatHelper.duration(diff, Precision.Whole);
+    } catch (Exception e) {
+      //
+    } catch (Throwable t) {
+      //
+    }
+    return retVal;
+  }
 
-	public String decorateDuration(HttpServletRequest request, IDuccWorkReservation reservation, String duration) {
-		String retVal = duration;
-		String cVal = getCompletion(request,reservation);
-		if(cVal != null) {
-			if(cVal.length() > 0) {
-				String title = "title=\""+"End="+cVal+"\"";
-				retVal = "<span "+title+">"+duration+"</span>";
-			}
-		}
-		return retVal;
-	}
+  public String decorateDuration(HttpServletRequest request, IDuccWorkJob job, String duration) {
+    String mName = "decorateDuration";
+    String retVal = duration;
+    try {
+      StringBuffer title = new StringBuffer();
+      double avgMillisPerWorkItem = getAvgMillisPerWorkItem(request, job);
+      if (avgMillisPerWorkItem > 0) {
+        if (avgMillisPerWorkItem < 500) {
+          avgMillisPerWorkItem = 500;
+        }
+      }
+      int iAvgMillisPerWorkItem = (int) avgMillisPerWorkItem;
+      if (iAvgMillisPerWorkItem > 0) {
+        if (title.length() > 0) {
+          title.append("; ");
+        }
+        title.append("Time (ddd:hh:mm:ss) elapsed for job, average processing time per work item="
+                + FormatHelper.duration(iAvgMillisPerWorkItem, Precision.Whole));
+      }
+      String cVal = getCompletion(request, job);
+      if (cVal != null) {
+        if (cVal.length() > 0) {
+          if (title.length() > 0) {
+            title.append("; ");
+          }
+          title.append("End=" + cVal);
+        }
+      }
+      if (title.length() > 0) {
+        retVal = "<span " + "title=\"" + title + "\"" + ">" + duration + "</span>";
+      }
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+    return retVal;
+  }
 
+  public String decorateDuration(HttpServletRequest request, IDuccWorkReservation reservation,
+          String duration) {
+    String retVal = duration;
+    String cVal = getCompletion(request, reservation);
+    if (cVal != null) {
+      if (cVal.length() > 0) {
+        String title = "title=\"" + "End=" + cVal + "\"";
+        retVal = "<span " + title + ">" + duration + "</span>";
+      }
+    }
+    return retVal;
+  }
 
-	public double getAvgMillisPerWorkItem(HttpServletRequest request, IDuccWorkJob job) {
-		double avgMillis = 0;
-		IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
-		IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
-		if (perWorkItemStatistics != null) {
-			avgMillis = perWorkItemStatistics.getMean();
-		}
-		return avgMillis;
-}
+  public double getAvgMillisPerWorkItem(HttpServletRequest request, IDuccWorkJob job) {
+    double avgMillis = 0;
+    IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
+    IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
+    if (perWorkItemStatistics != null) {
+      avgMillis = perWorkItemStatistics.getMean();
+    }
+    return avgMillis;
+  }
 
-	public String getCompletion(HttpServletRequest request, IDuccWorkJob job) {
-		String retVal = "";
-		try {
-			String tVal = job.getStandardInfo().getDateOfCompletion();
-			retVal = getTimeStamp(request,job.getDuccId(),tVal);
-		}
-		catch(Exception e) {
-		}
-		catch(Throwable t) {
-		}
-		return retVal;
-	}
+  public String getCompletion(HttpServletRequest request, IDuccWorkJob job) {
+    String retVal = "";
+    try {
+      String tVal = job.getStandardInfo().getDateOfCompletion();
+      retVal = getTimeStamp(request, job.getDuccId(), tVal);
+    } catch (Exception e) {
+    } catch (Throwable t) {
+    }
+    return retVal;
+  }
 
-	public String getCompletion(HttpServletRequest request, IDuccWorkReservation reservation) {
-		String retVal = "";
-		try {
-			String tVal = reservation.getStandardInfo().getDateOfCompletion();
-			retVal = getTimeStamp(request,reservation.getDuccId(),tVal);
-		}
-		catch(Exception e) {
-		}
-		catch(Throwable t) {
-		}
-		return retVal;
-	}
+  public String getCompletion(HttpServletRequest request, IDuccWorkReservation reservation) {
+    String retVal = "";
+    try {
+      String tVal = reservation.getStandardInfo().getDateOfCompletion();
+      retVal = getTimeStamp(request, reservation.getDuccId(), tVal);
+    } catch (Exception e) {
+    } catch (Throwable t) {
+    }
+    return retVal;
+  }
 
-	public String getTimeStamp(HttpServletRequest request, DuccId jobId, String millis) {
-		return getTimeStamp(DuccCookies.getDateStyle(request),getTimeStamp(jobId, millis));
-	}
+  public String getTimeStamp(HttpServletRequest request, DuccId jobId, String millis) {
+    return getTimeStamp(DuccCookies.getDateStyle(request), getTimeStamp(jobId, millis));
+  }
 
-	private String getTimeStamp(DuccId jobId, String millis) {
-		String mName = "getTimeStamp";
-		String retVal = "";
-		try {
-			retVal = TimeStamp.simpleFormat(millis);
-		}
-		catch(Throwable t) {
-			WsLog.debug(cName, mName, "millis:"+millis);
-		}
-		return retVal;
-	}
+  private String getTimeStamp(DuccId jobId, String millis) {
+    String mName = "getTimeStamp";
+    String retVal = "";
+    try {
+      retVal = TimeStamp.simpleFormat(millis);
+    } catch (Throwable t) {
+      WsLog.debug(cName, mName, "millis:" + millis);
+    }
+    return retVal;
+  }
 
-	public String getTimeStamp(DateStyle dateStyle, String date) {
-		String mName = "getTimeStamp";
-		StringBuffer sb = new StringBuffer();
-		if(date != null) {
-			sb.append(date);
-			if(date.trim().length() > 0) {
-				try {
-					switch(dateStyle) {
-					case Long:
-						break;
-					case Medium:
-						String day = sb.substring(sb.length()-4);
-						sb.delete(0, 5);
-						sb.delete(sb.lastIndexOf(":"), sb.length());
-						sb.append(day);
-						break;
-					case Short:
-						sb.delete(0, 5);
-						sb.delete(sb.lastIndexOf(":"), sb.length());
-						break;
-					}
-				}
-				catch(Exception e) {
-					 WsLog.error(cName, mName, e);
-				}
-			}
-		}
-		return sb.toString();
-	}
+  public String getTimeStamp(DateStyle dateStyle, String date) {
+    String mName = "getTimeStamp";
+    StringBuffer sb = new StringBuffer();
+    if (date != null) {
+      sb.append(date);
+      if (date.trim().length() > 0) {
+        try {
+          switch (dateStyle) {
+            case Long:
+              break;
+            case Medium:
+              String day = sb.substring(sb.length() - 4);
+              sb.delete(0, 5);
+              sb.delete(sb.lastIndexOf(":"), sb.length());
+              sb.append(day);
+              break;
+            case Short:
+              sb.delete(0, 5);
+              sb.delete(sb.lastIndexOf(":"), sb.length());
+              break;
+          }
+        } catch (Exception e) {
+          WsLog.error(cName, mName, e);
+        }
+      }
+    }
+    return sb.toString();
+  }
 
-	public String getProjection(HttpServletRequest request, IDuccWorkJob job) {
-		String mName = "getProjection";
-		String retVal = "";
-		try {
-			IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
-			IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
-			if (perWorkItemStatistics == null) {
-				return "";
-			}
-			int total = schedulingInfo.getIntWorkItemsTotal();
-			int completed = schedulingInfo.getIntWorkItemsCompleted();
-			int error = schedulingInfo.getIntWorkItemsError();
-			int remainingWorkItems = total - (completed + error);
-			if(remainingWorkItems > 0) {
-				int usableProcessCount = job.getProcessMap().getUsableProcessCount();
-				if(usableProcessCount > 0) {
-					if(completed > 0) {
-						int threadsPerProcess = schedulingInfo.getIntThreadsPerProcess();
-						int totalThreads = usableProcessCount * threadsPerProcess;
-						double remainingIterations = remainingWorkItems / totalThreads;
-						double avgMillis = perWorkItemStatistics.getMean();
-						double leastOperatingMillis = job.getWiMillisOperatingLeast();
-						double mostCompletedMillis = job.getWiMillisCompletedMost();
-						double projectedTime = (avgMillis * remainingIterations) + (mostCompletedMillis - leastOperatingMillis);
-						String text = "avgMillis:"+avgMillis+" "+"remainingIterations:"+remainingIterations+" "+"mostCompleteMillis:"+mostCompletedMillis+" "+"leastOperatingMillis:"+leastOperatingMillis;
-						WsLog.trace(cName, mName, text);
-						if(projectedTime > 0) {
-							long millis = Math.round(projectedTime);
-							if(millis > 1000) {
-								String projection = FormatHelper.duration(millis,Precision.Whole);
-								String health = "class=\"health_yellow\"";
-								String title = "title=\"Time (ddd:hh:mm:ss) until projected completion\"";
-								retVal = "+"+"<span "+health+" "+title+"><i>"+projection+"</i></span>";
-								retVal = " {"+retVal+"}";
-							}
-						}
-						else {
-							long millis = Math.round(0-projectedTime);
-							if(millis > 1000) {
-								String projection = FormatHelper.duration(millis,Precision.Whole);
-								String health = "class=\"health_purple\"";
-								String title = "title=\"Time (ddd:hh:mm:ss) past-due projected completion\"";
-								retVal = "-"+"<span "+health+" "+title+"><i>"+projection+"</i></span>";
-								retVal = " {"+retVal+"}";
-							}
-						}
-					}
-				}
-			}
-		}
-		catch(Throwable t) {
-			WsLog.error(cName, mName, t);
-		}
-		return retVal;
-	}
+  public String getProjection(HttpServletRequest request, IDuccWorkJob job) {
+    String mName = "getProjection";
+    String retVal = "";
+    try {
+      IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
+      IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
+      if (perWorkItemStatistics == null) {
+        return "";
+      }
+      int total = schedulingInfo.getIntWorkItemsTotal();
+      int completed = schedulingInfo.getIntWorkItemsCompleted();
+      int error = schedulingInfo.getIntWorkItemsError();
+      int remainingWorkItems = total - (completed + error);
+      if (remainingWorkItems > 0) {
+        int usableProcessCount = job.getProcessMap().getUsableProcessCount();
+        if (usableProcessCount > 0) {
+          if (completed > 0) {
+            int threadsPerProcess = schedulingInfo.getIntThreadsPerProcess();
+            int totalThreads = usableProcessCount * threadsPerProcess;
+            double remainingIterations = remainingWorkItems / totalThreads;
+            double avgMillis = perWorkItemStatistics.getMean();
+            double leastOperatingMillis = job.getWiMillisOperatingLeast();
+            double mostCompletedMillis = job.getWiMillisCompletedMost();
+            double projectedTime = (avgMillis * remainingIterations)
+                    + (mostCompletedMillis - leastOperatingMillis);
+            String text = "avgMillis:" + avgMillis + " " + "remainingIterations:"
+                    + remainingIterations + " " + "mostCompleteMillis:" + mostCompletedMillis + " "
+                    + "leastOperatingMillis:" + leastOperatingMillis;
+            WsLog.trace(cName, mName, text);
+            if (projectedTime > 0) {
+              long millis = Math.round(projectedTime);
+              if (millis > 1000) {
+                String projection = FormatHelper.duration(millis, Precision.Whole);
+                String health = "class=\"health_yellow\"";
+                String title = "title=\"Time (ddd:hh:mm:ss) until projected completion\"";
+                retVal = "+" + "<span " + health + " " + title + "><i>" + projection
+                        + "</i></span>";
+                retVal = " {" + retVal + "}";
+              }
+            } else {
+              long millis = Math.round(0 - projectedTime);
+              if (millis > 1000) {
+                String projection = FormatHelper.duration(millis, Precision.Whole);
+                String health = "class=\"health_purple\"";
+                String title = "title=\"Time (ddd:hh:mm:ss) past-due projected completion\"";
+                retVal = "-" + "<span " + health + " " + title + "><i>" + projection
+                        + "</i></span>";
+                retVal = " {" + retVal + "}";
+              }
+            }
+          }
+        }
+      }
+    } catch (Throwable t) {
+      WsLog.error(cName, mName, t);
+    }
+    return retVal;
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
index e921891..affddc3 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
@@ -57,1082 +57,1086 @@
 import com.google.gson.JsonPrimitive;
 
 public class HandlerExperimentsServlets extends HandlerExperimentsAbstract {
-	
-  //NOTE - this variable used to hold the class name before WsLog was simplified
+
+  // NOTE - this variable used to hold the class name before WsLog was simplified
   private static DuccLogger cName = DuccLogger.getLogger(HandlerExperimentsServlets.class);
 
-	public final int defaultRecordsExperiments = 16;
-	
-	public final String duccContextExperimentCancelRequest =  DuccLocalConstants.duccContextExperimentCancelRequest;
-	
-	public final String duccContextExperiments =  DuccLocalConstants.duccContextExperiments;
-	public final String duccContextExperimentDetails =  DuccLocalConstants.duccContextExperimentDetails;
-	public final String duccContextExperimentDetailsDirectory =  DuccLocalConstants.duccContextExperimentDetailsDirectory;
-	
-	public final String duccContextJsonExperiments =  DuccLocalConstants.duccContextJsonExperiments;
-	public final String duccContextJsonExperimentDetails =  DuccLocalConstants.duccContextJsonExperimentDetails;
+  public final int defaultRecordsExperiments = 16;
 
-	private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager.getInstance();
-	
-	private static DuccData duccData = DuccData.getInstance();
-	
-	protected boolean terminateEnabled = true;
-	
-	public HandlerExperimentsServlets(DuccWebServer duccWebServer) {
-		super.init(duccWebServer);
-	}
-	
-	private String getStartDate(HttpServletRequest request, IExperiment experiment) {
-		String startDate ="";
-		if(experiment.getStartDate() != null) {
-			startDate = experiment.getStartDate();
-			DateStyle dateStyle = DuccCookies.getDateStyle(request);
-			startDate = HandlersUtilities.reFormatDate(dateStyle, startDate);
-		}
-		return startDate;
-	}
-	
-	private long getRunTime(HttpServletRequest request, IExperiment experiment) {
-		long runTime = 0;
-		if(experiment.getTasks() != null) {
-			ArrayList<Task> tasks = experiment.getTasks();
-			for(Task task : tasks) {
-				if(task.parentId == 0) {
-					if(task.runTime > runTime) {
-						runTime = task.runTime;
-					}
-				}
-			}
-		}
-		return runTime;
-	}
-	
-	private String getDuration(HttpServletRequest request, IExperiment experiment) {
-		Status experimentStatus = experiment.getStatus();
-		String durationUntitled = "";
-		long runTime = getRunTime(request, experiment);
-		if(runTime > 0) {
-			durationUntitled = FormatHelper.duration(runTime,Precision.Whole);
-		}
-		else {
-			switch(experimentStatus) {
-			case Running:
-				try {
-					String startDate = "";
-					if(experiment.getStartDate() != null) {
-						startDate = experiment.getStartDate();
-					}
-					long millisStart = HandlersUtilities.getMillis(startDate);
-					long millisEnd = System.currentTimeMillis();
-					if(millisStart > 0) {
-						runTime = millisEnd - millisStart;
-						durationUntitled = FormatHelper.duration(runTime,Precision.Whole);
-					}
-				}
-				catch(Exception e) {
-					// no worries
-				}
-				break;
+  public final String duccContextExperimentCancelRequest = DuccLocalConstants.duccContextExperimentCancelRequest;
+
+  public final String duccContextExperiments = DuccLocalConstants.duccContextExperiments;
+
+  public final String duccContextExperimentDetails = DuccLocalConstants.duccContextExperimentDetails;
+
+  public final String duccContextExperimentDetailsDirectory = DuccLocalConstants.duccContextExperimentDetailsDirectory;
+
+  public final String duccContextJsonExperiments = DuccLocalConstants.duccContextJsonExperiments;
+
+  public final String duccContextJsonExperimentDetails = DuccLocalConstants.duccContextJsonExperimentDetails;
+
+  private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager
+          .getInstance();
+
+  private static DuccData duccData = DuccData.getInstance();
+
+  protected boolean terminateEnabled = true;
+
+  public HandlerExperimentsServlets(DuccWebServer duccWebServer) {
+    super.init(duccWebServer);
+  }
+
+  private String getStartDate(HttpServletRequest request, IExperiment experiment) {
+    String startDate = "";
+    if (experiment.getStartDate() != null) {
+      startDate = experiment.getStartDate();
+      DateStyle dateStyle = DuccCookies.getDateStyle(request);
+      startDate = HandlersUtilities.reFormatDate(dateStyle, startDate);
+    }
+    return startDate;
+  }
+
+  private long getRunTime(HttpServletRequest request, IExperiment experiment) {
+    long runTime = 0;
+    if (experiment.getTasks() != null) {
+      ArrayList<Task> tasks = experiment.getTasks();
+      for (Task task : tasks) {
+        if (task.parentId == 0) {
+          if (task.runTime > runTime) {
+            runTime = task.runTime;
+          }
+        }
+      }
+    }
+    return runTime;
+  }
+
+  private String getDuration(HttpServletRequest request, IExperiment experiment) {
+    Status experimentStatus = experiment.getStatus();
+    String durationUntitled = "";
+    long runTime = getRunTime(request, experiment);
+    if (runTime > 0) {
+      durationUntitled = FormatHelper.duration(runTime, Precision.Whole);
+    } else {
+      switch (experimentStatus) {
+        case Running:
+          try {
+            String startDate = "";
+            if (experiment.getStartDate() != null) {
+              startDate = experiment.getStartDate();
+            }
+            long millisStart = HandlersUtilities.getMillis(startDate);
+            long millisEnd = System.currentTimeMillis();
+            if (millisStart > 0) {
+              runTime = millisEnd - millisStart;
+              durationUntitled = FormatHelper.duration(runTime, Precision.Whole);
+            }
+          } catch (Exception e) {
+            // no worries
+          }
+          break;
+        default:
+          break;
+      }
+    }
+    String health = " class=\"health_black\" ";
+    switch (experimentStatus) {
+      case Running:
+        health = " class=\"health_green\" ";
+        break;
       default:
         break;
-			}
-		}
-		String health = " class=\"health_black\" ";
-		switch(experimentStatus) {
-		case Running:
-			health = " class=\"health_green\" ";
-			break;
-    default:
-      break;
-		}
-		StringBuffer db = new StringBuffer();
-		db.append("<span "+health+"title=\"Time (ddd:hh:mm:ss) elapsed for task, including all child tasks\">");
-		db.append(durationUntitled);
-		db.append("</span>");
-		String duration = db.toString();
-		return duration;
-	}
-	
-	private String getUser(HttpServletRequest request, IExperiment experiment) {
-		String user = "";
-		if(experiment.getUser() != null) {
-			user = experiment.getUser();
-		}
-		return user;
-	}
-	
-	private String getTasks(HttpServletRequest request, IExperiment experiment) {
-		String tasks = "0";
-		if(experiment.getTasks() != null) {
-			tasks = ""+experiment.getTasks().size();
-		}
-		return tasks;
-	}
-	
-	private String getState(HttpServletRequest request, IExperiment experiment) {
-		String health;
-		Status experimentStatus = experiment.getStatus();
-		switch (experimentStatus) {
-		    case Failed:
-		    case Canceled:
-		    case Unknown:
-		        health = "red";
-		        break;
-		    case Running:
-		        health = "green";
-		        break;
-		    default:
-		        health = "black";
-		}
-		String state = "<span class=\"health_" + health + "\">" +experimentStatus.name() + "</span>";
-		return state;
-	}
-	
-	private String getDirectoryLink(HttpServletRequest request, IExperiment experiment) {
-		String directory = experiment.getDirectory();
-		String id = experiment.getId();
-		String href = "href=\"experiment.details.html?id="+id+"\"";
-		String directoryLink = "<a"+" "+href+" "+">"+directory+"</a>";
-		return directoryLink;
-	}
-	
-	private boolean handleServletJsonExperiments(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletJsonExperiments";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		JsonObject jsonResponse = new JsonObject();
-		JsonArray data = new JsonArray();
+    }
+    StringBuffer db = new StringBuffer();
+    db.append("<span " + health
+            + "title=\"Time (ddd:hh:mm:ss) elapsed for task, including all child tasks\">");
+    db.append(durationUntitled);
+    db.append("</span>");
+    String duration = db.toString();
+    return duration;
+  }
 
-		TreeMap<IExperiment, String> map = experimentsRegistryManager.getMapByStatus();
-		
-		int maxRecords = HandlersUtilities.getExperimentsMax(request);
-		ArrayList<String> users = HandlersUtilities.getExperimentsUsers(request);
-		
-		int counter = 0;
-		
-		for(Entry<IExperiment, String> entry: map.entrySet()) {
-			
-			IExperiment experiment = entry.getKey();
+  private String getUser(HttpServletRequest request, IExperiment experiment) {
+    String user = "";
+    if (experiment.getUser() != null) {
+      user = experiment.getUser();
+    }
+    return user;
+  }
 
-			if(HandlersUtilities.isListable(request, users, maxRecords, counter, experiment)) {
-				counter++;
-				JsonArray row = new JsonArray();
-				// 00 Terminate
-				String terminate = "";
-				if(terminateEnabled) {
-					Status experimentStatus = experiment.getStatus();
-					switch(experimentStatus) {
-					case Running:
-						String id = experiment.getId();
-						String directory = experiment.getDirectory();
-						String disabled = "";
-						String resourceOwnerUserid = experiment.getUser();
-						if(!HandlersHelper.isUserAuthorized(request, resourceOwnerUserid)) {
-							disabled = "disabled title=\"Hint: use Login to enable\"";
-						}
-						String p0 = "'"+id+"'";
-						String p1 = "'"+directory+"'";
-						terminate = "<input type=\"button\" onclick=\"ducc_confirm_terminate_experiment("+p0+","+p1+")\" value=\"Terminate\" "+disabled+"/>";
+  private String getTasks(HttpServletRequest request, IExperiment experiment) {
+    String tasks = "0";
+    if (experiment.getTasks() != null) {
+      tasks = "" + experiment.getTasks().size();
+    }
+    return tasks;
+  }
+
+  private String getState(HttpServletRequest request, IExperiment experiment) {
+    String health;
+    Status experimentStatus = experiment.getStatus();
+    switch (experimentStatus) {
+      case Failed:
+      case Canceled:
+      case Unknown:
+        health = "red";
+        break;
+      case Running:
+        health = "green";
+        break;
+      default:
+        health = "black";
+    }
+    String state = "<span class=\"health_" + health + "\">" + experimentStatus.name() + "</span>";
+    return state;
+  }
+
+  private String getDirectoryLink(HttpServletRequest request, IExperiment experiment) {
+    String directory = experiment.getDirectory();
+    String id = experiment.getId();
+    String href = "href=\"experiment.details.html?id=" + id + "\"";
+    String directoryLink = "<a" + " " + href + " " + ">" + directory + "</a>";
+    return directoryLink;
+  }
+
+  private boolean handleServletJsonExperiments(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletJsonExperiments";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    JsonObject jsonResponse = new JsonObject();
+    JsonArray data = new JsonArray();
+
+    TreeMap<IExperiment, String> map = experimentsRegistryManager.getMapByStatus();
+
+    int maxRecords = HandlersUtilities.getExperimentsMax(request);
+    ArrayList<String> users = HandlersUtilities.getExperimentsUsers(request);
+
+    int counter = 0;
+
+    for (Entry<IExperiment, String> entry : map.entrySet()) {
+
+      IExperiment experiment = entry.getKey();
+
+      if (HandlersUtilities.isListable(request, users, maxRecords, counter, experiment)) {
+        counter++;
+        JsonArray row = new JsonArray();
+        // 00 Terminate
+        String terminate = "";
+        if (terminateEnabled) {
+          Status experimentStatus = experiment.getStatus();
+          switch (experimentStatus) {
+            case Running:
+              String id = experiment.getId();
+              String directory = experiment.getDirectory();
+              String disabled = "";
+              String resourceOwnerUserid = experiment.getUser();
+              if (!HandlersHelper.isUserAuthorized(request, resourceOwnerUserid)) {
+                disabled = "disabled title=\"Hint: use Login to enable\"";
+              }
+              String p0 = "'" + id + "'";
+              String p1 = "'" + directory + "'";
+              terminate = "<input type=\"button\" onclick=\"ducc_confirm_terminate_experiment(" + p0
+                      + "," + p1 + ")\" value=\"Terminate\" " + disabled + "/>";
+            default:
+              break;
+          }
+        }
+        row.add(new JsonPrimitive(terminate));
+        // 01 Start
+        String startDate = getStartDate(request, experiment);
+        row.add(new JsonPrimitive(startDate));
+        // 02 Duration
+        String duration = getDuration(request, experiment);
+        row.add(new JsonPrimitive(duration));
+        // 03 User
+        String user = getUser(request, experiment);
+        row.add(new JsonPrimitive(user));
+        // 04 Tasks
+        String tasks = getTasks(request, experiment);
+        row.add(new JsonPrimitive(tasks));
+        // 05 State
+        String state = getState(request, experiment);
+        row.add(new JsonPrimitive(state));
+        // 06 Directory (link)
+        String directoryLink = getDirectoryLink(request, experiment);
+        row.add(new JsonPrimitive(directoryLink));
+        // Row
+        data.add(row);
+      }
+    }
+
+    if (counter == 0) {
+      JsonArray row = new JsonArray();
+      row.add(new JsonPrimitive("no data"));
+      row.add(new JsonPrimitive(""));
+      row.add(new JsonPrimitive(""));
+      row.add(new JsonPrimitive(""));
+      row.add(new JsonPrimitive(""));
+      row.add(new JsonPrimitive(""));
+      data.add(row);
+    }
+
+    jsonResponse.add("aaData", data);
+
+    String json = jsonResponse.toString();
+    WsLog.debug(cName, mName, json);
+    response.getWriter().println(json);
+    response.setContentType("application/json");
+
+    handled = true;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private boolean handleServletExperiments(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletExperiments";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    StringBuffer sb = new StringBuffer();
+
+    TreeMap<IExperiment, String> map = experimentsRegistryManager.getMapByStatus();
+
+    int maxRecords = HandlersUtilities.getExperimentsMax(request);
+    ArrayList<String> users = HandlersUtilities.getExperimentsUsers(request);
+
+    int counter = -1;
+
+    for (Entry<IExperiment, String> entry : map.entrySet()) {
+
+      counter++;
+      IExperiment experiment = entry.getKey();
+
+      if (HandlersUtilities.isListable(request, users, maxRecords, counter, experiment)) {
+
+        int COLS = 7;
+        StringBuffer[] cbList = new StringBuffer[COLS];
+        for (int i = 0; i < COLS; i++) {
+          cbList[i] = new StringBuffer();
+        }
+
+        int index = -1;
+
+        // 00 Terminate
+        String terminate = "";
+        index++;
+        if (terminateEnabled) {
+          Status experimentStatus = experiment.getStatus();
+          switch (experimentStatus) {
+            case Running:
+              String id = experiment.getId();
+              String directory = experiment.getDirectory();
+              String disabled = "";
+              String resourceOwnerUserid = experiment.getUser();
+              if (!HandlersHelper.isUserAuthorized(request, resourceOwnerUserid)) {
+                disabled = "disabled title=\"Hint: use Login to enable\"";
+              }
+              String p0 = "'" + id + "'";
+              String p1 = "'" + directory + "'";
+              terminate = "<input type=\"button\" onclick=\"ducc_confirm_terminate_experiment(" + p0
+                      + "," + p1 + ")\" value=\"Terminate\" " + disabled + "/>";
+            default:
+              break;
+          }
+        }
+        cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+        cbList[index].append(terminate);
+        cbList[index].append("</td>");
+
+        // 01 Start
+        String startDate = getStartDate(request, experiment);
+        index++;
+        cbList[index].append("<td valign=\"bottom\">");
+        cbList[index].append(startDate);
+        cbList[index].append("</td>");
+
+        // 02 Duration
+        String duration = getDuration(request, experiment);
+        long runTime = getRunTime(request, experiment);
+        index++;
+        String sort = "sorttable_customkey=\"" + runTime + "\"";
+        cbList[index].append("<td valign=\"bottom\" " + sort + " align=\"right\">");
+        cbList[index].append(duration);
+        cbList[index].append("</td>");
+
+        // 03 User
+        String user = getUser(request, experiment);
+        index++;
+        cbList[index].append("<td valign=\"bottom\">");
+        cbList[index].append(user);
+        cbList[index].append("</td>");
+
+        // 04 Tasks
+        String tasks = getTasks(request, experiment);
+        index++;
+        cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+        cbList[index].append(tasks);
+        cbList[index].append("</td>");
+
+        // 05 State
+        String state = getState(request, experiment);
+        index++;
+        cbList[index].append("<td valign=\"bottom\">");
+        cbList[index].append(state);
+        cbList[index].append("</td>");
+
+        // 06 Directory (link)
+        String directoryLink = getDirectoryLink(request, experiment);
+        index++;
+        cbList[index].append("<td valign=\"bottom\">");
+        cbList[index].append(directoryLink);
+        cbList[index].append("</td>");
+
+        /////
+
+        StringBuffer row = new StringBuffer();
+
+        row.append(ResponseHelper.trStart(counter));
+        for (int i = 0; i < COLS; i++) {
+          row.append(cbList[i]);
+        }
+        row.append(ResponseHelper.trEnd(counter));
+        sb.append(row);
+      }
+    }
+
+    /////
+
+    if (sb.length() == 0) {
+      sb.append("<tr>");
+      sb.append("<td>");
+      sb.append("not found");
+      sb.append("</td>");
+      sb.append("</tr>");
+    }
+
+    response.getWriter().println(sb);
+
+    handled = true;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private boolean handleServletJsonExperimentDetails(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletJsonExperimentDetails";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private enum IdType {
+    Job, Reservation, None
+  };
+
+  private class IdBundle {
+
+    private IdType idType = IdType.None;
+
+    private int[] idList = new int[0];
+
+    public IdBundle() {
+    }
+
+    public IdBundle(IdType type, int[] list) {
+      idType = type;
+      idList = list;
+    }
+
+    public IdType getType() {
+      return idType;
+    }
+
+    public int[] getList() {
+      return idList;
+    }
+  }
+
+  private class IdListIterator {
+
+    private ArrayList<Long> reservations = new ArrayList<Long>();
+
+    private ArrayList<Long> jobs = new ArrayList<Long>();
+
+    public IdListIterator(Task task) {
+      if (task != null) {
+        long[] duccIdList = task.duccId;
+        for (long duccId : duccIdList) {
+          if (duccId < 0) {
+            Long r = new Long(duccId);
+            reservations.add(r);
+          } else {
+            Long j = new Long(duccId);
+            jobs.add(j);
+          }
+        }
+      }
+    }
+
+    public IdBundle getNext() {
+      IdBundle retVal = new IdBundle();
+      if (reservations.size() > 0) {
+        int[] list = new int[1];
+        Long r = reservations.remove(0);
+        list[0] = r.intValue();
+        retVal = new IdBundle(IdType.Reservation, list);
+      } else if (jobs.size() > 0) {
+        int[] list = new int[1];
+        Long j = jobs.remove(0);
+        list[0] = j.intValue();
+        retVal = new IdBundle(IdType.Job, list);
+      }
+      return retVal;
+    }
+
+    public boolean isEmpty() {
+      boolean retVal = true;
+      if (reservations.size() > 0) {
+        retVal = false;
+      }
+      if (jobs.size() > 0) {
+        retVal = false;
+      }
+      return retVal;
+    }
+  }
+
+  public enum ExperimentDetailsColumns {
+    Id(0), Name(1), Parent(2), State(3), Type(4), StepStart(5), StepDuration(6), DuccId(
+            7), DuccDuration(
+                    8), Total(9), Done(10), Error(11), Dispatch(12), Retry(13), Preempt(14);
+    private int index;
+
+    ExperimentDetailsColumns(int index) {
+      this.index = index;
+    }
+
+    public int getIndex() {
+      return index;
+    }
+
+    public static int getCols() {
+      return Preempt.getIndex() + 1;
+    }
+  }
+
+  private void addPlaceholder(StringBuffer[] cbList, int index) {
+    cbList[index].append("<td>");
+    cbList[index].append("</td>");
+  }
+
+  private void edId(StringBuffer[] cbList, Task task) {
+    long taskId = task.taskId;
+    int index = ExperimentDetailsColumns.Id.getIndex();
+    cbList[index].append("<td align=\"right\">");
+    cbList[index].append("" + taskId);
+    cbList[index].append("</td>");
+  }
+
+  private void edName(StringBuffer[] cbList, Task task) {
+    String name = "";
+    if (task.name != null) {
+      name = task.name;
+    }
+    int index = ExperimentDetailsColumns.Name.getIndex();
+    cbList[index].append("<td>");
+    cbList[index].append(name);
+    cbList[index].append("</td>");
+  }
+
+  private void edParent(StringBuffer[] cbList, Task task) {
+    long taskParentId = task.parentId;
+    int index = ExperimentDetailsColumns.Parent.getIndex();
+    cbList[index].append("<td align=\"right\">");
+    cbList[index].append("" + taskParentId);
+    cbList[index].append("</td>");
+  }
+
+  private void edState(StringBuffer[] cbList, IExperiment experiment, Task task) {
+    String mName = "edState";
+    String state = "";
+    if (task.status != null) {
+      state = task.status;
+      String type = task.type;
+      boolean leaf = Jed.Type.isLeaf(type);
+      if (leaf) {
+        Jed.Status status = Jed.Status.getEnum(state);
+        switch (status) {
+          case Running:
+            if (experiment.isStale()) {
+              state = "<span class=\"health_red\">Unknown";
+              WsLog.info(cName, mName, experiment.getDirectory() + " " + "stale:" + task.taskId);
+            } else {
+              state = "<span class=\"health_green\">Running";
+            }
+            break;
+          case Failed:
+          case DependencyFailed:
+          case Canceled:
+            state = "<span class=\"health_red\"" + ">" + state + "</span>";
+            break;
           default:
             break;
-					}
-				}
-				row.add(new JsonPrimitive(terminate));
-				// 01 Start
-				String startDate = getStartDate(request, experiment);
-				row.add(new JsonPrimitive(startDate));
-				// 02 Duration
-				String duration = getDuration(request, experiment);
-				row.add(new JsonPrimitive(duration));
-				// 03 User
-				String user = getUser(request, experiment);
-				row.add(new JsonPrimitive(user));
-				// 04 Tasks
-				String tasks = getTasks(request, experiment);
-				row.add(new JsonPrimitive(tasks));
-				// 05 State
-				String state = getState(request, experiment);
-				row.add(new JsonPrimitive(state));
-				// 06 Directory (link)
-				String directoryLink = getDirectoryLink(request, experiment);
-				row.add(new JsonPrimitive(directoryLink));
-				// Row
-				data.add(row);
-			}
-		}
-		
-		if(counter == 0) {
-			JsonArray row = new JsonArray();
-			row.add(new JsonPrimitive("no data"));
-			row.add(new JsonPrimitive(""));
-			row.add(new JsonPrimitive(""));
-			row.add(new JsonPrimitive(""));
-			row.add(new JsonPrimitive(""));
-			row.add(new JsonPrimitive(""));
-			data.add(row);
-		}
-		
-		jsonResponse.add("aaData", data);
-		
-		String json = jsonResponse.toString();
-		WsLog.debug(cName, mName, json);
-		response.getWriter().println(json);
-		response.setContentType("application/json");
-		
-		handled = true;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private boolean handleServletExperiments(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletExperiments";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		StringBuffer sb = new StringBuffer();
-		
-		TreeMap<IExperiment, String> map = experimentsRegistryManager.getMapByStatus();
-		
-		int maxRecords = HandlersUtilities.getExperimentsMax(request);
-		ArrayList<String> users = HandlersUtilities.getExperimentsUsers(request);
-		
-		int counter = -1;
-		
-		for(Entry<IExperiment, String> entry: map.entrySet()) {
-			
-			counter++;
-			IExperiment experiment = entry.getKey();
+        }
+      }
+    }
+    int index = ExperimentDetailsColumns.State.getIndex();
+    cbList[index].append("<td>");
+    cbList[index].append(state);
+    cbList[index].append("</td>");
+  }
 
-			if(HandlersUtilities.isListable(request, users, maxRecords, counter, experiment)) {
-				
-				int COLS = 7;
-				StringBuffer[] cbList = new StringBuffer[COLS];
-				for(int i=0; i < COLS; i++) {
-					cbList[i] = new StringBuffer();
-				}
-				
-				int index = -1;
-				
-				// 00 Terminate
-				String terminate = "";
-				index++;
-				if(terminateEnabled) {
-					Status experimentStatus = experiment.getStatus();
-					switch(experimentStatus) {
-					case Running:
-						String id = experiment.getId();
-						String directory = experiment.getDirectory();
-						String disabled = "";
-						String resourceOwnerUserid = experiment.getUser();
-						if(!HandlersHelper.isUserAuthorized(request, resourceOwnerUserid)) {
-							disabled = "disabled title=\"Hint: use Login to enable\"";
-						}
-						String p0 = "'"+id+"'";
-						String p1 = "'"+directory+"'";
-						terminate = "<input type=\"button\" onclick=\"ducc_confirm_terminate_experiment("+p0+","+p1+")\" value=\"Terminate\" "+disabled+"/>";
-          default:
-            break;
-					}
-				}
-				cbList[index].append("<td valign=\"bottom\" align=\"right\">"); 
-				cbList[index].append(terminate);
-				cbList[index].append("</td>");
-				
-				// 01 Start
-				String startDate = getStartDate(request, experiment);
-				index++;
-				cbList[index].append("<td valign=\"bottom\">");
-				cbList[index].append(startDate);
-				cbList[index].append("</td>");
-				
-				// 02 Duration
-				String duration = getDuration(request, experiment);
-				long runTime = getRunTime(request, experiment);
-				index++;
-				String sort = "sorttable_customkey=\""+runTime+"\"";
-				cbList[index].append("<td valign=\"bottom\" "+sort+" align=\"right\">");
-				cbList[index].append(duration);
-				cbList[index].append("</td>");
-				
-				// 03 User
-				String user = getUser(request, experiment);
-				index++;
-				cbList[index].append("<td valign=\"bottom\">"); 
-				cbList[index].append(user);
-				cbList[index].append("</td>");
-				
-				// 04 Tasks
-				String tasks = getTasks(request, experiment);
-				index++;
-				cbList[index].append("<td valign=\"bottom\" align=\"right\">"); 
-				cbList[index].append(tasks);
-				cbList[index].append("</td>");
-				
-				// 05 State
-				String state = getState(request, experiment);
-				index++;
-				cbList[index].append("<td valign=\"bottom\">"); 
-				cbList[index].append(state);
-				cbList[index].append("</td>");
-				
-				// 06 Directory (link)
-				String directoryLink = getDirectoryLink(request, experiment);
-				index++;
-				cbList[index].append("<td valign=\"bottom\">");
-				cbList[index].append(directoryLink);
-				cbList[index].append("</td>");
-				
-				/////
-				
-				StringBuffer row = new StringBuffer();
-				
-				row.append(ResponseHelper.trStart(counter));
-				for(int i=0; i < COLS; i++) {
-					row.append(cbList[i]);
-				}
-				row.append(ResponseHelper.trEnd(counter));
-				sb.append(row);
-			}
-		}
-		
-		/////
-		
-		if(sb.length() == 0) {
-			sb.append("<tr>");
-			sb.append("<td>");
-			sb.append("not found");
-			sb.append("</td>");
-			sb.append("</tr>");
-		}
-		
-		response.getWriter().println(sb);
-		
-		handled = true;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private boolean handleServletJsonExperimentDetails(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletJsonExperimentDetails";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private enum IdType { Job, Reservation, None };
-	
-	private class IdBundle {
-		
-		private IdType idType = IdType.None;
-		private int[] idList = new int[0];
-		
-		public IdBundle() {
-		}
-		
-		public IdBundle(IdType type, int[] list) {
-			idType = type;
-			idList = list;
-		}
-		
-		public IdType getType() {
-			return idType;
-		}
-		
-		public int[] getList() {
-			return idList;
-		}
-	}
-	
-	private class IdListIterator {
-		
-		private ArrayList<Long> reservations = new ArrayList<Long>();
-		private ArrayList<Long> jobs = new ArrayList<Long>();
-		
-		public IdListIterator(Task task) {
-			if(task != null) {
-				long[] duccIdList = task.duccId;
-				for(long duccId : duccIdList) {
-					if(duccId < 0) {
-						Long r = new Long(duccId);
-						reservations.add(r);
-					}
-					else {
-						Long j = new Long(duccId);
-						jobs.add(j);
-					}
-				}
-			}
-		}
-		
-		public IdBundle getNext() {
-			IdBundle retVal = new IdBundle();
-			if(reservations.size() > 0) {
-				int[] list = new int[1];
-				Long r = reservations.remove(0);
-				list[0] = r.intValue();
-				retVal = new IdBundle(IdType.Reservation, list);
-			}
-			else if(jobs.size() > 0) {
-				int[] list = new int[1];
-				Long j = jobs.remove(0);
-				list[0] = j.intValue();
-				retVal = new IdBundle(IdType.Job, list);
-			}
-			return retVal;
-		}
-		
-		public boolean isEmpty() {
-			boolean retVal = true;
-			if(reservations.size() > 0) {
-				retVal = false;
-			}
-			if(jobs.size() > 0) {
-				retVal = false;
-			}
-			return retVal;
-		}
-	}
-	
-	public enum ExperimentDetailsColumns {
-		Id(0), Name(1) , Parent(2), State(3), Type(4), StepStart(5), StepDuration(6), DuccId(7), DuccDuration(8), Total(9), Done(10), Error(11), Dispatch(12), Retry(13), Preempt(14);
-		private int index;
-		ExperimentDetailsColumns(int index){
-			this.index = index;
-		}
-		public int getIndex(){
-			return index;
-		}
-		public static int getCols() {
-			return Preempt.getIndex()+1;
-		}
-	}
+  private void edType(StringBuffer[] cbList, Task task) {
+    String type = "";
+    if (task.type != null) {
+      type = task.type;
+    }
+    int index = ExperimentDetailsColumns.Type.getIndex();
+    cbList[index].append("<td>");
+    cbList[index].append(type);
+    cbList[index].append("</td>");
+  }
 
-	private void addPlaceholder(StringBuffer[] cbList, int index) {
-		cbList[index].append("<td>");
-		cbList[index].append("</td>");
-	}
-	
-	private void edId(StringBuffer[] cbList, Task task) {
-		long taskId = task.taskId;
-		int index = ExperimentDetailsColumns.Id.getIndex();
-		cbList[index].append("<td align=\"right\">");
-		cbList[index].append(""+taskId);
-		cbList[index].append("</td>");
-	}
-	
-	private void edName(StringBuffer[] cbList, Task task) {
-		String name = "";
-		if(task.name != null) {
-			name = task.name;
-		}
-		int index = ExperimentDetailsColumns.Name.getIndex();
-		cbList[index].append("<td>");
-		cbList[index].append(name);
-		cbList[index].append("</td>");
-	}
-	
-	private void edParent(StringBuffer[] cbList, Task task) {
-		long taskParentId = task.parentId;
-		int index = ExperimentDetailsColumns.Parent.getIndex();
-		cbList[index].append("<td align=\"right\">");
-		cbList[index].append(""+taskParentId);
-		cbList[index].append("</td>");
-	}
-	
-	private void edState(StringBuffer[] cbList, IExperiment experiment, Task task) {
-		String mName = "edState";
-		String state = "";
-		if(task.status != null) {
-			state = task.status;
-			String type = task.type;
-			boolean leaf = Jed.Type.isLeaf(type);
-			if(leaf) {
-				Jed.Status status = Jed.Status.getEnum(state);
-				switch(status) {
-				case Running:
-					if(experiment.isStale()) {
-						state = "<span class=\"health_red\">Unknown";
-						WsLog.info(cName, mName, experiment.getDirectory()+" "+"stale:"+task.taskId);
-					}
-					else {
-						state = "<span class=\"health_green\">Running";
-					}
-					break;
-				case Failed:
-				case DependencyFailed:
-				case Canceled:
-					state = "<span class=\"health_red\""+">"+state+"</span>";
-					break;
-				default:
-					break;
-				}
-			}
-		}
-		int index = ExperimentDetailsColumns.State.getIndex();
-		cbList[index].append("<td>");
-		cbList[index].append(state);
-		cbList[index].append("</td>");
-	}
-	
-	private void edType(StringBuffer[] cbList, Task task) {
-		String type = "";
-		if(task.type != null) {
-			type = task.type;
-		}
-		int index = ExperimentDetailsColumns.Type.getIndex();
-		cbList[index].append("<td>");
-		cbList[index].append(type);
-		cbList[index].append("</td>");
-	}
-	
-	private void edStepStart(StringBuffer[] cbList, Task task, HttpServletRequest request) {
-		String startTime = "";
-		if(task.startTime != null) {
-			startTime = task.startTime;
-			//
-			DateStyle dateStyle = DuccCookies.getDateStyle(request);
-			startTime = HandlersUtilities.reFormatDate(dateStyle, startTime);
-			//
-		}
-		int index = ExperimentDetailsColumns.StepStart.getIndex();
-		cbList[index].append("<td>");
-		cbList[index].append(startTime);
-		cbList[index].append("</td>");
-	}
-	
-	private void edStepDuration(StringBuffer[] cbList, Task task, HttpServletRequest request) {
-		String displayRunTime = "";
-		long runTime = task.runTime;
-		if(runTime > 0) {
-			displayRunTime = FormatHelper.duration(runTime,Precision.Whole);
-		}
-		String sort = "sorttable_customkey=\""+runTime+"\"";
-		int index = ExperimentDetailsColumns.StepDuration.getIndex();
-		cbList[index].append("<td "+sort+" align=\"right\">");
-		cbList[index].append("<span title=\"Time (ddd:hh:mm:ss) elapsed for task, including all child tasks\">");
-		cbList[index].append(displayRunTime);
-		cbList[index].append("</span>");
-		cbList[index].append("</td>");
-	}
-	
-	private void edDuccId(StringBuffer[] cbList, Task task, int[] duccIdList) {
-	  //WsLog.info(cName, "edDuccId", "!! #ids = "+duccIdList.length);
-		StringBuffer db = new StringBuffer();
-		String type = "";
-		if(task.type != null) {
-			type = task.type;
-		}
-		Jed.Type jedType = Jed.Type.getEnum(type);
-		switch(jedType) {
-		case DuccJob:
-		case Java:
-		case Trainer:
-			for(int duccId : duccIdList) {
-				if(duccId < 0) {
-					String parm = ""+(0-duccId);
-					String displayId = "r"+parm;
-					String link = "<a href=\"reservation.details.html?id="+parm+"\">"+displayId+"</a>";
-					db.append(link+" ");
-				}
-				else {
-					String parm = ""+(0+duccId);
-					String displayId =  "j"+parm;
-					String link = "<a href=\"job.details.html?id="+parm+"\">"+displayId+"</a>";
-					db.append(link+" ");
-				}
-			}
-			break;
-		case Other:
-		default:
-			break;
-		}
-		String duccLinks = db.toString().trim();
-		int index = ExperimentDetailsColumns.DuccId.getIndex();
-		cbList[index].append("<td>");
-		cbList[index].append(duccLinks);
-		cbList[index].append("</td>");
-	}
-	
-	private void edDuccDuration(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job, long now) {
-		int index = ExperimentDetailsColumns.DuccDuration.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			if(job.isCompleted()) {
-				String duration = getDuration(request,job);
-				String decoratedDuration = decorateDuration(request,job, duration);
-				cbList[index].append("<span>");
-				cbList[index].append(decoratedDuration);
-				cbList[index].append("</span>");
-			}
-			else {
-				String duration = getDuration(request,job,now);
-				String decoratedDuration = decorateDuration(request,job, duration);
-				cbList[index].append("<span class=\"health_green\""+">");
-				cbList[index].append(decoratedDuration);
-				cbList[index].append("</span>");
-				String projection = getProjection(request,job);
-				cbList[index].append(projection);
-			}
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edDuccDuration(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWork dw, long now) {
-		int index = ExperimentDetailsColumns.DuccDuration.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			if(dw.isCompleted()) {
-				String duration = getDuration(request,dw);
-				cbList[index].append("<span>");
-				cbList[index].append(duration);
-				cbList[index].append("</span>");
-			}
-			else {
-				String duration = getDuration(request,dw,now);
-				cbList[index].append("<span class=\"health_green\""+">");
-				cbList[index].append(duration);
-				cbList[index].append("</span>");
-			}
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	private void edTotal(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Total.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			cbList[index].append(job.getSchedulingInfo().getWorkItemsTotal());
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edDone(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Done.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			cbList[index].append(job.getSchedulingInfo().getWorkItemsCompleted());
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edError(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Error.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			cbList[index].append(buildErrorLink(job));
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edDispatch(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Dispatch.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			if(duccData.isLive(job.getDuccId())) {
-				int dispatch = 0;
-				int unassigned = job.getSchedulingInfo().getCasQueuedMap().size();
-				try {
-					dispatch = Integer.parseInt(job.getSchedulingInfo().getWorkItemsDispatched())-unassigned;
-				}
-				catch(Exception e) {
-				}
-				cbList[index].append(dispatch);
-			}
-			else {
-				cbList[index].append("0");
-			}
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edRetry(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Retry.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			cbList[index].append(job.getSchedulingInfo().getWorkItemsRetry());
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edPreempt(StringBuffer[] cbList, Task task, HttpServletRequest request, IDuccWorkJob job) {
-		int index = ExperimentDetailsColumns.Preempt.getIndex();
-		cbList[index].append("<td valign=\"bottom\" align=\"right\">");
-		try {
-			cbList[index].append(job.getSchedulingInfo().getWorkItemsPreempt());
-		}
-		catch(Exception e) {
-		}
-		cbList[index].append("</td>");
-	}
-	
-	private void edTaskNonDucc(StringBuffer[] cbList, IExperiment experiment, Task task, HttpServletRequest request) {
-		edId(cbList, task);
-		edName(cbList, task);
-		edParent(cbList, task);
-		edState(cbList, experiment, task);
-		edType(cbList, task);
-		edStepStart(cbList, task, request);
-		edStepDuration(cbList, task, request);
-		addPlaceholder(cbList, ExperimentDetailsColumns.DuccId.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
-	}
-	
-	private void edTaskDuccFirst(StringBuffer[] cbList, IExperiment experiment, Task task, HttpServletRequest request, IdBundle idBundle, long now) {
-		int[] duccIdList = idBundle.getList();
-		//WsLog.info(cName, "edTaskDuccFirst", "!! #ids = "+duccIdList.length);
-		edId(cbList, task);
-		edName(cbList, task);
-		edParent(cbList, task);
-		edState(cbList, experiment, task);
-		edType(cbList, task);
-		edStepStart(cbList, task, request);
-		edStepDuration(cbList, task, request);
-		edDuccId(cbList, task, duccIdList);
-		switch(idBundle.getType()) {
-		case Job:
-			DuccId jDuccId = new DuccId(duccIdList[0]);
-			IDuccWorkJob dwj = duccData.getJob(jDuccId);
-			edDuccDuration(cbList, task, request, dwj, now);
-			edTotal(cbList, task, request, dwj);
-			edDone(cbList, task, request, dwj);
-			edError(cbList, task, request, dwj);
-			edDispatch(cbList, task, request, dwj);
-			edRetry(cbList, task, request, dwj);
-			edPreempt(cbList, task, request, dwj);
-			break;
-		case Reservation:
-			int id = 0-duccIdList[0];
-			DuccId rDuccId = new DuccId(id);
-			IDuccWork dw = duccData.getReservation(rDuccId);
-			edDuccDuration(cbList, task, request, dw, now);
-			addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
-			break;
-		default:
-			addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
-			break;
-		}
-	}
-	
-	private void edTaskDuccNext(StringBuffer[] cbList, Task task, HttpServletRequest request, IdBundle idBundle, long now) {
-		int[] duccIdList = idBundle.getList();
-		//WsLog.info(cName, "edTaskDuccNext", "!! #ids = "+duccIdList.length);
-		addPlaceholder(cbList, ExperimentDetailsColumns.Id.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Name.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Parent.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.State.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.Type.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.StepStart.getIndex());
-		addPlaceholder(cbList, ExperimentDetailsColumns.StepDuration.getIndex());
-		edDuccId(cbList, task, duccIdList);
-		switch(idBundle.getType()) {
-		case Job:
-			DuccId duccId = new DuccId(duccIdList[0]);
-			IDuccWorkJob job = duccData.getJob(duccId);
-			edDuccDuration(cbList, task, request, job, now);
-			edTotal(cbList, task, request, job);
-			edDone(cbList, task, request, job);
-			edError(cbList, task, request, job);
-			edDispatch(cbList, task, request, job);
-			edRetry(cbList, task, request, job);
-			edPreempt(cbList, task, request, job);
-			break;
-		case Reservation:
-			int id = 0-duccIdList[0];
-			DuccId rDuccId = new DuccId(id);
-			IDuccWork dw = duccData.getReservation(rDuccId);
-			edDuccDuration(cbList, task, request, dw, now);
-			addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
-			break;
-		default:
-			addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
-			addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
-			break;
-		}
-	}
-	
-	private StringBuffer[] getCbList() {
-		int COLS = ExperimentDetailsColumns.getCols();
-		StringBuffer[] cbList = new StringBuffer[COLS];
-		for(int i=0; i < COLS; i++) {
-			cbList[i] = new StringBuffer();
-		}
-		return cbList;
-	}
-	
-	private boolean handleServletExperimentDetails(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletExperimentDetails";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		StringBuffer sb = new StringBuffer();
-		
-		String id = request.getParameter("id");
-		
-		IExperiment experiment = experimentsRegistryManager.getById(id);
-		
-		long now = System.currentTimeMillis();
-		
-		if(experiment != null) {
-			ArrayList<Task> tasks = experiment.getTasks();
-			if(tasks != null) {
-				int counter = -1;
-				StringBuffer[] cbList;
-				StringBuffer row;
-				for(Task task : tasks) {
-					String type = "";
-					if(task.type != null) {
-						type = task.type;
-					}
-					Jed.Type jedType = Jed.Type.getEnum(type);
-					switch(jedType) {
-					case DuccJob:
-					case Java:
-					case Trainer:
-						counter++;
-						cbList = getCbList();
-						IdListIterator idListIterator = new IdListIterator(task);
-						edTaskDuccFirst(cbList, experiment, task, request, idListIterator.getNext(), now);
-						row = new StringBuffer();
-						row.append(ResponseHelper.trStart(counter));
-						for(int i=0; i < cbList.length; i++) {
-							row.append(cbList[i]);
-						}
-						row.append(ResponseHelper.trEnd(counter));
-						sb.append(row);
-						while(!idListIterator.isEmpty()) {
-							counter++;
-							cbList = getCbList();
-							edTaskDuccNext(cbList, task, request, idListIterator.getNext(), now);
-							row = new StringBuffer();
-							row.append(ResponseHelper.trStart(counter));
-							for(int i=0; i < cbList.length; i++) {
-								row.append(cbList[i]);
-							}
-							row.append(ResponseHelper.trEnd(counter));
-							sb.append(row);
-						}
-						break;
-					default:
-						counter++;
-						cbList = getCbList();
-						edTaskNonDucc(cbList, experiment, task, request);
-						row = new StringBuffer();
-						row.append(ResponseHelper.trStart(counter));
-						for(int i=0; i < cbList.length; i++) {
-							row.append(cbList[i]);
-						}
-						row.append(ResponseHelper.trEnd(counter));
-						sb.append(row);
-						break;
-					}
-				}
-			}
-		}
-	
-		/////
-		
-		if(sb.length() == 0) {
-			sb.append("<tr>");
-			sb.append("<td>");
-			sb.append("not found");
-			sb.append("</td>");
-			sb.append("</tr>");
-		}
-		
-		response.getWriter().println(sb);
-		
-		handled = true;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private boolean handleServletExperimentDetailsDirectory(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletExperimentDetailsDirectory";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		StringBuffer sb = new StringBuffer();
-		
-		String id = request.getParameter("id");
-		
-		IExperiment experiment = experimentsRegistryManager.getById(id);
-		
-		if(experiment != null) {
-			String directory = experiment.getDirectory();
-			if(directory != null) {
-				sb.append("<b>");
-				sb.append("Directory:");
-				sb.append(" ");
-				sb.append(directory);
-				sb.append("</b>");
-			}
-		}
-		
-		response.getWriter().println(sb);
-		
-		handled = true;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private boolean handleServletExperimentCancelRequest(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleServletExperimentCancelRequest";
-		WsLog.enter(cName, mName);
-		
-		boolean handled = false;
-		
-		StringBuffer sb = new StringBuffer();
+  private void edStepStart(StringBuffer[] cbList, Task task, HttpServletRequest request) {
+    String startTime = "";
+    if (task.startTime != null) {
+      startTime = task.startTime;
+      //
+      DateStyle dateStyle = DuccCookies.getDateStyle(request);
+      startTime = HandlersUtilities.reFormatDate(dateStyle, startTime);
+      //
+    }
+    int index = ExperimentDetailsColumns.StepStart.getIndex();
+    cbList[index].append("<td>");
+    cbList[index].append(startTime);
+    cbList[index].append("</td>");
+  }
 
-		String id = request.getParameter("id");
+  private void edStepDuration(StringBuffer[] cbList, Task task, HttpServletRequest request) {
+    String displayRunTime = "";
+    long runTime = task.runTime;
+    if (runTime > 0) {
+      displayRunTime = FormatHelper.duration(runTime, Precision.Whole);
+    }
+    String sort = "sorttable_customkey=\"" + runTime + "\"";
+    int index = ExperimentDetailsColumns.StepDuration.getIndex();
+    cbList[index].append("<td " + sort + " align=\"right\">");
+    cbList[index].append(
+            "<span title=\"Time (ddd:hh:mm:ss) elapsed for task, including all child tasks\">");
+    cbList[index].append(displayRunTime);
+    cbList[index].append("</span>");
+    cbList[index].append("</td>");
+  }
 
-		IExperiment experiment = experimentsRegistryManager.getById(id);
-		
-		String resourceOwnerUserId = experiment.getUser();
-		
-		String directory = experiment.getDirectory();
-		String file = "DRIVER.running";
-		String path = directory+File.separator+file;
-		
-		WsLog.info(cName, mName, path);
-		
-		String command = "/bin/rm";
-		
-		String result;
-		
-		if(HandlersHelper.isUserAuthorized(request,resourceOwnerUserId)) {
-			String userId = resourceOwnerUserId;
-			String[] arglist = { "-u", userId, "--", command, path };
-			result = DuccAsUser.duckling(userId, arglist);
-			response.getWriter().println(result);
-		}
-		else {
-			result = "user not authorized";
-		}
-		
-		sb.append(result);
-		
-		response.getWriter().println(sb);
-		
-		handled = true;
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	private boolean handleDuccRequest(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws Exception {
-		String mName = "handleDuccRequest";
-		WsLog.enter(cName, mName);
-		String reqURI = request.getRequestURI()+"";
-		boolean handled = false;
-		if(handled) {
-		}
-		else if(reqURI.startsWith(duccContextExperimentDetailsDirectory)) {
-			handled = handleServletExperimentDetailsDirectory(target, baseRequest, request, response);
-		}
-		else if(reqURI.startsWith(duccContextExperimentDetails)) {
-			handled = handleServletExperimentDetails(target, baseRequest, request, response);
-		}
-		else if(reqURI.startsWith(duccContextExperiments)) {
-			handled = handleServletExperiments(target, baseRequest, request, response);
-		}
-		else if(reqURI.startsWith(duccContextJsonExperimentDetails)) {
-			handled = handleServletJsonExperimentDetails(target, baseRequest, request, response);
-		}
-		else if(reqURI.startsWith(duccContextJsonExperiments)) {
-			handled = handleServletJsonExperiments(target, baseRequest, request, response);
-		}
-		else if(reqURI.startsWith(duccContextExperimentCancelRequest)) {
-			handled = handleServletExperimentCancelRequest(target, baseRequest, request, response);
-		}
-		
-		WsLog.exit(cName, mName);
-		return handled;
-	}
-	
-	public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-			throws IOException, ServletException {
-		String mName = "handle";
-		WsLog.enter(cName, mName);
-		try { 
-			WsLog.debug(cName, mName, request.toString());
-			//WsLog.debug(cName, mName, "getRequestURI():"+request.getRequestURI());
-			boolean handled = handleDuccRequest(target, baseRequest, request, response);
-			if(handled) {
-				response.setContentType("text/html;charset=utf-8");
-				response.setStatus(HttpServletResponse.SC_OK);
-				baseRequest.setHandled(true);
-				DuccWebUtil.noCache(response);
-			}
-		}
-		catch(Throwable t) {
-			if(isIgnorable(t)) {
-				WsLog.trace(cName, mName, t);
-			}
-			else {
-				WsLog.info(cName, mName, t.getMessage());
-				WsLog.error(cName, mName, t);
-			}
-		}
-		WsLog.exit(cName, mName);
-	}
+  private void edDuccId(StringBuffer[] cbList, Task task, int[] duccIdList) {
+    // WsLog.info(cName, "edDuccId", "!! #ids = "+duccIdList.length);
+    StringBuffer db = new StringBuffer();
+    String type = "";
+    if (task.type != null) {
+      type = task.type;
+    }
+    Jed.Type jedType = Jed.Type.getEnum(type);
+    switch (jedType) {
+      case DuccJob:
+      case Java:
+      case Trainer:
+        for (int duccId : duccIdList) {
+          if (duccId < 0) {
+            String parm = "" + (0 - duccId);
+            String displayId = "r" + parm;
+            String link = "<a href=\"reservation.details.html?id=" + parm + "\">" + displayId
+                    + "</a>";
+            db.append(link + " ");
+          } else {
+            String parm = "" + (0 + duccId);
+            String displayId = "j" + parm;
+            String link = "<a href=\"job.details.html?id=" + parm + "\">" + displayId + "</a>";
+            db.append(link + " ");
+          }
+        }
+        break;
+      case Other:
+      default:
+        break;
+    }
+    String duccLinks = db.toString().trim();
+    int index = ExperimentDetailsColumns.DuccId.getIndex();
+    cbList[index].append("<td>");
+    cbList[index].append(duccLinks);
+    cbList[index].append("</td>");
+  }
+
+  private void edDuccDuration(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job, long now) {
+    int index = ExperimentDetailsColumns.DuccDuration.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      if (job.isCompleted()) {
+        String duration = getDuration(request, job);
+        String decoratedDuration = decorateDuration(request, job, duration);
+        cbList[index].append("<span>");
+        cbList[index].append(decoratedDuration);
+        cbList[index].append("</span>");
+      } else {
+        String duration = getDuration(request, job, now);
+        String decoratedDuration = decorateDuration(request, job, duration);
+        cbList[index].append("<span class=\"health_green\"" + ">");
+        cbList[index].append(decoratedDuration);
+        cbList[index].append("</span>");
+        String projection = getProjection(request, job);
+        cbList[index].append(projection);
+      }
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edDuccDuration(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWork dw, long now) {
+    int index = ExperimentDetailsColumns.DuccDuration.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      if (dw.isCompleted()) {
+        String duration = getDuration(request, dw);
+        cbList[index].append("<span>");
+        cbList[index].append(duration);
+        cbList[index].append("</span>");
+      } else {
+        String duration = getDuration(request, dw, now);
+        cbList[index].append("<span class=\"health_green\"" + ">");
+        cbList[index].append(duration);
+        cbList[index].append("</span>");
+      }
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edTotal(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Total.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      cbList[index].append(job.getSchedulingInfo().getWorkItemsTotal());
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edDone(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Done.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      cbList[index].append(job.getSchedulingInfo().getWorkItemsCompleted());
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edError(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Error.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      cbList[index].append(buildErrorLink(job));
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edDispatch(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Dispatch.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      if (duccData.isLive(job.getDuccId())) {
+        int dispatch = 0;
+        int unassigned = job.getSchedulingInfo().getCasQueuedMap().size();
+        try {
+          dispatch = Integer.parseInt(job.getSchedulingInfo().getWorkItemsDispatched())
+                  - unassigned;
+        } catch (Exception e) {
+        }
+        cbList[index].append(dispatch);
+      } else {
+        cbList[index].append("0");
+      }
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edRetry(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Retry.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      cbList[index].append(job.getSchedulingInfo().getWorkItemsRetry());
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edPreempt(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IDuccWorkJob job) {
+    int index = ExperimentDetailsColumns.Preempt.getIndex();
+    cbList[index].append("<td valign=\"bottom\" align=\"right\">");
+    try {
+      cbList[index].append(job.getSchedulingInfo().getWorkItemsPreempt());
+    } catch (Exception e) {
+    }
+    cbList[index].append("</td>");
+  }
+
+  private void edTaskNonDucc(StringBuffer[] cbList, IExperiment experiment, Task task,
+          HttpServletRequest request) {
+    edId(cbList, task);
+    edName(cbList, task);
+    edParent(cbList, task);
+    edState(cbList, experiment, task);
+    edType(cbList, task);
+    edStepStart(cbList, task, request);
+    edStepDuration(cbList, task, request);
+    addPlaceholder(cbList, ExperimentDetailsColumns.DuccId.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
+  }
+
+  private void edTaskDuccFirst(StringBuffer[] cbList, IExperiment experiment, Task task,
+          HttpServletRequest request, IdBundle idBundle, long now) {
+    int[] duccIdList = idBundle.getList();
+    // WsLog.info(cName, "edTaskDuccFirst", "!! #ids = "+duccIdList.length);
+    edId(cbList, task);
+    edName(cbList, task);
+    edParent(cbList, task);
+    edState(cbList, experiment, task);
+    edType(cbList, task);
+    edStepStart(cbList, task, request);
+    edStepDuration(cbList, task, request);
+    edDuccId(cbList, task, duccIdList);
+    switch (idBundle.getType()) {
+      case Job:
+        DuccId jDuccId = new DuccId(duccIdList[0]);
+        IDuccWorkJob dwj = duccData.getJob(jDuccId);
+        edDuccDuration(cbList, task, request, dwj, now);
+        edTotal(cbList, task, request, dwj);
+        edDone(cbList, task, request, dwj);
+        edError(cbList, task, request, dwj);
+        edDispatch(cbList, task, request, dwj);
+        edRetry(cbList, task, request, dwj);
+        edPreempt(cbList, task, request, dwj);
+        break;
+      case Reservation:
+        int id = 0 - duccIdList[0];
+        DuccId rDuccId = new DuccId(id);
+        IDuccWork dw = duccData.getReservation(rDuccId);
+        edDuccDuration(cbList, task, request, dw, now);
+        addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
+        break;
+      default:
+        addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
+        break;
+    }
+  }
+
+  private void edTaskDuccNext(StringBuffer[] cbList, Task task, HttpServletRequest request,
+          IdBundle idBundle, long now) {
+    int[] duccIdList = idBundle.getList();
+    // WsLog.info(cName, "edTaskDuccNext", "!! #ids = "+duccIdList.length);
+    addPlaceholder(cbList, ExperimentDetailsColumns.Id.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Name.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Parent.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.State.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.Type.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.StepStart.getIndex());
+    addPlaceholder(cbList, ExperimentDetailsColumns.StepDuration.getIndex());
+    edDuccId(cbList, task, duccIdList);
+    switch (idBundle.getType()) {
+      case Job:
+        DuccId duccId = new DuccId(duccIdList[0]);
+        IDuccWorkJob job = duccData.getJob(duccId);
+        edDuccDuration(cbList, task, request, job, now);
+        edTotal(cbList, task, request, job);
+        edDone(cbList, task, request, job);
+        edError(cbList, task, request, job);
+        edDispatch(cbList, task, request, job);
+        edRetry(cbList, task, request, job);
+        edPreempt(cbList, task, request, job);
+        break;
+      case Reservation:
+        int id = 0 - duccIdList[0];
+        DuccId rDuccId = new DuccId(id);
+        IDuccWork dw = duccData.getReservation(rDuccId);
+        edDuccDuration(cbList, task, request, dw, now);
+        addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
+        break;
+      default:
+        addPlaceholder(cbList, ExperimentDetailsColumns.DuccDuration.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Total.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Done.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Error.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Dispatch.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Retry.getIndex());
+        addPlaceholder(cbList, ExperimentDetailsColumns.Preempt.getIndex());
+        break;
+    }
+  }
+
+  private StringBuffer[] getCbList() {
+    int COLS = ExperimentDetailsColumns.getCols();
+    StringBuffer[] cbList = new StringBuffer[COLS];
+    for (int i = 0; i < COLS; i++) {
+      cbList[i] = new StringBuffer();
+    }
+    return cbList;
+  }
+
+  private boolean handleServletExperimentDetails(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletExperimentDetails";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    StringBuffer sb = new StringBuffer();
+
+    String id = request.getParameter("id");
+
+    IExperiment experiment = experimentsRegistryManager.getById(id);
+
+    long now = System.currentTimeMillis();
+
+    if (experiment != null) {
+      ArrayList<Task> tasks = experiment.getTasks();
+      if (tasks != null) {
+        int counter = -1;
+        StringBuffer[] cbList;
+        StringBuffer row;
+        for (Task task : tasks) {
+          String type = "";
+          if (task.type != null) {
+            type = task.type;
+          }
+          Jed.Type jedType = Jed.Type.getEnum(type);
+          switch (jedType) {
+            case DuccJob:
+            case Java:
+            case Trainer:
+              counter++;
+              cbList = getCbList();
+              IdListIterator idListIterator = new IdListIterator(task);
+              edTaskDuccFirst(cbList, experiment, task, request, idListIterator.getNext(), now);
+              row = new StringBuffer();
+              row.append(ResponseHelper.trStart(counter));
+              for (int i = 0; i < cbList.length; i++) {
+                row.append(cbList[i]);
+              }
+              row.append(ResponseHelper.trEnd(counter));
+              sb.append(row);
+              while (!idListIterator.isEmpty()) {
+                counter++;
+                cbList = getCbList();
+                edTaskDuccNext(cbList, task, request, idListIterator.getNext(), now);
+                row = new StringBuffer();
+                row.append(ResponseHelper.trStart(counter));
+                for (int i = 0; i < cbList.length; i++) {
+                  row.append(cbList[i]);
+                }
+                row.append(ResponseHelper.trEnd(counter));
+                sb.append(row);
+              }
+              break;
+            default:
+              counter++;
+              cbList = getCbList();
+              edTaskNonDucc(cbList, experiment, task, request);
+              row = new StringBuffer();
+              row.append(ResponseHelper.trStart(counter));
+              for (int i = 0; i < cbList.length; i++) {
+                row.append(cbList[i]);
+              }
+              row.append(ResponseHelper.trEnd(counter));
+              sb.append(row);
+              break;
+          }
+        }
+      }
+    }
+
+    /////
+
+    if (sb.length() == 0) {
+      sb.append("<tr>");
+      sb.append("<td>");
+      sb.append("not found");
+      sb.append("</td>");
+      sb.append("</tr>");
+    }
+
+    response.getWriter().println(sb);
+
+    handled = true;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private boolean handleServletExperimentDetailsDirectory(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletExperimentDetailsDirectory";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    StringBuffer sb = new StringBuffer();
+
+    String id = request.getParameter("id");
+
+    IExperiment experiment = experimentsRegistryManager.getById(id);
+
+    if (experiment != null) {
+      String directory = experiment.getDirectory();
+      if (directory != null) {
+        sb.append("<b>");
+        sb.append("Directory:");
+        sb.append(" ");
+        sb.append(directory);
+        sb.append("</b>");
+      }
+    }
+
+    response.getWriter().println(sb);
+
+    handled = true;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private boolean handleServletExperimentCancelRequest(String target, Request baseRequest,
+          HttpServletRequest request, HttpServletResponse response) throws Exception {
+    String mName = "handleServletExperimentCancelRequest";
+    WsLog.enter(cName, mName);
+
+    boolean handled = false;
+
+    StringBuffer sb = new StringBuffer();
+
+    String id = request.getParameter("id");
+
+    IExperiment experiment = experimentsRegistryManager.getById(id);
+
+    String resourceOwnerUserId = experiment.getUser();
+
+    String directory = experiment.getDirectory();
+    String file = "DRIVER.running";
+    String path = directory + File.separator + file;
+
+    WsLog.info(cName, mName, path);
+
+    String command = "/bin/rm";
+
+    String result;
+
+    if (HandlersHelper.isUserAuthorized(request, resourceOwnerUserId)) {
+      String userId = resourceOwnerUserId;
+      String[] arglist = { "-u", userId, "--", command, path };
+      result = DuccAsUser.duckling(userId, arglist);
+      response.getWriter().println(result);
+    } else {
+      result = "user not authorized";
+    }
+
+    sb.append(result);
+
+    response.getWriter().println(sb);
+
+    handled = true;
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  private boolean handleDuccRequest(String target, Request baseRequest, HttpServletRequest request,
+          HttpServletResponse response) throws Exception {
+    String mName = "handleDuccRequest";
+    WsLog.enter(cName, mName);
+    String reqURI = request.getRequestURI() + "";
+    boolean handled = false;
+    if (handled) {
+    } else if (reqURI.startsWith(duccContextExperimentDetailsDirectory)) {
+      handled = handleServletExperimentDetailsDirectory(target, baseRequest, request, response);
+    } else if (reqURI.startsWith(duccContextExperimentDetails)) {
+      handled = handleServletExperimentDetails(target, baseRequest, request, response);
+    } else if (reqURI.startsWith(duccContextExperiments)) {
+      handled = handleServletExperiments(target, baseRequest, request, response);
+    } else if (reqURI.startsWith(duccContextJsonExperimentDetails)) {
+      handled = handleServletJsonExperimentDetails(target, baseRequest, request, response);
+    } else if (reqURI.startsWith(duccContextJsonExperiments)) {
+      handled = handleServletJsonExperiments(target, baseRequest, request, response);
+    } else if (reqURI.startsWith(duccContextExperimentCancelRequest)) {
+      handled = handleServletExperimentCancelRequest(target, baseRequest, request, response);
+    }
+
+    WsLog.exit(cName, mName);
+    return handled;
+  }
+
+  public void handle(String target, Request baseRequest, HttpServletRequest request,
+          HttpServletResponse response) throws IOException, ServletException {
+    String mName = "handle";
+    WsLog.enter(cName, mName);
+    try {
+      WsLog.debug(cName, mName, request.toString());
+      // WsLog.debug(cName, mName, "getRequestURI():"+request.getRequestURI());
+      boolean handled = handleDuccRequest(target, baseRequest, request, response);
+      if (handled) {
+        response.setContentType("text/html;charset=utf-8");
+        response.setStatus(HttpServletResponse.SC_OK);
+        baseRequest.setHandled(true);
+        DuccWebUtil.noCache(response);
+      }
+    } catch (Throwable t) {
+      if (isIgnorable(t)) {
+        WsLog.trace(cName, mName, t);
+      } else {
+        WsLog.info(cName, mName, t.getMessage());
+        WsLog.error(cName, mName, t);
+      }
+    }
+    WsLog.exit(cName, mName);
+  }
 
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/HandlersUtilities.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/HandlersUtilities.java
index 4020211..8fa8cee 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/HandlersUtilities.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/HandlersUtilities.java
@@ -41,169 +41,162 @@
 import org.apache.uima.ducc.ws.xd.IExperiment;
 
 public class HandlersUtilities {
-	
-	public static IDuccWorkJob getJob(DuccId duccId) {
-		IDuccWorkJob retVal = null;
-		DuccData duccData = DuccData.getInstance();
-		ConcurrentSkipListMap<JobInfo,JobInfo> sortedJobs = duccData.getSortedJobs();
-		if(sortedJobs.size()> 0) {
-			Iterator<Entry<JobInfo, JobInfo>> iterator = sortedJobs.entrySet().iterator();
-			while(iterator.hasNext()) {
-				JobInfo jobInfo = iterator.next().getValue();
-				DuccWorkJob job = jobInfo.getJob();
-				DuccId jobid = job.getDuccId();
-				if(jobid.equals(duccId)) {
-					retVal = job;
-					break;
-				}
-			}
-		}
-		return retVal;
-	}
-	
-	public static ArrayList<String> getExperimentsUsers(HttpServletRequest request) {
-		String cookie = DuccCookies.getCookie(request,DuccLocalCookies.cookieExperimentsUsers);
-		return getUsers(cookie);
-	}
-	
-	public static int getExperimentsMax(HttpServletRequest request) {
-		int maxRecords = DuccLocalConstants.defaultRecordsExperiments;
-		try {
-			String cookie = DuccCookies.getCookie(request,DuccLocalCookies.cookieExperimentsMax);
-			int reqRecords = Integer.parseInt(cookie);
-			if(reqRecords <= DuccLocalConstants.maximumRecordsExperiments) {
-				if(reqRecords > 0) {
-					maxRecords = reqRecords;
-				}
-			}
-		}
-		catch(Exception e) {
-		}
-		return maxRecords;
-	}
-	
-	private static ArrayList<String> getUsers(String usersString) {
-		ArrayList<String> userRecords = new ArrayList<String>();
-		try {
-			String[] users = usersString.split("\\s+");
-			if(users != null) {
-				for(String user : users) {
-					user = user.trim();
-					if(user.length() > 0) {
-						if(!userRecords.contains(user)) {
-							userRecords.add(user);
-						}
-					}
-				}
-			}
-		}
-		catch(Exception e) {
-		}
-		return userRecords;
-	}
-	
-	public static final boolean isListable(HttpServletRequest request, ArrayList<String> users, int maxRecords, int counter, IExperiment handle) {
-		boolean list = false;
-		DuccCookies.FilterUsersStyle filterUsersStyle = DuccCookies.getFilterUsersStyle(request);
-		if(!users.isEmpty()) {
-			String user = handle.getUser();
-			switch(filterUsersStyle) {
-			case IncludePlusActive:
-				if(handle.isActive()) {
-					list = true;
-				}
-				else if(users.contains(user)) {
-					if(maxRecords > 0) {
-						if (counter < maxRecords) {
-							list = true;
-						}
-					}
-				}
-				break;
-			case ExcludePlusActive:
-				if(handle.isActive()) {
-					list = true;
-				}
-				else if(!users.contains(user)) {
-					if(maxRecords > 0) {
-						if (counter < maxRecords) {
-							list = true;
-						}
-					}
-				}
-				break;
-			case Include:
-				if(users.contains(user)) {
-					if(maxRecords > 0) {
-						if (counter < maxRecords) {
-							list = true;
-						}
-					}
-				}
-				break;
-			case Exclude:
-				if(!users.contains(user)) {
-					if(maxRecords > 0) {
-						if (counter < maxRecords) {
-							list = true;
-						}
-					}
-				}
-				break;
-			}	
-		}
-		else {
-			if(handle.isActive()) {
-				list = true;
-			}
-			else if(maxRecords > 0) {
-				if (counter < maxRecords) {
-					list = true;
-				}
-			}
-		}
-		return list;
-	}
 
-	public static boolean isIgnorable(Throwable t) {
-		boolean retVal = false;
-		try {
-			String rcm = ExceptionUtils.getMessage(t).trim();
-			if(rcm.endsWith("java.io.IOException: Broken pipe")) {
-				retVal = true;
-			}
-		}
-		catch(Throwable throwable) {
-		}
-		return retVal;
-	}
-	
-	private static String inFormat = "yyyy.MM.dd-HH:mm:ss";
-	private static SimpleDateFormat inSdf = new SimpleDateFormat(inFormat);
+  public static IDuccWorkJob getJob(DuccId duccId) {
+    IDuccWorkJob retVal = null;
+    DuccData duccData = DuccData.getInstance();
+    ConcurrentSkipListMap<JobInfo, JobInfo> sortedJobs = duccData.getSortedJobs();
+    if (sortedJobs.size() > 0) {
+      Iterator<Entry<JobInfo, JobInfo>> iterator = sortedJobs.entrySet().iterator();
+      while (iterator.hasNext()) {
+        JobInfo jobInfo = iterator.next().getValue();
+        DuccWorkJob job = jobInfo.getJob();
+        DuccId jobid = job.getDuccId();
+        if (jobid.equals(duccId)) {
+          retVal = job;
+          break;
+        }
+      }
+    }
+    return retVal;
+  }
 
-	public static String reFormatDate(DateStyle dateStyle, String inDate) {
-		String outDate = inDate;
-		try { 
-			Date date = inSdf.parse(inDate);
-	        long millis = date.getTime();
-	        String unformattedDate = TimeStamp.simpleFormat(""+millis);
-	        outDate = ResponseHelper.getTimeStamp(dateStyle, unformattedDate);
-		}
-		catch(Exception e) {
-			
-		}
-		return outDate;
-	}
+  public static ArrayList<String> getExperimentsUsers(HttpServletRequest request) {
+    String cookie = DuccCookies.getCookie(request, DuccLocalCookies.cookieExperimentsUsers);
+    return getUsers(cookie);
+  }
 
-	public static long getMillis(String inDate) {
-		long millis = 0;
-		try {
-			Date date = inSdf.parse(inDate);
-	        millis = date.getTime();
-		}
-		catch(Exception e) {
-			
-		}
-		return millis;
-	}
+  public static int getExperimentsMax(HttpServletRequest request) {
+    int maxRecords = DuccLocalConstants.defaultRecordsExperiments;
+    try {
+      String cookie = DuccCookies.getCookie(request, DuccLocalCookies.cookieExperimentsMax);
+      int reqRecords = Integer.parseInt(cookie);
+      if (reqRecords <= DuccLocalConstants.maximumRecordsExperiments) {
+        if (reqRecords > 0) {
+          maxRecords = reqRecords;
+        }
+      }
+    } catch (Exception e) {
+    }
+    return maxRecords;
+  }
+
+  private static ArrayList<String> getUsers(String usersString) {
+    ArrayList<String> userRecords = new ArrayList<String>();
+    try {
+      String[] users = usersString.split("\\s+");
+      if (users != null) {
+        for (String user : users) {
+          user = user.trim();
+          if (user.length() > 0) {
+            if (!userRecords.contains(user)) {
+              userRecords.add(user);
+            }
+          }
+        }
+      }
+    } catch (Exception e) {
+    }
+    return userRecords;
+  }
+
+  public static final boolean isListable(HttpServletRequest request, ArrayList<String> users,
+          int maxRecords, int counter, IExperiment handle) {
+    boolean list = false;
+    DuccCookies.FilterUsersStyle filterUsersStyle = DuccCookies.getFilterUsersStyle(request);
+    if (!users.isEmpty()) {
+      String user = handle.getUser();
+      switch (filterUsersStyle) {
+        case IncludePlusActive:
+          if (handle.isActive()) {
+            list = true;
+          } else if (users.contains(user)) {
+            if (maxRecords > 0) {
+              if (counter < maxRecords) {
+                list = true;
+              }
+            }
+          }
+          break;
+        case ExcludePlusActive:
+          if (handle.isActive()) {
+            list = true;
+          } else if (!users.contains(user)) {
+            if (maxRecords > 0) {
+              if (counter < maxRecords) {
+                list = true;
+              }
+            }
+          }
+          break;
+        case Include:
+          if (users.contains(user)) {
+            if (maxRecords > 0) {
+              if (counter < maxRecords) {
+                list = true;
+              }
+            }
+          }
+          break;
+        case Exclude:
+          if (!users.contains(user)) {
+            if (maxRecords > 0) {
+              if (counter < maxRecords) {
+                list = true;
+              }
+            }
+          }
+          break;
+      }
+    } else {
+      if (handle.isActive()) {
+        list = true;
+      } else if (maxRecords > 0) {
+        if (counter < maxRecords) {
+          list = true;
+        }
+      }
+    }
+    return list;
+  }
+
+  public static boolean isIgnorable(Throwable t) {
+    boolean retVal = false;
+    try {
+      String rcm = ExceptionUtils.getMessage(t).trim();
+      if (rcm.endsWith("java.io.IOException: Broken pipe")) {
+        retVal = true;
+      }
+    } catch (Throwable throwable) {
+    }
+    return retVal;
+  }
+
+  private static String inFormat = "yyyy.MM.dd-HH:mm:ss";
+
+  private static SimpleDateFormat inSdf = new SimpleDateFormat(inFormat);
+
+  public static String reFormatDate(DateStyle dateStyle, String inDate) {
+    String outDate = inDate;
+    try {
+      Date date = inSdf.parse(inDate);
+      long millis = date.getTime();
+      String unformattedDate = TimeStamp.simpleFormat("" + millis);
+      outDate = ResponseHelper.getTimeStamp(dateStyle, unformattedDate);
+    } catch (Exception e) {
+
+    }
+    return outDate;
+  }
+
+  public static long getMillis(String inDate) {
+    long millis = 0;
+    try {
+      Date date = inSdf.parse(inDate);
+      millis = date.getTime();
+    } catch (Exception e) {
+
+    }
+    return millis;
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/ResponseHelper.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/ResponseHelper.java
index 173768e..2f2946e 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/ResponseHelper.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/utilities/ResponseHelper.java
@@ -23,50 +23,48 @@
 import org.apache.uima.ducc.ws.server.DuccCookies.DateStyle;
 
 public class ResponseHelper {
-	
-  //NOTE - this variable used to hold the class name before WsLog was simplified
-	private static DuccLogger cName = DuccLogger.getLogger(ResponseHelper.class);
-	
-	public static String trStart(int counter) {
-		if((counter % 2) > 0) {
-			return "<tr class=\"ducc-row-odd\">";
-		}
-		else {
-			return "<tr class=\"ducc-row-even\">";
-		}
-	}
 
-	public static String trEnd(int counter) {
-		return "</tr>";
-	}
+  // NOTE - this variable used to hold the class name before WsLog was simplified
+  private static DuccLogger cName = DuccLogger.getLogger(ResponseHelper.class);
 
-	public static String getTimeStamp(DateStyle dateStyle, String date) {
-		String mName = "getTimeStamp";
-		StringBuffer sb = new StringBuffer();
-		if(date != null) {
-			sb.append(date);
-			if(date.trim().length() > 0) {
-				try {
-					switch(dateStyle) {
-					case Long:
-						break;
-					case Medium:
-						String day = sb.substring(sb.length()-4);
-						sb.delete(0, 5);
-						sb.delete(sb.lastIndexOf(":"), sb.length());
-						sb.append(day);
-						break;
-					case Short:
-						sb.delete(0, 5);
-						sb.delete(sb.lastIndexOf(":"), sb.length());
-						break;
-					}
-				}
-				catch(Exception e) {
-					WsLog.error(cName, mName, e);
-				}
-			}
-		}
-		return sb.toString();
-	}
+  public static String trStart(int counter) {
+    if ((counter % 2) > 0) {
+      return "<tr class=\"ducc-row-odd\">";
+    } else {
+      return "<tr class=\"ducc-row-even\">";
+    }
+  }
+
+  public static String trEnd(int counter) {
+    return "</tr>";
+  }
+
+  public static String getTimeStamp(DateStyle dateStyle, String date) {
+    String mName = "getTimeStamp";
+    StringBuffer sb = new StringBuffer();
+    if (date != null) {
+      sb.append(date);
+      if (date.trim().length() > 0) {
+        try {
+          switch (dateStyle) {
+            case Long:
+              break;
+            case Medium:
+              String day = sb.substring(sb.length() - 4);
+              sb.delete(0, 5);
+              sb.delete(sb.lastIndexOf(":"), sb.length());
+              sb.append(day);
+              break;
+            case Short:
+              sb.delete(0, 5);
+              sb.delete(sb.lastIndexOf(":"), sb.length());
+              break;
+          }
+        } catch (Exception e) {
+          WsLog.error(cName, mName, e);
+        }
+      }
+    }
+    return sb.toString();
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/log/WsLog.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/log/WsLog.java
index 9498b58..12f33a5 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/log/WsLog.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/log/WsLog.java
@@ -25,67 +25,65 @@
 
 public class WsLog {
 
-	private static DuccId duccId = null;
-	
-	public static void enter(DuccLogger logger, String mName) {
-		logger.trace(mName, duccId, "enter");
-	}
-	
-	public static void exit(DuccLogger logger, String mName) {
-		logger.trace(mName, duccId, "exit");
-	}
-	
-	public static void info(DuccLogger logger, String mName, String text) {
-		logger.info(mName, duccId, text);
-	}
-	
-	public static void info(DuccLogger logger, String mName, DuccId duccId, String text) {
-		logger.info(mName, duccId, text);
-	}
-	
-	public static void debug(DuccLogger logger, String mName, DuccId duccid, String text) {
-		logger.debug(mName, duccid, text);
-	}
-	
-	public static void debug(DuccLogger logger, String mName, String text) {
-		logger.debug(mName, duccId, text);
-	}
-	
-	public static void debug(DuccLogger logger, String mName, Exception e) {
-		logger.debug(mName, duccId, e);
-	}
-	
-	public static void debug(DuccLogger logger, String mName, Throwable t) {
-		logger.debug(mName, duccId, t);
-	}
-	
-	public static void trace(DuccLogger logger, String mName, String text) {
-		logger.trace(mName, duccId, text);
-	}
-	
-	public static void trace(DuccLogger logger, String mName, Exception e) {
-		logger.trace(mName, duccId, e);
-	}
-	
-	public static void trace(DuccLogger logger, String mName, Throwable t) {
-		logger.trace(mName, duccId, t);
-	}
-	
-	public static void error(DuccLogger logger, String mName, Exception e) {
-		logger.error(mName, duccId, e);
-	}
-	
-	public static void error(DuccLogger logger, String mName, Throwable t) {
-		logger.error(mName, duccId, t);
-	}
-	
-	public static void error(DuccLogger logger, String mName, String text) {
-		logger.error(mName, duccId, text);
-	}
-	
-	public static void warn(DuccLogger logger, String mName, String text) {
-		logger.warn(mName, duccId, text);
-	}
+  private static DuccId duccId = null;
+
+  public static void enter(DuccLogger logger, String mName) {
+    logger.trace(mName, duccId, "enter");
+  }
+
+  public static void exit(DuccLogger logger, String mName) {
+    logger.trace(mName, duccId, "exit");
+  }
+
+  public static void info(DuccLogger logger, String mName, String text) {
+    logger.info(mName, duccId, text);
+  }
+
+  public static void info(DuccLogger logger, String mName, DuccId duccId, String text) {
+    logger.info(mName, duccId, text);
+  }
+
+  public static void debug(DuccLogger logger, String mName, DuccId duccid, String text) {
+    logger.debug(mName, duccid, text);
+  }
+
+  public static void debug(DuccLogger logger, String mName, String text) {
+    logger.debug(mName, duccId, text);
+  }
+
+  public static void debug(DuccLogger logger, String mName, Exception e) {
+    logger.debug(mName, duccId, e);
+  }
+
+  public static void debug(DuccLogger logger, String mName, Throwable t) {
+    logger.debug(mName, duccId, t);
+  }
+
+  public static void trace(DuccLogger logger, String mName, String text) {
+    logger.trace(mName, duccId, text);
+  }
+
+  public static void trace(DuccLogger logger, String mName, Exception e) {
+    logger.trace(mName, duccId, e);
+  }
+
+  public static void trace(DuccLogger logger, String mName, Throwable t) {
+    logger.trace(mName, duccId, t);
+  }
+
+  public static void error(DuccLogger logger, String mName, Exception e) {
+    logger.error(mName, duccId, e);
+  }
+
+  public static void error(DuccLogger logger, String mName, Throwable t) {
+    logger.error(mName, duccId, t);
+  }
+
+  public static void error(DuccLogger logger, String mName, String text) {
+    logger.error(mName, duccId, text);
+  }
+
+  public static void warn(DuccLogger logger, String mName, String text) {
+    logger.warn(mName, duccId, text);
+  }
 }
-
-
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalConstants.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalConstants.java
index d1e5021..705f268 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalConstants.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalConstants.java
@@ -19,20 +19,26 @@
 package org.apache.uima.ducc.ws.server;
 
 public class DuccLocalConstants {
-	
-	public static final String duccContext = "/ducc-servlet";
-	
-	public static final String duccContextExperimentCancelRequest = duccContext+"/experiment-cancel-request";
-	
-	public static final String duccContextExperiments = duccContext+"/experiments-data";
-	public static final String duccContextExperimentDetails = duccContext+"/experiment-details-data";
-	public static final String duccContextExperimentDetailsDirectory = duccContext+"/experiment-details-directory";
-	public static final String duccContextExperimentDetailsJobs = duccContext+"/experiment-details-jobs-data";
-	
-	public static final String duccContextJsonExperiments = duccContext+"/json-format-aaData-experiments";
-	public static final String duccContextJsonExperimentDetails = duccContext+"/json-format-aaData-experiment-details";
-	public static final String duccContextJsonExperimentDetailsJobs = duccContext+"/json-format-aaData-experiment-details-jobs";
-	
-	public static final int maximumRecordsExperiments = 4096;
-	public static final int defaultRecordsExperiments = 16;
+
+  public static final String duccContext = "/ducc-servlet";
+
+  public static final String duccContextExperimentCancelRequest = duccContext + "/experiment-cancel-request";
+
+  public static final String duccContextExperiments = duccContext + "/experiments-data";
+
+  public static final String duccContextExperimentDetails = duccContext + "/experiment-details-data";
+
+  public static final String duccContextExperimentDetailsDirectory = duccContext + "/experiment-details-directory";
+
+  public static final String duccContextExperimentDetailsJobs = duccContext + "/experiment-details-jobs-data";
+
+  public static final String duccContextJsonExperiments = duccContext + "/json-format-aaData-experiments";
+
+  public static final String duccContextJsonExperimentDetails = duccContext + "/json-format-aaData-experiment-details";
+
+  public static final String duccContextJsonExperimentDetailsJobs = duccContext + "/json-format-aaData-experiment-details-jobs";
+
+  public static final int maximumRecordsExperiments = 4096;
+
+  public static final int defaultRecordsExperiments = 16;
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalCookies.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalCookies.java
index a7cdda6..21a463b 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalCookies.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccLocalCookies.java
@@ -19,15 +19,19 @@
 package org.apache.uima.ducc.ws.server;
 
 public class DuccLocalCookies {
-	
-	private static final String application = DuccCookies.duccCookiePrefix;
-	private static final String max = DuccCookies.max;
-	private static final String users = DuccCookies.users;
-	
-	private static final String experiments = "experiments";
-	
-	public static final String cookieExperimentsMax = application+experiments+max;
-	public static final String cookieExperimentsUsers = application+experiments+users;
-	//public static final String cookieExperimentsUsersQualifier = application+join+experiments+users+qualifier;
-	
+
+  private static final String application = DuccCookies.duccCookiePrefix;
+
+  private static final String max = DuccCookies.max;
+
+  private static final String users = DuccCookies.users;
+
+  private static final String experiments = "experiments";
+
+  public static final String cookieExperimentsMax = application + experiments + max;
+
+  public static final String cookieExperimentsUsers = application + experiments + users;
+  // public static final String cookieExperimentsUsersQualifier =
+  // application+join+experiments+users+qualifier;
+
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
index c949918..cc9dd6c 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
@@ -24,98 +24,103 @@
 import java.util.UUID;
 
 public class Experiment implements IExperiment {
-	
-	private String user = null;
-	private String directory = null;
-	private ArrayList<Task> tasks = null;
-	private long fileDate = 0;
-	
-	private String id = UUID.randomUUID().toString();
-    private int version;
-	
-	public Experiment(String user, String directory, long date, int version, ArrayList<Task> tasks) throws Exception {
-		initialize(user, directory, date, version, tasks);
-	}
-	
-	private void initialize(String user, String directory, long fileDate, int version, ArrayList<Task> tasks) throws Exception {
-		if(user == null) {
-			throw new ExperimentException("missing user");
-		}
-		if(directory == null) {
-			throw new ExperimentException("missing directory");
-		}
-		if(tasks == null) {
-			throw new ExperimentException("missing tasks");
-		}
-		this.user = user;
-		this.directory = directory;
-		this.fileDate = fileDate;
-		this.version = version;
-		this.tasks = tasks;
-	}
-	
-	@Override
-	public void setId(String value) {
-		id = value;
-	}
-	
-	@Override
-	public String getId() {
-		return id;
-	}
 
-	@Override
-	public String getUser() {
-		return user;
-	}
+  private String user = null;
 
-	@Override
-	public String getDirectory() {
-		return directory;
-	}
-	
-	@Override
-	public ArrayList<Task> getTasks() {
-		return tasks;
-	}
-	
-	@Override
-	public ArrayList<String> getJobIds() {
-		ArrayList<String> jobIds = new ArrayList<String>();
-		if(tasks != null) {
-			for(Task task : tasks) {
-				if(task.type != null) {
-					Jed.Type jedType = Jed.Type.getEnum(task.type);
-					switch(jedType) {
-					case DuccJob:
-					case Java:
-					case Trainer:	
-						long[] duccIdList = task.duccId;
-						for(long duccId : duccIdList) {
-							if(duccId < 0) {
-								// reservation
-							}
-							else {
-								// job
-								String jobId = ""+(0+duccId);
-								jobIds.add(jobId);
-							}
-						}
-						break;
-					default:
-						break;
-					}
-				}
-			}
-		}
-		return jobIds;
-	}
-	
-    @Override
-    public int getVersion() {
-        return version;
+  private String directory = null;
+
+  private ArrayList<Task> tasks = null;
+
+  private long fileDate = 0;
+
+  private String id = UUID.randomUUID().toString();
+
+  private int version;
+
+  public Experiment(String user, String directory, long date, int version, ArrayList<Task> tasks)
+          throws Exception {
+    initialize(user, directory, date, version, tasks);
+  }
+
+  private void initialize(String user, String directory, long fileDate, int version,
+          ArrayList<Task> tasks) throws Exception {
+    if (user == null) {
+      throw new ExperimentException("missing user");
     }
-  
+    if (directory == null) {
+      throw new ExperimentException("missing directory");
+    }
+    if (tasks == null) {
+      throw new ExperimentException("missing tasks");
+    }
+    this.user = user;
+    this.directory = directory;
+    this.fileDate = fileDate;
+    this.version = version;
+    this.tasks = tasks;
+  }
+
+  @Override
+  public void setId(String value) {
+    id = value;
+  }
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  @Override
+  public String getUser() {
+    return user;
+  }
+
+  @Override
+  public String getDirectory() {
+    return directory;
+  }
+
+  @Override
+  public ArrayList<Task> getTasks() {
+    return tasks;
+  }
+
+  @Override
+  public ArrayList<String> getJobIds() {
+    ArrayList<String> jobIds = new ArrayList<String>();
+    if (tasks != null) {
+      for (Task task : tasks) {
+        if (task.type != null) {
+          Jed.Type jedType = Jed.Type.getEnum(task.type);
+          switch (jedType) {
+            case DuccJob:
+            case Java:
+            case Trainer:
+              long[] duccIdList = task.duccId;
+              for (long duccId : duccIdList) {
+                if (duccId < 0) {
+                  // reservation
+                } else {
+                  // job
+                  String jobId = "" + (0 + duccId);
+                  jobIds.add(jobId);
+                }
+              }
+              break;
+            default:
+              break;
+          }
+        }
+      }
+    }
+    return jobIds;
+  }
+
+  @Override
+  public int getVersion() {
+    return version;
+  }
+
   @Override
   public boolean isActive() {
     boolean retVal = false;
@@ -128,217 +133,213 @@
     }
     return retVal;
   }
-	
-	@Override
-	public Jed.Status getStatus() {
-		Jed.Status retVal = Jed.Status.Unknown;
-		ArrayList<Task> tasks = getTasks();
-		if(tasks != null) {
-			boolean canceled = false;
-			boolean failed = false;
-			boolean running = false;
-			boolean done = false;
-            for (Task task : tasks) {
-                if (task.parentId == 0 && task.status != null) {
-                    Jed.Status status = Jed.Status.getEnum(task.status);
-                    switch (status) {
-                        case Canceled:
-                            canceled = true;
-                            break;
-                        case Running:
-                            running = true;
-                            break;
-                        case Failed:
-                        case DependencyFailed:
-                            failed = true;
-                            break;
-                        case Done:
-                        case Completed:
-                            done = true;
-                            break;
-                        default:
-                            break;
-                    }
-                }
-            }
-            // If more than 1 parent task use the most "important" state
-            // Running > Failed/DependencyFailed > Canceled > Done/Completed
-            // But if JED appears to have been killed while running change state to Unknown 
-            if(running) {
-                retVal = isStale() ? Jed.Status.Unknown : Jed.Status.Running;
-            }
-			else if(failed) {
-				retVal = Jed.Status.Failed;
-			}
-            else if(canceled) {
-                retVal = Jed.Status.Canceled;
-            }
-			else if(done) {
-				retVal = Jed.Status.Done;
-			}
-			else {
-				retVal = Jed.Status.Unknown;
-			}
-		}
-		return retVal;
-	}
-	
-	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
-	
-	private static long getMillis(String dateString) {
-		long retVal = 0;
-		try {
-			if(dateString != null) {
-				 Date date = sdf.parse(dateString);
-				 retVal = date.getTime();
-			}
-		}
-		catch(Exception e) {
-		}
-		return retVal;
-	}
-	
-	@Override
-	public long getStartTime() {
-		return getMillis(getStartDate());
-	}
-	
-	@Override
-	public String getStartDate() {
-		String retVal = "";
-		long experimentStartMillis = Long.MAX_VALUE;
-		if(tasks != null) {
-			for(Task task : tasks) {
-				String dateString = task.startTime;
-				if(dateString != null) {
-					long taskStartMillis = getMillis(dateString);
-					if(taskStartMillis < experimentStartMillis) {
-						experimentStartMillis = taskStartMillis;
-						retVal = dateString;
-					}
-				}
-			}
-		}
-		return retVal;
-	}
 
-	@Override
-	public void setFileDate(long value) {
-		fileDate = value;
-	}
-	
-	@Override
-	public long getFileDate() {
-		return fileDate;
-	}
-	
-    private long staleTime = 1000 * 60 * 6;                
-    private long staleTimeOld = 1000 * 60 * 60 * 24;
-    
-    @Override
-	public boolean isStale() {
-        // If the log file has been removed then the driver has stopped.
-        // If the lock file is still present the driver may have been killed, so check the age of the state file.
-        // If an old version-less file then may have a long job running so wait 24 hrs - new ones are touched every 5 mins
-        // Check that the lock-file exists by reading it as the user if necessary,
-        boolean logLocked = null != ExperimentsRegistryUtilities.getFileContents(user, directory + "/DRIVER.log.lck");
-        if (logLocked) {
-            long now = System.currentTimeMillis();
-            long fileDate = ExperimentsRegistryUtilities.getFileDate(this);
-            if (fileDate > 0) {
-                if (fileDate < now) {
-                    long elapsed = now - fileDate;
-                    long tStale = (version == 0) ? staleTimeOld : staleTime; 
-                    if (elapsed < tStale) {
-                        return false;
-                    }
-                }
-            }
+  @Override
+  public Jed.Status getStatus() {
+    Jed.Status retVal = Jed.Status.Unknown;
+    ArrayList<Task> tasks = getTasks();
+    if (tasks != null) {
+      boolean canceled = false;
+      boolean failed = false;
+      boolean running = false;
+      boolean done = false;
+      for (Task task : tasks) {
+        if (task.parentId == 0 && task.status != null) {
+          Jed.Status status = Jed.Status.getEnum(task.status);
+          switch (status) {
+            case Canceled:
+              canceled = true;
+              break;
+            case Running:
+              running = true;
+              break;
+            case Failed:
+            case DependencyFailed:
+              failed = true;
+              break;
+            case Done:
+            case Completed:
+              done = true;
+              break;
+            default:
+              break;
+          }
         }
-        return true;
-	}
-	
-	@Override
-	public int hashCode() {
-		return directory.hashCode();
-	}
-	
-	@Override
-	public int compareTo(Object object) {
-		int retVal = 0;
-		if(object != null) {
-			if(object instanceof Experiment) {
-				Experiment that = (Experiment)object;
-				if(retVal == 0) {
-					retVal = compareState(that);
-				}
-				if(retVal == 0) {
-					retVal = compareStartDate(that);
-				}
-				if(retVal == 0) {
-					retVal = compareDirectory(that);
-				}
-				if(retVal == 0) {
-					retVal = compareUser(that);
-				}
-			}
-		}
-		return retVal;
-	}
-	
-	private int compareState(Experiment that) {
-		int retVal = 0;
-		if(this.isActive()) {
-			if(that.isActive()) {
-				//retVal = 0;
-			}
-			else {
-				retVal = -1;
-			}
-		}
-		else {
-			if(that.isActive()) {
-				retVal = 1;
-			}
-			else {
-				//retVal = 0;
-			}
-		}
-		return retVal;
-	}
-	
-	private int compareStrings(String s0, String s1) {
-		int retVal = 0;
-		if(s0 != null) {
-			if(s1 != null) {
-				retVal = s1.compareTo(s0);
-			}
-		}
-		return retVal;
-	}
-	
-	private int compareStartDate(Experiment that) {
-		int retVal = 0;
-		if(that != null) {
-			retVal = compareStrings(this.getStartDate(), that.getStartDate());
-		}
-		return retVal;
-	}
-	
-	private int compareDirectory(Experiment that) {
-		int retVal = 0;
-		if(that != null) {
-			retVal = compareStrings(this.getDirectory(), that.getDirectory());
-		}
-		return retVal;
-	}
-	
-	private int compareUser(Experiment that) {
-		int retVal = 0;
-		if(that != null) {
-			retVal = compareStrings(this.getUser(), that.getUser());
-		}
-		return retVal;
-	}
+      }
+      // If more than 1 parent task use the most "important" state
+      // Running > Failed/DependencyFailed > Canceled > Done/Completed
+      // But if JED appears to have been killed while running change state to Unknown
+      if (running) {
+        retVal = isStale() ? Jed.Status.Unknown : Jed.Status.Running;
+      } else if (failed) {
+        retVal = Jed.Status.Failed;
+      } else if (canceled) {
+        retVal = Jed.Status.Canceled;
+      } else if (done) {
+        retVal = Jed.Status.Done;
+      } else {
+        retVal = Jed.Status.Unknown;
+      }
+    }
+    return retVal;
+  }
+
+  private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
+
+  private static long getMillis(String dateString) {
+    long retVal = 0;
+    try {
+      if (dateString != null) {
+        Date date = sdf.parse(dateString);
+        retVal = date.getTime();
+      }
+    } catch (Exception e) {
+    }
+    return retVal;
+  }
+
+  @Override
+  public long getStartTime() {
+    return getMillis(getStartDate());
+  }
+
+  @Override
+  public String getStartDate() {
+    String retVal = "";
+    long experimentStartMillis = Long.MAX_VALUE;
+    if (tasks != null) {
+      for (Task task : tasks) {
+        String dateString = task.startTime;
+        if (dateString != null) {
+          long taskStartMillis = getMillis(dateString);
+          if (taskStartMillis < experimentStartMillis) {
+            experimentStartMillis = taskStartMillis;
+            retVal = dateString;
+          }
+        }
+      }
+    }
+    return retVal;
+  }
+
+  @Override
+  public void setFileDate(long value) {
+    fileDate = value;
+  }
+
+  @Override
+  public long getFileDate() {
+    return fileDate;
+  }
+
+  private long staleTime = 1000 * 60 * 6;
+
+  private long staleTimeOld = 1000 * 60 * 60 * 24;
+
+  @Override
+  public boolean isStale() {
+    // If the log file has been removed then the driver has stopped.
+    // If the lock file is still present the driver may have been killed, so check the age of the
+    // state file.
+    // If an old version-less file then may have a long job running so wait 24 hrs - new ones are
+    // touched every 5 mins
+    // Check that the lock-file exists by reading it as the user if necessary,
+    boolean logLocked = null != ExperimentsRegistryUtilities.getFileContents(user,
+            directory + "/DRIVER.log.lck");
+    if (logLocked) {
+      long now = System.currentTimeMillis();
+      long fileDate = ExperimentsRegistryUtilities.getFileDate(this);
+      if (fileDate > 0) {
+        if (fileDate < now) {
+          long elapsed = now - fileDate;
+          long tStale = (version == 0) ? staleTimeOld : staleTime;
+          if (elapsed < tStale) {
+            return false;
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return directory.hashCode();
+  }
+
+  @Override
+  public int compareTo(Object object) {
+    int retVal = 0;
+    if (object != null) {
+      if (object instanceof Experiment) {
+        Experiment that = (Experiment) object;
+        if (retVal == 0) {
+          retVal = compareState(that);
+        }
+        if (retVal == 0) {
+          retVal = compareStartDate(that);
+        }
+        if (retVal == 0) {
+          retVal = compareDirectory(that);
+        }
+        if (retVal == 0) {
+          retVal = compareUser(that);
+        }
+      }
+    }
+    return retVal;
+  }
+
+  private int compareState(Experiment that) {
+    int retVal = 0;
+    if (this.isActive()) {
+      if (that.isActive()) {
+        // retVal = 0;
+      } else {
+        retVal = -1;
+      }
+    } else {
+      if (that.isActive()) {
+        retVal = 1;
+      } else {
+        // retVal = 0;
+      }
+    }
+    return retVal;
+  }
+
+  private int compareStrings(String s0, String s1) {
+    int retVal = 0;
+    if (s0 != null) {
+      if (s1 != null) {
+        retVal = s1.compareTo(s0);
+      }
+    }
+    return retVal;
+  }
+
+  private int compareStartDate(Experiment that) {
+    int retVal = 0;
+    if (that != null) {
+      retVal = compareStrings(this.getStartDate(), that.getStartDate());
+    }
+    return retVal;
+  }
+
+  private int compareDirectory(Experiment that) {
+    int retVal = 0;
+    if (that != null) {
+      retVal = compareStrings(this.getDirectory(), that.getDirectory());
+    }
+    return retVal;
+  }
+
+  private int compareUser(Experiment that) {
+    int retVal = 0;
+    if (that != null) {
+      retVal = compareStrings(this.getUser(), that.getUser());
+    }
+    return retVal;
+  }
 
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentException.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentException.java
index 0c479f6..c9f53d5 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentException.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentException.java
@@ -19,10 +19,10 @@
 package org.apache.uima.ducc.ws.xd;
 
 public class ExperimentException extends Exception {
-	
-	private static final long serialVersionUID = 1L;
-	
-	public ExperimentException(String text) {
-		super(text);
-	}
+
+  private static final long serialVersionUID = 1L;
+
+  public ExperimentException(String text) {
+    super(text);
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
index e2a5886..1e6879d 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
@@ -40,298 +40,287 @@
 public class ExperimentsRegistryManager {
 
   // NOTE - this variable used to hold the class name before WsLog was simplified
-	private static DuccLogger cName = DuccLogger.getLogger(ExperimentsRegistryManager.class);
-	
-	private static Gson gson = new Gson();
-	private static ExperimentsRegistryManager instance = new ExperimentsRegistryManager();
-	
-	private int MAX_CACHE_SIZE = 4096;
-	
-	private TreeMap<String,IExperiment> map = new TreeMap<String,IExperiment>();
-	
-	private AtomicLong updateCounter = new AtomicLong(0);
-	
-	public static ExperimentsRegistryManager getInstance() {
-		return instance;
-	}
-	
-	public TreeMap<IExperiment,String> getMapByStatus() {
-		TreeMap<IExperiment,String> mapInverse = new TreeMap<IExperiment,String>();
-		synchronized(map) {
-			for(Entry<String, IExperiment> entry : map.entrySet()) {
-				mapInverse.put(entry.getValue(), entry.getKey());
-			}
-		}
-		return mapInverse;
-	}
-	
-	private TreeMap<Long, String> getMapByDate() {
-		TreeMap<Long, String> mapByDate = new TreeMap<Long, String>();
-		synchronized(map) {
-			for(Entry<String, IExperiment> entry : map.entrySet()) {
-				IExperiment experiment = entry.getValue();
-				Long key = new Long(experiment.getStartTime());
-				String value = experiment.getId();
-				mapByDate.put(key, value);
-			}
-		}
-		return mapByDate;
-	}
-	
-	public IExperiment getById(String id) {
-		IExperiment retVal = null;
-		if(id != null) {
-			synchronized(map) {
-				for(Entry<String, IExperiment> entry : map.entrySet()) {
-					IExperiment experiment = entry.getValue();
-					if(id.equals(experiment.getId())) {
-						retVal = experiment;
-						break;
-					}
-				}
-			}
-		}
-		return retVal;
-	}
-	
-	private void replace(String directory, Experiment experiment) {
-		String mName = "replace";
-		String id = map.get(directory).getId();
-		experiment.setId(id);
-		map.put(directory, experiment);
-		WsLog.debug(cName, mName, directory);
-	}
-	
-	private void add(String directory, Experiment experiment) {
-		String mName = "add";
-		map.put(directory, experiment);
-		WsLog.debug(cName, mName, directory);
-	}
-	
-	private void put(String directory, Experiment experiment) {
-		synchronized(map) {
-			if(map.containsKey(directory)) {
-				replace(directory, experiment);
-			}
-			else {
-				add(directory, experiment);
-			}
-		}
-	}
-	
-	private void remove(String directory) {
-		String mName = "remove";
-		synchronized(map) {
-			map.remove(directory);
-			
-		}
-		WsLog.debug(cName, mName, directory);
-	}
-	
-	private boolean containsKey(String directory) {
-		synchronized(map) {
-			return map.containsKey(directory);
-		}
-	}
-	
-	public void initialize(String user, String directory) {
-		String mName = "initialize";
-		if(user == null) {
-			WsLog.warn(cName, mName, "missing user");
-		}
-		else if(directory == null) {
-			WsLog.warn(cName, mName, "missing directory");
-		}
-		else {
-			String parent = ExperimentsRegistryUtilities.upOne(directory);
-			update(user, parent, false);
-		}
-	}
-	
-	private void update(String user, String directory) {
-		String mName = "update";
-		try {
-			String fileName = ExperimentsRegistryUtilities.getStateFilePath(directory);
-			long date = ExperimentsRegistryUtilities.getFileDate(user, fileName);
-			WsLog.info(cName, mName, "Reading " + fileName + " date: " + date);
-			String contents = ExperimentsRegistryUtilities.getFileContents(user, fileName);
-			if(contents != null) {
-                // Version may precede the initial '[' and may be on a separate line
-			    int version = 0;
-			    int offset = contents.indexOf('[');
-			    if (offset > 0) {
-			        String s = contents.substring(0, offset).trim();
-			        try {
-			            version = Integer.parseInt(s);
-			        } catch (NumberFormatException e) {
-			            WsLog.warn(cName, mName, "Invalid version '" + s + "' in state file : " + fileName);
-			            return;
-			        }
-			        contents = contents.substring(offset);
-			    }
-			    if (offset < 0) {
-		             WsLog.warn(cName, mName, "Invalid syntax (missing '[') in state file : " + fileName);
-		             return;
-			    }
-				StringReader sr = new StringReader(contents);
-				Type tasksType = new TypeToken<ArrayList<Task>>(){}.getType();
-				try {
-				    ArrayList<Task> taskArray = gson.fromJson(sr, tasksType);
-	                Experiment experiment = new Experiment(user, directory, date, version, taskArray);
-	                put(directory, experiment);
-                } catch (JsonParseException e) {
-                    WsLog.warn(cName, mName,"Ignoring " + fileName + " as has Json syntax error " + e.getMessage());
-                }
-			}
-			else {
-				WsLog.trace(cName, mName,"state file missing or inaccessible in "+directory);
-				remove(directory);
-			}
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-	}
-	
-	private void update(String user, String directory, boolean overwrite) {
-		String mName = "update";
-		WsLog.enter(cName, mName);
-		try {
-			if(overwrite) {
-				update(user, directory);
-			}
-			else {
-				if(!containsKey(directory)) {
-					update(user, directory);
-				}
-				else {
-					WsLog.trace(cName, mName, "duplicate directory: "+directory);
-				}
-			}
-			
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-		//WsLog.exit(cName, mName);
-	}
-	
-	private void check() {
-		String mName = "check";
-		try {
-			ArrayList<IExperiment> list = new ArrayList<IExperiment>();
-			synchronized(map) {
-				for(Entry<String, IExperiment> entry : map.entrySet()) {
-					IExperiment experiment = entry.getValue();
-					if(experiment.isActive()) {
-						list.add(experiment);
-					}
-				}
-			}
-			for(IExperiment experiment : list) {
-				String user = experiment.getUser();
-				String directory = experiment.getDirectory();
-				WsLog.debug(cName, mName, "user: "+user+" "+"dirextory: "+directory);
-				update(experiment.getUser(), experiment.getDirectory(), true);
-			}
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-	}
-	
-	private boolean timeToPrune() {
-		boolean retVal = false;
-		TreeMap<Long, String> mapByDate = getMapByDate();
-		int size = mapByDate.size();
-		if(size > MAX_CACHE_SIZE) {
-			retVal = true;
-		}
-		if((updateCounter.get() % 3) == 0) {
-			retVal = true;
-		}
-		return retVal;
-	}
-	
-	private void prune() {
-		String mName = "prune";
-		WsLog.enter(cName, mName);
-		try {
-			TreeMap<Long, String> mapByDate = getMapByDate();
-			if(timeToPrune()) {
-				int cacheCount = 0;
-				for(Entry<Long, String> entry : mapByDate.entrySet()) {
-					String key = entry.getValue();
-					IExperiment experiment = getById(key);
-					if(experiment != null) {
-						if(experiment.isActive()) {
-							cacheCount++;
-						}
-						else {
-							if(cacheCount < MAX_CACHE_SIZE) {
-								cacheCount++;
-							}
-							else {
-								String directory = experiment.getDirectory();
-								remove(directory);
-							}
-						}
-					}
-				}
-			}
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-		//WsLog.exit(cName, mName);
-	}
-	
-	public void update(IDuccWorkMap dwm) {
-		String mName = "update";
-		WsLog.enter(cName, mName);
-		try {
-			if(dwm == null) {
-				WsLog.warn(cName, mName, "missing map");
-			}
-			else {
-				updateCounter.incrementAndGet();
-				Iterator<DuccId> iterator = dwm.getJobKeySet().iterator();
-				while(iterator.hasNext()) {
-					DuccId duccId = iterator.next();
-					IDuccWork job = dwm.findDuccWork(duccId);
-					if(job != null) {
-						IDuccStandardInfo stdInfo = job.getStandardInfo();
-						if(stdInfo != null) {
-							String user = stdInfo.getUser();
-							String directory = stdInfo.getLogDirectory();
-							String parent = ExperimentsRegistryUtilities.upOne(directory);
-							update(user, parent, true);
-						}
-					}
-				}
+  private static DuccLogger cName = DuccLogger.getLogger(ExperimentsRegistryManager.class);
 
-				// Also process managed reservations in case the experiment has only these.
-                iterator = dwm.getManagedReservationKeySet().iterator();
-                while(iterator.hasNext()) {
-                    DuccId duccId = iterator.next();
-                    IDuccWork job = dwm.findDuccWork(duccId);
-                    if(job != null) {
-                        IDuccStandardInfo stdInfo = job.getStandardInfo();
-                        if(stdInfo != null) {
-                            String user = stdInfo.getUser();
-                            String directory = stdInfo.getLogDirectory();
-                            String parent = ExperimentsRegistryUtilities.upOne(directory);
-                            update(user, parent, true);
-                        }
-                    }
-                }
-			}
-			check();
-			prune();
-		}
-		catch(Exception e) {
-			WsLog.error(cName, mName, e);
-		}
-		//WsLog.exit(cName, mName);
-	}
+  private static Gson gson = new Gson();
+
+  private static ExperimentsRegistryManager instance = new ExperimentsRegistryManager();
+
+  private int MAX_CACHE_SIZE = 4096;
+
+  private TreeMap<String, IExperiment> map = new TreeMap<String, IExperiment>();
+
+  private AtomicLong updateCounter = new AtomicLong(0);
+
+  public static ExperimentsRegistryManager getInstance() {
+    return instance;
+  }
+
+  public TreeMap<IExperiment, String> getMapByStatus() {
+    TreeMap<IExperiment, String> mapInverse = new TreeMap<IExperiment, String>();
+    synchronized (map) {
+      for (Entry<String, IExperiment> entry : map.entrySet()) {
+        mapInverse.put(entry.getValue(), entry.getKey());
+      }
+    }
+    return mapInverse;
+  }
+
+  private TreeMap<Long, String> getMapByDate() {
+    TreeMap<Long, String> mapByDate = new TreeMap<Long, String>();
+    synchronized (map) {
+      for (Entry<String, IExperiment> entry : map.entrySet()) {
+        IExperiment experiment = entry.getValue();
+        Long key = new Long(experiment.getStartTime());
+        String value = experiment.getId();
+        mapByDate.put(key, value);
+      }
+    }
+    return mapByDate;
+  }
+
+  public IExperiment getById(String id) {
+    IExperiment retVal = null;
+    if (id != null) {
+      synchronized (map) {
+        for (Entry<String, IExperiment> entry : map.entrySet()) {
+          IExperiment experiment = entry.getValue();
+          if (id.equals(experiment.getId())) {
+            retVal = experiment;
+            break;
+          }
+        }
+      }
+    }
+    return retVal;
+  }
+
+  private void replace(String directory, Experiment experiment) {
+    String mName = "replace";
+    String id = map.get(directory).getId();
+    experiment.setId(id);
+    map.put(directory, experiment);
+    WsLog.debug(cName, mName, directory);
+  }
+
+  private void add(String directory, Experiment experiment) {
+    String mName = "add";
+    map.put(directory, experiment);
+    WsLog.debug(cName, mName, directory);
+  }
+
+  private void put(String directory, Experiment experiment) {
+    synchronized (map) {
+      if (map.containsKey(directory)) {
+        replace(directory, experiment);
+      } else {
+        add(directory, experiment);
+      }
+    }
+  }
+
+  private void remove(String directory) {
+    String mName = "remove";
+    synchronized (map) {
+      map.remove(directory);
+
+    }
+    WsLog.debug(cName, mName, directory);
+  }
+
+  private boolean containsKey(String directory) {
+    synchronized (map) {
+      return map.containsKey(directory);
+    }
+  }
+
+  public void initialize(String user, String directory) {
+    String mName = "initialize";
+    if (user == null) {
+      WsLog.warn(cName, mName, "missing user");
+    } else if (directory == null) {
+      WsLog.warn(cName, mName, "missing directory");
+    } else {
+      String parent = ExperimentsRegistryUtilities.upOne(directory);
+      update(user, parent, false);
+    }
+  }
+
+  private void update(String user, String directory) {
+    String mName = "update";
+    try {
+      String fileName = ExperimentsRegistryUtilities.getStateFilePath(directory);
+      long date = ExperimentsRegistryUtilities.getFileDate(user, fileName);
+      WsLog.info(cName, mName, "Reading " + fileName + " date: " + date);
+      String contents = ExperimentsRegistryUtilities.getFileContents(user, fileName);
+      if (contents != null) {
+        // Version may precede the initial '[' and may be on a separate line
+        int version = 0;
+        int offset = contents.indexOf('[');
+        if (offset > 0) {
+          String s = contents.substring(0, offset).trim();
+          try {
+            version = Integer.parseInt(s);
+          } catch (NumberFormatException e) {
+            WsLog.warn(cName, mName, "Invalid version '" + s + "' in state file : " + fileName);
+            return;
+          }
+          contents = contents.substring(offset);
+        }
+        if (offset < 0) {
+          WsLog.warn(cName, mName, "Invalid syntax (missing '[') in state file : " + fileName);
+          return;
+        }
+        StringReader sr = new StringReader(contents);
+        Type tasksType = new TypeToken<ArrayList<Task>>() {
+        }.getType();
+        try {
+          ArrayList<Task> taskArray = gson.fromJson(sr, tasksType);
+          Experiment experiment = new Experiment(user, directory, date, version, taskArray);
+          put(directory, experiment);
+        } catch (JsonParseException e) {
+          WsLog.warn(cName, mName,
+                  "Ignoring " + fileName + " as has Json syntax error " + e.getMessage());
+        }
+      } else {
+        WsLog.trace(cName, mName, "state file missing or inaccessible in " + directory);
+        remove(directory);
+      }
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+  }
+
+  private void update(String user, String directory, boolean overwrite) {
+    String mName = "update";
+    WsLog.enter(cName, mName);
+    try {
+      if (overwrite) {
+        update(user, directory);
+      } else {
+        if (!containsKey(directory)) {
+          update(user, directory);
+        } else {
+          WsLog.trace(cName, mName, "duplicate directory: " + directory);
+        }
+      }
+
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+    // WsLog.exit(cName, mName);
+  }
+
+  private void check() {
+    String mName = "check";
+    try {
+      ArrayList<IExperiment> list = new ArrayList<IExperiment>();
+      synchronized (map) {
+        for (Entry<String, IExperiment> entry : map.entrySet()) {
+          IExperiment experiment = entry.getValue();
+          if (experiment.isActive()) {
+            list.add(experiment);
+          }
+        }
+      }
+      for (IExperiment experiment : list) {
+        String user = experiment.getUser();
+        String directory = experiment.getDirectory();
+        WsLog.debug(cName, mName, "user: " + user + " " + "dirextory: " + directory);
+        update(experiment.getUser(), experiment.getDirectory(), true);
+      }
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+  }
+
+  private boolean timeToPrune() {
+    boolean retVal = false;
+    TreeMap<Long, String> mapByDate = getMapByDate();
+    int size = mapByDate.size();
+    if (size > MAX_CACHE_SIZE) {
+      retVal = true;
+    }
+    if ((updateCounter.get() % 3) == 0) {
+      retVal = true;
+    }
+    return retVal;
+  }
+
+  private void prune() {
+    String mName = "prune";
+    WsLog.enter(cName, mName);
+    try {
+      TreeMap<Long, String> mapByDate = getMapByDate();
+      if (timeToPrune()) {
+        int cacheCount = 0;
+        for (Entry<Long, String> entry : mapByDate.entrySet()) {
+          String key = entry.getValue();
+          IExperiment experiment = getById(key);
+          if (experiment != null) {
+            if (experiment.isActive()) {
+              cacheCount++;
+            } else {
+              if (cacheCount < MAX_CACHE_SIZE) {
+                cacheCount++;
+              } else {
+                String directory = experiment.getDirectory();
+                remove(directory);
+              }
+            }
+          }
+        }
+      }
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+    // WsLog.exit(cName, mName);
+  }
+
+  public void update(IDuccWorkMap dwm) {
+    String mName = "update";
+    WsLog.enter(cName, mName);
+    try {
+      if (dwm == null) {
+        WsLog.warn(cName, mName, "missing map");
+      } else {
+        updateCounter.incrementAndGet();
+        Iterator<DuccId> iterator = dwm.getJobKeySet().iterator();
+        while (iterator.hasNext()) {
+          DuccId duccId = iterator.next();
+          IDuccWork job = dwm.findDuccWork(duccId);
+          if (job != null) {
+            IDuccStandardInfo stdInfo = job.getStandardInfo();
+            if (stdInfo != null) {
+              String user = stdInfo.getUser();
+              String directory = stdInfo.getLogDirectory();
+              String parent = ExperimentsRegistryUtilities.upOne(directory);
+              update(user, parent, true);
+            }
+          }
+        }
+
+        // Also process managed reservations in case the experiment has only these.
+        iterator = dwm.getManagedReservationKeySet().iterator();
+        while (iterator.hasNext()) {
+          DuccId duccId = iterator.next();
+          IDuccWork job = dwm.findDuccWork(duccId);
+          if (job != null) {
+            IDuccStandardInfo stdInfo = job.getStandardInfo();
+            if (stdInfo != null) {
+              String user = stdInfo.getUser();
+              String directory = stdInfo.getLogDirectory();
+              String parent = ExperimentsRegistryUtilities.upOne(directory);
+              update(user, parent, true);
+            }
+          }
+        }
+      }
+      check();
+      prune();
+    } catch (Exception e) {
+      WsLog.error(cName, mName, e);
+    }
+    // WsLog.exit(cName, mName);
+  }
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
index 97e6ead..3a4d82d 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
@@ -29,150 +29,147 @@
 import org.apache.uima.ducc.ws.log.WsLog;
 
 public class ExperimentsRegistryUtilities {
-	
+
   // NOTE - this variable used to hold the class name before WsLog was simplified
-	private static DuccLogger cName = DuccLogger.getLogger(ExperimentsRegistryUtilities.class);
-	
-	private static String stateFileName = "Experiment.state";
-	
-	public static String upOne(String directory) {
-		String retVal = directory;
-		if(directory != null) {
-		  retVal = new File(directory).getParent();
-		}
-		return retVal;
-	}
-	
-	public static String getStateFilePath(String directory) {
-		String retVal = new File(directory, stateFileName).getAbsolutePath();
-		return retVal;
-	}
-	
-	private static void closer(Closeable object) {
-		String mName = "closer";
-		try {
-			object.close();
-		}
-		catch(Exception e) {
-			WsLog.debug(cName, mName, e);
-		}
-	}
-	
-	public static long getFileDate(IExperiment experiment) {
-		String mName = "getFileDate";
-		WsLog.enter(cName, mName);
-		String user = experiment.getUser();
-		String filename = getStateFilePath(experiment.getDirectory());
-		long retVal = getFileDate(user, filename);
-		return retVal;
-	}
-	
-	public static long getFileDate(String user, String filename) {
-		String mName = "getFileDate";
-		WsLog.enter(cName, mName);
-		long retVal = getDomesticFileDate(user, filename);
-		if(retVal == 0) {
-			retVal = getAlienFileDate(user, filename);
-		}
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
-	
-	private static long getAlienFileDate(String user, String filename) {
-		String mName = "getAlienFileDate";
-		WsLog.enter(cName, mName);
-		long retVal = 0;
-		AlienFile alienFile = new AlienFile(user, filename);
-		// NOTE - should not need the "--" ... or this could be moved to AlienFile
-        String[] lines = alienFile.getResult(false, "--", "/bin/ls", "-l", "--time-style=+%s", filename );
-        // Should have 1 line with secs-since-epoch in 6th token
-        if (lines.length == 1) {
-            String[] toks = lines[0].split("\\s+");
-            if (toks.length >= 6) {
-                retVal = Long.valueOf(toks[5]) * 1000;
-            }
-        }
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
-	
-	private static long getDomesticFileDate(String user, String filename) {
-		String mName = "getDomesticFileDate";
-		WsLog.enter(cName, mName);
-		long retVal =0;
-		try {
-			File file = new File(filename);
-			retVal = file.lastModified();
-		}
-		catch(Exception e) {
-			WsLog.trace(cName, mName, e);
-		}
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
-	
-	/*
-	 * Returns null if file is missing or can't be read
-	 */
-	public static String getFileContents(String user, String filename) {
-		String mName = "getFileContents";
-		WsLog.enter(cName, mName);
-		boolean canRead = ((new File(filename)).canRead());
-		String retVal = canRead ? getDomesticFileContents(user, filename) : getAlienFileContents(user, filename);
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
-	
-	private static String getAlienFileContents(String user, String filename) {
-		String mName = "getAlienFileContents";
-		WsLog.enter(cName, mName);
-		String retVal = null;
-		try {
-			AlienFile alienFile = new AlienFile(user, filename);
-			retVal = alienFile.getString();
-		}
-		catch(Throwable t) {
-			WsLog.trace(cName, mName, t);
-		}
-		
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
-	
-	private static String getDomesticFileContents(String user, String filename) {
-		String mName = "getDomesticFileContents";
-		WsLog.enter(cName, mName);
-		String retVal = null;
-		FileReader fr = null;
-		BufferedReader br = null;
-		StringReader sr = null;
-		try {
-			fr = new FileReader(filename);
-			br = new BufferedReader(fr);
-			StringBuffer sb = new StringBuffer();
-			String line = br.readLine();
-			while(line != null) {
-				sb.append(line);
-				line = br.readLine();
-			}
-			retVal = sb.toString();
-		}
-		catch(Exception e) {
-			WsLog.debug(cName, mName, e);
-		}
-		finally {
-			if(br != null) {
-				closer(br);
-			}
-			if(fr != null) {
-				closer(fr);
-			}
-			if(sr != null) {
-				closer(sr);
-			}
-		}
-		WsLog.exit(cName, mName);
-		return retVal;
-	}
+  private static DuccLogger cName = DuccLogger.getLogger(ExperimentsRegistryUtilities.class);
+
+  private static String stateFileName = "Experiment.state";
+
+  public static String upOne(String directory) {
+    String retVal = directory;
+    if (directory != null) {
+      retVal = new File(directory).getParent();
+    }
+    return retVal;
+  }
+
+  public static String getStateFilePath(String directory) {
+    String retVal = new File(directory, stateFileName).getAbsolutePath();
+    return retVal;
+  }
+
+  private static void closer(Closeable object) {
+    String mName = "closer";
+    try {
+      object.close();
+    } catch (Exception e) {
+      WsLog.debug(cName, mName, e);
+    }
+  }
+
+  public static long getFileDate(IExperiment experiment) {
+    String mName = "getFileDate";
+    WsLog.enter(cName, mName);
+    String user = experiment.getUser();
+    String filename = getStateFilePath(experiment.getDirectory());
+    long retVal = getFileDate(user, filename);
+    return retVal;
+  }
+
+  public static long getFileDate(String user, String filename) {
+    String mName = "getFileDate";
+    WsLog.enter(cName, mName);
+    long retVal = getDomesticFileDate(user, filename);
+    if (retVal == 0) {
+      retVal = getAlienFileDate(user, filename);
+    }
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
+
+  private static long getAlienFileDate(String user, String filename) {
+    String mName = "getAlienFileDate";
+    WsLog.enter(cName, mName);
+    long retVal = 0;
+    AlienFile alienFile = new AlienFile(user, filename);
+    // NOTE - should not need the "--" ... or this could be moved to AlienFile
+    String[] lines = alienFile.getResult(false, "--", "/bin/ls", "-l", "--time-style=+%s",
+            filename);
+    // Should have 1 line with secs-since-epoch in 6th token
+    if (lines.length == 1) {
+      String[] toks = lines[0].split("\\s+");
+      if (toks.length >= 6) {
+        retVal = Long.valueOf(toks[5]) * 1000;
+      }
+    }
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
+
+  private static long getDomesticFileDate(String user, String filename) {
+    String mName = "getDomesticFileDate";
+    WsLog.enter(cName, mName);
+    long retVal = 0;
+    try {
+      File file = new File(filename);
+      retVal = file.lastModified();
+    } catch (Exception e) {
+      WsLog.trace(cName, mName, e);
+    }
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
+
+  /*
+   * Returns null if file is missing or can't be read
+   */
+  public static String getFileContents(String user, String filename) {
+    String mName = "getFileContents";
+    WsLog.enter(cName, mName);
+    boolean canRead = ((new File(filename)).canRead());
+    String retVal = canRead ? getDomesticFileContents(user, filename)
+            : getAlienFileContents(user, filename);
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
+
+  private static String getAlienFileContents(String user, String filename) {
+    String mName = "getAlienFileContents";
+    WsLog.enter(cName, mName);
+    String retVal = null;
+    try {
+      AlienFile alienFile = new AlienFile(user, filename);
+      retVal = alienFile.getString();
+    } catch (Throwable t) {
+      WsLog.trace(cName, mName, t);
+    }
+
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
+
+  private static String getDomesticFileContents(String user, String filename) {
+    String mName = "getDomesticFileContents";
+    WsLog.enter(cName, mName);
+    String retVal = null;
+    FileReader fr = null;
+    BufferedReader br = null;
+    StringReader sr = null;
+    try {
+      fr = new FileReader(filename);
+      br = new BufferedReader(fr);
+      StringBuffer sb = new StringBuffer();
+      String line = br.readLine();
+      while (line != null) {
+        sb.append(line);
+        line = br.readLine();
+      }
+      retVal = sb.toString();
+    } catch (Exception e) {
+      WsLog.debug(cName, mName, e);
+    } finally {
+      if (br != null) {
+        closer(br);
+      }
+      if (fr != null) {
+        closer(fr);
+      }
+      if (sr != null) {
+        closer(sr);
+      }
+    }
+    WsLog.exit(cName, mName);
+    return retVal;
+  }
 
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
index f2bf0de..bc39bb5 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
@@ -21,18 +21,31 @@
 import java.util.ArrayList;
 
 public interface IExperiment extends Comparable<Object> {
-	public void setId(String value);
-	public String getId();
-	public String getUser();
-	public String getDirectory();
-	public ArrayList<Task> getTasks();
-	public ArrayList<String> getJobIds();
-	public String getStartDate();
-	public long getStartTime();
-	public boolean isActive();
-	public Jed.Status getStatus();
-	public void setFileDate(long value);
-	public long getFileDate();
-    public int getVersion();
-    public boolean isStale();
+  public void setId(String value);
+
+  public String getId();
+
+  public String getUser();
+
+  public String getDirectory();
+
+  public ArrayList<Task> getTasks();
+
+  public ArrayList<String> getJobIds();
+
+  public String getStartDate();
+
+  public long getStartTime();
+
+  public boolean isActive();
+
+  public Jed.Status getStatus();
+
+  public void setFileDate(long value);
+
+  public long getFileDate();
+
+  public int getVersion();
+
+  public boolean isStale();
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
index d44057a..4e750fb 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
@@ -20,122 +20,103 @@
 
 public class Jed {
 
-	public enum Type {
+  public enum Type {
 
-		DuccJob, Java, File, Exec, Trainer, Sequential, Parallel, ParallelData, SetPhase, Other;
+    DuccJob, Java, File, Exec, Trainer, Sequential, Parallel, ParallelData, SetPhase, Other;
 
-		private static String DUCC_JOB = "DUCC_JOB";
-		private static String PARALLEL_DATA = "PARALLEL_DATA";
-		private static String SET_PHASE = "SET_PHASE";
-		
-	    public static Type getEnum(String value) {
-	    	Type retVal = Other;
-	    	if(value == null) {
-	    	}
-	    	else if(DUCC_JOB.equalsIgnoreCase(value)) {
-	            retVal = DuccJob;
-	        }
-	        else if(PARALLEL_DATA.equalsIgnoreCase(value)) {
-	            retVal = ParallelData;
-	        }
-	        else if(SET_PHASE.equalsIgnoreCase(value)) {
-	            retVal = SetPhase;
-	        }
-	        else if(DuccJob.name().equalsIgnoreCase(value)) {
-	            retVal = DuccJob;
-	        }
-	        else if(Java.name().equalsIgnoreCase(value)) {
-	            retVal = Java;
-	        }
-	        else if(File.name().equalsIgnoreCase(value)) {
-	            retVal = File;
-	        }
-	        else if(Exec.name().equalsIgnoreCase(value)) {
-	            retVal = Exec;
-	        }
-	        else if(Trainer.name().equalsIgnoreCase(value)) {
-	            retVal =  Trainer;
-	        }
-	        else if(Sequential.name().equalsIgnoreCase(value)) {
-	            retVal = Sequential;
-	        }
-	        else if(ParallelData.name().equalsIgnoreCase(value)) {
-	            retVal = ParallelData;
-	        }
-	        else if(Parallel.name().equalsIgnoreCase(value)) {
-	            retVal = Parallel;
-	        }
-	        else if(SetPhase.name().equalsIgnoreCase(value)) {
-	            retVal = SetPhase;
-	        }
-	        return retVal;
-	    }
-	    
-	    public static boolean isLeaf(Type value) {
-	    	boolean retVal = true;
-	    	if(value != null) {
-	    		switch(value) {
-		    	case Parallel:
-		    	case ParallelData:
-		    	case Sequential:
-		    		retVal = false;
-		    		break;
-		    	default:
-		    		break;
-		    	}
-	    	}
-	    	return retVal;
-	    }
-	    
-	    public static boolean isLeaf(String value){
-	    	boolean retVal = isLeaf(getEnum(value));
-	    	return retVal;
-	    }
-	}
-	
-	public enum Status {
+    private static String DUCC_JOB = "DUCC_JOB";
 
-		Running, Completed, Done, Canceled, Failed, DependencyFailed, Ignored, Unknown, Other;
+    private static String PARALLEL_DATA = "PARALLEL_DATA";
 
-		private static String Dependency_Failed = "Dependency-Failed";
-		private static String Cancelled = "Cancelled";
-		
-	    public static Status getEnum(String value) {
-	    	Status retVal = Other;
-	    	if(value == null) {
-	    	}
-	    	else if(Cancelled.equalsIgnoreCase(value)) {
-	            retVal = Canceled;
-	        }
-	    	else if(Dependency_Failed.equalsIgnoreCase(value)) {
-	            retVal = DependencyFailed;
-	        }
-	        else if(Running.name().equalsIgnoreCase(value)) {
-	            retVal = Running;
-	        }
-	        else if(Completed.name().equalsIgnoreCase(value)) {
-	            retVal = Completed;
-	        }
-	        else if(Done.name().equalsIgnoreCase(value)) {
-	            retVal = Done;
-	        }
-	        else if(Canceled.name().equalsIgnoreCase(value)) {
-	            retVal = Canceled;
-	        }
-	        else if(Failed.name().equalsIgnoreCase(value)) {
-	            retVal = Failed;
-	        }
-	        else if(DependencyFailed.name().equalsIgnoreCase(value)) {
-	            retVal = DependencyFailed;
-	        }
-	        else if(Ignored.name().equalsIgnoreCase(value)) {
-	            retVal = Ignored;
-	        }
-	        else if(Unknown.name().equalsIgnoreCase(value)) {
-	            retVal = Unknown;
-	        }
-	        return retVal;
-	    }
-	}
+    private static String SET_PHASE = "SET_PHASE";
+
+    public static Type getEnum(String value) {
+      Type retVal = Other;
+      if (value == null) {
+      } else if (DUCC_JOB.equalsIgnoreCase(value)) {
+        retVal = DuccJob;
+      } else if (PARALLEL_DATA.equalsIgnoreCase(value)) {
+        retVal = ParallelData;
+      } else if (SET_PHASE.equalsIgnoreCase(value)) {
+        retVal = SetPhase;
+      } else if (DuccJob.name().equalsIgnoreCase(value)) {
+        retVal = DuccJob;
+      } else if (Java.name().equalsIgnoreCase(value)) {
+        retVal = Java;
+      } else if (File.name().equalsIgnoreCase(value)) {
+        retVal = File;
+      } else if (Exec.name().equalsIgnoreCase(value)) {
+        retVal = Exec;
+      } else if (Trainer.name().equalsIgnoreCase(value)) {
+        retVal = Trainer;
+      } else if (Sequential.name().equalsIgnoreCase(value)) {
+        retVal = Sequential;
+      } else if (ParallelData.name().equalsIgnoreCase(value)) {
+        retVal = ParallelData;
+      } else if (Parallel.name().equalsIgnoreCase(value)) {
+        retVal = Parallel;
+      } else if (SetPhase.name().equalsIgnoreCase(value)) {
+        retVal = SetPhase;
+      }
+      return retVal;
+    }
+
+    public static boolean isLeaf(Type value) {
+      boolean retVal = true;
+      if (value != null) {
+        switch (value) {
+          case Parallel:
+          case ParallelData:
+          case Sequential:
+            retVal = false;
+            break;
+          default:
+            break;
+        }
+      }
+      return retVal;
+    }
+
+    public static boolean isLeaf(String value) {
+      boolean retVal = isLeaf(getEnum(value));
+      return retVal;
+    }
+  }
+
+  public enum Status {
+
+    Running, Completed, Done, Canceled, Failed, DependencyFailed, Ignored, Unknown, Other;
+
+    private static String Dependency_Failed = "Dependency-Failed";
+
+    private static String Cancelled = "Cancelled";
+
+    public static Status getEnum(String value) {
+      Status retVal = Other;
+      if (value == null) {
+      } else if (Cancelled.equalsIgnoreCase(value)) {
+        retVal = Canceled;
+      } else if (Dependency_Failed.equalsIgnoreCase(value)) {
+        retVal = DependencyFailed;
+      } else if (Running.name().equalsIgnoreCase(value)) {
+        retVal = Running;
+      } else if (Completed.name().equalsIgnoreCase(value)) {
+        retVal = Completed;
+      } else if (Done.name().equalsIgnoreCase(value)) {
+        retVal = Done;
+      } else if (Canceled.name().equalsIgnoreCase(value)) {
+        retVal = Canceled;
+      } else if (Failed.name().equalsIgnoreCase(value)) {
+        retVal = Failed;
+      } else if (DependencyFailed.name().equalsIgnoreCase(value)) {
+        retVal = DependencyFailed;
+      } else if (Ignored.name().equalsIgnoreCase(value)) {
+        retVal = Ignored;
+      } else if (Unknown.name().equalsIgnoreCase(value)) {
+        retVal = Unknown;
+      }
+      return retVal;
+    }
+  }
 
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
index df7f5bb..18e1772 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
@@ -23,13 +23,21 @@
  * See com.ibm.bluej.system.driver/src/com/ibm/bluej/system/driver/TaskState.java 
  */
 public class Task {
-	  public int taskId = 0;
-    public int parentId = 0;
-    public String name = null;
-    public String type = null;
-    public String status = null;
-    public String startTime = null;
-    public long runTime = 0;
-    public int[] subTasks = new int[0];
-    public long[] duccId = new long[0];
+  public int taskId = 0;
+
+  public int parentId = 0;
+
+  public String name = null;
+
+  public String type = null;
+
+  public String status = null;
+
+  public String startTime = null;
+
+  public long runTime = 0;
+
+  public int[] subTasks = new int[0];
+
+  public long[] duccId = new long[0];
 }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/TaskArray.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/TaskArray.java
index 94f7e7a..f3e799d 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/TaskArray.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/TaskArray.java
@@ -21,5 +21,5 @@
 import java.util.ArrayList;
 
 public class TaskArray {
-	public ArrayList<Task> tasks = new ArrayList<Task>();
+  public ArrayList<Task> tasks = new ArrayList<Task>();
 }