private void addTldLocationsFromJarDirectoryEntryURL()

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;
            }
        }
    }