mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
platform: unified loading of system libraries (done right)
This commit is contained in:
@@ -62,7 +62,6 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore {
|
||||
addAdditionalClassPath(classpath);
|
||||
UrlClassLoader newClassLoader = UrlClassLoader.build()
|
||||
.urls(filterClassPath(classpath))
|
||||
.nativeLibs("IdeaWin32", "focusKiller", "jumpListBridge")
|
||||
.allowLock().useCache().get();
|
||||
|
||||
// prepare plugins
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.SnappyInitializer;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
import com.intellij.util.text.DateFormatUtilRt;
|
||||
import com.sun.jna.Native;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -246,7 +247,7 @@ public class StartupUtil {
|
||||
|
||||
if (SystemInfo.isWin2kOrNewer && !Main.isHeadless()) {
|
||||
try {
|
||||
System.loadLibrary("focusKiller");
|
||||
UrlClassLoader.loadPlatformLibrary("focusKiller");
|
||||
log.info("Using \"FocusKiller\" library to prevent focus stealing.");
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.ui.win;
|
||||
|
||||
import com.intellij.idea.StartupUtil;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -29,7 +30,7 @@ public class RecentTasks {
|
||||
new WeakReference<Thread>(Thread.currentThread());
|
||||
|
||||
static {
|
||||
System.loadLibrary("jumpListBridge");
|
||||
UrlClassLoader.loadPlatformLibrary("jumpListBridge");
|
||||
}
|
||||
|
||||
private synchronized static void init() {
|
||||
|
||||
@@ -15,16 +15,12 @@
|
||||
*/
|
||||
package com.intellij.openapi.util.io.win32;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Do not use this class directly.
|
||||
*
|
||||
@@ -38,36 +34,10 @@ public class IdeaWin32 {
|
||||
private static final IdeaWin32 ourInstance;
|
||||
|
||||
static {
|
||||
boolean available = false;
|
||||
if (SystemInfo.isWin2kOrNewer) {
|
||||
String libName = SystemInfo.is64Bit ? "IdeaWin64.dll" : "IdeaWin32.dll";
|
||||
try {
|
||||
String path = PathManager.getBinPath() + "/" + libName;
|
||||
if (!new File(path).exists()) {
|
||||
path = PathManager.getHomePath() + "/community/bin/win/" + libName;
|
||||
if (!new File(path).exists()) {
|
||||
path = PathManager.getHomePath() + "/bin/win/" + libName;
|
||||
if (!new File(path).exists()) {
|
||||
path = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libName;
|
||||
if (!new File(path).exists()) {
|
||||
throw new FileNotFoundException("Native filesystem .dll is missing (path=" + PathManager.getBinPath() +
|
||||
" content=" + Arrays.toString(new File(PathManager.getBinPath()).list()) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG.debug("Loading " + path);
|
||||
System.load(path);
|
||||
available = true;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("Failed to load native filesystem for Windows", t);
|
||||
}
|
||||
}
|
||||
|
||||
IdeaWin32 instance = null;
|
||||
if (available) {
|
||||
if (SystemInfo.isWin2kOrNewer) {
|
||||
try {
|
||||
UrlClassLoader.loadPlatformLibrary("IdeaWin32");
|
||||
instance = new IdeaWin32();
|
||||
LOG.info("Native filesystem for Windows is operational");
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.util.lang;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.win32.IdeaWin32;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -31,7 +32,10 @@ import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
public class UrlClassLoader extends ClassLoader {
|
||||
@NonNls static final String CLASS_EXTENSION = ".class";
|
||||
@@ -43,7 +47,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
private boolean myUseCache = false;
|
||||
private boolean myAcceptUnescaped = false;
|
||||
private boolean myPreload = true;
|
||||
private String[] myNativeLibs = null;
|
||||
|
||||
private Builder() { }
|
||||
|
||||
@@ -56,7 +59,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
public Builder useCache(boolean useCache) { myUseCache = useCache; return this; }
|
||||
public Builder allowUnescaped() { myAcceptUnescaped = true; return this; }
|
||||
public Builder noPreload() { myPreload = false; return this; }
|
||||
public Builder nativeLibs(String... libNames) { myNativeLibs = libNames; return this; }
|
||||
public UrlClassLoader get() { return new UrlClassLoader(this); }
|
||||
}
|
||||
|
||||
@@ -66,7 +68,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
|
||||
private final List<URL> myURLs;
|
||||
private final ClassPath myClassPath;
|
||||
private final Set<String> myNativeLibs;
|
||||
|
||||
/** @deprecated use {@link #build()} (to remove in IDEA 14) */
|
||||
public UrlClassLoader(@NotNull ClassLoader parent) {
|
||||
@@ -98,7 +99,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
}
|
||||
});
|
||||
myClassPath = new ClassPath(myURLs, lockJars, useCache, allowUnescaped, preload);
|
||||
myNativeLibs = Collections.emptySet();
|
||||
}
|
||||
|
||||
protected UrlClassLoader(@NotNull Builder builder) {
|
||||
@@ -110,7 +110,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
}
|
||||
});
|
||||
myClassPath = new ClassPath(myURLs, builder.myLockJars, builder.myUseCache, builder.myAcceptUnescaped, builder.myPreload);
|
||||
myNativeLibs = builder.myNativeLibs != null ? ContainerUtil.newHashSet(builder.myNativeLibs) : Collections.<String>emptySet();
|
||||
}
|
||||
|
||||
public static URL internProtocol(@NotNull URL url) {
|
||||
@@ -151,12 +150,6 @@ public class UrlClassLoader extends ClassLoader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Class _findClass(@NotNull String name) {
|
||||
Resource res = myClassPath.getResource(name.replace('.', '/').concat(CLASS_EXTENSION), false);
|
||||
@@ -233,38 +226,22 @@ public class UrlClassLoader extends ClassLoader {
|
||||
return myClassPath.getResources(name, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String findLibrary(String libName) {
|
||||
if (BinPathHolder.path != null && myNativeLibs.contains(libName)) {
|
||||
String fileName = mapLibraryName(libName);
|
||||
return BinPathHolder.path + File.separator + fileName;
|
||||
}
|
||||
public static void loadPlatformLibrary(@NotNull String libName) {
|
||||
String libFileName = mapLibraryName(libName);
|
||||
String libPath = PathManager.getBinPath() + "/" + libFileName;
|
||||
|
||||
return super.findLibrary(libName);
|
||||
}
|
||||
|
||||
private static class BinPathHolder {
|
||||
private static final String path;
|
||||
|
||||
static {
|
||||
String homePath = PathManager.getHomePath();
|
||||
if (new File(homePath, ".idea").exists()) {
|
||||
if (new File(homePath, "community").exists()) {
|
||||
homePath += File.separator + "community";
|
||||
if (!new File(libPath).exists()) {
|
||||
String platform = getPlatformName();
|
||||
if (!new File(libPath = PathManager.getHomePath() + "/community/bin/" + platform + libFileName).exists()) {
|
||||
if (!new File(libPath = PathManager.getHomePath() + "/bin/" + platform + libFileName).exists()) {
|
||||
if (!new File(libPath = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libFileName).exists()) {
|
||||
throw new UnsatisfiedLinkError("'" + libFileName + "' not found among " + Arrays.toString(new File(PathManager.getBinPath()).listFiles()));
|
||||
}
|
||||
}
|
||||
|
||||
String libDir = null;
|
||||
String prefix = homePath + File.separator + "bin" + File.separator;
|
||||
if (SystemInfo.isWindows) libDir = prefix + "win";
|
||||
else if (SystemInfo.isMac) libDir = prefix + "mac";
|
||||
else if (SystemInfo.isLinux) libDir = prefix + "linux";
|
||||
|
||||
path = libDir;
|
||||
}
|
||||
else {
|
||||
path = PathManager.getBinPath();
|
||||
}
|
||||
}
|
||||
|
||||
System.load(libPath);
|
||||
}
|
||||
|
||||
private static String mapLibraryName(String libName) {
|
||||
@@ -278,4 +255,11 @@ public class UrlClassLoader extends ClassLoader {
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
private static String getPlatformName() {
|
||||
if (SystemInfo.isWindows) return "win/";
|
||||
else if (SystemInfo.isMac) return "mac/";
|
||||
else if (SystemInfo.isLinux) return "linux/";
|
||||
else return "";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user