/* * Written by Dawid Kurzyniec and released to the public domain, as explained * at http://creativecommons.org/licenses/publicdomain */ package edu.emory.mathcs.util.classloader.jar; import java.net.*; import java.io.*; import java.util.jar.*; import java.security.*; /** * Alternative implementation of {@link java.net.JarURLConnection} which * supports customizable JAR caching policies. It addresses bugs * 4405789, 4388666, 4639900 in Java Bug Parade. SUN recommends to disable * caches completely as a workaround for those bugs; however, this may * significantly affect performance in case of resources downloaded from the * network. This class is a part of the solution that allows to tailor the * caching policy according to the program needs, with cache-per-classloader * default policy. * * @see edu.emory.mathcs.util.classloader.jar.JarURLStreamHandler * * @author Dawid Kurzyniec * @version 1.0 */ public class JarURLConnection extends java.net.JarURLConnection { final JarOpener opener; boolean connected; JarFile jfile; JarEntry jentry; /** * Creates JarURLConnection for a given URL, using specified JAR opener. * @param url the URL to open connection to * @param opener the JAR opener to use * @throws java.io.IOException */ public JarURLConnection(URL url, JarOpener opener) throws IOException { super(url); this.opener = opener; } public synchronized void connect() throws IOException { if (connected) return; jfile = opener.openJarFile(this); if (jfile != null && getEntryName() != null) { jentry = jfile.getJarEntry(getEntryName()); if (jentry == null) { throw new FileNotFoundException("Entry " + getEntryName() + " not found in " + getJarFileURL()); } } connected = true; } public synchronized JarFile getJarFile() throws IOException { connect(); return jfile; } public synchronized JarEntry getJarEntry() throws IOException { connect(); return jentry; } public synchronized InputStream getInputStream() throws IOException { connect(); return jfile.getInputStream(jentry); } public Permission getPermission() throws IOException { return getJarFileURL().openConnection().getPermission(); } /** * Abstraction of JAR opener which allows to implement various caching * policies. The opener receives URL pointing to the JAR file, along * with other meta-information, as a JarURLConnection instance. Then it has * to download the file (if it is remote) and open it. * * @author Dawid Kurzyniec * @version 1.0 */ public static interface JarOpener { /** * Given the URL connection (not yet connected), return JarFile * representing the resource. This method is invoked as a part of * the {@link #connect} method in JarURLConnection. * * @param conn the connection for which the JAR file is required * @return opened JAR file * @throws java.io.IOException if I/O error occurs */ public JarFile openJarFile(java.net.JarURLConnection conn) throws IOException; } }