/*
 * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed 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.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import com.sun.appserv.ProxyHandler;
import java.io.CharConversionException;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.LogFacade;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.util.ResponseUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.StringManager;
import org.glassfish.common.util.InputValidationUtil;
import org.glassfish.grizzly.http.Method;
import org.glassfish.grizzly.http.server.AfterServiceListener;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.Note;
import org.glassfish.grizzly.http.server.util.MappingData;
import org.glassfish.grizzly.http.util.ByteChunk;
import org.glassfish.grizzly.http.util.CharChunk;
import org.glassfish.grizzly.http.util.DataChunk;
import org.glassfish.grizzly.http.util.MessageBytes;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.web.valve.GlassFishValve;
import org.glassfish.web.valve.ServletContainerInterceptor;

/**
 * Implementation of a request processor which delegates the processing to a
 * Coyote processor.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @version $Revision: 1.34 $ $Date: 2007/08/24 18:38:28 $
 */

public class CoyoteAdapter extends HttpHandler {

    private static final Logger log = LogFacade.getLogger();
    private static final ResourceBundle rb = log.getResourceBundle();

    // -------------------------------------------------------------- Constants
    private static final String POWERED_BY = "Servlet/3.1 JSP/2.3 " +
            "(" + ServerInfo.getServerInfo() + " Java/" +
            System.getProperty("java.vm.vendor") + "/" +
            System.getProperty("java.specification.version") + ")";


//    protected boolean v3Enabled =
//        Boolean.valueOf(System.getProperty("v3.grizzly.useMapper", "true"));


//    public static final int ADAPTER_NOTES = 1;

    static final String JVM_ROUTE = System.getProperty("jvmRoute");

    private Collection<ServletContainerInterceptor> interceptors = null;

    protected static final boolean ALLOW_BACKSLASH =
        Boolean.valueOf(System.getProperty("org.glassfish.grizzly.tcp.tomcat5.CoyoteAdapter.ALLOW_BACKSLASH", "false"));

    private static final boolean COLLAPSE_ADJACENT_SLASHES =
        Boolean.valueOf(System.getProperty(
            "com.sun.enterprise.web.collapseAdjacentSlashes", "true"));

    /**
     * When mod_jk is used, the adapter must be invoked the same way
     * Tomcat does by invoking service(...) and the afterService(...). This
     * is a hack to make it compatible with Tomcat 5|6.
     */
    private boolean compatWithTomcat = false;

    private String serverName = ServerInfo.getPublicServerInfo();

    // Make sure this value is always aligned with {@link ContainerMapper}
    // (@see com.sun.enterprise.v3.service.impl.ContainerMapper)
    protected final static Note<MappingData> MAPPING_DATA =
            org.glassfish.grizzly.http.server.Request.<MappingData>createNote("MappingData");

    static final Note<Request> CATALINA_REQUEST_NOTE =
            org.glassfish.grizzly.http.server.Request.createNote(Request.class.getName());
    static final Note<Response> CATALINA_RESPONSE_NOTE =
            org.glassfish.grizzly.http.server.Request.createNote(Response.class.getName());

    static final CatalinaAfterServiceListener catalinaAfterServiceListener =
            new CatalinaAfterServiceListener();

    // Make sure this value is always aligned with {@link ContainerMapper}
    // (@see com.sun.enterprise.v3.service.impl.ContainerMapper)
    private final static Note<DataChunk> DATA_CHUNK =
            org.glassfish.grizzly.http.server.Request.<DataChunk>createNote("DataChunk");

    // ----------------------------------------------------------- Constructors


    /**
     * Construct a new CoyoteProcessor associated with the specified connector.
     *
     * @param connector CoyoteConnector that owns this processor
     */
    public CoyoteAdapter(Connector connector) {
        super();
        this.connector = connector;
        initServletInterceptors();
    }


    // ----------------------------------------------------- Instance Variables


    /**
     * The CoyoteConnector with which this processor is associated.
     */
    private Connector connector = null;


    // -------------------------------------------------------- Adapter Methods


