in freemarker-javax-servlet/src/main/java/freemarker/ext/jsp/TaglibFactory.java [657:741]
private void addTldLocationsFromJarDirectoryEntryURL(final URL jarBaseEntryUrl)
throws IOException, MalformedURLException, SAXException {
// Null for non-random-access backing resource:
final JarFile jarFile;
// Not null; the path of the directory *inside* the JAR where we will search
// (like "/META-INF/" in "jar:file:/C:/foo%20bar/baaz.jar!/META-INF/"):
final String baseEntryPath;
// Null when URLConnection is used
// (like "file:/C:/foo%20bar/baaz.jar" in "jar:file:/C:/foo%20bar/baaz.jar!/META-INF/"):
final String rawJarContentUrlEF;
{
final URLConnection urlCon = jarBaseEntryUrl.openConnection();
if (!test_emulateNoJarURLConnections && urlCon instanceof JarURLConnection) {
final JarURLConnection jarCon = (JarURLConnection) urlCon;
jarFile = jarCon.getJarFile();
rawJarContentUrlEF = null; // Not used as we have a JarURLConnection
baseEntryPath = normalizeJarEntryPath(jarCon.getEntryName(), true);
if (baseEntryPath == null) {
throw newFailedToExtractEntryPathException(jarBaseEntryUrl);
}
} else {
final String jarBaseEntryUrlEF = jarBaseEntryUrl.toExternalForm();
final int jarEntrySepIdx = jarBaseEntryUrlEF.indexOf(JAR_URL_ENTRY_PATH_START);
if (jarEntrySepIdx == -1) {
throw newFailedToExtractEntryPathException(jarBaseEntryUrl);
}
rawJarContentUrlEF = jarBaseEntryUrlEF.substring(jarBaseEntryUrlEF.indexOf(':') + 1, jarEntrySepIdx);
baseEntryPath = normalizeJarEntryPath(
jarBaseEntryUrlEF.substring(jarEntrySepIdx + JAR_URL_ENTRY_PATH_START.length()), true);
File rawJarContentAsFile = urlToFileOrNull(new URL(rawJarContentUrlEF));
jarFile = rawJarContentAsFile != null ? new JarFile(rawJarContentAsFile) : null;
}
}
if (jarFile != null) { // jarFile == null => fall back to streamed access
if (LOG.isDebugEnabled()) {
LOG.debug("Scanning for " + META_INF_ABS_PATH + "**/*.tld-s in random access mode: "
+ jarBaseEntryUrl);
}
for (Enumeration/*<JarEntry>*/ entries = jarFile.entries(); entries.hasMoreElements(); ) {
final JarEntry curEntry = (JarEntry) entries.nextElement();
final String curEntryPath = normalizeJarEntryPath(curEntry.getName(), false);
if (curEntryPath.startsWith(baseEntryPath) && curEntryPath.endsWith(".tld")) {
final String curEntryBaseRelativePath = curEntryPath.substring(baseEntryPath.length());
final URL tldUrl = createJarEntryUrl(jarBaseEntryUrl, curEntryBaseRelativePath);
addTldLocationFromTld(new JarEntryUrlTldLocation(tldUrl, null));
}
}
} else {
// Not a random-access file, so we fall back to the slower ZipInputStream approach.
if (LOG.isDebugEnabled()) {
LOG.debug("Scanning for " + META_INF_ABS_PATH + "**/*.tld-s in stream mode (slow): "
+ rawJarContentUrlEF);
}
try (InputStream in = new URL(rawJarContentUrlEF).openStream()) {
ZipInputStream zipIn = new ZipInputStream(in);
try {
while (true) {
ZipEntry curEntry = zipIn.getNextEntry();
if (curEntry == null) break;
String curEntryPath = normalizeJarEntryPath(curEntry.getName(), false);
if (curEntryPath.startsWith(baseEntryPath) && curEntryPath.endsWith(".tld")) {
final String curEntryBaseRelativePath = curEntryPath.substring(baseEntryPath.length());
final URL tldUrl = createJarEntryUrl(jarBaseEntryUrl, curEntryBaseRelativePath);
addTldLocationFromTld(zipIn, new JarEntryUrlTldLocation(tldUrl, null));
}
}
} finally {
zipIn.close();
}
} catch (ZipException e) {
// ZipException messages miss the zip URL
IOException ioe = new IOException("Error reading ZIP (see cause excepetion) from: "
+ rawJarContentUrlEF);
try {
ioe.initCause(e);
} catch (Exception e2) {
throw e;
}
throw ioe;
}
}
}