mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Add option to tolerate unexpected problem with jar file (IDEA-163705)
This commit is contained in:
@@ -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<URL, Loader> myLoadersMap = new HashMap<URL, Loader>();
|
||||
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<URL> 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) {
|
||||
|
||||
@@ -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<JarMemoryLoader> myMemoryLoader;
|
||||
private volatile SoftReference<ZipFile> myZipFileSoftReference; // Used only when myCanLockJar==true
|
||||
private final Map<Resource.Attribute, String> myAttributes;
|
||||
private volatile SoftReference<Attributes> 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<Attributes>(manifestAttributes);
|
||||
|
||||
if (preloadJarContents) {
|
||||
if (configuration.myPreloadJarContents) {
|
||||
JarMemoryLoader loader = JarMemoryLoader.load(zipFile, getBaseURL(), myAttributes);
|
||||
if (loader != null) {
|
||||
myMemoryLoader = new SoftReference<JarMemoryLoader>(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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user