diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 9559d83eb641..cf6d75137918 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -3,6 +3,7 @@ package com.jetbrains.python.sdk; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.OSProcessHandler; +import com.intellij.execution.process.ProcessOutput; import com.intellij.facet.Facet; import com.intellij.facet.FacetConfiguration; import com.intellij.facet.FacetManager; @@ -307,7 +308,7 @@ public class PythonSdkType extends SdkType { out.close(); } - return SdkUtil.getProcessOutput(sdk_path, new String[] {bin_path, scriptFile.getPath()}).getStdout(); + return SdkUtil.getProcessOutput(sdk_path, new String[] {bin_path, scriptFile.getPath()}).getStdoutLines(); } finally { FileUtil.delete(scriptFile); @@ -333,7 +334,7 @@ public class PythonSdkType extends SdkType { version_opt = "-V"; } Pattern pattern = Pattern.compile(version_regexp); - String version = SdkUtil.getFirstMatch(SdkUtil.getProcessOutput(sdkHome, new String[] {binaryPath, version_opt}).getStderr(), pattern); + String version = SdkUtil.getFirstMatch(SdkUtil.getProcessOutput(sdkHome, new String[] {binaryPath, version_opt}).getStderrLines(), pattern); return version; } @@ -409,10 +410,10 @@ public class PythonSdkType extends SdkType { out.close(); try { - final SdkUtil.ProcessCallInfo run_result = SdkUtil.getProcessOutput(sdkPath, new String[] {bin_path, find_bin_file.getPath()}); + final ProcessOutput run_result = SdkUtil.getProcessOutput(sdkPath, new String[] {bin_path, find_bin_file.getPath()}); - if (run_result.getExitValue() == 0) { - for (String line : run_result.getStdout()) { + if (run_result.getExitCode() == 0) { + for (String line : run_result.getStdoutLines()) { // line = "mod_name path" int cutpos = line.indexOf(' '); String modname = line.substring(0, cutpos); @@ -428,13 +429,13 @@ public class PythonSdkType extends SdkType { indicator.setText2(modname); } LOG.info("Skeleton for " + modname); - final SdkUtil.ProcessCallInfo gen_result = SdkUtil.getProcessOutput(sdkPath, + final ProcessOutput gen_result = SdkUtil.getProcessOutput(sdkPath, new String[] {bin_path, gen3_file.getPath(), "-d", stubsRoot, modname}, RUN_TIMEOUT ); - if (gen_result.getExitValue() != 0) { + if (gen_result.getExitCode() != 0) { StringBuffer sb = new StringBuffer("Skeleton for "); sb.append(modname).append(" failed. stderr: --"); - for (String err_line : gen_result.getStderr()) sb.append(err_line).append("\n"); + for (String err_line : gen_result.getStderrLines()) sb.append(err_line).append("\n"); sb.append("--"); LOG.warn(sb.toString()); } @@ -443,8 +444,8 @@ public class PythonSdkType extends SdkType { } else { StringBuffer sb = new StringBuffer(); - for (String err_line : run_result.getStderr()) sb.append(err_line).append("\n"); - LOG.error("failed to run find_binaries, exit code " + run_result.getExitValue() + ", stderr '" + sb.toString() + "'"); + for (String err_line : run_result.getStderrLines()) sb.append(err_line).append("\n"); + LOG.error("failed to run find_binaries, exit code " + run_result.getExitCode() + ", stderr '" + sb.toString() + "'"); } } finally { diff --git a/python/src/com/jetbrains/python/sdk/SdkUtil.java b/python/src/com/jetbrains/python/sdk/SdkUtil.java index 6cf7f98d7996..e63898fc7018 100644 --- a/python/src/com/jetbrains/python/sdk/SdkUtil.java +++ b/python/src/com/jetbrains/python/sdk/SdkUtil.java @@ -1,17 +1,15 @@ package com.jetbrains.python.sdk; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.execution.process.CapturingProcessHandler; +import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.*; -import java.util.ArrayList; +import java.io.File; +import java.io.IOException; import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -25,41 +23,10 @@ import java.util.regex.Pattern; public class SdkUtil { protected static final Logger LOG = Logger.getInstance("#com.jetbrains.python.sdk.SdkVersionUtil"); - private static final List NO_LINES = new ArrayList(); - private SdkUtil() { // explicitly none } - /** - * A holder for stdout and stderr lines of a finished process. - */ - public static class ProcessCallInfo { - private final List myStdoutLines; - private final List myStderrLines; - private final int myExitCode; - - public static final int TIMEOUT_CODE = -32768; - - protected ProcessCallInfo(List stdout_lines, List stderr_lines, int exit_code) { - myStdoutLines = stdout_lines; - myStderrLines = stderr_lines; - myExitCode = exit_code; - } - - public List getStdout() { - return myStdoutLines; - } - - public List getStderr() { - return myStderrLines; - } - - public int getExitValue() { - return myExitCode; - } - } - /** * Executes a process and returns its stdout and stderr outputs as lists of lines. * @param homePath process run directory @@ -67,7 +34,7 @@ public class SdkUtil { * @return a tuple of (stdout lines, stderr lines, exit_code), lines in them have line terminators stripped, or may be null. */ @NotNull - public static ProcessCallInfo getProcessOutput(String homePath, @NonNls String[] command) { + public static ProcessOutput getProcessOutput(String homePath, @NonNls String[] command) { return getProcessOutput(homePath, command, -1); } @@ -81,110 +48,22 @@ public class SdkUtil { * the process timed out, exit code is ProcessCallInfo.TIMEOUT_CODE. */ @NotNull - public static ProcessCallInfo getProcessOutput(String homePath, @NonNls String[] command, final int timeout) { + public static ProcessOutput getProcessOutput(String homePath, @NonNls String[] command, final int timeout) { if (homePath == null || !new File(homePath).exists()) { - return new ProcessCallInfo(null, null, -1); + return new ProcessOutput(); } - List stdout = NO_LINES; - List stderr = NO_LINES; - int exit_code = -1; try { //noinspection HardCodedStringLiteral - Application app = ApplicationManager.getApplication(); - Process process = Runtime.getRuntime().exec(command); - - ReadLinesThread stdout_thread = new ReadLinesThread(process.getInputStream()); - final Future stdout_future = app.executeOnPooledThread(stdout_thread); - - ReadLinesThread stderr_thread = new ReadLinesThread(process.getErrorStream()); - final Future stderr_future = app.executeOnPooledThread(stderr_thread); - - final AtomicBoolean done = new AtomicBoolean(false); - final AtomicBoolean timed_out = new AtomicBoolean(false); - - if (timeout > 0) { - final Thread worker = Thread.currentThread(); - Runnable watchdog = new Runnable() { - public void run() { - try { - Thread.sleep(timeout); - if (! done.get()) { - timed_out.set(true); - worker.interrupt(); - } - } - catch (InterruptedException ignore) { } - } - }; - app.executeOnPooledThread(watchdog); - } - - try { - try { - process.waitFor(); - } - catch (InterruptedException e) { - if (! timed_out.get()) { - LOG.info(e); - } - process.destroy(); - } - } - finally { - done.set(true); - try { - stdout_future.get(); - stderr_future.get(); - stdout = stdout_thread.getResult(); - stderr = stderr_thread.getResult(); - if (timed_out.get()){ - exit_code = ProcessCallInfo.TIMEOUT_CODE; - } - else { - exit_code = process.exitValue(); - } - } - catch (Exception e) { - LOG.info(e); - } - } + Process process = Runtime.getRuntime().exec(command, null, new File(homePath)); + CapturingProcessHandler processHandler = new CapturingProcessHandler(process); + return processHandler.runProcess(timeout); } catch (IOException ex) { LOG.info(ex); + return new ProcessOutput(); } - return new ProcessCallInfo(stdout, stderr, exit_code); } - public static class ReadLinesThread implements Runnable { - private final InputStream myStream; - private final List my_lines = new ArrayList(); - - protected ReadLinesThread(InputStream stream) { - myStream = stream; - } - - public void run() { - BufferedReader reader = new BufferedReader(new InputStreamReader(myStream)); // NOTE: [dch] I wonder if it needs closing - try { - while (true) { - String s = reader.readLine(); - if (s == null) break; - my_lines.add(s); - } - reader.close(); - } - catch (IOException e) { - LOG.info(e); - } - } - - @NotNull - public List getResult() { - return my_lines; - } - - } - /** * Finds the first match in a list os Strings. * @param lines list of lines, may be null.