package jetbrains.mps.core.tool.environment.classloading;
/*Generated by MPS */
import org.jetbrains.annotations.NonNls;
import java.net.URL;
import java.util.zip.ZipFile;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.core.tool.environment.common.FileUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.io.InputStream;
import java.io.FilterInputStream;
/*package*/ class JarLoader extends Loader {
private static final boolean myDebugTime = false;
@NonNls
private static final String JAR_PROTOCOL = "jar";
@NonNls
private static final String FILE_PROTOCOL = "file";
private static final long NS_THRESHOLD = 10000000;
private final URL myURL;
private final boolean myCanLockJar;
private final TimedComputable<ZipFile> myZipFileRef = new TimedComputable<ZipFile>() {
@NotNull
@Override
protected ZipFile calc() {
try {
final ZipFile zipFile = doGetZipFile();
if (zipFile == null) {
throw new RuntimeException("Can't load zip file");
}
return zipFile;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
/*package*/ JarLoader(URL url, boolean canLockJar) throws IOException {
super(new URL(JarLoader.JAR_PROTOCOL, "", -1, url + "!/"));
myURL = url;
myCanLockJar = canLockJar;
}
@Nullable
private ZipFile acquireZipFile() throws IOException {
if (myCanLockJar) {
return myZipFileRef.acquire();
}
return doGetZipFile();
}
private void releaseZipFile(final ZipFile zipFile) throws IOException {
if (myCanLockJar) {
myZipFileRef.release();
} else
if (zipFile != null) {
zipFile.close();
}
}
@Nullable
private ZipFile doGetZipFile() throws IOException {
if (JarLoader.FILE_PROTOCOL.equals(myURL.getProtocol())) {
String s = FileUtil.unquote(myURL.getFile());
if (!(new File(s).exists())) {
throw new FileNotFoundException(s);
} else {
return new ZipFile(s);
}
}
return null;
}
@Override
/*package*/ void dispose() {
myZipFileRef.dispose();
}
@Override
/*package*/ void buildCache(final ClasspathCache cache) throws IOException {
ZipFile zipFile = null;
try {
zipFile = acquireZipFile();
if (zipFile == null) {
return;
}
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
cache.addResourceEntry(zipEntry.getName(), this);
}
} finally {
releaseZipFile(zipFile);
}
}
@Nullable
@Override
/*package*/ Resource getResource(String name, boolean flag) {
final long started = (JarLoader.myDebugTime ? System.nanoTime() : 0);
ZipFile file = null;
try {
file = acquireZipFile();
if (file == null) {
return null;
}
ZipEntry entry = file.getEntry(name);
if (entry != null) {
return new JarLoader.MyResource(entry, new URL(getBaseURL(), name));
}
} catch (Exception e) {
return null;
} finally {
try {
releaseZipFile(file);
} catch (IOException ignored) {
}
final long doneFor = (JarLoader.myDebugTime ? System.nanoTime() - started : 0);
if (doneFor > JarLoader.NS_THRESHOLD) {
System.out.println(doneFor / 1000000 + " ms for jar loader get resource:" + name);
}
}
return null;
}
@NonNls
@Override
public String toString() {
return "JarLoader [" + myURL + "]";
}
private class MyResource extends Resource {
private final ZipEntry myEntry;
private final URL myUrl;
public MyResource(ZipEntry name, URL url) {
myEntry = name;
myUrl = url;
}
@Override
public URL getURL() {
return myUrl;
}
@Override
protected InputStream getInputStream() throws IOException {
final boolean[] wasReleased = {false};
ZipFile file = null;
try {
file = acquireZipFile();
if (file == null) {
releaseZipFile(file);
return null;
}
final InputStream inputStream = file.getInputStream(myEntry);
if (inputStream == null) {
releaseZipFile(file);
return null;
// if entry was not found
}
final ZipFile finalFile = file;
return new FilterInputStream(inputStream) {
private boolean myClosed = false;
@Override
public void close() throws IOException {
super.close();
if (!(myClosed)) {
releaseZipFile(finalFile);
}
myClosed = true;
wasReleased[0] = true;
}
};
} catch (IOException e) {
e.printStackTrace();
releaseZipFile(file);
assert !(wasReleased[0]);
return null;
}
}
@Override
protected int getContentLength() {
return (int) myEntry.getSize();
}
}
}