Commit a8777eda authored by Phillip Webb's avatar Phillip Webb

Add JarFile caching

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

See gh-1119
parent 88195292
...@@ -18,11 +18,14 @@ package org.springframework.boot.loader.jar; ...@@ -18,11 +18,14 @@ package org.springframework.boot.loader.jar;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLStreamHandler; import java.net.URLStreamHandler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
...@@ -55,6 +58,11 @@ public class Handler extends URLStreamHandler { ...@@ -55,6 +58,11 @@ public class Handler extends URLStreamHandler {
OPEN_CONNECTION_METHOD = method; 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 Logger logger = Logger.getLogger(getClass().getName());
private final JarFile jarFile; private final JarFile jarFile;
...@@ -153,7 +161,14 @@ public class Handler extends URLStreamHandler { ...@@ -153,7 +161,14 @@ public class Handler extends URLStreamHandler {
throw new IllegalStateException("Not a file URL"); throw new IllegalStateException("Not a file URL");
} }
String path = name.substring(FILE_PROTOCOL.length()); 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) { catch (Exception ex) {
throw new IOException("Unable to open root Jar file '" + name + "'", ex); throw new IOException("Unable to open root Jar file '" + name + "'", ex);
...@@ -168,4 +183,19 @@ public class Handler extends URLStreamHandler { ...@@ -168,4 +183,19 @@ public class Handler extends URLStreamHandler {
} }
return jarFile.getNestedJarFile(jarEntry); 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 { ...@@ -53,6 +53,8 @@ public final class JarEntryData {
private SoftReference<JarEntry> entry; private SoftReference<JarEntry> entry;
JarFile nestedJar;
public JarEntryData(JarFile source, byte[] header, InputStream inputStream) public JarEntryData(JarFile source, byte[] header, InputStream inputStream)
throws IOException { throws IOException {
this.source = source; this.source = source;
......
...@@ -322,13 +322,13 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD ...@@ -322,13 +322,13 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD
* @return a {@link JarFile} for the entry * @return a {@link JarFile} for the entry
* @throws IOException * @throws IOException
*/ */
public synchronized JarFile getNestedJarFile(final JarEntryData sourceEntry) public synchronized JarFile getNestedJarFile(JarEntryData sourceEntry)
throws IOException { throws IOException {
try { try {
if (sourceEntry.isDirectory()) { if (sourceEntry.nestedJar == null) {
return getNestedJarFileFromDirectoryEntry(sourceEntry); sourceEntry.nestedJar = createJarFileFromEntry(sourceEntry);
} }
return getNestedJarFileFromFileEntry(sourceEntry); return sourceEntry.nestedJar;
} }
catch (IOException ex) { catch (IOException ex) {
throw new IOException("Unable to open nested jar file '" throw new IOException("Unable to open nested jar file '"
...@@ -336,7 +336,14 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD ...@@ -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 { throws IOException {
final AsciiBytes sourceName = sourceEntry.getName(); final AsciiBytes sourceName = sourceEntry.getName();
JarEntryFilter filter = new JarEntryFilter() { JarEntryFilter filter = new JarEntryFilter() {
...@@ -353,7 +360,7 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD ...@@ -353,7 +360,7 @@ public class JarFile extends java.util.jar.JarFile implements Iterable<JarEntryD
this.entries, filter); this.entries, filter);
} }
private JarFile getNestedJarFileFromFileEntry(JarEntryData sourceEntry) private JarFile createJarFileFromFileEntry(JarEntryData sourceEntry)
throws IOException { throws IOException {
if (sourceEntry.getMethod() != ZipEntry.STORED) { if (sourceEntry.getMethod() != ZipEntry.STORED) {
throw new IllegalStateException("Unable to open nested compressed entry " throw new IllegalStateException("Unable to open nested compressed entry "
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment