@SuppressWarnings("deprecation")
  protected void beforeStart(Map flags, Task<?> task) {
    activeTaskCount.incrementAndGet();

    // set thread _before_ start time, so we won't get a null thread when there is a start-time
    if (log.isTraceEnabled()) log.trace("" + this + " beforeStart, task: " + task);
    if (!task.isCancelled()) {
      ((BasicTask) task).thread = Thread.currentThread();
      if (RENAME_THREADS) {
        String newThreadName =
            "brooklyn-"
                + CaseFormat.LOWER_HYPHEN.to(
                    CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", ""))
                + "-"
                + task.getId().substring(0, 8);
        ((BasicTask) task).thread.setName(newThreadName);
      }
      PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task);
      ((BasicTask) task).startTimeUtc = System.currentTimeMillis();
    }
    for (Object to : (Collection) flags.get("tagLinkedPreprocessors")) {
      TaskPreprocessor t = (TaskPreprocessor) to;
      t.onStart(flags, task);
    }
    ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task);
  }
 protected boolean deleteTaskNonRecursive(Task<?> task) {
   Set<?> tags = checkNotNull(task, "task").getTags();
   for (Object tag : tags) {
     Set<Task<?>> tasks = getMutableTasksWithTagOrNull(tag);
     if (tasks != null) tasks.remove(task);
   }
   Task<?> removed = tasksById.remove(task.getId());
   return removed != null;
 }
  protected void beforeStart(Map<?, ?> flags, Task<?> task) {
    activeTaskCount.incrementAndGet();

    // set thread _before_ start time, so we won't get a null thread when there is a start-time
    if (log.isTraceEnabled()) log.trace("" + this + " beforeStart, task: " + task);
    if (!task.isCancelled()) {
      ((TaskInternal<?>) task).setThread(Thread.currentThread());
      if (RENAME_THREADS) {
        String newThreadName =
            "brooklyn-"
                + CaseFormat.LOWER_HYPHEN.to(
                    CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", ""))
                + "-"
                + task.getId().substring(0, 8);
        task.getThread().setName(newThreadName);
      }
      PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task);
      ((TaskInternal<?>) task).setStartTimeUtc(System.currentTimeMillis());
    }
    ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task);
  }
  @SuppressWarnings("unchecked")
  protected <T> Task<T> submitNewTask(final Map<?, ?> flags, final Task<T> task) {
    if (task instanceof ScheduledTask)
      return (Task<T>) submitNewScheduledTask(flags, (ScheduledTask) task);

    tasksById.put(task.getId(), task);
    totalTaskCount.incrementAndGet();

    beforeSubmit(flags, task);

    if (((TaskInternal<T>) task).getJob() == null)
      throw new NullPointerException(
          "Task " + task + " submitted with with null job: job must be supplied.");

    Callable<T> job =
        new Callable<T>() {
          public T call() {
            try {
              T result = null;
              Throwable error = null;
              String oldThreadName = Thread.currentThread().getName();
              try {
                if (RENAME_THREADS) {
                  String newThreadName =
                      oldThreadName
                          + "-"
                          + task.getDisplayName()
                          + "["
                          + task.getId().substring(0, 8)
                          + "]";
                  Thread.currentThread().setName(newThreadName);
                }
                beforeStart(flags, task);
                if (!task.isCancelled()) {
                  result = ((TaskInternal<T>) task).getJob().call();
                } else throw new CancellationException();
              } catch (Throwable e) {
                error = e;
              } finally {
                if (RENAME_THREADS) {
                  Thread.currentThread().setName(oldThreadName);
                }
                afterEnd(flags, task);
              }
              if (error != null) {
                if (log.isDebugEnabled()) {
                  // debug only here, because we rethrow
                  log.debug(
                      "Exception running task " + task + " (rethrowing): " + error.getMessage(),
                      error);
                  if (log.isTraceEnabled())
                    log.trace(
                        "Trace for exception running task "
                            + task
                            + " (rethrowing): "
                            + error.getMessage(),
                        error);
                }
                throw Exceptions.propagate(error);
              }
              return result;
            } finally {
              ((TaskInternal<?>) task).runListeners();
            }
          }
        };

    // If there's a scheduler then use that; otherwise execute it directly
    Set<TaskScheduler> schedulers = null;
    for (Object tago : task.getTags()) {
      TaskScheduler scheduler = getTaskSchedulerForTag(tago);
      if (scheduler != null) {
        if (schedulers == null) schedulers = new LinkedHashSet<TaskScheduler>(2);
        schedulers.add(scheduler);
      }
    }
    Future<T> future;
    if (schedulers != null && !schedulers.isEmpty()) {
      if (schedulers.size() > 1)
        log.warn(
            "multiple schedulers detected, using only the first, for " + task + ": " + schedulers);
      future = schedulers.iterator().next().submit(job);
    } else {
      future = runner.submit(job);
    }
    // on completion, listeners get triggered above; here, below we ensure they get triggered on
    // cancel
    // (and we make sure the same ExecutionList is used in the future as in the task)
    ListenableFuture<T> listenableFuture =
        new ListenableForwardingFuture<T>(future, ((TaskInternal<T>) task).getListeners()) {
          @Override
          public boolean cancel(boolean mayInterruptIfRunning) {
            boolean result = false;
            if (!task.isCancelled()) result |= task.cancel(mayInterruptIfRunning);
            result |= super.cancel(mayInterruptIfRunning);
            ((TaskInternal<?>) task).runListeners();
            return result;
          }
        };

    ((TaskInternal<T>) task).initResult(listenableFuture);
    return task;
  }