/* ------------------------------------------------------------ */
  private List<String> listEntries() {
    checkConnection();

    ArrayList<String> list = new ArrayList<String>(32);
    JarFile jarFile = _jarFile;
    if (jarFile == null) {
      try {
        JarURLConnection jc = (JarURLConnection) ((new URL(_jarUrl)).openConnection());
        jc.setUseCaches(getUseCaches());
        jarFile = jc.getJarFile();
      } catch (Exception e) {

        e.printStackTrace();
        LOG.ignore(e);
      }
      if (jarFile == null) throw new IllegalStateException();
    }

    Enumeration e = jarFile.entries();
    String dir = _urlString.substring(_urlString.indexOf("!/") + 2);
    while (e.hasMoreElements()) {

      JarEntry entry = (JarEntry) e.nextElement();
      String name = entry.getName().replace('\\', '/');
      if (!name.startsWith(dir) || name.length() == dir.length()) {
        continue;
      }
      String listName = name.substring(dir.length());
      int dash = listName.indexOf('/');
      if (dash >= 0) {
        // when listing jar:file urls, you get back one
        // entry for the dir itself, which we ignore
        if (dash == 0 && listName.length() == 1) continue;
        // when listing jar:file urls, all files and
        // subdirs have a leading /, which we remove
        if (dash == 0) listName = listName.substring(dash + 1, listName.length());
        else listName = listName.substring(0, dash + 1);

        if (list.contains(listName)) continue;
      }

      list.add(listName);
    }

    return list;
  }
  /** Returns true if the represented resource exists. */
  @Override
  public boolean exists() {
    if (_exists) return true;

    if (_urlString.endsWith("!/")) {

      String file_url = _urlString.substring(4, _urlString.length() - 2);
      try {
        return newResource(file_url).exists();
      } catch (Exception e) {
        LOG.ignore(e);
        return false;
      }
    }

    boolean check = checkConnection();

    // Is this a root URL?
    if (_jarUrl != null && _path == null) {
      // Then if it exists it is a directory
      _directory = check;
      return true;
    } else {
      // Can we find a file for it?
      JarFile jarFile = null;
      if (check)
        // Yes
        jarFile = _jarFile;
      else {
        // No - so lets look if the root entry exists.
        try {
          JarURLConnection c = (JarURLConnection) ((new URL(_jarUrl)).openConnection());
          c.setUseCaches(getUseCaches());
          jarFile = c.getJarFile();
        } catch (Exception e) {
          LOG.ignore(e);
        }
      }

      // Do we need to look more closely?
      if (jarFile != null && _entry == null && !_directory) {
        // OK - we have a JarFile, lets look at the entries for our path
        Enumeration<JarEntry> e = jarFile.entries();
        while (e.hasMoreElements()) {
          JarEntry entry = e.nextElement();
          String name = entry.getName().replace('\\', '/');

          // Do we have a match
          if (name.equals(_path)) {
            _entry = entry;
            // Is the match a directory
            _directory = _path.endsWith("/");
            break;
          } else if (_path.endsWith("/")) {
            if (name.startsWith(_path)) {
              _directory = true;
              break;
            }
          } else if (name.startsWith(_path)
              && name.length() > _path.length()
              && name.charAt(_path.length()) == '/') {
            _directory = true;
            break;
          }
        }

        if (_directory && !_urlString.endsWith("/")) {
          _urlString += "/";
          try {
            _url = new URL(_urlString);
          } catch (MalformedURLException ex) {
            LOG.warn(ex);
          }
        }
      }
    }

    _exists = (_directory || _entry != null);
    return _exists;
  }
  /** Constructor. */
  public TagLibraryInfoImpl(
      JspCompilationContext ctxt,
      ParserController pc,
      PageInfo pi,
      String prefix,
      String uriIn,
      String[] location,
      ErrorDispatcher err)
      throws JasperException {
    super(prefix, uriIn);

    this.ctxt = ctxt;
    this.parserController = pc;
    this.pi = pi;
    this.err = err;
    InputStream in = null;
    JarFile jarFile = null;

    if (location == null) {
      // The URI points to the TLD itself or to a JAR file in which the
      // TLD is stored
      location = generateTLDLocation(uri, ctxt);
    }

    try {
      if (!location[0].endsWith("jar")) {
        // Location points to TLD file
        try {
          in = getResourceAsStream(location[0]);
          if (in == null) {
            throw new FileNotFoundException(location[0]);
          }
        } catch (FileNotFoundException ex) {
          err.jspError("jsp.error.file.not.found", location[0]);
        }

        parseTLD(ctxt, location[0], in, null);
        // Add TLD to dependency list
        PageInfo pageInfo = ctxt.createCompiler().getPageInfo();
        if (pageInfo != null) {
          pageInfo.addDependant(location[0]);
        }
      } else {
        // Tag library is packaged in JAR file
        try {
          URL jarFileUrl = new URL("jar:" + location[0] + "!/");
          JarURLConnection conn = (JarURLConnection) jarFileUrl.openConnection();
          conn.setUseCaches(false);
          conn.connect();
          jarFile = conn.getJarFile();
          ZipEntry jarEntry = jarFile.getEntry(location[1]);
          in = jarFile.getInputStream(jarEntry);
          parseTLD(ctxt, location[0], in, jarFileUrl);
        } catch (Exception ex) {
          err.jspError("jsp.error.tld.unable_to_read", location[0], location[1], ex.toString());
        }
      }
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (Throwable t) {
        }
      }
      if (jarFile != null) {
        try {
          jarFile.close();
        } catch (Throwable t) {
        }
      }
    }
  }