/* ------------------------------------------------------------ */
  public PrintWriter getWriter() throws java.io.IOException {
    if (_outputState == DISABLED) return __nullServletWriter;

    if (_outputState != NO_OUT && _outputState != WRITER_OUT) throw new IllegalStateException();

    // If we are switching modes, flush output to try avoid overlaps.
    if (_out != null) _out.flush();

    /* if there is no writer yet */
    if (_writer == null) {
      /* get encoding from Content-Type header */
      String encoding = _httpResponse.getCharacterEncoding();

      if (encoding == null) {
        if (_servletHttpRequest != null) {
          /* implementation of educated defaults */
          String mimeType = _httpResponse.getMimeType();
          encoding =
              _servletHttpRequest
                  .getServletHandler()
                  .getHttpContext()
                  .getEncodingByMimeType(mimeType);
        }
        if (encoding == null) encoding = StringUtil.__ISO_8859_1;
        _httpResponse.setCharacterEncoding(encoding, true);
      }

      /* construct Writer using correct encoding */
      _writer = new ServletWriter(_httpResponse.getOutputStream(), encoding);
    }
    _outputState = WRITER_OUT;
    return _writer;
  }
  /* ------------------------------------------------------------ */
  public void flushBuffer() throws IOException {
    if (((HttpOutputStream) _httpResponse.getOutputStream()).isClosed()) return;

    if (_writer != null) _writer.flush();
    if (_out != null) _out.flush();
    if (_writer == null && _out == null) _httpResponse.getOutputStream().flush();
    if (!_httpResponse.isCommitted()) _httpResponse.commit();
  }
 /* ------------------------------------------------------------ */
 public void setDateHeader(String name, long value) {
   try {
     _httpResponse.setDateField(name, value);
   } catch (IllegalStateException e) {
     LogSupport.ignore(log, e);
   }
 }
 /* ------------------------------------------------------------ */
 public void addIntHeader(String name, int value) {
   try {
     _httpResponse.addIntField(name, value);
   } catch (IllegalStateException e) {
     LogSupport.ignore(log, e);
   }
 }
  /**
   * Sets the locale of the response, setting the headers (including the Content-Type's charset) as
   * appropriate. This method should be called before a call to {@link #getWriter}. By default, the
   * response locale is the default locale for the server.
   *
   * @see #getLocale
   * @param locale the Locale of the response
   */
  public void setLocale(Locale locale) {
    if (locale == null || isCommitted()) return;

    _locale = locale;
    setHeader(HttpFields.__ContentLanguage, locale.toString().replace('_', '-'));

    if (this._outputState == 0) {
      /* get current MIME type from Content-Type header */
      String type = _httpResponse.getField(HttpFields.__ContentType);
      if (type == null) {
        // servlet did not set Content-Type yet
        // so lets assume default one
        type = "application/octet-stream";
      }

      HttpContext httpContext = _servletHttpRequest.getServletHandler().getHttpContext();
      if (httpContext instanceof ServletHttpContext) {
        String charset = ((ServletHttpContext) httpContext).getLocaleEncoding(locale);
        if (charset != null && charset.length() > 0) {
          int semi = type.indexOf(';');
          if (semi < 0) type += "; charset=" + charset;
          else if (!_charEncodingSetInContentType)
            type = type.substring(0, semi) + "; charset=" + charset;

          setHeader(HttpFields.__ContentType, type);
        }
      }
    }
  }
  /* ------------------------------------------------------------ */
  public void sendError(int status, String message) throws IOException {
    // Find  error page.
    String error_page =
        _servletHttpRequest.getServletHandler().getErrorPage(status, _servletHttpRequest);

    resetBuffer();

    // Handle error page?
    if (error_page == null) {
      // handle normally
      _httpResponse.sendError(status, message);
    } else {
      _httpResponse.setStatus(status, message);

      if (message == null) {
        message = (String) HttpResponse.__statusMsg.get(TypeUtil.newInteger(status));
        if (message == null) message = "" + status;
      }

      // handle error page
      ServletHolder holder = _servletHttpRequest.getServletHolder();
      if (holder != null)
        _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_SERVLET_NAME, holder.getName());
      _servletHttpRequest.setAttribute(
          ServletHandler.__J_S_ERROR_REQUEST_URI, _servletHttpRequest.getRequestURI());
      _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_STATUS_CODE, new Integer(status));
      _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_MESSAGE, message);

      RequestDispatcher dispatcher =
          _servletHttpRequest
              .getServletHandler()
              .getServletContext()
              .getRequestDispatcher(error_page);

      try {
        ((Dispatcher) dispatcher).error(_servletHttpRequest, this);
      } catch (ServletException e) {
        log.warn(LogSupport.EXCEPTION, e);
        _httpResponse.sendError(status, message);
      }
    }
    complete();
  }
  /* ------------------------------------------------------------ */
  public void setContentType(String contentType) {
    if (isCommitted() || contentType == null) return;

    int semi = contentType.indexOf(';');
    if (semi > 0) {
      int charset0 = contentType.indexOf("charset=", semi);
      if (charset0 > 0) {
        if (_outputState == WRITER_OUT) {
          // need to strip charset= from params
          int charset1 = contentType.indexOf(' ', charset0);

          if ((charset0 == semi + 1 && charset1 < 0)
              || (charset0 == semi + 2 && charset1 < 0 && contentType.charAt(semi + 1) == ' '))
            _httpResponse.setContentType(contentType.substring(0, semi));
          else if (charset1 < 0)
            _httpResponse.setContentType(contentType.substring(0, charset0).trim());
          else
            _httpResponse.setContentType(
                contentType.substring(0, charset0) + contentType.substring(charset1));
        } else {
          _charEncodingSetInContentType = true;
          _httpResponse.setContentType(contentType);
        }
      } else _httpResponse.setContentType(contentType);
    } else _httpResponse.setContentType(contentType);

    if (_locale != null) setLocale(_locale);
  }
  /* ------------------------------------------------------------ */
  public void sendRedirect(String url) throws IOException {
    if (url == null) throw new IllegalArgumentException();

    if (!URI.hasScheme(url)) {
      StringBuffer buf = _servletHttpRequest.getHttpRequest().getRootURL();
      if (url.startsWith("/")) buf.append(URI.canonicalPath(url));
      else {
        String path = _servletHttpRequest.getRequestURI();
        String parent = (path.endsWith("/")) ? path : URI.parentPath(path);
        url = URI.canonicalPath(URI.addPaths(parent, url));
        if (!url.startsWith("/")) buf.append('/');
        buf.append(url);
      }

      url = buf.toString();
    }

    resetBuffer();

    _httpResponse.setField(HttpFields.__Location, url);
    _httpResponse.setStatus(HttpResponse.__302_Moved_Temporarily);
    complete();
  }
 /**
  * @deprecated As of version 2.1 of the Servlet spec. To set a status code use <code>
  *     setStatus(int)</code>, to send an error with a description use <code>sendError(int, String)
  *     </code>.
  *     <p>Sets the status code and message for this response.
  * @param status the status code
  * @param message the status message
  */
 public void setStatus(int status, String message) {
   setStatus(status);
   _httpResponse.setReason(message);
 }
 /* ------------------------------------------------------------ */
 public void setStatus(int status) {
   _httpResponse.setStatus(status);
 }
 /* ------------------------------------------------------------ */
 public boolean isCommitted() {
   return _httpResponse.isCommitted();
 }
 /* ------------------------------------------------------------ */
 boolean isDirty() {
   return _httpResponse.isDirty();
 }
 /* ------------------------------------------------------------ */
 void complete() throws IOException {
   _httpResponse.completing();
   commit();
   setOutputState(DISABLED);
 }
 /* ------------------------------------------------------------ */
 public String getCharacterEncoding() {
   String encoding = _httpResponse.getCharacterEncoding();
   return (encoding == null) ? StringUtil.__ISO_8859_1 : encoding;
 }
 /* ------------------------------------------------------------ */
 public void setBufferSize(int size) {
   HttpOutputStream out = (HttpOutputStream) _httpResponse.getOutputStream();
   if (out.isWritten() || _writer != null && _writer.isWritten())
     throw new IllegalStateException("Output written");
   out.setBufferSize(size);
 }
 /* ------------------------------------------------------------ */
 public void reset() {
   resetBuffer();
   _httpResponse.reset();
 }
  /* ------------------------------------------------------------ */
  public void resetBuffer() {
    if (isCommitted()) throw new IllegalStateException("Committed");

    ((HttpOutputStream) _httpResponse.getOutputStream()).resetBuffer();
    if (_writer != null) _writer.reset();
  }
 /* ------------------------------------------------------------ */
 public int getBufferSize() {
   return ((HttpOutputStream) _httpResponse.getOutputStream()).getBufferSize();
 }
 /* ------------------------------------------------------------ */
 public String getContentType() {
   return _httpResponse.getContentType();
 }
 /* ------------------------------------------------------------ */
 public void addCookie(Cookie cookie) {
   _httpResponse.addSetCookie(cookie);
 }
 /* ------------------------------------------------------------ */
 public void setCharacterEncoding(String encoding) {
   if (this._outputState == 0 && !isCommitted()) {
     _charEncodingSetInContentType = true;
     _httpResponse.setCharacterEncoding(encoding, true);
   }
 }
 /* ------------------------------------------------------------ */
 public boolean containsHeader(String name) {
   return _httpResponse.containsField(name);
 }
 /* ------------------------------------------------------------ */
 public String toString() {
   return _httpResponse.toString();
 }
 /* ------------------------------------------------------------ */
 void commit() throws IOException {
   if (_writer != null && _writer.isWritten()) _writer.flush();
   else _httpResponse.commit();
 }