private Reader acquireReader() throws IOException, JspException {
    if (!isAbsoluteUrl) {
      // for relative URLs, delegate to our peer
      return new StringReader(acquireString());
    } else {
      // absolute URL
      String target = targetUrl();
      try {
        // handle absolute URLs ourselves, using java.net.URL
        URL u = new URL(target);
        URLConnection uc = u.openConnection();
        InputStream i = uc.getInputStream();

        // okay, we've got a stream; encode it appropriately
        Reader r = null;
        String charSet;
        if (charEncoding != null && !charEncoding.equals("")) {
          charSet = charEncoding;
        } else {
          // charSet extracted according to RFC 2045, section 5.1
          String contentType = uc.getContentType();
          if (contentType != null) {
            charSet = Util.getContentTypeAttribute(contentType, "charset");
            if (charSet == null) charSet = DEFAULT_ENCODING;
          } else {
            charSet = DEFAULT_ENCODING;
          }
        }
        try {
          r = new InputStreamReader(i, charSet);
        } catch (Exception ex) {
          r = new InputStreamReader(i, DEFAULT_ENCODING);
        }

        // check response code for HTTP URLs before returning, per spec,
        // before returning
        if (uc instanceof HttpURLConnection) {
          int status = ((HttpURLConnection) uc).getResponseCode();
          if (status < 200 || status > 299) throw new JspTagException(status + " " + target);
        }
        return r;
      } catch (IOException ex) {
        throw new JspException(Resources.getMessage("IMPORT_ABS_ERROR", target, ex), ex);
      } catch (RuntimeException ex) { // because the spec makes us
        throw new JspException(Resources.getMessage("IMPORT_ABS_ERROR", target, ex), ex);
      }
    }
  }
  // determines what kind of import and variable exposure to perform
  public int doStartTag() throws JspException {
    // Sanity check
    if (context != null && (!context.startsWith("/") || !url.startsWith("/"))) {
      throw new JspTagException(Resources.getMessage("IMPORT_BAD_RELATIVE"));
    }

    // reset parameter-related state
    urlWithParams = null;
    params = new ParamSupport.ParamManager();

    // check the URL
    if (url == null || url.equals("")) throw new NullAttributeException("import", "url");

    // Record whether our URL is absolute or relative
    isAbsoluteUrl = isAbsoluteUrl();

    try {
      // If we need to expose a Reader, we've got to do it right away
      if (varReader != null) {
        r = acquireReader();
        pageContext.setAttribute(varReader, r);
      }
    } catch (IOException ex) {
      throw new JspTagException(ex.toString(), ex);
    }

    return EVAL_BODY_INCLUDE;
  }
    public InputSource resolveEntity(String publicId, String systemId)
        throws FileNotFoundException {

      // pass if we don't have a systemId
      if (systemId == null) {
        return null;
      }

      // strip leading "jstl:" off URL if applicable
      if (systemId.startsWith("jstl:")) {
        systemId = systemId.substring(5);
      }

      // we're only concerned with relative URLs
      if (ImportSupport.isAbsoluteUrl(systemId)) {
        return null;
      }

      // for relative URLs, load and wrap the resource.
      // don't bother checking for 'null' since we specifically want
      // the parser to fail if the resource doesn't exist
      InputStream s;
      if (systemId.startsWith("/")) {
        s = ctx.getServletContext().getResourceAsStream(systemId);
        if (s == null) {
          throw new FileNotFoundException(
              Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", systemId));
        }
      } else {
        String pagePath = ((HttpServletRequest) ctx.getRequest()).getServletPath();
        String basePath = pagePath.substring(0, pagePath.lastIndexOf("/"));
        s = ctx.getServletContext().getResourceAsStream(basePath + "/" + systemId);
        if (s == null) {
          throw new FileNotFoundException(
              Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", systemId));
        }
      }
      return new InputSource(s);
    }
  @Override
  public int doEndTag() throws JspException {
    try {

      // set up our DocumentBuilder
      if (dbf == null) {
        dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        dbf.setValidating(false);
      }
      db = dbf.newDocumentBuilder();

      // if we've gotten a filter, set up a transformer to support it
      if (filter != null) {
        if (tf == null) {
          tf = TransformerFactory.newInstance();
        }
        if (!tf.getFeature(SAXTransformerFactory.FEATURE)) {
          throw new JspTagException(Resources.getMessage("PARSE_NO_SAXTRANSFORMER"));
        }
        SAXTransformerFactory stf = (SAXTransformerFactory) tf;
        th = stf.newTransformerHandler();
      }

      // produce a Document by parsing whatever the attributes tell us to use
      Document d;
      Object xmlText = this.xml;
      if (xmlText == null) {
        // if the attribute was specified, use the body as 'xml'
        if (bodyContent != null && bodyContent.getString() != null) {
          xmlText = bodyContent.getString().trim();
        } else {
          xmlText = "";
        }
      }
      if (xmlText instanceof String) {
        d = parseStringWithFilter((String) xmlText, filter);
      } else if (xmlText instanceof Reader) {
        d = parseReaderWithFilter((Reader) xmlText, filter);
      } else {
        throw new JspTagException(Resources.getMessage("PARSE_INVALID_SOURCE"));
      }

      // we've got a Document object; store it out as appropriate
      // (let any exclusivity or other constraints be enforced by TEI/TLV)
      if (var != null) {
        pageContext.setAttribute(var, d, scope);
      }
      if (varDom != null) {
        pageContext.setAttribute(varDom, d, scopeDom);
      }

      return EVAL_PAGE;
    } catch (SAXException ex) {
      throw new JspException(ex);
    } catch (IOException ex) {
      throw new JspException(ex);
    } catch (ParserConfigurationException ex) {
      throw new JspException(ex);
    } catch (TransformerConfigurationException ex) {
      throw new JspException(ex);
    }
  }
 /** Returns a ServletOutputStream designed to buffer the output. */
 public ServletOutputStream getOutputStream() {
   if (isWriterUsed)
     throw new IllegalStateException(Resources.getMessage("IMPORT_ILLEGAL_WRITER"));
   isStreamUsed = true;
   return sos;
 }
 /** Returns a Writer designed to buffer the output. */
 public PrintWriter getWriter() throws IOException {
   if (isStreamUsed)
     throw new IllegalStateException(Resources.getMessage("IMPORT_ILLEGAL_STREAM"));
   isWriterUsed = true;
   return new PrintWriterWrapper(sw, pageContext.getOut());
 }
  private String acquireString() throws IOException, JspException {
    if (isAbsoluteUrl) {
      // for absolute URLs, delegate to our peer
      BufferedReader r = new BufferedReader(acquireReader());
      StringBuffer sb = new StringBuffer();
      int i;

      // under JIT, testing seems to show this simple loop is as fast
      // as any of the alternatives
      //
      // gmurray71 : putting in try/catch/finally block to make sure the
      // reader is closed to fix a bug with file descriptors being left open
      try {
        while ((i = r.read()) != -1) sb.append((char) i);
      } catch (IOException iox) {
        throw iox;
      } finally {
        r.close();
      }

      return sb.toString();
    } else {
      // handle relative URLs ourselves

      // URL is relative, so we must be an HTTP request
      if (!(pageContext.getRequest() instanceof HttpServletRequest
          && pageContext.getResponse() instanceof HttpServletResponse))
        throw new JspTagException(Resources.getMessage("IMPORT_REL_WITHOUT_HTTP"));

      // retrieve an appropriate ServletContext
      ServletContext c = null;
      String targetUrl = targetUrl();
      if (context != null) c = pageContext.getServletContext().getContext(context);
      else {
        c = pageContext.getServletContext();

        // normalize the URL if we have an HttpServletRequest
        if (!targetUrl.startsWith("/")) {
          String sp = ((HttpServletRequest) pageContext.getRequest()).getServletPath();
          targetUrl = sp.substring(0, sp.lastIndexOf('/')) + '/' + targetUrl;
        }
      }

      if (c == null) {
        throw new JspTagException(
            Resources.getMessage("IMPORT_REL_WITHOUT_DISPATCHER", context, targetUrl));
      }

      // from this context, get a dispatcher
      RequestDispatcher rd = c.getRequestDispatcher(stripSession(targetUrl));
      if (rd == null) throw new JspTagException(stripSession(targetUrl));

      // include the resource, using our custom wrapper
      ImportResponseWrapper irw = new ImportResponseWrapper(pageContext);

      // spec mandates specific error handling form include()
      try {
        rd.include(pageContext.getRequest(), irw);
      } catch (IOException ex) {
        throw new JspException(ex);
      } catch (RuntimeException ex) {
        throw new JspException(ex);
      } catch (ServletException ex) {
        Throwable rc = ex.getRootCause();
        if (rc == null) throw new JspException(ex);
        else throw new JspException(rc);
      }

      // disallow inappropriate response codes per JSTL spec
      if (irw.getStatus() < 200 || irw.getStatus() > 299) {
        throw new JspTagException(irw.getStatus() + " " + stripSession(targetUrl));
      }

      // recover the response String from our wrapper
      return irw.getString();
    }
  }