From dc730e866d394441b11eb5fa47f45130eff37265 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 1 Dec 2016 13:15:43 +0100 Subject: [PATCH] [platform] environment-based lookup for (Unix) utilities (IDEA-164810) --- .../com/intellij/execution/util/ExecUtil.java | 37 +++++--------- .../ide/actions/ShowFilePathAction.java | 2 +- .../com/intellij/openapi/util/SystemInfo.java | 18 ++----- .../openapi/util/io/PathExecLazyValue.java | 50 +++++++++++++++++++ .../openapi/util/io/PathExecLazyValueTest.kt | 38 ++++++++++++++ 5 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 platform/util/src/com/intellij/openapi/util/io/PathExecLazyValue.java create mode 100644 platform/util/testSrc/com/intellij/openapi/util/io/PathExecLazyValueTest.kt diff --git a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java index 877730c3a02d..b78203d1ef69 100644 --- a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java +++ b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.PathExecLazyValue; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.containers.ContainerUtil; @@ -36,26 +37,12 @@ import java.util.List; import java.util.Map; public class ExecUtil { - private static class ExecutableExistsLazyValue extends NotNullLazyValue { - private final String myPathname; - - public ExecutableExistsLazyValue(String pathname) { - myPathname = pathname; - } - - @NotNull - @Override - protected Boolean compute() { - return new File(myPathname).canExecute(); - } - } - - private static final NotNullLazyValue hasGkSudo = new ExecutableExistsLazyValue("/usr/bin/gksudo"); - private static final NotNullLazyValue hasKdeSudo = new ExecutableExistsLazyValue("/usr/bin/kdesudo"); - private static final NotNullLazyValue hasPkExec = new ExecutableExistsLazyValue("/usr/bin/pkexec"); - private static final NotNullLazyValue hasGnomeTerminal = new ExecutableExistsLazyValue("/usr/bin/gnome-terminal"); - private static final NotNullLazyValue hasKdeTerminal = new ExecutableExistsLazyValue("/usr/bin/konsole"); - private static final NotNullLazyValue hasXTerm = new ExecutableExistsLazyValue("/usr/bin/xterm"); + private static final NotNullLazyValue hasGkSudo = new PathExecLazyValue("gksudo"); + private static final NotNullLazyValue hasKdeSudo = new PathExecLazyValue("kdesudo"); + private static final NotNullLazyValue hasPkExec = new PathExecLazyValue("pkexec"); + private static final NotNullLazyValue hasGnomeTerminal = new PathExecLazyValue("gnome-terminal"); + private static final NotNullLazyValue hasKdeTerminal = new PathExecLazyValue("konsole"); + private static final NotNullLazyValue hasXTerm = new PathExecLazyValue("xterm"); private ExecUtil() { } @@ -236,15 +223,15 @@ public class ExecUtil { return Arrays.asList(getOpenCommandPath(), "-a", "Terminal", command); } else if (hasKdeTerminal.getValue()) { - return Arrays.asList("/usr/bin/konsole", "-e", command); + return Arrays.asList("konsole", "-e", command); } else if (hasGnomeTerminal.getValue()) { - return title != null ? Arrays.asList("/usr/bin/gnome-terminal", "-t", title, "-x", command) - : Arrays.asList("/usr/bin/gnome-terminal", "-x", command); + return title != null ? Arrays.asList("gnome-terminal", "-t", title, "-x", command) + : Arrays.asList("gnome-terminal", "-x", command); } else if (hasXTerm.getValue()) { - return title != null ? Arrays.asList("/usr/bin/xterm", "-T", title, "-e", command) - : Arrays.asList("/usr/bin/xterm", "-e", command); + return title != null ? Arrays.asList("xterm", "-T", title, "-e", command) + : Arrays.asList("xterm", "-e", command); } throw new UnsupportedOperationException("Unsupported OS/desktop: " + SystemInfo.OS_NAME + '/' + SystemInfo.SUN_DESKTOP); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java index 7147062c270f..9c3343a7e922 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java @@ -295,7 +295,7 @@ public class ShowFilePathAction extends AnAction { }); } else if (SystemInfo.hasXdgOpen()) { - GeneralCommandLine cmd = new GeneralCommandLine("/usr/bin/xdg-open", dir); + GeneralCommandLine cmd = new GeneralCommandLine("xdg-open", dir); ExecUtil.execAndGetOutput(cmd).checkSuccess(LOG); } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index 73423f53e7a6..0d0b681a496d 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -16,13 +16,13 @@ package com.intellij.openapi.util; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.PathExecLazyValue; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -112,24 +112,12 @@ public class SystemInfo extends SystemInfoRt { public static final boolean is64Bit = !is32Bit; public static final boolean isMacIntel64 = isMac && "x86_64".equals(OS_ARCH); - private static final NotNullLazyValue ourHasXdgOpen = new AtomicNotNullLazyValue() { - @NotNull - @Override - protected Boolean compute() { - return new File("/usr/bin/xdg-open").canExecute(); - } - }; + private static final NotNullLazyValue ourHasXdgOpen = new PathExecLazyValue("xdg-open"); public static boolean hasXdgOpen() { return isXWindow && ourHasXdgOpen.getValue(); } - private static final NotNullLazyValue ourHasXdgMime = new AtomicNotNullLazyValue() { - @NotNull - @Override - protected Boolean compute() { - return new File("/usr/bin/xdg-mime").canExecute(); - } - }; + private static final NotNullLazyValue ourHasXdgMime = new PathExecLazyValue("xdg-mime"); public static boolean hasXdgMime() { return isXWindow && ourHasXdgMime.getValue(); } diff --git a/platform/util/src/com/intellij/openapi/util/io/PathExecLazyValue.java b/platform/util/src/com/intellij/openapi/util/io/PathExecLazyValue.java new file mode 100644 index 000000000000..a539f04bffb3 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/io/PathExecLazyValue.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2016 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.openapi.util.io; + +import com.intellij.openapi.util.AtomicNotNullLazyValue; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.EnvironmentUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class PathExecLazyValue extends AtomicNotNullLazyValue { + private final String myName; + + public PathExecLazyValue(@NotNull String name) { + if (StringUtil.containsAnyChar(name, "/\\")) { + throw new IllegalArgumentException(name); + } + myName = name; + } + + @NotNull + @Override + protected Boolean compute() { + String path = EnvironmentUtil.getValue(SystemInfo.isWindows ? "Path" : "PATH"); + if (path != null) { + for (String dir : StringUtil.tokenize(path, File.pathSeparator)) { + if (new File(dir, myName).canExecute()) { + return true; + } + } + } + + return false; + } +} \ No newline at end of file diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/PathExecLazyValueTest.kt b/platform/util/testSrc/com/intellij/openapi/util/io/PathExecLazyValueTest.kt new file mode 100644 index 000000000000..c594b0849de9 --- /dev/null +++ b/platform/util/testSrc/com/intellij/openapi/util/io/PathExecLazyValueTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2016 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.openapi.util.io + +import com.intellij.openapi.util.SystemInfo +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.File + +class PathExecLazyValueTest { + @Test fun positive() { + val shell = File(if (SystemInfo.isWindows) "C:\\Windows\\System32\\cmd.exe" else "/bin/sh") + assertTrue(shell.canExecute()) + assertTrue(PathExecLazyValue(shell.name).value) + } + + @Test fun negative() { + assertFalse(PathExecLazyValue("no-one-in-his-right-mind-names-an-exec-like-this").value) + } + + @Test(expected = IllegalArgumentException::class) fun contract() { + PathExecLazyValue("bad\\path") + } +} \ No newline at end of file