From c33dc4a870a3ff3d28fac00ce748755853bdd7f5 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 26 Aug 2013 00:18:33 +0400 Subject: [PATCH] platform: unified loading of system libraries (done right) --- .../ide/BootstrapClassLoaderUtil.java | 1 - .../src/com/intellij/idea/StartupUtil.java | 3 +- .../src/com/intellij/ui/win/RecentTasks.java | 3 +- .../openapi/util/io/win32/IdeaWin32.java | 36 +---------- .../intellij/util/lang/UrlClassLoader.java | 64 +++++++------------ 5 files changed, 31 insertions(+), 76 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index 179d0d3c20e3..d1dabcb94e18 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -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 diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index 2417910a504b..76f34c61588a 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java index 12ad39f4cea2..99524492ed6d 100644 --- a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java +++ b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java @@ -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.currentThread()); static { - System.loadLibrary("jumpListBridge"); + UrlClassLoader.loadPlatformLibrary("jumpListBridge"); } private synchronized static void init() { diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java index 4d89732dd0fd..ce0ec3da03e1 100644 --- a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java +++ b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java @@ -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"); } diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java index 70a71f9787f6..b6f981638294 100644 --- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java +++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java @@ -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 myURLs; private final ClassPath myClassPath; - private final Set 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.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 ""; + } }