/**
   * Create a command line for launching.
   *
   * @param actualRun if true it'll make the variable substitution and start the listen connector in
   *     the case of a debug session.
   * @return command line ready to be exec'd
   * @throws CoreException
   * @throws JDTNotAvailableException
   */
  public String[] getCommandLine(boolean actualRun) throws CoreException, JDTNotAvailableException {
    List<String> cmdArgs = new ArrayList<String>();

    if (isJython()) {
      // "java.exe" -classpath "C:\bin\jython21\jython.jar" org.python.util.jython script %ARGS%
      String javaLoc = JavaVmLocationFinder.findDefaultJavaExecutable().getAbsolutePath();
      if (!InterpreterInfo.isJythonExecutable(interpreter.toOSString())) {
        throw new RuntimeException(
            "The jython jar must be specified as the interpreter to run. Found: " + interpreter);
      }
      cmdArgs.add(javaLoc);

      // some nice things on the classpath config: http://mindprod.com/jgloss/classpath.html
      cmdArgs.add("-classpath");
      String cpath;

      // TODO: add some option in the project so that the user can choose to use the
      // classpath specified in the java project instead of the pythonpath itself

      //            if (project.getNature(Constants.JAVA_NATURE) != null){
      //                cpath  = getClasspath(JavaCore.create(project));
      //            } else {
      cpath = interpreter + SimpleRunner.getPythonPathSeparator() + pythonpathUsed;
      //            }
      cmdArgs.add(cpath);
      cmdArgs.add(
          "-Dpython.path="
              + pythonpathUsed); // will be added to the env variables in the run (check if this
      // works on all platforms...)

      addVmArgs(cmdArgs);

      if (isDebug) {
        // This was removed because it cannot be used. See:
        // http://bugs.jython.org/issue1438
        // cmdArgs.add("-Dpython.security.respectJavaAccessibility=false");

        cmdArgs.add("org.python.util.jython");
        addDebugArgs(cmdArgs, "jython", actualRun);
      } else {
        cmdArgs.add("org.python.util.jython");
      }

    } else {
      // python or iron python

      cmdArgs.add(interpreter.toOSString());
      // Next option is for unbuffered stdout, otherwise Eclipse will not see any output until done
      cmdArgs.add("-u");

      addVmArgs(cmdArgs);
      if (isDebug && isIronpython()) {
        addIronPythonDebugVmArgs(cmdArgs);
      }

      addDebugArgs(cmdArgs, "python", actualRun);
    }

    // Check if we should do code-coverage...
    boolean coverageRun = PyCoveragePreferences.getAllRunsDoCoverage();
    if (coverageRun && isDebug) {
      if (actualRun) {
        RunInUiThread.async(
            new Runnable() {

              public void run() {
                PyDialogHelpers.openWarning(
                    "Conflicting options: coverage with debug.",
                    "Making a debug run with coverage enabled will not yield the expected results.\n\n"
                        + "They'll conflict because both use the python tracing facility (i.e.: sys.settrace()).\n"
                        + "\n"
                        + "To debug a coverage run, do a regular run and use the remote debugger "
                        + "(but note that the coverage will stop when it's enabled).\n"
                        + "\n"
                        + "Note: the run will be continued anyways.");
              }
            });
      }
    }

    if (isUnittest()) {
      cmdArgs.add(getRunFilesScript());
    } else {
      if (coverageRun) {
        // Separate support (unittest has the coverage support builtin).
        cmdArgs.add(getCoverageScript());
        cmdArgs.add(PyCoverage.getCoverageFileLocation().getAbsolutePath());
        cmdArgs.add("run");
        cmdArgs.add("--source");
        cmdArgs.add(PyCodeCoverageView.getChosenDir().getLocation().toOSString());
      }
    }

    for (IPath p : resource) {
      cmdArgs.add(p.toOSString());
    }

    if (!isUnittest()) {
      // The program arguments are not used when running a unittest (excluded from the tab group in
      // favor
      // of a way to overriding the default unittest arguments).
      String runArguments[] = null;
      if (actualRun && arguments != null) {
        String expanded =
            getStringSubstitution(PythonNature.getPythonNature(project))
                .performStringSubstitution(arguments);
        runArguments = parseStringIntoList(expanded);
      }

      for (int i = 0; runArguments != null && i < runArguments.length; i++) {
        cmdArgs.add(runArguments[i]);
      }

    } else {
      // Last thing (first the files and last the special parameters the user passed -- i.e.: nose
      // parameters)
      addUnittestArgs(cmdArgs, actualRun, coverageRun);
    }

    String[] retVal = new String[cmdArgs.size()];
    cmdArgs.toArray(retVal);

    if (actualRun) {
      CreatedCommandLineParams createdCommandLineParams =
          new CreatedCommandLineParams(retVal, coverageRun);
      // Provide a way for clients to alter the command line.
      List<Object> participants =
          ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_COMMAND_LINE_PARTICIPANT);
      for (Object object : participants) {
        try {
          IPyCommandLineParticipant c = (IPyCommandLineParticipant) object;
          createdCommandLineParams = c.updateCommandLine(createdCommandLineParams);
        } catch (Exception e) {
          Log.log(e);
        }
      }

      retVal = createdCommandLineParams.cmdLine;
      PythonRunnerCallbacks.onCreatedCommandLine.call(createdCommandLineParams);
    }

    return retVal;
  }
  public void testInterpreterInfoBuilder() throws Exception {
    Collection<String> pythonpath = new ArrayList<String>();
    pythonpath.add(libDir.toString());

    final InterpreterInfo info = new InterpreterInfo("2.6", TestDependent.PYTHON_EXE, pythonpath);

    IPreferenceStore preferences = new PreferenceStore();
    final PythonInterpreterManager manager = new PythonInterpreterManager(preferences);
    PydevPlugin.setPythonInterpreterManager(manager);
    manager.setInfos(new IInterpreterInfo[] {info}, new HashSet<String>(), null);

    final AdditionalSystemInterpreterInfo additionalInfo =
        new AdditionalSystemInterpreterInfo(manager, info.getExecutableOrJar());
    AdditionalSystemInterpreterInfo.setAdditionalSystemInfo(
        manager, info.getExecutableOrJar(), additionalInfo);

    // Don't load it (otherwise it'll get the 'proper' info).
    // AdditionalSystemInterpreterInfo.loadAdditionalSystemInfo(manager, info.getExecutableOrJar());

    final ISystemModulesManager modulesManager = info.getModulesManager();
    assertEquals(0, modulesManager.getSize(false));
    assertEquals(0, additionalInfo.getAllTokens().size());

    InterpreterInfoBuilder builder = new InterpreterInfoBuilder();
    builder.setInfo(info, 0);

    waitUntilCondition(
        new ICallback<String, Object>() {

          public String call(Object arg) {
            int size = modulesManager.getSize(false);
            if (size == 3) {
              return null;
            }
            return "Expected size = 3, found: " + size;
          }
        });

    waitUntilCondition(
        new ICallback<String, Object>() {

          public String call(Object arg) {
            try {
              AbstractAdditionalDependencyInfo additionalSystemInfo =
                  AdditionalSystemInterpreterInfo.getAdditionalSystemInfo(
                      manager, manager.getInterpreterInfos()[0].getExecutableOrJar());
              if (additionalInfo != additionalSystemInfo) {
                throw new RuntimeException("Expecting it to be the same instance.");
              }
            } catch (MisconfigurationException e) {
              throw new RuntimeException(e);
            }

            Collection<IInfo> allTokens = additionalInfo.getAllTokens();
            int size = allTokens.size();
            if (size == 3) {
              return null;
            }

            FastStringBuffer buf = new FastStringBuffer();
            for (IInfo i : allTokens) {
              buf.append(i.toString());
            }
            return "Expected size = 3, found: " + size + "\nTokens: " + buf;
          }
        });
  }