/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.connector;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.SessionTrackingMode;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;

import org.apache.catalina.Context;
import org.apache.catalina.Session;
import org.apache.catalina.util.SessionConfig;
import org.apache.coyote.ActionCode;
import org.apache.coyote.ContinueResponseTiming;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.CharsetHolder;
import org.apache.tomcat.util.buf.UEncoder;
import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
import org.apache.tomcat.util.buf.UriUtil;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.parser.MediaTypeCache;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.security.Escape;

/**
 * Wrapper object for the Coyote response.
 */
public class Response implements HttpServletResponse {

    private static final Log log = LogFactory.getLog(Response.class);
    protected static final StringManager sm = StringManager.getManager(Response.class);

    private static final MediaTypeCache MEDIA_TYPE_CACHE = new MediaTypeCache(100);

    /**
     * Coyote response.
     */
    protected final org.apache.coyote.Response coyoteResponse;


    /**
     * The associated output buffer.
     */
    protected final OutputBuffer outputBuffer;


    /**
     * The associated output stream.
     */
    protected CoyoteOutputStream outputStream;


    /**
     * The associated writer.
     */
    protected CoyoteWriter writer;


    /**
     * The application commit flag.
     */
    protected boolean appCommitted = false;


    /**
     * The included flag.
     */
    protected boolean included = false;


    /**
     * The characterEncoding flag
     */
    private boolean isCharacterEncodingSet = false;


    /**
     * Using output stream flag.
     */
    protected boolean usingOutputStream = false;


    /**
     * Using writer flag.
     */
    protected boolean usingWriter = false;


