Hi,
Our download manager http://jdownloader.org/ has millions of customers.
Some of them also suffered from the 13 year old bug
http://bugs.java.com/view_bug.do?bug_id=4523159.
The issue happens because '!/' is used as seperator between a jar file
and its content in URLStreamHandler and JarURLConnection.
I hereby want to suggest our bugfix.
It consists of a modified sun.net.www.protocol.jar.Handler and
sun.net.www.protocol.jar.JarURLConnection.
Instead of searching for '!/' and using the first hit, our customized
sun.net.www.protocol.jar.Handler loops through URL.getFile()
via indexof and substring and tests if it specifies the actual jar file
on disk.
In case the path contains '!/' we return a customized
sun.net.www.protocol.jar.JarURLConnection that overrides
getJarFileURL(),getJarEntry(),getEntryName() to provide the correct
information.
The one disadvantage of this bugfix is the additional IO introduced by
File.exits(), but that can be considered//neglectable/./
Please find attached our customized classes.
Best Regards
Daniel Wilhelm
PS: sean.cof...@oracle.com/sean.cof...@oracle.com told me to post this
to net-dev
--
-----------------------------------------------
Daniel Wilhelm
CTO, Co-Founder
Appwork GmbH
T: +49 (911)97923112 (Mo-Fr 9:00 - 17:00 CET)
Schwabacherstraße 117, 90763 Fürth, Germany
public class OracleWorkaroundJarHandler extends sun.net.www.protocol.jar.Handler {
@Override
protected URLConnection openConnection(final URL url) throws IOException {
try {
// System.out.println("openConnection:" + url);
final String path = url.getFile();
URL jarFileURL = null;
int lastIndex = 0;
if (path.startsWith("file:")) {
while (true) {
final int indexOf = path.indexOf(".jar", lastIndex);
if (indexOf > 0) {
final int index = indexOf + 4;
lastIndex = index;
final String jarFileName = path.substring(0, index);
if (jarFileName.contains("!/")) {
final File jarFile;
final URL jarURL;
try {
jarURL = new URL(jarFileName);
jarFile = new File(jarURL.toURI());
} catch (Exception e) {
e.printStackTrace();
continue;
}
if (jarFile.exists() && jarFile.isFile()) {
jarFileURL = jarURL;
break;
}
}
} else {
break;
}
}
}
if (jarFileURL != null) {
lastIndex++;// skip !
final URL finalJarFileURL = jarFileURL;
final String entryName;
if (++lastIndex != path.length()) {
final String tempEntryName = path.substring(lastIndex, path.length());
entryName = sun.net.www.ParseUtil.decode(tempEntryName);
} else {
entryName = null;
}
System.out.println("Workaround for URL.openConnection:" + finalJarFileURL + " Entry:" + entryName);
return new sun.net.www.protocol.jar.JarURLConnection(url, this) {
@Override
public URL getJarFileURL() {
return finalJarFileURL;
}
@Override
public JarEntry getJarEntry() throws IOException {
return getJarFile().getJarEntry(getEntryName());
}
@Override
public String getEntryName() {
return entryName;
}
};
}
} catch (final Throwable e) {
e.printStackTrace();
}
return super.openConnection(url);
}
}