    /**
     * Service method.
     */
    @Override
    public void service(org.glassfish.grizzly.http.server.Request req,
                        org.glassfish.grizzly.http.server.Response res)
            throws Exception {

        res.getResponse().setAllowCustomReasonPhrase(Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER);

        Request request = req.getNote(CATALINA_REQUEST_NOTE);
        Response response = req.getNote(CATALINA_RESPONSE_NOTE);

        // Grizzly already parsed, decoded, and mapped the request.
        // Let's re-use this info here, before firing the
        // requestStartEvent probe, so that the mapping data will be
        // available to any probe event listener via standard
        // ServletRequest APIs (such as getContextPath())
        MappingData md = req.getNote(MAPPING_DATA);
        final boolean v3Enabled = md != null;
        if (request == null) {

            // Create objects
            request = (Request) connector.createRequest();
            response = (Response) connector.createResponse();

            // Link objects
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            req.setNote(CATALINA_REQUEST_NOTE, request);
            req.setNote(CATALINA_RESPONSE_NOTE, response);
//            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            req.getRequest().getRequestURIRef().setDefaultURIEncoding(Charset.forName(connector.getURIEncoding()));
        }

        request.setCoyoteRequest(req);
        response.setCoyoteResponse(res);

        if (v3Enabled && !compatWithTomcat) {
            request.setMappingData(md);
            request.updatePaths(md);
        }

        req.addAfterServiceListener(catalinaAfterServiceListener);

        try {
            doService(req, request, res, response, v3Enabled);

            // Request may want to initialize async processing
            request.onExitService();
        } catch (Throwable t) {
            log.log(Level.SEVERE, LogFacade.REQUEST_PROCESSING_EXCEPTION, t);
        }
    }

    private void enteringServletContainer(Request req, Response res) {
        if (interceptors == null)
            return;
        for(ServletContainerInterceptor interceptor:interceptors) {
            try{
                interceptor.preInvoke(req, res);
            } catch (Throwable th) {
                log.log(Level.SEVERE, LogFacade.INTERNAL_ERROR, th);
            }
        }
    }

    private void leavingServletContainer(Request req, Response res) {
        if (interceptors == null)
            return;
        for(ServletContainerInterceptor interceptor:interceptors) {
            try{
                interceptor.postInvoke(req, res);
            } catch (Throwable th) {
                log.log(Level.SEVERE, LogFacade.INTERNAL_ERROR, th);
            }
        }
    }

    private void initServletInterceptors() {
        try {
            ServiceLocator services = org.glassfish.internal.api.Globals.getDefaultHabitat();
            interceptors = services.getAllServices(ServletContainerInterceptor.class);
        } catch (Throwable th) {
            log.log(Level.SEVERE, LogFacade.FAILED_TO_INITIALIZE_THE_INTERCEPTOR, th);
        }
    }


