
org.jruby.util.JarCache Maven / Gradle / Ivy
package org.jruby.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.security.AccessControlException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.jruby.util.cli.Options;
import static org.jruby.RubyFile.canonicalize;
/**
* Instances of JarCache provides jar index information.
*
*
* Implementation is threadsafe.
*
* Since loading index information is O(jar-entries) we cache the snapshot in a WeakHashMap.
* The implementation pays attention to lastModified timestamp of the jar and will invalidate
* the cache entry if jar has been updated since the snapshot calculation.
*
*
* ******************************************************************************************
* DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER
* ******************************************************************************************
*
* The spec for this cache is disabled currently for #2655, because of last-modified time
* oddities on CloudBees. Please be cautious modifying this code and make sure you run the
* associated spec locally.
*/
class JarCache {
static class JarIndex {
private static final String ROOT_KEY = "";
private final Map cachedDirEntries;
private final JarFile jar;
private final long lastModified;
private Long lastModifiedExpiration;
JarIndex(String jarPath) throws IOException {
this.jar = new JarFile(jarPath);
this.lastModified = getLastModified(jarPath);
Map> mutableCache = new HashMap<>();
// Always have a root directory
mutableCache.put(ROOT_KEY, new HashSet<>());
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String path = entry.getName();
int lastPathSep;
while ((lastPathSep = path.lastIndexOf('/')) != -1) {
String dirPath = path.substring(0, lastPathSep);
HashSet paths = mutableCache.get(dirPath);
if (paths == null) {
mutableCache.put(dirPath, paths = new HashSet<>());
}
String entryPath = path.substring(lastPathSep + 1);
// "" is not really a child path, even if we see foo/ entry
if (entryPath.length() > 0) paths.add(entryPath);
path = dirPath;
}
mutableCache.get(ROOT_KEY).add(path);
}
Map cachedDirEntries = new HashMap<>(mutableCache.size() + 8, 1);
for (Map.Entry> entry : mutableCache.entrySet()) {
Set value = entry.getValue();
cachedDirEntries.put(entry.getKey(), value.toArray(new String[value.size()]));
}
this.cachedDirEntries = Collections.unmodifiableMap(cachedDirEntries);
}
/**
* Determines the last modification timestamp of a file.
*
© 2015 - 2025 Weber Informatics LLC | Privacy Policy