/**
   * Starts pub serve for a given launch configuration. Checks if the current pub serve is for the
   * same pubspec.yaml, if not then starts up pub serve.
   *
   * @param wrapper - the launch config wrapper
   * @return - true if pub serve starts
   */
  public boolean startPubServe(DartLaunchConfigWrapper wrapper) {

    // TODO(keertip): output to process console
    console = DartCore.getConsole();

    if (currentLaunch != null) {
      IResource resource = currentLaunch.getApplicationResource();
      if (resource != null) {
        // check if previous launch and new launch share the same pubspec. If so, and pub serve is
        // running, then current pub serve can be used.
        IContainer appDir = DartCore.getApplicationDirectory(resource);
        if (appDir.equals(DartCore.getApplicationDirectory(wrapper.getApplicationResource()))) {
          // TODO(keertip): make this separate checks so that new connection can be started without
          // starting new process
          if (process != null
              && !isTerminated()
              && pubConnection != null
              && pubConnection.isConnected()) {
            console.printSeparator("Starting pub serve : " + resource.getProject().getName());
            // make sure pub is serving the directory, send serve directory command
            boolean isServed = serveDirectory(wrapper.getApplicationResource());
            if (isServed) {
              currentLaunch = wrapper;
              return true;
            }
          }
        }
      }
    }

    // terminate existing pub serve if any
    dispose();
    return runPubServe(wrapper);
  }
  private boolean runPubServe(DartLaunchConfigWrapper wrapper) {

    stdOut = new StringBuilder();
    stdError = new StringBuilder();
    IResource resource = wrapper.getApplicationResource();
    console.printSeparator("Starting pub serve : " + resource.getProject().getName());

    workingDir = DartCore.getApplicationDirectory(resource);

    List<String> args = buildPubServeCommand();
    String dirName = getPubserveRootDir(workingDir, resource);
    if (dirName != null) {
      args.add(getPubserveRootDir(workingDir, resource));
    }
    ProcessBuilder builder = new ProcessBuilder();
    builder.command(args);

    builder.directory(workingDir.getLocation().toFile());

    try {
      process = builder.start();
    } catch (IOException e) {
      DartCore.logError(e);
      return false;
    }

    Thread stdoutThread =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                copyStream(process.getInputStream(), stdOut, true);
              }
            });
    stdoutThread.start();

    Thread stderrThread =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                copyStream(process.getErrorStream(), stdError, true);
              }
            });
    stderrThread.start();

    while (!isTerminated() && !stdOut.toString().contains(LOCAL_HOST_ADDR)) {
      try {
        Thread.sleep(200);
      } catch (Exception exception) {

      }
    }

    if (isTerminated()) {
      return false;
    }
    currentLaunch = wrapper;
    return true;
  }
  private boolean sendGetUrlCommand(PubCallback<String> callback) {

    PubCommands command = pubConnection.getCommands();
    try {
      command.pathToUrl(getPathFromWorkingDir(currentLaunch.getApplicationResource()), callback);
    } catch (IOException e) {
      DartDebugCorePlugin.logError(e);
      return false;
    }
    return true;
  }