Add JarFile caching

Cache root jar files in the Handler and also store nested jar files in
the JarEntryData.

See gh-1119
pull/1129/head
Phillip Webb 11 years ago
parent 88195292dd
commit a8777eda76

@ -18,11 +18,14 @@ package org.springframework.boot.loader.jar;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -55,6 +58,11 @@ public class Handler extends URLStreamHandler {
OPEN_CONNECTION_METHOD = method;
}
private static SoftReference<Map<File, JarFile>> rootFileCache;
static {
rootFileCache = new SoftReference<Map<File, JarFile>>(null);
}
private final Logger logger = Logger.getLogger(getClass().getName());
private final JarFile jarFile;
@ -153,7 +161,14 @@ public class Handler extends URLStreamHandler {
throw new IllegalStateException("Not a file URL");
}
String path = name.substring(FILE_PROTOCOL.length());
return new JarFile(new File(path));
File file = new File(path);
Map<File, JarFile> cache = rootFileCache.get();
JarFile jarFile = (cache == null ? null : cache.get(file));
if (jarFile == null) {
jarFile = new JarFile(file);
addToRootFileCache(file, jarFile);
}
return jarFile;
}
catch (Exception ex) {
throw new IOException("Unable to open root Jar file '" + name + "'", ex);
@ -168,4 +183,19 @@ public class Handler extends URLStreamHandler {
}
return jarFile.getNestedJarFile(jarEntry);
}
/**
* Add the given {@link JarFile} to the root file cache.
* @param sourceFile the source file to add
* @param jarFile the jar file.
*/
static void addToRootFileCache(File sourceFile, JarFile jarFile) {
Map<File, JarFile> cache = rootFileCache.get();
if (cache == null) {
cache = new ConcurrentHashMap<File, JarFile>();
rootFileCache = new SoftReference<Map<File, JarFile>>(cache);
}
cache.put(sourceFile, jarFile);
}
}

@ -53,6 +53,8 @@ public final class JarEntryData {
private SoftReference<JarEntry> entry;
JarFile nestedJar;
public JarEntryData(JarFile source, byte[] header, InputStream inputStream)
throws IOException {
this.source = source;

@ -322,13 +322,13 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD
* @return a {@link JarFile} for the entry
* @throws IOException
*/
public synchronized JarFile getNestedJarFile(final JarEntryData sourceEntry)
public synchronized JarFile getNestedJarFile(JarEntryData sourceEntry)
throws IOException {
try {
if (sourceEntry.isDirectory()) {
return getNestedJarFileFromDirectoryEntry(sourceEntry);
if (sourceEntry.nestedJar == null) {
sourceEntry.nestedJar = createJarFileFromEntry(sourceEntry);
}
return getNestedJarFileFromFileEntry(sourceEntry);
return sourceEntry.nestedJar;
}
catch (IOException ex) {
throw new IOException("Unable to open nested jar file '"
@ -336,7 +336,14 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD
}
}
private JarFile getNestedJarFileFromDirectoryEntry(JarEntryData sourceEntry)
private JarFile createJarFileFromEntry(JarEntryData sourceEntry) throws IOException {
if (sourceEntry.isDirectory()) {
return createJarFileFromDirectoryEntry(sourceEntry);
}
return createJarFileFromFileEntry(sourceEntry);
}
private JarFile createJarFileFromDirectoryEntry(JarEntryData sourceEntry)
throws IOException {
final AsciiBytes sourceName = sourceEntry.getName();
JarEntryFilter filter = new JarEntryFilter() {
@ -353,7 +360,7 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD
this.entries, filter);
}
private JarFile getNestedJarFileFromFileEntry(JarEntryData sourceEntry)
private JarFile createJarFileFromFileEntry(JarEntryData sourceEntry)
throws IOException {
if (sourceEntry.getMethod() != ZipEntry.STORED) {
throw new IllegalStateException("Unable to open nested compressed entry "

Loading…
Cancel
Save