mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-99154 (fix refined)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import org.intellij.images.ImagesBundle;
|
||||
@@ -39,7 +39,6 @@ import org.intellij.images.options.impl.OptionsConfigurabe;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Open image file externally.
|
||||
@@ -60,9 +59,8 @@ public final class EditExternallyAction extends AnAction {
|
||||
}
|
||||
else {
|
||||
if (files != null) {
|
||||
Map<String, String> env = EnvironmentUtil.getEnvironmentProperties();
|
||||
Set<String> varNames = env.keySet();
|
||||
for (String varName : varNames) {
|
||||
Map<String, String> env = EnvironmentUtil.getEnvironmentMap();
|
||||
for (String varName : env.keySet()) {
|
||||
if (SystemInfo.isWindows) {
|
||||
executablePath = StringUtil.replace(executablePath, "%" + varName + "%", env.get(varName), true);
|
||||
}
|
||||
@@ -85,7 +83,7 @@ public final class EditExternallyAction extends AnAction {
|
||||
ImageFileTypeManager typeManager = ImageFileTypeManager.getInstance();
|
||||
for (VirtualFile file : files) {
|
||||
if (file.isInLocalFileSystem() && typeManager.isImage(file)) {
|
||||
commandLine.addParameter(VfsUtil.virtualToIoFile(file).getAbsolutePath());
|
||||
commandLine.addParameter(VfsUtilCore.virtualToIoFile(file).getAbsolutePath());
|
||||
}
|
||||
}
|
||||
commandLine.setWorkDirectory(new File(executablePath).getParentFile());
|
||||
@@ -94,9 +92,7 @@ public final class EditExternallyAction extends AnAction {
|
||||
commandLine.createProcess();
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
Messages.showErrorDialog(project,
|
||||
ex.getLocalizedMessage(),
|
||||
ImagesBundle.message("error.title.launching.external.editor"));
|
||||
Messages.showErrorDialog(project, ex.getLocalizedMessage(), ImagesBundle.message("error.title.launching.external.editor"));
|
||||
OptionsConfigurabe.show(project);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
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 com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -252,8 +253,10 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
}
|
||||
|
||||
private void setupEnvironment(final Map<String, String> environment) {
|
||||
if (!myPassParentEnvironment) {
|
||||
environment.clear();
|
||||
environment.clear();
|
||||
|
||||
if (myPassParentEnvironment) {
|
||||
environment.putAll(EnvironmentUtil.getEnvironmentMap());
|
||||
}
|
||||
|
||||
if (!myEnvParams.isEmpty()) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.execution.ParametersListUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -303,7 +302,7 @@ public class ParametersList implements Cloneable {
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<String, String> env = EnvironmentUtil.getEnvironmentProperties();
|
||||
final Map<String, String> env = EnvironmentUtil.getEnvironmentMap();
|
||||
for (String name : env.keySet()) {
|
||||
final String key = "${" + name + "}";
|
||||
if (!myMacroMap.containsKey(key)) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.win32.IdeaWin32;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.text.DateFormatUtilRt;
|
||||
import com.sun.jna.Native;
|
||||
@@ -37,14 +38,13 @@ import org.xerial.snappy.Snappy;
|
||||
import org.xerial.snappy.SnappyLoader;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -55,8 +55,6 @@ public class StartupUtil {
|
||||
public static final boolean NO_SNAPPY = SystemProperties.getBooleanProperty("idea.no.snappy", false) ||
|
||||
SystemInfo.isMac && SystemInfo.is32Bit; // todo[maxim] drop once available
|
||||
|
||||
private static final boolean FIX_MAC_ENV = SystemProperties.getBooleanProperty("idea.fix.mac.env", false);
|
||||
|
||||
static boolean isHeadless;
|
||||
|
||||
private static SocketLock ourLock;
|
||||
@@ -180,101 +178,7 @@ public class StartupUtil {
|
||||
|
||||
|
||||
static void fixProcessEnvironment(Logger log) {
|
||||
if (!SystemInfo.isMac || !FIX_MAC_ENV) return;
|
||||
|
||||
Map<String, String> envDiff = getEnvironmentDifference(log);
|
||||
if (!envDiff.isEmpty()) {
|
||||
updateEnvironment(log, envDiff);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> getEnvironmentDifference(Logger log) {
|
||||
try {
|
||||
String shell = System.getenv("SHELL");
|
||||
if (shell != null && new File(shell).canExecute()) {
|
||||
String[] command = {shell, "-l", "-c", "/usr/bin/printenv"};
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
|
||||
InputStream input = process.getInputStream();
|
||||
List<String> lines = new ArrayList<String>();
|
||||
ByteArrayOutputStream lineBuf = new ByteArrayOutputStream();
|
||||
int b;
|
||||
while ((b = input.read()) >= 0) {
|
||||
if (b != '\n') {
|
||||
lineBuf.write(b);
|
||||
}
|
||||
else {
|
||||
String line = new String(lineBuf.toByteArray());
|
||||
lines.add(line);
|
||||
lineBuf = new ByteArrayOutputStream();
|
||||
}
|
||||
}
|
||||
input.close();
|
||||
|
||||
int rv;
|
||||
try {
|
||||
rv = process.exitValue();
|
||||
}
|
||||
catch (IllegalThreadStateException e) {
|
||||
process.destroy();
|
||||
rv = -1;
|
||||
}
|
||||
if (rv != 0 || lines.isEmpty()) {
|
||||
throw new Exception("rv:" + rv + " lines:" + lines.size());
|
||||
}
|
||||
|
||||
Map<String, String> env = System.getenv();
|
||||
Map<String, String> envDiff = new HashMap<String, String>();
|
||||
Set<String> varsToIgnore = new HashSet<String>(Arrays.asList("_", "PWD", "SHLVL"));
|
||||
|
||||
for (String line : lines) {
|
||||
int pos = line.indexOf('=');
|
||||
if (pos > 0) {
|
||||
String name = line.substring(0, pos);
|
||||
if (!varsToIgnore.contains(name)) {
|
||||
String value = line.substring(pos + 1);
|
||||
if (!env.containsKey(name) || !value.equals(env.get(name))) {
|
||||
envDiff.put(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return envDiff;
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
log.warn("can't get shell environment", t);
|
||||
}
|
||||
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PrimitiveArrayArgumentToVariableArgMethod", "SSBasedInspection", "unchecked"})
|
||||
private static void updateEnvironment(Logger log, Map<String, String> envDiff) {
|
||||
try {
|
||||
Class<?> envClass = Class.forName("java.lang.ProcessEnvironment");
|
||||
Field theEnvironment = envClass.getDeclaredField("theEnvironment");
|
||||
theEnvironment.setAccessible(true);
|
||||
|
||||
Class<?> varClass = Class.forName("java.lang.ProcessEnvironment$Variable");
|
||||
Method makeVar = varClass.getDeclaredMethod("valueOf", byte[].class);
|
||||
makeVar.setAccessible(true);
|
||||
|
||||
Class<?> valClass = Class.forName("java.lang.ProcessEnvironment$Value");
|
||||
Method makeVal = valClass.getDeclaredMethod("valueOf", byte[].class);
|
||||
makeVal.setAccessible(true);
|
||||
|
||||
Map envMap = (Map)theEnvironment.get(null);
|
||||
for (Map.Entry<String, String> entry : envDiff.entrySet()) {
|
||||
Object name = makeVar.invoke(null, entry.getKey().getBytes());
|
||||
Object value = makeVal.invoke(null, entry.getValue().getBytes());
|
||||
envMap.put(name, value);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
log.warn("can't update environment", t);
|
||||
}
|
||||
log.info("initializing " + EnvironmentUtil.class.getName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,9 +22,11 @@ import com.intellij.util.Processor;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Platform;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
@@ -54,15 +56,7 @@ public class UnixProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> ourCachedConsoleEnv;
|
||||
|
||||
private UnixProcessManager() {
|
||||
}
|
||||
|
||||
public static int getProcessPid() {
|
||||
checkCLib();
|
||||
return C_LIB.getpid();
|
||||
}
|
||||
private UnixProcessManager() { }
|
||||
|
||||
public static int getProcessPid(Process process) {
|
||||
try {
|
||||
@@ -78,11 +72,6 @@ public class UnixProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendSignal(Process process, int signal) {
|
||||
int process_pid = getProcessPid(process);
|
||||
sendSignal(process_pid, signal);
|
||||
}
|
||||
|
||||
public static void sendSignal(int pid, int signal) {
|
||||
checkCLib();
|
||||
C_LIB.kill(pid, signal);
|
||||
@@ -109,32 +98,33 @@ public class UnixProcessManager {
|
||||
*/
|
||||
public static boolean sendSignalToProcessTree(Process process, int signal) {
|
||||
try {
|
||||
checkCLib();
|
||||
checkCLib();
|
||||
|
||||
final int our_pid = C_LIB.getpid();
|
||||
final int process_pid = getProcessPid(process);
|
||||
final int our_pid = C_LIB.getpid();
|
||||
final int process_pid = getProcessPid(process);
|
||||
|
||||
final Ref<Integer> foundPid = new Ref<Integer>();
|
||||
final ProcessInfo processInfo = new ProcessInfo();
|
||||
final List<Integer> childrenPids = new ArrayList<Integer>();
|
||||
final Ref<Integer> foundPid = new Ref<Integer>();
|
||||
final ProcessInfo processInfo = new ProcessInfo();
|
||||
final List<Integer> childrenPids = new ArrayList<Integer>();
|
||||
|
||||
findChildProcesses(our_pid, process_pid, foundPid, processInfo, childrenPids);
|
||||
findChildProcesses(our_pid, process_pid, foundPid, processInfo, childrenPids);
|
||||
|
||||
// result is true if signal was sent to at least one process
|
||||
final boolean result;
|
||||
if (!foundPid.isNull()) {
|
||||
processInfo.killProcTree(foundPid.get(), signal, UNIX_KILLER);
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
for (Integer pid : childrenPids) {
|
||||
processInfo.killProcTree(pid, signal, UNIX_KILLER);
|
||||
// result is true if signal was sent to at least one process
|
||||
final boolean result;
|
||||
if (!foundPid.isNull()) {
|
||||
processInfo.killProcTree(foundPid.get(), signal, UNIX_KILLER);
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
for (Integer pid : childrenPids) {
|
||||
processInfo.killProcTree(pid, signal, UNIX_KILLER);
|
||||
}
|
||||
result = !childrenPids.isEmpty(); //we've tried to kill at least one process
|
||||
}
|
||||
result = !childrenPids.isEmpty(); //we've tried to kill at least one process
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
//If we fail somehow just return false
|
||||
LOG.warn("Error killing the process", e);
|
||||
return false;
|
||||
@@ -186,7 +176,6 @@ public class UnixProcessManager {
|
||||
public static void processCommandOutput(String[] cmd, Processor<String> processor, boolean skipFirstLine, boolean throwOnError) {
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
|
||||
processCommandOutput(p, processor, skipFirstLine, throwOnError);
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -194,36 +183,36 @@ public class UnixProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processCommandOutput(Process psProcess, Processor<String> processor, boolean skipFirstLine, boolean throwOnError) throws IOException {
|
||||
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
|
||||
BufferedReader stdOutput = new BufferedReader(new
|
||||
InputStreamReader(psProcess.getInputStream()));
|
||||
BufferedReader stdError = new BufferedReader(new
|
||||
InputStreamReader(psProcess.getErrorStream()));
|
||||
|
||||
private static void processCommandOutput(Process process, Processor<String> processor, boolean skipFirstLine, boolean throwOnError) throws IOException {
|
||||
BufferedReader stdOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
try {
|
||||
String s;
|
||||
if (skipFirstLine) {
|
||||
stdOutput.readLine(); //ps output header
|
||||
}
|
||||
while ((s = stdOutput.readLine()) != null) {
|
||||
processor.process(s);
|
||||
}
|
||||
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
try {
|
||||
if (skipFirstLine) {
|
||||
stdOutput.readLine(); //ps output header
|
||||
}
|
||||
String s;
|
||||
while ((s = stdOutput.readLine()) != null) {
|
||||
processor.process(s);
|
||||
}
|
||||
|
||||
StringBuilder errorStr = new StringBuilder();
|
||||
while ((s = stdError.readLine()) != null) {
|
||||
if (s.contains("environment variables being ignored")) { // PY-8160
|
||||
continue;
|
||||
StringBuilder errorStr = new StringBuilder();
|
||||
while ((s = stdError.readLine()) != null) {
|
||||
if (s.contains("environment variables being ignored")) { // PY-8160
|
||||
continue;
|
||||
}
|
||||
errorStr.append(s).append("\n");
|
||||
}
|
||||
if (throwOnError && errorStr.length() > 0) {
|
||||
throw new IOException("Error reading ps output:" + errorStr.toString());
|
||||
}
|
||||
errorStr.append(s).append("\n");
|
||||
}
|
||||
if (throwOnError && errorStr.length() > 0) {
|
||||
throw new IOException("Error reading ps output:" + errorStr.toString());
|
||||
finally {
|
||||
stdError.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stdOutput.close();
|
||||
stdError.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,42 +237,6 @@ public class UnixProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String readProcEnviron(int child_pid) throws FileNotFoundException {
|
||||
StringBuffer res = new StringBuffer();
|
||||
Scanner s = new Scanner(new File("/proc/" + child_pid + "/environ"));
|
||||
while (s.hasNextLine()) {
|
||||
res.append(s).append("\n");
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
public static Map<? extends String, ? extends String> getOrLoadConsoleEnvironment() {
|
||||
if (ourCachedConsoleEnv == null) {
|
||||
loadConsoleEnvironment();
|
||||
}
|
||||
return ourCachedConsoleEnv;
|
||||
}
|
||||
|
||||
private static void loadConsoleEnvironment() {
|
||||
final Map<String, String> env = new HashMap<String, String>();
|
||||
final String shell = System.getenv("SHELL");
|
||||
if (shell != null && (shell.contains("bash") || shell.contains("zsh"))) {
|
||||
processCommandOutput(new String[] {shell, "--login", "-c", "printenv"}, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(String s) {
|
||||
final String[] split = s.split("=", 2);
|
||||
if (split.length > 1) {
|
||||
env.put(split[0], split[1]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, false, false);
|
||||
}
|
||||
ourCachedConsoleEnv = !env.isEmpty() ? Collections.unmodifiableMap(env) : System.getenv();
|
||||
}
|
||||
|
||||
|
||||
private interface CLib extends Library {
|
||||
int getpid();
|
||||
int kill(int pid, int signal);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.FixedFuture;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
@@ -345,7 +346,7 @@ public class FileUtil extends FileUtilRt {
|
||||
if (!tempFiles.isEmpty()) {
|
||||
return startDeletionThread(tempFiles.toArray(new File[tempFiles.size()]));
|
||||
}
|
||||
return new CompletedFuture<Void>();
|
||||
return new FixedFuture<Void>(null);
|
||||
}
|
||||
|
||||
private static Future<Void> startDeletionThread(@NotNull final File... tempFiles) {
|
||||
@@ -1337,6 +1338,28 @@ public class FileUtil extends FileUtilRt {
|
||||
return FileUtilRt.loadText(reader, length);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> loadLines(@NotNull InputStream stream) throws IOException {
|
||||
//noinspection IOResourceOpenedButNotSafelyClosed
|
||||
return loadLines(new InputStreamReader(stream));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> loadLines(@NotNull Reader reader) throws IOException {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
BufferedReader bufferedReader = new BufferedReader(reader);
|
||||
try {
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
bufferedReader.close();
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static byte[] loadBytes(@NotNull InputStream stream) throws IOException {
|
||||
return FileUtilRt.loadBytes(stream);
|
||||
@@ -1359,28 +1382,4 @@ public class FileUtil extends FileUtilRt {
|
||||
list.add(path.substring(index, path.length()));
|
||||
return list;
|
||||
}
|
||||
|
||||
private static final class CompletedFuture<T> implements Future<T> {
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get() throws InterruptedException, ExecutionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,41 +15,84 @@
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.concurrency.FixedFuture;
|
||||
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class EnvironmentUtil {
|
||||
private static final Map<String, String> ourEnvironmentProperties;
|
||||
private static final Map<String, String> ourEnvironmentVariablesOsSpecific;
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.EnvironmentUtil");
|
||||
|
||||
private static final int SHELL_ENV_READING_TIMEOUT = 10000;
|
||||
|
||||
private static final Future<Map<String, String>> ourEnvGetter;
|
||||
static {
|
||||
ourEnvironmentProperties = Collections.unmodifiableMap(new ProcessBuilder().environment());
|
||||
if (SystemInfo.isWindows) {
|
||||
ourEnvironmentVariablesOsSpecific = Collections.unmodifiableMap(
|
||||
new THashMap<String, String>(ourEnvironmentProperties, CaseInsensitiveStringHashingStrategy.INSTANCE));
|
||||
boolean readShellEnv = SystemInfo.isMac && SystemProperties.getBooleanProperty("idea.fix.mac.env", false); // todo: UI setting?
|
||||
if (readShellEnv) {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
ourEnvGetter = executor.submit(new Callable<Map<String, String>>() {
|
||||
@Override
|
||||
public Map<String, String> call() throws Exception {
|
||||
return getShellEnv();
|
||||
}
|
||||
});
|
||||
executor.shutdown();
|
||||
}
|
||||
else {
|
||||
ourEnvironmentVariablesOsSpecific = ourEnvironmentProperties;
|
||||
ourEnvGetter = new FixedFuture<Map<String, String>>(System.getenv());
|
||||
}
|
||||
}
|
||||
|
||||
private static final NotNullLazyValue<Map<String, String>> ourEnvironment = new AtomicNotNullLazyValue<Map<String, String>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<String, String> compute() {
|
||||
try {
|
||||
return ourEnvGetter.get();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
return System.getenv();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final NotNullLazyValue<Map<String, String>> ourEnvironmentOsSpecific = new AtomicNotNullLazyValue<Map<String, String>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<String, String> compute() {
|
||||
Map<String, String> env = ourEnvironment.getValue();
|
||||
if (SystemInfo.isWindows) {
|
||||
env = Collections.unmodifiableMap(new THashMap<String, String>(env, CaseInsensitiveStringHashingStrategy.INSTANCE));
|
||||
}
|
||||
return env;
|
||||
}
|
||||
};
|
||||
|
||||
private EnvironmentUtil() { }
|
||||
|
||||
/** @deprecated use {@link #getEnvironmentProperties()} (to remove in IDEA 14) */
|
||||
@SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
|
||||
public static Map<String, String> getEnviromentProperties() {
|
||||
return getEnvironmentProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the process environment. On Mac OS X, a shell environment is returned if
|
||||
* todo: some property is set.
|
||||
*
|
||||
* @return unmodifiable map of the process environment.
|
||||
*/
|
||||
@NotNull
|
||||
public static Map<String, String> getEnvironmentProperties() {
|
||||
return ourEnvironmentProperties;
|
||||
public static Map<String, String> getEnvironmentMap() {
|
||||
return ourEnvironment.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,19 +105,125 @@ public class EnvironmentUtil {
|
||||
*/
|
||||
@Nullable
|
||||
public static String getValue(@NotNull String name) {
|
||||
return ourEnvironmentVariablesOsSpecific.get(name);
|
||||
return ourEnvironmentOsSpecific.getValue().get(name);
|
||||
}
|
||||
|
||||
public static String[] getEnvironment() {
|
||||
return flattenEnvironment(getEnvironmentProperties());
|
||||
return flattenEnvironment(getEnvironmentMap());
|
||||
}
|
||||
|
||||
public static String[] flattenEnvironment(Map<String, String> environment) {
|
||||
String[] array = new String[environment.size()];
|
||||
int i = 0;
|
||||
for (String name : environment.keySet()) {
|
||||
array[i++] = name + "=" + environment.get(name);
|
||||
for (Map.Entry<String, String> entry : environment.entrySet()) {
|
||||
array[i++] = entry.getKey() + "=" + entry.getValue();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private static Map<String, String> getShellEnv() {
|
||||
try {
|
||||
String shell = System.getenv("SHELL");
|
||||
if (shell == null || !new File(shell).canExecute()) {
|
||||
throw new Exception("shell:" + shell);
|
||||
}
|
||||
|
||||
String[] command = {shell, "-l", "-c", "/usr/bin/printenv"};
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
ProcessKiller processKiller = new ProcessKiller(process);
|
||||
processKiller.killAfter(SHELL_ENV_READING_TIMEOUT);
|
||||
List<String> lines = FileUtil.loadLines(process.getInputStream());
|
||||
processKiller.stopWaiting();
|
||||
int rv = process.exitValue();
|
||||
if (rv != 0 || lines.isEmpty()) {
|
||||
throw new Exception("rv:" + rv + " lines:" + lines.size());
|
||||
}
|
||||
|
||||
Set<String> toIgnore = new HashSet<String>(Arrays.asList("_", "PWD", "SHLVL"));
|
||||
Map<String, String> env = System.getenv();
|
||||
Map<String, String> newEnv = new HashMap<String, String>();
|
||||
for (String line : lines) {
|
||||
int pos = line.indexOf('=');
|
||||
if (pos <= 0) {
|
||||
LOG.warn("malformed:" + line);
|
||||
continue;
|
||||
}
|
||||
String name = line.substring(0, pos);
|
||||
if (!toIgnore.contains(name)) {
|
||||
newEnv.put(name, line.substring(pos + 1));
|
||||
}
|
||||
else if (env.containsKey(name)) {
|
||||
newEnv.put(name, env.get(name));
|
||||
}
|
||||
}
|
||||
if (newEnv.size() < lines.size() - toIgnore.size()) {
|
||||
throw new Exception("env:" + newEnv.size() + " lines:" + lines.size());
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(newEnv);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.warn("can't get shell environment", t);
|
||||
return System.getenv();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProcessKiller {
|
||||
private final Process myProcess;
|
||||
private final Object myWaiter = new Object();
|
||||
|
||||
public ProcessKiller(Process process) {
|
||||
myProcess = process;
|
||||
}
|
||||
|
||||
public void killAfter(long timeout) {
|
||||
final long stop = System.currentTimeMillis() + timeout;
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (myWaiter) {
|
||||
while (System.currentTimeMillis() < stop) {
|
||||
try {
|
||||
myProcess.exitValue();
|
||||
break;
|
||||
}
|
||||
catch (IllegalThreadStateException ignore) { }
|
||||
|
||||
try {
|
||||
myWaiter.wait(100);
|
||||
}
|
||||
catch (InterruptedException ignore) { }
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
myProcess.exitValue();
|
||||
}
|
||||
catch (IllegalThreadStateException e) {
|
||||
myProcess.destroy();
|
||||
LOG.warn("timed out");
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void stopWaiting() {
|
||||
synchronized (myWaiter) {
|
||||
myWaiter.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #getEnvironmentMap()} (to remove in IDEA 14) */
|
||||
@SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
|
||||
public static Map<String, String> getEnviromentProperties() {
|
||||
return getEnvironmentMap();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #getEnvironmentMap()} (to remove in IDEA 14) */
|
||||
@SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
|
||||
public static Map<String, String> getEnvironmentProperties() {
|
||||
return getEnvironmentMap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FixedFuture<T> implements Future<T> {
|
||||
private final T myValue;
|
||||
|
||||
public FixedFuture(T value) {
|
||||
myValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, @NotNull TimeUnit unit) {
|
||||
return myValue;
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,14 @@ import static org.junit.Assert.assertNotNull;
|
||||
* @since Sep 19, 2002
|
||||
*/
|
||||
public class EnvironmentUtilTest {
|
||||
@Test(timeout = 60000)
|
||||
public void map() throws Exception {
|
||||
System.setProperty("idea.fix.mac.env", "true");
|
||||
assertNotNull(EnvironmentUtil.getEnvironmentMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basic() {
|
||||
assertNotNull(EnvironmentUtil.getEnvironmentProperties());
|
||||
public void path() {
|
||||
assertNotNull(EnvironmentUtil.getValue("PATH"));
|
||||
if (SystemInfo.isWindows) {
|
||||
assertNotNull(EnvironmentUtil.getValue("Path"));
|
||||
|
||||
+1
-3
@@ -21,7 +21,6 @@ import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingManager;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import org.netbeans.lib.cvsclient.connection.AuthenticationException;
|
||||
import org.netbeans.lib.cvsclient.connection.IConnection;
|
||||
@@ -142,8 +141,7 @@ public abstract class ConnectionOnProcess implements IConnection {
|
||||
|
||||
protected synchronized void execute(GeneralCommandLine commandLine) throws AuthenticationException {
|
||||
try {
|
||||
commandLine.getEnvironment().clear();
|
||||
commandLine.getEnvironment().putAll(EnvironmentUtil.getEnvironmentProperties());
|
||||
commandLine.setPassParentEnvironment(true);
|
||||
myProcess = commandLine.createProcess();
|
||||
|
||||
myErrThread = new ReadProcessThread(
|
||||
|
||||
+2
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,11 +64,7 @@ public class ExtConnection extends ConnectionOnProcess {
|
||||
if (isOpen()) throw new RuntimeException(CvsBundle.message("error.message.connection.already.open"));
|
||||
|
||||
GeneralCommandLine command = createRshCommand(myHost, myUserName, myConfiguration);
|
||||
|
||||
for (String command1 : commands) {
|
||||
command.addParameter(command1);
|
||||
}
|
||||
|
||||
command.addParameters(commands);
|
||||
execute(command);
|
||||
|
||||
if (expectedResult != null) {
|
||||
|
||||
+25
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ import com.intellij.cvsSupport2.config.CvsApplicationLevelConfiguration;
|
||||
import com.intellij.cvsSupport2.connections.CvsEnvironment;
|
||||
import com.intellij.cvsSupport2.cvshandlers.CvsHandler;
|
||||
import com.intellij.cvsSupport2.errorHandling.CannotFindCvsRootException;
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,54 +34,30 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class CvsOperation {
|
||||
private final static String[] ourKnownToCvs = {"CVSIGNORE",
|
||||
"CVSWRAPPERS",
|
||||
"CVSREAD",
|
||||
"CVSREADONLYFS",
|
||||
"CVSUMASK",
|
||||
private static final NotNullLazyValue<Map<String, String>> ourCvsEnvironment = new AtomicNotNullLazyValue<Map<String, String>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<String, String> compute() {
|
||||
Map<String, String> cvsEnv = new HashMap<String, String>();
|
||||
|
||||
"CVSROOT",
|
||||
"CVSEDITOR",
|
||||
"EDITOR",
|
||||
"VISUAL",
|
||||
"PATH",
|
||||
//10
|
||||
"HOME",
|
||||
"HOMEPATH",
|
||||
"HOMEDRIVE",
|
||||
"CVS_RSH",
|
||||
"CVS_SERVER",
|
||||
|
||||
"CVS_PASSFILE",
|
||||
"CVS_CLIENT_PORT",
|
||||
"CVS_PROXY_PORT",
|
||||
"CVS_RCMD_PORT",
|
||||
"CVS_CLIENT_LOG",
|
||||
|
||||
"CVS_SERVER_SLEEP",
|
||||
"CVS_IGNORE_REMOTE_ROOT",
|
||||
"CVS_LOCAL_BRANCH_NUM",
|
||||
"COMSPEC",
|
||||
"TMPDIR",
|
||||
|
||||
"CVS_PID",
|
||||
"COMSPEC",
|
||||
"CVS_VERIFY_TEMPLATE",
|
||||
"CVS_NOBASES",
|
||||
"CVS_SIGN_COMMITS",
|
||||
|
||||
"CVS_VERIFY_CHECKOUTS"
|
||||
};
|
||||
private final static Map<String, String> ourEnvironmentVariablesMap = new HashMap<String, String>();
|
||||
static {
|
||||
final Map<String, String> environmentProperties = EnvironmentUtil.getEnvironmentProperties();
|
||||
for (String name : ourKnownToCvs) {
|
||||
final String value = environmentProperties.get(name);
|
||||
if (value != null) {
|
||||
ourEnvironmentVariablesMap.put(name, value);
|
||||
Map<String, String> knownToCvs = EnvironmentUtil.getEnvironmentMap();
|
||||
@SuppressWarnings("SpellCheckingInspection") String[] toCvs = {
|
||||
"CVSIGNORE", "CVSWRAPPERS", "CVSREAD", "CVSREADONLYFS", "CVSUMASK",
|
||||
"CVSROOT", "CVSEDITOR", "EDITOR", "VISUAL", "PATH", "HOME", "HOMEPATH", "HOMEDRIVE", "CVS_RSH", "CVS_SERVER",
|
||||
"CVS_PASSFILE", "CVS_CLIENT_PORT", "CVS_PROXY_PORT", "CVS_RCMD_PORT", "CVS_CLIENT_LOG",
|
||||
"CVS_SERVER_SLEEP", "CVS_IGNORE_REMOTE_ROOT", "CVS_LOCAL_BRANCH_NUM", "COMSPEC", "TMPDIR",
|
||||
"CVS_PID", "COMSPEC", "CVS_VERIFY_TEMPLATE", "CVS_NOBASES", "CVS_SIGN_COMMITS", "CVS_VERIFY_CHECKOUTS"
|
||||
};
|
||||
for (String name : toCvs) {
|
||||
String value = knownToCvs.get(name);
|
||||
if (value != null) {
|
||||
cvsEnv.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
return cvsEnv;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Collection<Runnable> myFinishActions = new ArrayList<Runnable>();
|
||||
|
||||
@@ -100,7 +78,7 @@ public abstract class CvsOperation {
|
||||
protected void modifyOptions(GlobalOptions options) {
|
||||
options.setUseGzip(CvsApplicationLevelConfiguration.getInstance().USE_GZIP);
|
||||
if (CvsApplicationLevelConfiguration.getInstance().SEND_ENVIRONMENT_VARIABLES_TO_SERVER) {
|
||||
options.setEnvVariables(ourEnvironmentVariablesMap);
|
||||
options.setEnvVariables(ourCvsEnvironment.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user