    /**
     * URL encoder.
     */
    protected final UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);


    /**
     * Recyclable buffer to hold the redirect URL.
     */
    protected final CharChunk redirectURLCC = new CharChunk();


    private HttpServletResponse applicationResponse = null;


    public Response(org.apache.coyote.Response coyoteResponse) {
        this(coyoteResponse, OutputBuffer.DEFAULT_BUFFER_SIZE);
    }


    public Response(org.apache.coyote.Response coyoteResponse, int outputBufferSize) {
        this.coyoteResponse = coyoteResponse;
        outputBuffer = new OutputBuffer(outputBufferSize, coyoteResponse);
    }


    // --------------------------------------------------------- Public Methods

    /**
     * @return the Coyote response.
     */
    public org.apache.coyote.Response getCoyoteResponse() {
        return this.coyoteResponse;
    }


    /**
     * @return the Context within which this Request is being processed.
     */
    public Context getContext() {
        return request.getContext();
    }


    /**
     * Release all object references, and initialize instance variables, in preparation for reuse of this object.
     */
    public void recycle() {

        outputBuffer.recycle();
        usingOutputStream = false;
        usingWriter = false;
        appCommitted = false;
        included = false;
        isCharacterEncodingSet = false;

        applicationResponse = null;
        if (getRequest().getDiscardFacades()) {
            if (facade != null) {
                facade.clear();
                facade = null;
            }
            if (outputStream != null) {
                outputStream.clear();
                outputStream = null;
            }
            if (writer != null) {
                writer.clear();
                writer = null;
            }
        } else if (writer != null) {
            writer.recycle();
        }

    }


    // ------------------------------------------------------- Response Methods

    /**
     * @return the number of bytes the application has actually written to the output stream. This excludes chunking,
     *             compression, etc. as well as headers.
     */
    public long getContentWritten() {
        return outputBuffer.getContentWritten();
    }


    /**
     * @return the number of bytes the actually written to the socket. This includes chunking, compression, etc. but
     *             excludes headers.
     *
     * @param flush if <code>true</code> will perform a buffer flush first
     */
    public long getBytesWritten(boolean flush) {
        if (flush) {
            try {
                outputBuffer.flush();
            } catch (IOException ioe) {
                // Ignore - the client has probably closed the connection
            }
        }
        return getCoyoteResponse().getBytesWritten(flush);
    }

    /**
     * Set the application commit flag.
     *
     * @param appCommitted The new application committed flag value
     */
    public void setAppCommitted(boolean appCommitted) {
        this.appCommitted = appCommitted;
    }


    /**
     * Application commit flag accessor.
     *
     * @return <code>true</code> if the application has committed the response
     */
    public boolean isAppCommitted() {
        return this.appCommitted || isCommitted() || isSuspended() ||
                ((getContentLength() > 0) && (getContentWritten() >= getContentLength()));
    }


    /**
     * The request with which this response is associated.
     */
    protected Request request = null;

    /**
     * @return the Request with which this Response is associated.
     */
    public Request getRequest() {
        return this.request;
    }

    /**
     * Set the Request with which this Response is associated.
     *
     * @param request The new associated request
     */
    public void setRequest(Request request) {
        this.request = request;
    }


    /**
     * The facade associated with this response.
     */
    protected ResponseFacade facade = null;


    /**
     * @return the <code>ServletResponse</code> for which this object is the facade.
     */
    public HttpServletResponse getResponse() {
        if (facade == null) {
            facade = new ResponseFacade(this);
        }
        if (applicationResponse == null) {
            applicationResponse = facade;
        }
        return applicationResponse;
    }


    /**
     * Set a wrapped HttpServletResponse to pass to the application. Components wishing to wrap the response should
     * obtain the response via {@link #getResponse()}, wrap it and then call this method with the wrapped response.
     *
     * @param applicationResponse The wrapped response to pass to the application
     */
    public void setResponse(HttpServletResponse applicationResponse) {
        // Check the wrapper wraps this request
        ServletResponse r = applicationResponse;
        while (r instanceof HttpServletResponseWrapper) {
            r = ((HttpServletResponseWrapper) r).getResponse();
        }
        if (r != facade) {
            throw new IllegalArgumentException(sm.getString("response.illegalWrap"));
        }
        this.applicationResponse = applicationResponse;
    }


    /**
     * Set the suspended flag.
     *
     * @param suspended The new suspended flag value
     */
    public void setSuspended(boolean suspended) {
        outputBuffer.setSuspended(suspended);
    }


    /**
     * Suspended flag accessor.
     *
     * @return <code>true</code> if the response is suspended
     */
    public boolean isSuspended() {
        return outputBuffer.isSuspended();
    }


    /**
     * Closed flag accessor.
     *
     * @return <code>true</code> if the response has been closed
     */
    public boolean isClosed() {
        return outputBuffer.isClosed();
    }


    /**
     * Set the error flag if not already set.
     */
    public void setError() {
        getCoyoteResponse().setError();
    }


    /**
     * Error flag accessor.
     *
     * @return <code>true</code> if the response has encountered an error
     */
    public boolean isError() {
        return getCoyoteResponse().isError();
    }


    public boolean isErrorReportRequired() {
        return getCoyoteResponse().isErrorReportRequired();
    }


    public boolean setErrorReported() {
        return getCoyoteResponse().setErrorReported();
    }


    public void resetError() {
        getCoyoteResponse().resetError();
    }


    /**
     * Perform whatever actions are required to flush and close the output stream or writer, in a single operation.
     *
     * @exception IOException if an input/output error occurs
     */
    public void finishResponse() throws IOException {
        // Writing leftover bytes
        outputBuffer.close();
    }


    /**
     * @return the content length that was set or calculated for this Response.
     */
    public int getContentLength() {
        return getCoyoteResponse().getContentLength();
    }


    @Override
    public String getContentType() {
        return getCoyoteResponse().getContentType();
    }


    /**
     * Return a PrintWriter that can be used to render error messages, regardless of whether a stream or writer has
     * already been acquired.
     *
     * @return Writer which can be used for error reports. If the response is not an error report returned using
     *             sendError or triggered by an unexpected exception thrown during the servlet processing (and only in
     *             that case), null will be returned if the response stream has already been used.
     *
     * @exception IOException if an input/output error occurs
     */
    public PrintWriter getReporter() throws IOException {
        if (outputBuffer.isNew()) {
            outputBuffer.checkConverter();
            if (writer == null) {
                writer = new CoyoteWriter(outputBuffer);
            }
            return writer;
        } else {
            return null;
        }
    }


    // ------------------------------------------------ ServletResponse Methods


    @Override
    public void flushBuffer() throws IOException {
        outputBuffer.flush();
    }


    @Override
    public int getBufferSize() {
        return outputBuffer.getBufferSize();
    }


    @Override
    public String getCharacterEncoding() {
        String charset = getCoyoteResponse().getCharsetHolder().getName();
        if (charset == null) {
            Context context = getContext();
            if (context != null) {
                charset = context.getResponseCharacterEncoding();
            }
        }

        if (charset == null) {
            charset = org.apache.coyote.Constants.DEFAULT_BODY_CHARSET.name();
        }

        return charset;
    }


    @Override
    public ServletOutputStream getOutputStream() throws IOException {

        if (usingWriter) {
            throw new IllegalStateException(sm.getString("coyoteResponse.getOutputStream.ise"));
        }

        usingOutputStream = true;
        if (outputStream == null) {
            outputStream = new CoyoteOutputStream(outputBuffer);
        }
        return outputStream;

    }


    @Override
    public Locale getLocale() {
        return getCoyoteResponse().getLocale();
    }


    @Override
    public PrintWriter getWriter() throws IOException {

        if (usingOutputStream) {
            throw new IllegalStateException(sm.getString("coyoteResponse.getWriter.ise"));
        }

        if (request.getConnector().getEnforceEncodingInGetWriter()) {
            /*
             * If the response's character encoding has not been specified as described in
             * <code>getCharacterEncoding</code> (i.e., the method just returns the default value
             * <code>ISO-8859-1</code>), <code>getWriter</code> updates it to <code>ISO-8859-1</code> (with the effect
             * that a subsequent call to getContentType() will include a charset=ISO-8859-1 component which will also be
             * reflected in the Content-Type response header, thereby satisfying the Servlet spec requirement that
             * containers must communicate the character encoding used for the servlet response's writer to the client).
             */
            setCharacterEncoding(getCharacterEncoding());
        }

        usingWriter = true;
        outputBuffer.checkConverter();
        if (writer == null) {
            writer = new CoyoteWriter(outputBuffer);
        }
        return writer;
    }


    @Override
    public boolean isCommitted() {
        return getCoyoteResponse().isCommitted();
    }


    @Override
    public void reset() {
        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().reset();
        outputBuffer.reset();
        usingOutputStream = false;
        usingWriter = false;
        isCharacterEncodingSet = false;
    }


    @Override
    public void resetBuffer() {
        resetBuffer(false);
    }


    /**
     * Reset the data buffer and the using Writer/Stream flags but not any status or header information.
     *
     * @param resetWriterStreamFlags <code>true</code> if the internal <code>usingWriter</code>,
     *                                   <code>usingOutputStream</code>, <code>isCharacterEncodingSet</code> flags
     *                                   should also be reset
     *
     * @exception IllegalStateException if the response has already been committed
     */
    public void resetBuffer(boolean resetWriterStreamFlags) {

        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.resetBuffer.ise"));
        }

        outputBuffer.reset(resetWriterStreamFlags);

        if (resetWriterStreamFlags) {
            usingOutputStream = false;
            usingWriter = false;
            isCharacterEncodingSet = false;
        }

    }


    @Override
    public void setBufferSize(int size) {

        if (isCommitted() || !outputBuffer.isNew()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.setBufferSize.ise"));
        }

        outputBuffer.setBufferSize(size);

    }


    @Override
    public void setContentLength(int length) {

        setContentLengthLong(length);
    }


    @Override
    public void setContentLengthLong(long length) {
        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().setContentLength(length);
    }


    @Override
    public void setContentType(String type) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        if (type == null) {
            getCoyoteResponse().setContentType(null);
            getCoyoteResponse().setCharsetHolder(CharsetHolder.EMPTY);
            isCharacterEncodingSet = false;
            return;
        }

        String[] m = MEDIA_TYPE_CACHE.parse(type);
        if (m == null) {
            // Invalid - Assume no charset and just pass through whatever
            // the user provided.
            getCoyoteResponse().setContentTypeNoCharset(type);
            return;
        }


        if (m[1] == null) {
            // No charset and we know value is valid as cache lookup was
            // successful
            // Pass-through user provided value in case user-agent is buggy and
            // requires specific format
            getCoyoteResponse().setContentTypeNoCharset(type);
        } else {
            // There is a charset so have to rebuild content-type without it
            getCoyoteResponse().setContentTypeNoCharset(m[0]);

            // Ignore charset if getWriter() has already been called
            if (!usingWriter) {
                getCoyoteResponse().setCharsetHolder(CharsetHolder.getInstance(m[1]));
                try {
                    getCoyoteResponse().getCharsetHolder().validate();
                } catch (UnsupportedEncodingException e) {
                    log.warn(sm.getString("coyoteResponse.encoding.invalid", m[1]), e);
                }

                isCharacterEncodingSet = true;
            }
        }
    }


    @Override
    public void setCharacterEncoding(String encoding) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        // Ignore any call made after the getWriter has been invoked
        // The default should be used
        if (usingWriter) {
            return;
        }

        getCoyoteResponse().setCharsetHolder(CharsetHolder.getInstance(encoding));
        try {
            getCoyoteResponse().getCharsetHolder().validate();
        } catch (UnsupportedEncodingException e) {
            log.warn(sm.getString("coyoteResponse.encoding.invalid", encoding), e);
            return;
        }
        isCharacterEncodingSet = encoding != null;
    }


    @Override
    public void setCharacterEncoding(Charset charset) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        // Ignore any call made after the getWriter has been invoked
        // The default should be used
        if (usingWriter) {
            return;
        }

        getCoyoteResponse().setCharsetHolder(CharsetHolder.getInstance(charset));
        isCharacterEncodingSet = charset != null;
    }


    @Override
    public void setLocale(Locale locale) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().setLocale(locale);

        // Ignore any call made after the getWriter has been invoked.
        // The default should be used
        if (usingWriter) {
            return;
        }

        if (isCharacterEncodingSet) {
            return;
        }

        if (locale == null) {
            getCoyoteResponse().setCharsetHolder(CharsetHolder.EMPTY);
        } else {
            // In some error handling scenarios, the context is unknown
            // (e.g. a 404 when a ROOT context is not present)
            Context context = getContext();
            if (context != null) {
                String charset = context.getCharset(locale);
                if (charset != null) {
                    getCoyoteResponse().setCharsetHolder(CharsetHolder.getInstance(charset));
                    try {
                        getCoyoteResponse().getCharsetHolder().validate();
                    } catch (UnsupportedEncodingException e) {
                        log.warn(sm.getString("coyoteResponse.encoding.invalid", charset), e);
                    }
                }
            }
        }
    }


    // --------------------------------------------------- HttpResponse Methods


    @Override
    public String getHeader(String name) {
        return getCoyoteResponse().getMimeHeaders().getHeader(name);
    }


    @Override
    public Collection<String> getHeaderNames() {
        MimeHeaders headers = getCoyoteResponse().getMimeHeaders();
        int n = headers.size();
        List<String> result = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            result.add(headers.getName(i).toString());
        }
        return result;

    }


    @Override
    public Collection<String> getHeaders(String name) {
        Enumeration<String> enumeration = getCoyoteResponse().getMimeHeaders().values(name);
        Set<String> result = new LinkedHashSet<>();
        while (enumeration.hasMoreElements()) {
            result.add(enumeration.nextElement());
        }
        return result;
    }


    /**
     * @return the error message that was set with <code>sendError()</code> for this Response.
     */
    public String getMessage() {
        return getCoyoteResponse().getMessage();
    }


    @Override
    public int getStatus() {
        return getCoyoteResponse().getStatus();
    }


    // -------------------------------------------- HttpServletResponse Methods

    /**
     * Add the specified Cookie to those that will be included with this Response.
     *
     * @param cookie Cookie to be added
     */
    @Override
    public void addCookie(final Cookie cookie) {

        // Ignore any call from an included servlet
        if (included || isCommitted()) {
            return;
        }

        String header = generateCookieString(cookie);
        // if we reached here, no exception, cookie is valid
        addHeader("Set-Cookie", header, getContext().getCookieProcessor().getCharset());
    }

    /**
     * Special method for adding a session cookie as we should be overriding any previous.
     *
     * @param cookie The new session cookie to add the response
     */
    public void addSessionCookieInternal(final Cookie cookie) {
        if (isCommitted()) {
            return;
        }

        String name = cookie.getName();
        final String headername = "Set-Cookie";
        final String startsWith = name + "=";
        String header = generateCookieString(cookie);
        boolean set = false;
        MimeHeaders headers = getCoyoteResponse().getMimeHeaders();
        int n = headers.size();
        for (int i = 0; i < n; i++) {
            if (headers.getName(i).toString().equals(headername)) {
                if (headers.getValue(i).toString().startsWith(startsWith)) {
                    headers.getValue(i).setString(header);
                    set = true;
                }
            }
        }
        if (!set) {
            addHeader(headername, header);
        }


    }

    public String generateCookieString(final Cookie cookie) {
        // Web application code can receive a IllegalArgumentException
        // from the generateHeader() invocation
        return getContext().getCookieProcessor().generateHeader(cookie, request.getRequest());
    }


    @Override
    public void addDateHeader(String name, long value) {

        if (name == null || name.isEmpty()) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        addHeader(name, FastHttpDateFormat.formatDate(value));
    }


    @Override
    public void addHeader(String name, String value) {
        addHeader(name, value, null);
    }


    private void addHeader(String name, String value, Charset charset) {

        if (name == null || name.isEmpty() || value == null) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        char cc = name.charAt(0);
        if (cc == 'C' || cc == 'c') {
            if (checkSpecialHeader(name, value)) {
                return;
            }
        }

        getCoyoteResponse().addHeader(name, value, charset);
    }


    /**
     * An extended version of this exists in {@link org.apache.coyote.Response}. This check is required here to ensure
     * that the usingWriter check in {@link #setContentType(String)} is applied since usingWriter is not visible to
     * {@link org.apache.coyote.Response} Called from set/addHeader.
     *
     * @return <code>true</code> if the header is special, no need to set the header.
     */
    private boolean checkSpecialHeader(String name, String value) {
        if (name.equalsIgnoreCase("Content-Type")) {
            setContentType(value);
            return true;
        }
        return false;
    }


    @Override
    public void addIntHeader(String name, int value) {

        if (name == null || name.isEmpty()) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        addHeader(name, "" + value);

    }


    @Override
    public boolean containsHeader(String name) {
        // Need special handling for Content-Type and Content-Length due to
        // special handling of these in coyoteResponse
        char cc = name.charAt(0);
        if (cc == 'C' || cc == 'c') {
            if (name.equalsIgnoreCase("Content-Type")) {
                // Will return null if this has not been set
                return (getCoyoteResponse().getContentType() != null);
            }
            if (name.equalsIgnoreCase("Content-Length")) {
                // -1 means not known and is not sent to client
                return (getCoyoteResponse().getContentLengthLong() != -1);
            }
        }

        return getCoyoteResponse().containsHeader(name);
    }


    @Override
    public void setTrailerFields(Supplier<Map<String,String>> supplier) {
        getCoyoteResponse().setTrailerFields(supplier);
    }


    @Override
    public Supplier<Map<String,String>> getTrailerFields() {
        return getCoyoteResponse().getTrailerFields();
    }


    @Override
    public String encodeRedirectURL(String url) {
        if (isEncodeable(toAbsolute(url))) {
            return toEncoded(url, request.getSessionInternal().getIdInternal());
        } else {
            return url;
        }
    }


    @Override
    public String encodeURL(String url) {

        String absolute;
        try {
            absolute = toAbsolute(url);
        } catch (IllegalArgumentException iae) {
            // Relative URL
            return url;
        }

        if (isEncodeable(absolute)) {
            // W3c spec clearly said
            if (url.equalsIgnoreCase("")) {
                url = absolute;
            } else if (url.equals(absolute) && !hasPath(url)) {
                url += '/';
            }
            return toEncoded(url, request.getSessionInternal().getIdInternal());
        } else {
            return url;
        }

    }


    /**
     * Send an acknowledgement of a request.
     *
     * @param continueResponseTiming Indicates when the request for the ACK originated so it can be compared with the
     *                                   configured timing for ACK responses.
     */
    public void sendAcknowledgement(ContinueResponseTiming continueResponseTiming) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().action(ActionCode.ACK, continueResponseTiming);
    }


    @Override
    public void sendEarlyHints() {
        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().action(ActionCode.EARLY_HINTS, null);
    }


    /**
     * {@inheritDoc}
     * <p>
     * <i>Deprecated functionality</i>: calling <code>sendError</code> with a status code of 103 differs from the usual
     * behavior. Sending 103 will trigger the container to send a "103 Early Hints" informational response including all
     * current headers. The application can continue to use the request and response after calling sendError with a 103
     * status code, including triggering a more typical response of any type.
     * <p>
     * Starting with Tomcat 12, applications should use {@link #sendEarlyHints}.
     */
    @Override
    public void sendError(int status) throws IOException {
        sendError(status, null);
    }


    /**
     * {@inheritDoc}
     * <p>
     * <i>Deprecated functionality</i>: calling <code>sendError</code> with a status code of 103 differs from the usual
     * behavior. Sending 103 will trigger the container to send a "103 Early Hints" informational response including all
     * current headers. The application can continue to use the request and response after calling sendError with a 103
     * status code, including triggering a more typical response of any type.
     * <p>
     * Starting with Tomcat 12, applications should use {@link #sendEarlyHints}.
     */
    @Override
    public void sendError(int status, String message) throws IOException {

        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.sendError.ise"));
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        if (HttpServletResponse.SC_EARLY_HINTS == status) {
            sendEarlyHints();
        } else {
            setError();

            getCoyoteResponse().setStatus(status);
            getCoyoteResponse().setMessage(message);

            // Clear any data content that has been buffered
            resetBuffer();

            // Cause the response to be finished (from the application perspective)
            setSuspended(true);
        }
    }


    @Override
    public void sendRedirect(String location, int status, boolean clearBuffer) throws IOException {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.sendRedirect.ise"));
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        // Clear any data content that has been buffered
        if (clearBuffer) {
            resetBuffer(true);
        }

        // Generate a temporary redirect to the specified location
        try {
            Context context = getContext();
            // If no ROOT context is defined, the context can be null.
            // In this case, the default Tomcat values are assumed, but without
            // reference to org.apache.catalina.STRICT_SERVLET_COMPLIANCE.
            String locationUri;
            // Relative redirects require HTTP/1.1 or later
            if (getRequest().getCoyoteRequest().getSupportsRelativeRedirects() &&
                    (context == null || context.getUseRelativeRedirects())) {
                locationUri = location;
            } else {
                locationUri = toAbsolute(location);
            }
            setStatus(status);
            setHeader("Location", locationUri);
            if (clearBuffer && context != null && context.getSendRedirectBody()) {
                PrintWriter writer = getWriter();
                writer.print(sm.getString("coyoteResponse.sendRedirect.note", Escape.htmlElementContent(locationUri)));
                flushBuffer();
            }
        } catch (IllegalArgumentException e) {
            log.warn(sm.getString("response.sendRedirectFail", location), e);
            setStatus(SC_NOT_FOUND);
        }

        // Cause the response to be finished (from the application perspective)
        setSuspended(true);
    }


    @Override
    public void setDateHeader(String name, long value) {

        if (name == null || name.isEmpty()) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        setHeader(name, FastHttpDateFormat.formatDate(value));
    }


    @Override
    public void setHeader(String name, String value) {

        if (name == null || name.isEmpty()) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        char cc = name.charAt(0);
        if (cc == 'C' || cc == 'c') {
            if (checkSpecialHeader(name, value)) {
                return;
            }
        }

        getCoyoteResponse().setHeader(name, value);
    }


    @Override
    public void setIntHeader(String name, int value) {

        if (name == null || name.isEmpty()) {
            return;
        }

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        setHeader(name, "" + value);

    }


    @Override
    public void setStatus(int status) {

        if (isCommitted()) {
            return;
        }

        // Ignore any call from an included servlet
        if (included) {
            return;
        }

        getCoyoteResponse().setStatus(status);
    }


    // ------------------------------------------------------ Protected Methods

    /**
     * Return <code>true</code> if the specified URL should be encoded with a session identifier. This will be true if
     * all of the following conditions are met:
     * <ul>
     * <li>The request we are responding to asked for a valid session
     * <li>The requested session ID was not received via a cookie
     * <li>The specified URL points back to somewhere within the web application that is responding to this request
     * </ul>
     *
     * @param location Absolute URL to be validated
     *
     * @return <code>true</code> if the URL should be encoded
     */
    protected boolean isEncodeable(final String location) {

        if (location == null) {
            return false;
        }

        // Is this an intra-document reference?
        if (location.startsWith("#")) {
            return false;
        }

        // Are we in a valid session that is not using cookies?
        final Request hreq = request;
        final Session session = hreq.getSessionInternal(false);
        if (session == null) {
            return false;
        }
        if (hreq.isRequestedSessionIdFromCookie()) {
            return false;
        }

        // Is URL encoding permitted
        if (!hreq.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {
            return false;
        }

        return doIsEncodeable(getContext(), hreq, session, location);
    }


    private static boolean doIsEncodeable(Context context, Request hreq, Session session, String location) {
        // Is this a valid absolute URL?
        URL url;
        try {
            URI uri = new URI(location);
            url = uri.toURL();
        } catch (MalformedURLException | URISyntaxException | IllegalArgumentException e) {
            return false;
        }

        // Does this URL match down to (and including) the context path?
        if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol())) {
            return false;
        }
        if (!hreq.getServerName().equalsIgnoreCase(url.getHost())) {
            return false;
        }
        int serverPort = hreq.getServerPort();
        if (serverPort == -1) {
            if ("https".equals(hreq.getScheme())) {
                serverPort = 443;
            } else {
                serverPort = 80;
            }
        }
        int urlPort = url.getPort();
        if (urlPort == -1) {
            if ("https".equals(url.getProtocol())) {
                urlPort = 443;
            } else {
                urlPort = 80;
            }
        }
        if (serverPort != urlPort) {
            return false;
        }

        String contextPath = context.getPath();
        if (contextPath != null) {
            String file = url.getFile();
            if (!file.startsWith(contextPath)) {
                return false;
            }
            String tok = ";" + SessionConfig.getSessionUriParamName(context) + "=" + session.getIdInternal();
            return file.indexOf(tok, contextPath.length()) < 0;
        }

        // This URL belongs to our web application, so it is encodeable
        return true;

    }


    /**
     * Convert (if necessary) and return the absolute URL that represents the resource referenced by this possibly
     * relative URL. If this URL is already absolute, return it unchanged.
     *
     * @param location URL to be (possibly) converted and then returned
     *
     * @return the encoded URL
     *
     * @exception IllegalArgumentException if a MalformedURLException is thrown when converting the relative URL to an
     *                                         absolute one
     */
    protected String toAbsolute(String location) {

        if (location == null) {
            return null;
        }

        boolean leadingSlash = location.startsWith("/");

        if (location.startsWith("//")) {
            // Scheme relative
            redirectURLCC.recycle();
            // Add the scheme
            String scheme = request.getScheme();
            try {
                redirectURLCC.append(scheme, 0, scheme.length());
                redirectURLCC.append(':');
                redirectURLCC.append(location, 0, location.length());
                return redirectURLCC.toString();
            } catch (IOException ioe) {
                throw new IllegalArgumentException(location, ioe);
            }

        } else if (leadingSlash || !UriUtil.hasScheme(location)) {

            redirectURLCC.recycle();

            String scheme = request.getScheme();
            String name = request.getServerName();
            int port = request.getServerPort();

            try {
                redirectURLCC.append(scheme, 0, scheme.length());
                redirectURLCC.append("://", 0, 3);
                redirectURLCC.append(name, 0, name.length());
                if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
                    redirectURLCC.append(':');
                    String portS = port + "";
                    redirectURLCC.append(portS, 0, portS.length());
                }
                if (!leadingSlash) {
                    String relativePath = request.getDecodedRequestURI();
                    int pos = relativePath.lastIndexOf('/');
                    CharChunk encodedURI = urlEncoder.encodeURL(relativePath, 0, pos);
                    redirectURLCC.append(encodedURI);
                    encodedURI.recycle();
                    redirectURLCC.append('/');
                }
                redirectURLCC.append(location, 0, location.length());

                normalize(redirectURLCC);
            } catch (IOException ioe) {
                throw new IllegalArgumentException(location, ioe);
            }

            return redirectURLCC.toString();

        } else {

            return location;

        }

    }

    /**
     * Removes /./ and /../ sequences from absolute URLs. Code borrowed heavily from CoyoteAdapter.normalize()
     *
     * @param cc the char chunk containing the chars to normalize
     */
    private void normalize(CharChunk cc) {
        // Strip query string and/or fragment first as doing it this way makes
        // the normalization logic a lot simpler
        int truncate = cc.indexOf('?');
        if (truncate == -1) {
            truncate = cc.indexOf('#');
        }
        char[] truncateCC = null;
        if (truncate > -1) {
            truncateCC = Arrays.copyOfRange(cc.getBuffer(), cc.getStart() + truncate, cc.getEnd());
            cc.setEnd(cc.getStart() + truncate);
        }

        if (cc.endsWith("/.") || cc.endsWith("/..")) {
            try {
                cc.append('/');
            } catch (IOException ioe) {
                throw new IllegalArgumentException(cc.toString(), ioe);
            }
        }

        char[] c = cc.getChars();
        int start = cc.getStart();
        int end = cc.getEnd();
        int startIndex = 0;

        // Advance past the first three / characters (should place index just
        // scheme://host[:port]

        for (int i = 0; i < 3; i++) {
            startIndex = cc.indexOf('/', startIndex + 1);
        }

        // Remove /./
        int index = startIndex;
        while (true) {
            index = cc.indexOf("/./", 0, 3, index);
            if (index < 0) {
                break;
            }
            copyChars(c, start + index, start + index + 2, end - start - index - 2);
            end = end - 2;
            cc.setEnd(end);
        }

        // Remove /../
        index = startIndex;
        int pos;
        while (true) {
            index = cc.indexOf("/../", 0, 4, index);
            if (index < 0) {
                break;
            }
            // Can't go above the server root
            if (index == startIndex) {
                throw new IllegalArgumentException();
            }
            int index2 = -1;
            for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos--) {
                if (c[pos] == (byte) '/') {
                    index2 = pos;
                }
            }
            copyChars(c, start + index2, start + index + 3, end - start - index - 3);
            end = end + index2 - index - 3;
            cc.setEnd(end);
            index = index2;
        }

        // Add the query string and/or fragment (if present) back in
        if (truncateCC != null) {
            try {
                cc.append(truncateCC, 0, truncateCC.length);
            } catch (IOException ioe) {
                throw new IllegalArgumentException(ioe);
            }
        }
    }

    private void copyChars(char[] c, int dest, int src, int len) {
        System.arraycopy(c, src, c, dest, len);
    }


    /**
     * Determine if an absolute URL has a path component.
     *
     * @param uri the URL that will be checked
     *
     * @return <code>true</code> if the URL has a path
     */
    private boolean hasPath(String uri) {
        int pos = uri.indexOf("://");
        if (pos < 0) {
            return false;
        }
        pos = uri.indexOf('/', pos + 3);
        return pos >= 0;
    }

    /**
     * Return the specified URL with the specified session identifier suitably encoded.
     *
     * @param url       URL to be encoded with the session id
     * @param sessionId Session id to be included in the encoded URL
     *
     * @return the encoded URL
     */
    protected String toEncoded(String url, String sessionId) {
        if (url == null || sessionId == null) {
            return url;
        }

        String path = url;
        String query = "";
        String anchor = "";
        int question = url.indexOf('?');
        if (question >= 0) {
            path = url.substring(0, question);
            query = url.substring(question);
        }
        int pound = path.indexOf('#');
        if (pound >= 0) {
            anchor = path.substring(pound);
            path = path.substring(0, pound);
        }
        StringBuilder sb = new StringBuilder(path);
        if (!sb.isEmpty()) { // jsessionid can't be first.
            sb.append(';');
            sb.append(SessionConfig.getSessionUriParamName(request.getContext()));
            sb.append('=');
            sb.append(sessionId);
        }
        sb.append(anchor);
        sb.append(query);
        return sb.toString();
    }
}
