diff --git a/platform/util/src/com/intellij/util/lang/ClassPath.java b/platform/util/src/com/intellij/util/lang/ClassPath.java index f333023a55d8..0e4e0e8df701 100644 --- a/platform/util/src/com/intellij/util/lang/ClassPath.java +++ b/platform/util/src/com/intellij/util/lang/ClassPath.java @@ -20,12 +20,14 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import java.util.HashMap; import com.intellij.util.containers.Stack; import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.Nullable; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -47,13 +49,14 @@ public class ClassPath { private final Map myLoadersMap = new HashMap(); private final ClasspathCache myCache = new ClasspathCache(); - private final boolean myCanLockJars; + final boolean myCanLockJars; // true implies that the .jar file will not be modified in the lifetime of the JarLoader private final boolean myCanUseCache; private final boolean myAcceptUnescapedUrls; - private final boolean myPreloadJarContents; - private final boolean myCanHavePersistentIndex; + final boolean myPreloadJarContents; + final boolean myCanHavePersistentIndex; @Nullable private final CachePoolImpl myCachePool; @Nullable private final UrlClassLoader.CachingCondition myCachingCondition; + final boolean myLogErrorOnMissingJar; public ClassPath(List urls, boolean canLockJars, @@ -62,7 +65,8 @@ public class ClassPath { boolean preloadJarContents, boolean canHavePersistentIndex, @Nullable CachePoolImpl cachePool, - @Nullable UrlClassLoader.CachingCondition cachingCondition) { + @Nullable UrlClassLoader.CachingCondition cachingCondition, + boolean logErrorOnMissingJar) { myCanLockJars = canLockJars; myCanUseCache = canUseCache; myAcceptUnescapedUrls = acceptUnescapedUrls; @@ -70,6 +74,7 @@ public class ClassPath { myCachePool = cachePool; myCachingCondition = cachingCondition; myCanHavePersistentIndex = canHavePersistentIndex; + myLogErrorOnMissingJar = logErrorOnMissingJar; push(urls); } @@ -199,7 +204,7 @@ public class ClassPath { return new FileLoader(url, index, myCanHavePersistentIndex); } if (file.isFile()) { - Loader loader = new JarLoader(url, myCanLockJars, index, myPreloadJarContents, this); + Loader loader = new JarLoader(url, index, this); if (processRecursively) { String[] referencedJars = loadManifestClasspath((JarLoader)loader); if (referencedJars != null) { diff --git a/platform/util/src/com/intellij/util/lang/JarLoader.java b/platform/util/src/com/intellij/util/lang/JarLoader.java index 01208487513e..47408bd2e2e1 100644 --- a/platform/util/src/com/intellij/util/lang/JarLoader.java +++ b/platform/util/src/com/intellij/util/lang/JarLoader.java @@ -44,32 +44,32 @@ class JarLoader extends Loader { pair(Resource.Attribute.IMPL_VENDOR, Attributes.Name.IMPLEMENTATION_VENDOR)); private final String myFilePath; - private final boolean myCanLockJar; // true implies that the .jar file will not be modified in the lifetime of the JarLoader + private final ClassPath myConfiguration; private SoftReference myMemoryLoader; private volatile SoftReference myZipFileSoftReference; // Used only when myCanLockJar==true private final Map myAttributes; private volatile SoftReference myCachedManifestAttributes; - JarLoader(URL url, boolean canLockJar, int index, boolean preloadJarContents, ClassPath classPath) throws IOException { + JarLoader(URL url, int index, ClassPath configuration) throws IOException { super(new URL("jar", "", -1, url + "!/"), index); myFilePath = urlToFilePath(url); - myCanLockJar = canLockJar; + myConfiguration = configuration; ZipFile zipFile = getZipFile(); // IOException from opening is propagated to caller if zip file isn't valid, try { - Attributes manifestAttributes = classPath.getManifestData(url); + Attributes manifestAttributes = configuration.getManifestData(url); if (manifestAttributes == null) { ZipEntry entry = zipFile.getEntry(JarFile.MANIFEST_NAME); manifestAttributes = loadManifestAttributes(entry != null ? zipFile.getInputStream(entry) : null); if (manifestAttributes == null) manifestAttributes = new Attributes(0); - classPath.cacheManifestData(url, manifestAttributes); + configuration.cacheManifestData(url, manifestAttributes); } myAttributes = getAttributes(manifestAttributes); myCachedManifestAttributes = new SoftReference(manifestAttributes); - if (preloadJarContents) { + if (configuration.myPreloadJarContents) { JarMemoryLoader loader = JarMemoryLoader.load(zipFile, getBaseURL(), myAttributes); if (loader != null) { myMemoryLoader = new SoftReference(loader); @@ -211,7 +211,12 @@ class JarLoader extends Loader { } protected void error(String message, Throwable t) { - Logger.getInstance(JarLoader.class).error(message, t); + if (myConfiguration.myLogErrorOnMissingJar) { + Logger.getInstance(JarLoader.class).error(message, t); + } + else { + Logger.getInstance(JarLoader.class).warn(message, t); + } } private static final Object ourLock = new Object(); @@ -220,7 +225,7 @@ class JarLoader extends Loader { private ZipFile getZipFile() throws IOException { // This code is executed at least 100K times (O(number of classes needed to load)) and it takes considerable time to open ZipFile's // such number of times so we store reference to ZipFile if we allowed to lock the file (assume it isn't changed) - if (myCanLockJar) { + if (myConfiguration.myCanLockJars) { ZipFile zipFile = SoftReference.dereference(myZipFileSoftReference); if (zipFile != null) return zipFile; @@ -241,7 +246,7 @@ class JarLoader extends Loader { private void releaseZipFile(ZipFile zipFile) throws IOException { // Closing of zip file when myCanLockJar=true happens in ZipFile.finalize - if (!myCanLockJar) { + if (!myConfiguration.myCanLockJars) { zipFile.close(); } } diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java index 2bd6b2a45e74..24e4bded6c2e 100644 --- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java +++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java @@ -92,6 +92,7 @@ public class UrlClassLoader extends ClassLoader { private boolean myAcceptUnescaped; private boolean myPreload = true; private boolean myAllowBootstrapResources; + private boolean myErrorOnMissingJar = true; @Nullable private CachePoolImpl myCachePool; @Nullable private CachingCondition myCachingCondition; @@ -137,6 +138,7 @@ public class UrlClassLoader extends ClassLoader { public Builder allowUnescaped() { myAcceptUnescaped = true; return this; } public Builder noPreload() { myPreload = false; return this; } public Builder allowBootstrapResources() { myAllowBootstrapResources = true; return this; } + public Builder setLogErrorOnMissingJar(boolean log) {myErrorOnMissingJar = log; return this; } /** @deprecated use {@link #allowUnescaped()} (to be removed in IDEA 2018) */ public Builder allowUnescaped(boolean acceptUnescaped) { myAcceptUnescaped = acceptUnescaped; return this; } @@ -177,7 +179,8 @@ public class UrlClassLoader extends ClassLoader { @NotNull protected final ClassPath createClassPath(@NotNull Builder builder) { return new ClassPath(myURLs, builder.myLockJars, builder.myUseCache, builder.myAcceptUnescaped, builder.myPreload, - builder.myUsePersistentClasspathIndex, builder.myCachePool, builder.myCachingCondition); + builder.myUsePersistentClasspathIndex, builder.myCachePool, builder.myCachingCondition, + builder.myErrorOnMissingJar); } public static URL internProtocol(@NotNull URL url) {