/** Default stop will stop all Startable children */
  public void stop() {
    log.info("Stopping application " + this);

    setAttribute(SERVICE_UP, false);
    setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPING);
    try {
      StartableMethods.stop(this);
    } catch (Exception e) {
      setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
      log.warn("Error stopping application " + this + " (rethrowing): " + e);
      throw Exceptions.propagate(e);
    }
    setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPED);

    synchronized (this) {
      deployed = false;
      // TODO review mgmt destroy lifecycle
      //  we don't necessarily want to forget all about the app on stop,
      // since operator may be interested in things recently stopped;
      // but that could be handled by the impl at management
      // (keeping recently unmanaged things)
      //  however unmanaging must be done last, _after_ we stop children and set attributes
      getEntityManager().unmanage(this);
    }

    log.info("Stopped application " + this);
  }
  /**
   * Default start will start all Startable children (child.start(Collection<? extends Location>)),
   * calling preStart(locations) first and postStart(locations) afterwards.
   */
  public void start(Collection<? extends Location> locations) {
    this.addLocations(locations);

    setAttribute(Attributes.SERVICE_STATE, Lifecycle.STARTING);
    try {
      preStart(locations);
      StartableMethods.start(this, locations);
      postStart(locations);
    } catch (Exception e) {
      setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
      log.warn("Error starting application " + this + " (rethrowing): " + e);
      throw Exceptions.propagate(e);
    }

    setAttribute(SERVICE_UP, true);
    setAttribute(Attributes.SERVICE_STATE, Lifecycle.RUNNING);
    deployed = true;

    log.info("Started application " + this);
  }