private void checkTasks(JobInfo info) {
    if (keep(info)) {
      TaskInfo tinfo = info.getTaskInfo();
      if (tinfo != null) {
        JobTreeElement[] toBeRemoved = null;
        boolean fire = false;
        JobTreeElement element = (JobTreeElement) tinfo.getParent();
        synchronized (keptjobinfos) {
          if (element == info && !keptjobinfos.contains(tinfo)) {
            toBeRemoved = findJobsToRemove(element);
            keptjobinfos.add(tinfo);
            finishedTime.put(tinfo, new Long(System.currentTimeMillis()));
          }
        }

        if (toBeRemoved != null) {
          for (int i = 0; i < toBeRemoved.length; i++) {
            remove(toBeRemoved[i]);
          }
        }

        if (fire) {
          Object l[] = getListeners();
          for (int i = 0; i < l.length; i++) {
            KeptJobsListener jv = (KeptJobsListener) l[i];
            jv.finished(info);
          }
        }
      }
    }
  }
  /** Add given Job to list of kept jobs. */
  private void add(JobInfo info) {
    boolean fire = false;

    synchronized (keptjobinfos) {
      if (!keptjobinfos.contains(info)) {
        keptjobinfos.add(info);

        long now = System.currentTimeMillis();
        finishedTime.put(info, new Long(now));

        Object parent = info.getParent();
        if (parent != null && !keptjobinfos.contains(parent)) {
          keptjobinfos.add(parent);
          finishedTime.put(parent, new Long(now));
        }

        fire = true;
      }
    }

    if (fire) {
      Object l[] = getListeners();
      for (int i = 0; i < l.length; i++) {
        KeptJobsListener jv = (KeptJobsListener) l[i];
        jv.finished(info);
      }
    }
  }
  /** Clear all kept jobs. */
  public void clearAll() {
    synchronized (keptjobinfos) {
      JobTreeElement[] all =
          (JobTreeElement[]) keptjobinfos.toArray(new JobTreeElement[keptjobinfos.size()]);
      for (int i = 0; i < all.length; i++) {
        disposeAction(all[i]);
      }
      keptjobinfos.clear();
      finishedTime.clear();
    }

    // notify listeners
    Object l[] = getListeners();
    for (int i = 0; i < l.length; i++) {
      KeptJobsListener jv = (KeptJobsListener) l[i];
      jv.removed(null);
    }
  }
  boolean remove(JobTreeElement jte) {
    boolean fire = false;
    boolean removed = false;

    synchronized (keptjobinfos) {
      if (keptjobinfos.remove(jte)) {
        removed = true;
        finishedTime.remove(jte);
        disposeAction(jte);

        // delete all elements that have jte as their direct or indirect
        // parent
        JobTreeElement jtes[] =
            (JobTreeElement[]) keptjobinfos.toArray(new JobTreeElement[keptjobinfos.size()]);
        for (int i = 0; i < jtes.length; i++) {
          JobTreeElement parent = (JobTreeElement) jtes[i].getParent();
          if (parent != null) {
            if (parent == jte || parent.getParent() == jte) {
              if (keptjobinfos.remove(jtes[i])) {
                disposeAction(jtes[i]);
              }
              finishedTime.remove(jtes[i]);
            }
          }
        }
        fire = true;
      }
    }

    if (fire) {
      // notify listeners
      Object l[] = getListeners();
      for (int i = 0; i < l.length; i++) {
        KeptJobsListener jv = (KeptJobsListener) l[i];
        jv.removed(jte);
      }
    }
    return removed;
  }