    private void doService(final org.glassfish.grizzly.http.server.Request req,
                           final Request request,
                           final org.glassfish.grizzly.http.server.Response res,
                           final Response response,
                           final boolean v3Enabled)
            throws Exception {

        // START SJSAS 6331392
        // Check connector for disabled state
        if (!connector.isEnabled()) {
            String msg = MessageFormat.format(rb.getString(LogFacade.HTTP_LISTENER_DISABLED),
                                              String.valueOf(connector.getPort()));
            if (log.isLoggable(Level.FINE)) {
                log.log(Level.FINE, msg);
            }
            response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
            return;
        }
        // END SJSAS 6331392

////            "X-Powered-By" header is set by GlassfishHttpCodecFilter
//        if (connector.isXpoweredBy()) {
//            response.addHeader("X-Powered-By", POWERED_BY);
//        }


        // Parse and set Catalina and configuration specific
        // request parameters
        if ( postParseRequest(req, request, res, response, v3Enabled) ) {

            // START S1AS 6188932
            boolean authPassthroughEnabled =
                connector.getAuthPassthroughEnabled();
            ProxyHandler proxyHandler = connector.getProxyHandler();
            if (authPassthroughEnabled && proxyHandler != null) {

                // START SJSAS 6397218
                if (proxyHandler.getSSLKeysize(
                        (HttpServletRequest)request.getRequest()) > 0) {
                    request.setSecure(true);
                }
                // END SJSAS 6397218

                X509Certificate[] certs = null;
                try {
                    certs = proxyHandler.getSSLClientCertificateChain(
                                request.getRequest());
                } catch (CertificateException ce) {
                    log.log(Level.SEVERE, LogFacade.PARSING_CLIENT_CERT_EXCEPTION,
                            ce);
                }
                if (certs != null) {
                    request.setAttribute(Globals.CERTIFICATES_ATTR,
                                         certs);
                }

            }
            // END S1AS 6188932

////            "Server" header is set by GlassfishHttpCodecFilter
//            if (serverName != null && !serverName.isEmpty()) {
//                response.addHeader("Server", serverName);
//            }

            // Invoke the web container
            connector.requestStartEvent(request.getRequest(),
                request.getHost(), request.getContext());
            Container container = connector.getContainer();
            enteringServletContainer(request, response);
            try {
                request.lockSession();
                if (container.getPipeline().hasNonBasicValves() ||
                        container.hasCustomPipeline()) {
                    container.getPipeline().invoke(request, response);
                } else {
                    // Invoke host directly
                    Host host = request.getHost();
                    if (host == null) {
                        response.sendError(HttpServletResponse.SC_BAD_REQUEST);

                        String msg = MessageFormat.format(rb.getString(LogFacade.NO_HOST_MATCHES_SERVER_NAME_INFO),
                                                          request.getRequest().getServerName());
                        response.setDetailMessage(msg);
                        return;
                    }
                    if (host.getPipeline().hasNonBasicValves() ||
                            host.hasCustomPipeline()) {
                        host.getPipeline().invoke(request, response);
                    } else {
                        GlassFishValve hostValve = host.getPipeline().getBasic();
                        hostValve.invoke(request, response);
                        // Error handling
                        hostValve.postInvoke(request, response);
                    }
                }
            } finally {
                try {
                    connector.requestEndEvent(request.getRequest(),
                        request.getHost(), request.getContext(),
                        response.getStatus());
                } finally {
                    leavingServletContainer(request, response);
                }
            }
        }

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


    /**
     * Parse additional request parameters.
     */
    protected boolean postParseRequest(final org.glassfish.grizzly.http.server.Request req,
                                       final Request request,
                                       final org.glassfish.grizzly.http.server.Response res,
                                       final Response response,
                                       final boolean v3Enabled)
        throws Exception {
        // XXX the processor may have set a correct scheme and port prior to this point,
        // in ajp13 protocols dont make sense to get the port from the connector...
        // otherwise, use connector configuration
        request.setSecure(req.isSecure());

        // URI decoding
        DataChunk decodedURI;
        try {
            decodedURI = req.getRequest().getRequestURIRef().getDecodedRequestURIBC();
        } catch (CharConversionException cce) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid URI");
            return false;
        }

        if (compatWithTomcat || !v3Enabled) {
//            decodedURI.duplicate(req.requestURI());
//            try {
//              req.getURLDecoder().convert(decodedURI, false);
//            } catch (IOException ioe) {
//              res.setStatus(400);
//              res.setMessage("Invalid URI: " + ioe.getMessage());
//              return false;
//            }

            /* GlassFish Issue 2339
            // Normalize decoded URI
            if (!normalize(req.decodedURI())) {
                res.setStatus(400);
                res.setMessage("Invalid URI");
                return false;
            }
            */

            // Set the remote principal
            String principal = req.getRemoteUser();
            if (principal != null) {
                request.setUserPrincipal(new CoyotePrincipal(principal));
            }

            // Set the authorization type
            String authtype = req.getAuthType();
            if (authtype != null) {
                request.setAuthType(authtype);
            }

            /* CR 6309511
            // URI character decoding
            convertURI(decodedURI, request);

            // Parse session Id
            parseSessionId(req, request);
             */
            // START CR 6309511
//             URI character decoding
//            request.convertURI(decodedURI);

            // START GlassFish Issue 2339
            // Normalize decoded URI
//            if (!normalize(decodedURI)) {
//                res.setStatus(400);
//                res.setMessage("Invalid URI");
//                return false;
//            }
            // END GlassFish Issue 2339
        }
        // END CR 6309511

        /*
         * Remove any parameters from the URI, so they won't be considered
         * by the mapping algorithm, and save them in a temporary CharChunk,
         * so that any session id param may be parsed once the target
         * context, which may use a custom session parameter name, has been
         * identified
         */
        final CharChunk uriParamsCC = request.getURIParams();
        final CharChunk uriCC = decodedURI.getCharChunk();
        final int semicolon = uriCC.indexOf(';');
        if (semicolon > 0) {
            final int absSemicolon = uriCC.getStart() + semicolon;
            uriParamsCC.setChars(uriCC.getBuffer(), absSemicolon,
                uriCC.getEnd() - absSemicolon);
            decodedURI.setChars(uriCC.getBuffer(), uriCC.getStart(),
                absSemicolon - uriCC.getStart());
        }

        if (compatWithTomcat || !v3Enabled) {
            /*mod_jk*/
            DataChunk localDecodedURI = decodedURI;
            if (semicolon > 0) {
                localDecodedURI = req.getNote(DATA_CHUNK);
                if (localDecodedURI == null) {
                    localDecodedURI = DataChunk.newInstance();
                    req.setNote(DATA_CHUNK, localDecodedURI);
                }
                localDecodedURI.duplicate(decodedURI);
            }
            connector.getMapper().map(req.getRequest().serverName(), localDecodedURI,
                                  request.getMappingData());
            MappingData md = request.getMappingData();
            req.setNote(MAPPING_DATA, md);
            request.updatePaths(md);
        }

        // FIXME: the code below doesnt belongs to here,
        // this is only have sense
        // in Http11, not in ajp13..
        // At this point the Host header has been processed.
        // Override if the proxyPort/proxyHost are set
        String proxyName = connector.getProxyName();
        int proxyPort = connector.getProxyPort();
        if (proxyPort != 0) {
            req.setServerPort(proxyPort);
        }
        if (proxyName != null) {
            req.setServerName(proxyName);
        }

        Context ctx = (Context) request.getMappingData().context;

        // Parse session id
        if (ctx != null) {
            if (req.isRequestedSessionIdFromURL() &&
                    Globals.SESSION_PARAMETER_NAME.equals(ctx.getSessionParameterName())) {
                request.obtainSessionId();
            } else if (!uriParamsCC.isNull()) {
//            String sessionParam = ";" + ctx.getSessionParameterName() + "=";
                request.parseSessionId(ctx.getSessionParameterName(), uriParamsCC);
            }
        }

        // START GlassFish 1024
        request.setDefaultContext(request.getMappingData().isDefaultContext);
        // END GlassFish 1024

        // START SJSAS 6253524
        // request.setContext((Context) request.getMappingData().context);
        // END SJSAS 6253524
        // START SJSAS 6253524
        request.setContext(ctx);
        // END SJSAS 6253524

        if (ctx != null && !uriParamsCC.isNull()) {
            request.parseSessionVersion(uriParamsCC);
        }

        if (!uriParamsCC.isNull()) {
            request.parseJReplica(uriParamsCC);
        }

        request.setWrapper((Wrapper) request.getMappingData().wrapper);

        // Filter trace method
        if (!connector.getAllowTrace() && Method.TRACE.equals(req.getMethod())) {
            Wrapper wrapper = request.getWrapper();
            String header = null;
            if (wrapper != null) {
                String[] methods = wrapper.getServletMethods();
                if (methods != null) {
                    for (String method : methods) {
                        // Exclude TRACE from methods returned in Allow header
                        if ("TRACE".equals(method)) {
                            continue;
                        }
                        if (header == null) {
                            header = method;
                        } else {
                            header += ", " + method;
                        }
                    }
                }
            }
            res.setStatus(405, "TRACE method is not allowed");
            res.addHeader("Allow", header);
            return false;
        }

        // Possible redirect
        DataChunk redirectPathMB = request.getMappingData().redirectPath;
        // START SJSAS 6253524
        // if (!redirectPathMB.isNull()) {
        // END SJSAS 6253524
        // START SJSAS 6253524
        if (!redirectPathMB.isNull()
            && (!ctx.hasAdHocPaths()
                || (ctx.getAdHocServletName(((HttpServletRequest)
                        request.getRequest()).getServletPath()) == null))) {
        // END SJSAS 6253524
            String redirectPath = redirectPathMB.toString();
            String query = request.getQueryString();
            if (request.isRequestedSessionIdFromURL()) {
                // This is not optimal, but as this is not very common, it
                // shouldn't matter
                redirectPath = redirectPath + ";" + ctx.getSessionParameterName() + "="
                    + request.getRequestedSessionId();
            }
            // START GlassFish 936
            redirectPath = response.encode(redirectPath);
            // END GlassFish 936
            if (query != null) {
                // This is not optimal, but as this is not very common, it
                // shouldn't matter
                redirectPath = redirectPath + "?" + query;
            }

            // START CR 6590921
            boolean authPassthroughEnabled =
                connector.getAuthPassthroughEnabled();
            ProxyHandler proxyHandler = connector.getProxyHandler();
            if (authPassthroughEnabled && proxyHandler != null) {

                if (proxyHandler.getSSLKeysize(
                        (HttpServletRequest)request.getRequest()) > 0) {
                    request.setSecure(true);
                }
            }
            // END CR 6590921
            // Issue a permanent redirect
            // Validating the redirectPath for header injection
            if (InputValidationUtil.validateStringforCRLF(redirectPath)) {
                response.sendError(403, "Forbidden");
            } else {
                response.sendRedirect(InputValidationUtil.removeLinearWhiteSpaces(redirectPath),
                        false);
            }

            return false;
        }

        // Parse session Id
        /* CR 6309511
        parseSessionCookiesId(req, request);
         */
        // START CR 6309511
        request.parseSessionCookiesId();
        // END CR 6309511

        // START SJSAS 6346226
        request.parseJrouteCookie();
        // END SJSAS 6346226

        return true;
    }


