protected void setEnvironmentVariable(
      CloudFoundryApplicationModule appModule,
      CloudFoundryServer cloudServer,
      int remoteDebugPort,
      IProgressMonitor monitor)
      throws CoreException {

    ApplicationDeploymentInfo info = appModule.getDeploymentInfo();
    List<EnvironmentVariable> vars = info.getEnvVariables();
    EnvironmentVariable javaOpts = getDebugEnvironment(info);

    IModule[] mod = new IModule[] {appModule.getLocalModule()};

    boolean restart = CloudFoundryProperties.isModuleStopped.testProperty(mod, cloudServer);

    if (!containsDebugOption(javaOpts)) {

      if (javaOpts == null) {
        javaOpts = new EnvironmentVariable();
        javaOpts.setVariable(JAVA_OPTS);
        vars.add(javaOpts);
      }

      String debugOpts =
          "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address="
              + remoteDebugPort //$NON-NLS-1$
              + ",suspend=n"; //$NON-NLS-1$
      javaOpts.setValue(debugOpts);

      cloudServer
          .getBehaviour()
          .operations()
          .environmentVariablesUpdate(
              appModule.getLocalModule(), appModule.getDeployedApplicationName(), vars)
          .run(monitor);

      restart = true;
    }

    if (restart) {
      printToConsole(
          appModule,
          cloudServer,
          NLS.bind(
              Messages.SshDebugLaunchConfigDelegate_RESTARTING_APP,
              appModule.getDeployedApplicationName()),
          false);

      cloudServer
          .getBehaviour()
          .operations()
          .applicationDeployment(mod, ApplicationAction.START, false)
          .run(monitor);
    }
  }
  /**
   * Returns non-null Cloud application module mapped to the first module in the list of modules. If
   * the cloud module module does not exist for the given module, it will attempt to create it. To
   * avoid re-creating a cloud application module that may have been deleted, restrict invoking this
   * method to only operations that start, restart, or update an application. Should not be called
   * when deleting an application.
   *
   * @param local WST modules representing app to be deployed.
   * @return non-null Cloud Application module mapped to the given WST module.
   * @throws CoreException if no modules specified or mapped cloud application module cannot be
   *     resolved.
   */
  protected CloudFoundryApplicationModule getOrCreateCloudApplicationModule(IModule[] modules)
      throws CoreException {

    IModule module = modules[0];

    CloudFoundryServer cloudServer = getBehaviour().getCloudFoundryServer();

    CloudFoundryApplicationModule appModule = cloudServer.getCloudModule(module);

    if (appModule == null) {
      throw CloudErrorUtil.toCoreException(
          NLS.bind(INTERNAL_ERROR_NO_MAPPED_CLOUD_MODULE, modules[0].getId()));
    }

    return appModule;
  }
  @Override
  public void run(IProgressMonitor monitor) throws CoreException {

    try {
      doApplicationOperation(monitor);
      getBehaviour().getRefreshHandler().scheduleRefreshForDeploymentChange(getModule());
    } catch (OperationCanceledException e) {
      // ignore so webtools does not show an exception
      ((Server) getBehaviour().getServer()).setModuleState(getModules(), IServer.STATE_UNKNOWN);

      // If application operations, like Restart, Start, or
      // PushApplication are canceled, then the publish state is
      // 'indeterminate'
      // TODO: Don't reference internal Server class. We need to revisit
      // this change and revert back to the original state.
      ((Server) getBehaviour().getServer())
          .setServerPublishState(IServer.PUBLISH_STATE_INCREMENTAL);
      ((Server) getBehaviour().getServer())
          .setModulePublishState(modules, IServer.PUBLISH_STATE_INCREMENTAL);

      // Record the canceled operation 'description' to the log file.
      CloudFoundryPlugin.logWarning(e.getMessage());

      CloudFoundryServer cloudServer = getBehaviour().getCloudFoundryServer();

      CloudFoundryApplicationModule appModule = cloudServer.getCloudModule(getModule());
      if (appModule != null && e.getMessage() != null) {
        CloudFoundryPlugin.getCallback()
            .printToConsole(
                cloudServer,
                appModule,
                NLS.bind(
                        Messages.AbstractPublishApplicationOperation_OPERATION_CANCELED,
                        e.getMessage())
                    + '\n',
                false,
                false);
      }
    }
  }
  public CloudSpacesSelectionPart(
      CloudSpacesDelegate cloudSpaceServerDelegate,
      CloudFoundryServer cloudServer,
      IWizardHandle wizardHandle) {
    this.cloudSpaceServerDelegate = cloudSpaceServerDelegate;

    String serverTypeId = cloudServer.getServer().getServerType().getId();

    wizardHandle.setTitle(Messages.CloudSpacesSelectionPart_TEXT_ORG_AND_SPACE);
    wizardHandle.setDescription(DEFAULT_DESCRIPTION);
    ImageDescriptor banner = CloudFoundryImages.getWizardBanner(serverTypeId);
    if (banner != null) {
      wizardHandle.setImageDescriptor(banner);
    }
  }
  protected DebugConnectionDescriptor getSshConnectionDescriptor(
      CloudFoundryApplicationModule appModule,
      CloudFoundryServer cloudServer,
      int appInstance,
      int remoteDebugPort,
      IProgressMonitor monitor)
      throws CoreException {

    CFInfo cloudInfo = cloudServer.getBehaviour().getCloudInfo();
    if (cloudInfo instanceof CloudInfoSsh) {
      ISshClientSupport ssh = cloudServer.getBehaviour().getSshClientSupport(monitor);
      if (ssh == null) {
        return null;
      }
      try {
        printToConsole(
            appModule,
            cloudServer,
            NLS.bind(
                Messages.SshDebugLaunchConfigDelegate_CONNECTING_FOR_USER,
                appModule.getDeployedApplicationName()),
            false);

        Session session =
            ssh.connect(
                appModule.getDeployedApplicationName(),
                appInstance,
                cloudServer.getServer(),
                monitor);

        printToConsole(
            appModule,
            cloudServer,
            NLS.bind(
                Messages.SshDebugLaunchConfigDelegate_CONNECTION_SUCCESSFUL,
                appModule.getDeployedApplicationName()),
            false);

        int localDebuggerPort =
            session.setPortForwardingL(0, "localhost", remoteDebugPort); // $NON-NLS-1$

        printToConsole(
            appModule,
            cloudServer,
            NLS.bind(
                Messages.SshDebugLaunchConfigDelegate_PORT_FORWARDING_SUCCESSFUL,
                remoteDebugPort,
                localDebuggerPort),
            false);

        return new DebugConnectionDescriptor("localhost", localDebuggerPort); // $NON-NLS-1$

      } catch (JSchException e) {
        throw CloudErrorUtil.toCoreException(
            "SSH connection error " + e.getMessage()); // $NON-NLS-1$
      }
    } else {
      throw CloudErrorUtil.toCoreException(
          "Unable to resolve SSH connection information from the Cloud Foundry target. Please ensure SSH is supported."); //$NON-NLS-1$
    }
  }