mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added setenv method from "c" lib
This commit is contained in:
+34
-82
@@ -1,44 +1,37 @@
|
||||
package com.intellij.execution.configurations;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.execution.process.UnixProcessManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Sergey Simonchik
|
||||
*/
|
||||
public class PathEnvironmentVariableUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(PathEnvironmentVariableUtil.class);
|
||||
public static final String PATH_ENV_VAR_NAME = "PATH";
|
||||
private static final int BLOCK_TIMEOUT_MILLIS = 50;
|
||||
|
||||
private static volatile String ourFixedMacPathEnvVarValue;
|
||||
private static final String ourFixedMacPathEnvVarValue;
|
||||
|
||||
static {
|
||||
asyncCalcFixedMacPathEnvVarValue();
|
||||
ourFixedMacPathEnvVarValue = calcFixedMacPathEnvVarValue();
|
||||
}
|
||||
|
||||
private PathEnvironmentVariableUtil() {}
|
||||
private PathEnvironmentVariableUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to return a real value for PATH environment variable by parsing the result of
|
||||
* {@code /usr/libexec/path_helper -s} command execution.
|
||||
* Tries to return a real value for PATH environment variable.
|
||||
* Workaround for http://youtrack.jetbrains.com/issue/IDEA-99154
|
||||
*/
|
||||
@Nullable
|
||||
@@ -46,78 +39,17 @@ public class PathEnvironmentVariableUtil {
|
||||
return ourFixedMacPathEnvVarValue;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getOriginalPathEnvVarValue() {
|
||||
Map<String, String> envVars = EnvironmentUtil.getEnvironmentProperties();
|
||||
return envVars.get(PATH_ENV_VAR_NAME);
|
||||
}
|
||||
|
||||
private static void asyncCalcFixedMacPathEnvVarValue() {
|
||||
private static String calcFixedMacPathEnvVarValue() {
|
||||
if (SystemInfo.isMac) {
|
||||
final String originalValue = getOriginalPathEnvVarValue();
|
||||
final Semaphore semaphore = new Semaphore(0, true);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ourFixedMacPathEnvVarValue = findFixedPathEnvVarValue(originalValue);
|
||||
}
|
||||
finally {
|
||||
semaphore.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
semaphore.tryAcquire(BLOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.info("Unexpected thread interruption", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String findFixedPathEnvVarValue(@Nullable String originalValue) {
|
||||
File executable = new File("/usr/libexec/path_helper");
|
||||
if (executable.isFile() && executable.canExecute()) {
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine();
|
||||
try {
|
||||
commandLine.setExePath(executable.getAbsolutePath());
|
||||
commandLine.addParameter("-s");
|
||||
List<String> stdout = executeAndGetStdout(commandLine);
|
||||
final String prefix = "PATH=\"";
|
||||
final String suffix = "\"; export PATH;";
|
||||
for (String line : stdout) {
|
||||
if (line.startsWith(prefix) && line.endsWith(suffix)) {
|
||||
String value = line.substring(prefix.length(), line.length() - suffix.length());
|
||||
return mergePaths(ContainerUtil.newArrayList(originalValue, value));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.info("Can't execute '" + commandLine.getCommandLineString() + "'", e);
|
||||
}
|
||||
Map<String, String> originalEnvVars = EnvironmentUtil.getEnvironmentProperties();
|
||||
final String originalPath = originalEnvVars.get(PATH_ENV_VAR_NAME);
|
||||
Map<? extends String, ? extends String> envVars = UnixProcessManager.getOrLoadConsoleEnvironment();
|
||||
String consolePath = envVars.get(PATH_ENV_VAR_NAME);
|
||||
return mergePaths(ContainerUtil.newArrayList(originalPath, consolePath));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> executeAndGetStdout(@NotNull GeneralCommandLine commandLine) throws ExecutionException {
|
||||
final Process process = commandLine.createProcess();
|
||||
CapturingProcessHandler processHandler = new CapturingProcessHandler(process, CharsetToolkit.UTF8_CHARSET);
|
||||
ProcessOutput output = processHandler.runProcess(2000);
|
||||
int exitCode = output.getExitCode();
|
||||
if (exitCode != 0) {
|
||||
throw new ExecutionException("Exit code of '" + commandLine.getCommandLineString()
|
||||
+ "' is " + exitCode);
|
||||
}
|
||||
if (!output.getStderr().isEmpty()) {
|
||||
throw new ExecutionException("Stderr of '" + commandLine.getCommandLineString()
|
||||
+ "': " + output.getStderr());
|
||||
}
|
||||
return output.getStdoutLines();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String mergePaths(@NotNull List<String> pathStrings) {
|
||||
LinkedHashSet<String> paths = ContainerUtil.newLinkedHashSet();
|
||||
@@ -135,4 +67,24 @@ public class PathEnvironmentVariableUtil {
|
||||
return StringUtil.join(paths, File.pathSeparator);
|
||||
}
|
||||
|
||||
public static void setPathEnvVarAtProcessLevel() {
|
||||
if (ourFixedMacPathEnvVarValue != null) {
|
||||
UnixProcessManager.setEnv(PATH_ENV_VAR_NAME, ourFixedMacPathEnvVarValue, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPathEnvVarInSystemEnv() {
|
||||
try {
|
||||
Map<String, String> unmodifiable = System.getenv();
|
||||
Class<?> cu = unmodifiable.getClass();
|
||||
Field m = cu.getDeclaredField("m");
|
||||
m.setAccessible(true);
|
||||
Map<String, String> map = (Map<String, String>)m.get(unmodifiable);
|
||||
if (ourFixedMacPathEnvVarValue != null) {
|
||||
map.put(PATH_ENV_VAR_NAME, ourFixedMacPathEnvVarValue);
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,21 @@ public class UnixProcessManager {
|
||||
C_LIB.kill(pid, signal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds or changes an environment variable.
|
||||
* @param name string that contains the name of the environment variable to be added or changed
|
||||
* @param value the value of the environment variable
|
||||
* @param overwrite change the existing entry. If {@code name} has already been defined and exists in the environment variable table,
|
||||
* its value will be updated with {@code value}. If {@code name} was previously undefined, it will be appended to the table.
|
||||
*/
|
||||
public static void setEnv(@NotNull String name, @NotNull String value, boolean overwrite) {
|
||||
if (C_LIB != null) {
|
||||
checkCLib();
|
||||
C_LIB.setenv(name, value, overwrite ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkCLib() {
|
||||
if (C_LIB == null) {
|
||||
throw new IllegalStateException("System is not unix(couldn't load c library)");
|
||||
@@ -290,10 +305,10 @@ public class UnixProcessManager {
|
||||
}
|
||||
|
||||
|
||||
public interface CLib extends Library {
|
||||
private interface CLib extends Library {
|
||||
int getpid();
|
||||
|
||||
int kill(int pid, int signal);
|
||||
int setenv(String name, String value, int overwrite);
|
||||
}
|
||||
|
||||
public static class ProcessInfo {
|
||||
|
||||
Reference in New Issue
Block a user