/**
   * This starts a websocket connection with pub and if successful, sends a "assetIdToUrl" command
   * to pub to get the url to launch for the resource that was specifed in the launch configuration
   *
   * @param pubCallback - users should pass in a method to process the response for the
   *     "assetIdToUrl" command
   * @return true if the websocket connection was established and the command sent
   */
  public boolean connectToPub(PubCallback<String> pubCallback) {

    if (pubConnection != null && pubConnection.isConnected()) {
      return sendGetUrlCommand(pubCallback);
    } else {

      try {
        pubConnection =
            new PubConnection(new URI(NLS.bind(WEBSOCKET_URL, LOCAL_HOST_ADDR, PORT_NUMBER)));

        pubConnection.addConnectionListener(
            new PubConnectionListener() {
              @Override
              public void connectionClosed(PubConnection connection) {
                pubConnection = null;
              }
            });

        pubConnection.connect();

        return sendGetUrlCommand(pubCallback);

      } catch (URISyntaxException e) {
        DartDebugCorePlugin.logError(e);
        return false;
      } catch (IOException e) {
        DartDebugCorePlugin.logError(e);
        return false;
      }
    }
  }
  /**
   * 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 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;
  }
 /**
  * Send a serve directory command to the current pub serve
  *
  * @param resource
  * @return
  */
 private boolean serveDirectory(IResource resource) {
   CountDownLatch latch = new CountDownLatch(1);
   final boolean[] done = new boolean[1];
   done[0] = false;
   try {
     pubConnection
         .getCommands()
         .serveDirectory(
             getPubserveRootDir(workingDir, resource), new ServeDirectoryCallback(latch, done));
   } catch (IOException e) {
     DartCore.logError(e);
   }
   try {
     latch.await(3000, TimeUnit.MILLISECONDS);
   } catch (InterruptedException e) {
     // do nothing
   }
   return done[0];
 }
  public void dispose() {
    // TODO(keertip): stop pub serve first when api available
    if (pubConnection != null) {
      try {
        pubConnection.close();
      } catch (IOException e) {
        DartDebugCorePlugin.logError(e);
      } finally {
        pubConnection = null;
      }
    }
    if (process != null) {
      try {
        process.destroy();
      } catch (Exception e) {

      } finally {
        process = null;
      }
    }
  }