mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
use unified implementation of capturing stdout and stderr
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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<String> NO_LINES = new ArrayList<String>();
|
||||
|
||||
private SdkUtil() {
|
||||
// explicitly none
|
||||
}
|
||||
|
||||
/**
|
||||
* A holder for stdout and stderr lines of a finished process.
|
||||
*/
|
||||
public static class ProcessCallInfo {
|
||||
private final List<String> myStdoutLines;
|
||||
private final List<String> myStderrLines;
|
||||
private final int myExitCode;
|
||||
|
||||
public static final int TIMEOUT_CODE = -32768;
|
||||
|
||||
protected ProcessCallInfo(List<String> stdout_lines, List<String> stderr_lines, int exit_code) {
|
||||
myStdoutLines = stdout_lines;
|
||||
myStderrLines = stderr_lines;
|
||||
myExitCode = exit_code;
|
||||
}
|
||||
|
||||
public List<String> getStdout() {
|
||||
return myStdoutLines;
|
||||
}
|
||||
|
||||
public List<String> 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<String> stdout = NO_LINES;
|
||||
List<String> 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<String> my_lines = new ArrayList<String>();
|
||||
|
||||
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<String> getResult() {
|
||||
return my_lines;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first match in a list os Strings.
|
||||
* @param lines list of lines, may be null.
|
||||
|
||||
Reference in New Issue
Block a user