    /**
     * Normalize URI.
     * <p>
     * This method normalizes "\", "//", "/./" and "/../". This method will
     * return false when trying to go above the root, or if the URI contains
     * a null byte.
     *
     * @param uriMB URI to be normalized
     */
    public static boolean normalize(MessageBytes uriMB) {

        int type = uriMB.getType();
        if (type == MessageBytes.T_CHARS) {
            return normalizeChars(uriMB);
        } else {
            return normalizeBytes(uriMB);
        }
    }


    private static boolean normalizeBytes(MessageBytes uriMB) {

        ByteChunk uriBC = uriMB.getByteChunk();
        byte[] b = uriBC.getBytes();
        int start = uriBC.getStart();
        int end = uriBC.getEnd();

        // An empty URL is not acceptable
        if (start == end)
            return false;

        // URL * is acceptable
        if ((end - start == 1) && b[start] == (byte) '*')
          return true;

        int pos = 0;
        int index = 0;

        // Replace '\' with '/'
        // Check for null byte
        for (pos = start; pos < end; pos++) {
            if (b[pos] == (byte) '\\') {
                if (ALLOW_BACKSLASH) {
                    b[pos] = (byte) '/';
                } else {
                    return false;
                }
            }
            if (b[pos] == (byte) 0) {
                return false;
            }
        }

        // The URL must start with '/'
        if (b[start] != (byte) '/') {
            return false;
        }

        // Replace "//" with "/"
        if (COLLAPSE_ADJACENT_SLASHES) {
            for (pos = start; pos < (end - 1); pos++) {
                if (b[pos] == (byte) '/') {
                    while ((pos + 1 < end) && (b[pos + 1] == (byte) '/')) {
                        copyBytes(b, pos, pos + 1, end - pos - 1);
                        end--;
                    }
                }
            }
        }

        // If the URI ends with "/." or "/..", then we append an extra "/"
        // Note: It is possible to extend the URI by 1 without any side effect
        // as the next character is a non-significant WS.
        if (((end - start) > 2) && (b[end - 1] == (byte) '.')) {
            if ((b[end - 2] == (byte) '/')
                || ((b[end - 2] == (byte) '.')
                    && (b[end - 3] == (byte) '/'))) {
                b[end] = (byte) '/';
                end++;
            }
        }

        uriBC.setEnd(end);

        index = 0;

        // Resolve occurrences of "/./" in the normalized path
        while (true) {
            index = uriBC.indexOf("/./", 0, 3, index);
            if (index < 0)
                break;
            copyBytes(b, start + index, start + index + 2,
                      end - start - index - 2);
            end = end - 2;
            uriBC.setEnd(end);
        }

        index = 0;

        // Resolve occurrences of "/../" in the normalized path
        while (true) {
            index = uriBC.indexOf("/../", 0, 4, index);
            if (index < 0)
                break;
            // Prevent from going outside our context
            if (index == 0)
                return false;
            int index2 = -1;
            for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos --) {
                if (b[pos] == (byte) '/') {
                    index2 = pos;
                }
            }
            copyBytes(b, start + index2, start + index + 3,
                      end - start - index - 3);
            end = end + index2 - index - 3;
            uriBC.setEnd(end);
            index = index2;
        }

        uriBC.setBytes(b, start, end);

        return true;

    }


    private static boolean normalizeChars(MessageBytes uriMB) {

        CharChunk uriCC = uriMB.getCharChunk();
        char[] c = uriCC.getChars();
        int start = uriCC.getStart();
        int end = uriCC.getEnd();

        // URL * is acceptable
        if ((end - start == 1) && c[start] == (char) '*')
          return true;

        int pos = 0;
        int index = 0;

        // Replace '\' with '/'
        // Check for null char
        for (pos = start; pos < end; pos++) {
            if (c[pos] == (char) '\\') {
                if (ALLOW_BACKSLASH) {
                    c[pos] = (char) '/';
                } else {
                    return false;
                }
            }
            if (c[pos] == (char) 0) {
                return false;
            }
        }

        // The URL must start with '/'
        if (c[start] != (char) '/') {
            return false;
        }

        // Replace "//" with "/"
        if (COLLAPSE_ADJACENT_SLASHES) {
            for (pos = start; pos < (end - 1); pos++) {
                if (c[pos] == (char) '/') {
                    while ((pos + 1 < end) && (c[pos + 1] == (char) '/')) {
                        copyChars(c, pos, pos + 1, end - pos - 1);
                        end--;
                    }
                }
            }
        }

        // If the URI ends with "/." or "/..", then we append an extra "/"
        // Note: It is possible to extend the URI by 1 without any side effect
        // as the next character is a non-significant WS.
        if (((end - start) > 2) && (c[end - 1] == (char) '.')) {
            if ((c[end - 2] == (char) '/')
                || ((c[end - 2] == (char) '.')
                    && (c[end - 3] == (char) '/'))) {
                c[end] = (char) '/';
                end++;
            }
        }

        uriCC.setEnd(end);

        index = 0;

        // Resolve occurrences of "/./" in the normalized path
        while (true) {
            index = uriCC.indexOf("/./", 0, 3, index);
            if (index < 0)
                break;
            copyChars(c, start + index, start + index + 2,
                      end - start - index - 2);
            end = end - 2;
            uriCC.setEnd(end);
        }

        index = 0;

        // Resolve occurrences of "/../" in the normalized path
        while (true) {
            index = uriCC.indexOf("/../", 0, 4, index);
            if (index < 0)
                break;
            // Prevent from going outside our context
            if (index == 0)
                return false;
            int index2 = -1;
            for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos --) {
                if (c[pos] == (char) '/') {
                    index2 = pos;
                }
            }
            copyChars(c, start + index2, start + index + 3,
                      end - start - index - 3);
            end = end + index2 - index - 3;
            uriCC.setEnd(end);
            index = index2;
        }

        uriCC.setChars(c, start, end);

        return true;

    }


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


    /**
     * Copy an array of bytes to a different position. Used during
     * normalization.
     */
    protected static void copyBytes(byte[] b, int dest, int src, int len) {
        for (int pos = 0; pos < len; pos++) {
            b[pos + dest] = b[pos + src];
        }
    }


    /**
     * Copy an array of chars to a different position. Used during
     * normalization.
     */
    private static void copyChars(char[] c, int dest, int src, int len) {
        for (int pos = 0; pos < len; pos++) {
            c[pos + dest] = c[pos + src];
        }
    }


    /**
     * Log a message on the Logger associated with our Container (if any)
     *
     * @param message Message to be logged
     */
    protected void log(String message) {
        log.log(Level.INFO, message);
    }


    /**
     * Log a message on the Logger associated with our Container (if any)
     *
     * @param message Message to be logged
     * @param throwable Associated exception
     */
    protected void log(String message, Throwable throwable) {
        log.log(Level.SEVERE, message, throwable);
    }


     /**
      * Character conversion of the a US-ASCII MessageBytes.
      */
    /* CR 6309511
     protected void convertMB(MessageBytes mb) {

        // This is of course only meaningful for bytes
        if (mb.getType() != MessageBytes.T_BYTES)
            return;

        ByteChunk bc = mb.getByteChunk();
        CharChunk cc = mb.getCharChunk();
        cc.allocate(bc.getLength(), -1);

        // Default encoding: fast conversion
        byte[] bbuf = bc.getBuffer();
        char[] cbuf = cc.getBuffer();
        int start = bc.getStart();
        for (int i = 0; i < bc.getLength(); i++) {
            cbuf[i] = (char) (bbuf[i + start] & 0xff);
        }
        mb.setChars(cbuf, 0, bc.getLength());

     }
     */


    // START SJSAS 6349248
    /**
     * Notify all container event listeners that a particular event has
     * occurred for this Adapter.  The default implementation performs
     * this notification synchronously using the calling thread.
     *
     * @param type Event type
     * @param data Event data
     */
    public void fireAdapterEvent(String type, Object data) {
        if ( connector != null && connector.getContainer() != null) {
            try{
                ((ContainerBase)connector.getContainer())
                    .fireContainerEvent(type,data);
            } catch (Throwable t){
                log.log(Level.SEVERE, LogFacade.REQUEST_PROCESSING_EXCEPTION, t);
            }
        }
    }
    // END SJSAS 6349248


    /**
     * Return true when an instance is executed the same way it does in Tomcat.
     */
    public boolean isCompatWithTomcat() {
        return compatWithTomcat;
    }


    /**
     * <tt>true</tt> if this class needs to be compatible with Tomcat
     * Adapter class. Since Tomcat Adapter implementation doesn't support
     * the afterService method, the afterService method must be invoked
     * inside the service method.
     */
    public void setCompatWithTomcat(boolean compatWithTomcat) {
        this.compatWithTomcat = compatWithTomcat;

        // Add server header
        if (compatWithTomcat){
            serverName = "Apache/" + serverName;
        } else {
            // Recalculate.
            serverName = ServerInfo.getPublicServerInfo();
        }
    }


    /**
     * Gets the port of this CoyoteAdapter.
     *
     * @return the port of this CoyoteAdapter
     */
    public int getPort() {
        return connector.getPort();
    }

    /**
     * AfterServiceListener, which is responsible for recycle catalina request and response
     * objects.
     */
    static final class CatalinaAfterServiceListener implements AfterServiceListener {

        @Override
        public void onAfterService(final org.glassfish.grizzly.http.server.Request request) {
            final Request servletRequest = request.getNote(CATALINA_REQUEST_NOTE);
            final Response servletResponse = request.getNote(CATALINA_RESPONSE_NOTE);

            if (servletRequest != null) {
                try {
                    if (!servletRequest.isUpgrade()) {
                        servletResponse.finishResponse();
                    } else {
                        servletResponse.setUpgrade(servletRequest.isUpgrade());
                    }
                } catch (Exception e) {
                    log.log(Level.SEVERE, LogFacade.REQUEST_PROCESSING_EXCEPTION, e);
                } finally {
                    try {
                        servletRequest.unlockSession();
                    } finally {
                        servletRequest.recycle();
                        servletResponse.recycle();
                    }
                }
            }
        }
    }
}
