Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
src/main/java/org/apache/sling/engine/impl/Config.java
### 代码内容：
/*
 * 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.sling.engine.impl;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

/**
 * The OSGi configuration for the main servlet. This configuration is actually
 * used by various components throughout the bundle.
 */
@ObjectClassDefinition(name ="Apache Sling Main Servlet",
        description="Main processor of the Sling framework controlling all " +
                "aspects of processing requests inside of Sling, namely authentication, " +
                "resource resolution, servlet/script resolution and execution of servlets " +
                "and scripts.")
public @interface Config {

    String PID = "org.apache.sling.engine.impl.SlingMainServlet";

    /**
     * The default value for the number of recursive inclusions for a single
     * instance of this class (value is 50).
     */
    int DEFAULT_MAX_INCLUSION_COUNTER = 50;

    /**
     * The default value for the number of calls to the
     * {@link #service(SlingHttpServletRequest, SlingHttpServletResponse)}
     * method for a single instance of this class (value is 1000).
     */
    int DEFAULT_MAX_CALL_COUNTER = 1000;

    @AttributeDefinition(name = "Number of Calls per Request",
            description = "Defines the maximum number of Servlet and Script " +
                 "calls while processing a single client request. This number should be high " +
                 "enough to not limit request processing artificially. On the other hand it " +
                 "should not be too high to allow the mechanism to limit the resources required " +
                 "to process a request in case of errors. The default value is 1000.")
    int sling_max_calls() default DEFAULT_MAX_CALL_COUNTER;

    @AttributeDefinition(name = "Recursion Depth",
            description = "The maximum number of recursive Servlet and " +
                 "Script calls while processing a single client request. This number should not " +
                 "be too high, otherwise StackOverflowErrors may occurr in case of erroneous " +
                 "scripts and servlets. The default value is 50. ")
    int sling_max_inclusions() default DEFAULT_MAX_INCLUSION_COUNTER;

    @AttributeDefinition(name = "Allow the HTTP TRACE method",
            description = "If set to true, the HTTP TRACE method will be " +
                 "enabled. By default the HTTP TRACE methods is disabled as it can be used in " +
                 "Cross Site Scripting attacks on HTTP servers.")
    boolean sling_trace_allow() default false;

    @AttributeDefinition(name = "Number of Requests to Record",
            description = "Defines the number of requests that " +
                 "internally recorded for display on the \"Recent Requests\" Web Console page. If " +
                 "this value is less than or equal to zero, no requests are internally kept. The " +
                 "default value is 20. ")
    int sling_max_record_requests() default 20;

    @AttributeDefinition(name = "Recorded Request Path Patterns",
            description = "One or more regular expressions which " +
                        "limit the requests which are stored by the \"Recent Requests\" Web Console page.")
    String[] sling_store_pattern_requests();

    @AttributeDefinition(name = "Server Info",
            description = "The server info returned by Sling. If this field is left empty, Sling generates a default into.")
    String sling_serverinfo();

    @AttributeDefinition(name = "Additional response headers",
            description = "Provides mappings for additional response headers "
                + "Each entry is of the form 'bundleId [ \":\" responseHeaderName ] \"=\" responseHeaderValue'")
    String[] sling_additional_response_headers() default {"X-Content-Type-Options=nosniff", "X-Frame-Options=SAMEORIGIN"};

    @AttributeDefinition(name = "Servlet Name", description = "Optional name for the Sling main servlet registered by this component")
    String servlet_name();
}
## 内容2
### 文件路径：
src/main/java/org/apache/sling/engine/impl/SlingHttpServletRequestImpl.java
### 代码内容：
/*
 * 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.sling.engine.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.Part;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestDispatcherOptions;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.request.RequestProgressTracker;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.engine.impl.helper.NullResourceBundle;
import org.apache.sling.engine.impl.parameters.ParameterSupport;
import org.apache.sling.engine.impl.request.ContentData;
import org.apache.sling.engine.impl.request.RequestData;
import org.apache.sling.engine.impl.request.SlingRequestDispatcher;
import org.osgi.service.http.HttpContext;
import org.osgi.service.useradmin.Authorization;

public class SlingHttpServletRequestImpl extends HttpServletRequestWrapper implements
        SlingHttpServletRequest {

    private final RequestData requestData;
    private final String pathInfo;
    private String responseContentType;

    public SlingHttpServletRequestImpl(RequestData requestData,
            HttpServletRequest servletRequest) {
        super(servletRequest);
        this.requestData = requestData;

        // prepare the pathInfo property
        String pathInfo = servletRequest.getServletPath();
        if (servletRequest.getPathInfo() != null) {
            pathInfo = pathInfo.concat(servletRequest.getPathInfo());
        }
        this.pathInfo = pathInfo;
    }

    /**
     * @return the requestData
     */
    public final RequestData getRequestData() {
        return this.requestData;
    }

    //---------- Adaptable interface

    @Override
    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
        return getRequestData().getSlingRequestProcessor().adaptTo(this, type);
    }

    //---------- SlingHttpServletRequest interface

    ParameterSupport getParameterSupport() {
        return this.getRequestData().getParameterSupport();
    }

    @Override
    public Resource getResource() {
        final ContentData cd = getRequestData().getContentData();
        return (cd == null) ? null : cd.getResource();
    }

    @Override
    public ResourceResolver getResourceResolver() {
        return getRequestData().getResourceResolver();
    }

    @Override
    public RequestProgressTracker getRequestProgressTracker() {
        return getRequestData().getRequestProgressTracker();
    }

    /**
     * Returns null if resource is null.
     */
    @Override
    public RequestDispatcher getRequestDispatcher(Resource resource) {
        return getRequestDispatcher(resource, null);
    }

    /**
     * Returns null if resource is null.
     */
    @Override
    public RequestDispatcher getRequestDispatcher(Resource resource,
            RequestDispatcherOptions options) {
        return (resource != null) ? new SlingRequestDispatcher(resource, options) : null;
    }

    /**
     * Returns null if path is null.
     */
    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        return getRequestDispatcher(path, null);
    }

    /**
     * Returns null if path is null.
     */
    @Override
    public RequestDispatcher getRequestDispatcher(String path,
            RequestDispatcherOptions options) {
        return (path != null) ? new SlingRequestDispatcher(path, options) : null;
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
     */
    @Override
    public String getParameter(String name) {
        return this.getParameterSupport().getParameter(name);
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getParameterMap()
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        return this.getParameterSupport().getParameterMap();
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getParameterNames()
     */
    @Override
    public Enumeration<String> getParameterNames() {
        return this.getParameterSupport().getParameterNames();
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String)
     */
    @Override
    public String[] getParameterValues(String name) {
        return this.getParameterSupport().getParameterValues(name);
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getRequestParameter(java.lang.String)
     */
    @Override
    public RequestParameter getRequestParameter(String name) {
        return this.getParameterSupport().getRequestParameter(name);
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getRequestParameters(java.lang.String)
     */
    @Override
    public RequestParameter[] getRequestParameters(String name) {
        return this.getParameterSupport().getRequestParameters(name);
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getRequestParameterMap()
     */
    @Override
    public RequestParameterMap getRequestParameterMap() {
        return this.getParameterSupport().getRequestParameterMap();
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getRequestParameterList()
     */
    @Override
    public List<RequestParameter> getRequestParameterList() {
        return this.getParameterSupport().getRequestParameterList();
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getCookie(java.lang.String)
     */
    @Override
    public Cookie getCookie(String name) {
        Cookie[] cookies = getCookies();

        if (cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                if (cookies[i].getName().equals(name)) {
                    return cookies[i];
                }
            }
        }

        return null;
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getRequestPathInfo()
     */
    @Override
    public RequestPathInfo getRequestPathInfo() {
        final ContentData cd = getRequestData().getContentData();
        return (cd == null) ? null : cd.getRequestPathInfo();
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getResourceBundle(java.util.Locale)
     */
    @Override
    public ResourceBundle getResourceBundle(Locale locale) {
        return getResourceBundle(null, locale);
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getResourceBundle(String, Locale)
     */
    @Override
    public ResourceBundle getResourceBundle(String baseName, Locale locale) {
        if (locale == null) {
            locale = getLocale();
        }

        return new NullResourceBundle(locale);
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getResponseContentType()
     */
    @Override
    public String getResponseContentType() {
        if (responseContentType == null) {
            final String ext = getRequestPathInfo().getExtension();
            if ( ext != null ) {
                responseContentType = this.requestData.getSlingRequestProcessor().getMimeType("dummy.".concat(ext));
            }
        }
        return responseContentType;
    }

    /**
     * @see org.apache.sling.api.SlingHttpServletRequest#getResponseContentTypes()
     */
    @Override
    public Enumeration<String> getResponseContentTypes() {
        final String singleType = getResponseContentType();
        if (singleType != null) {
            return Collections.enumeration(Collections.singleton(singleType));
        }

        return Collections.emptyEnumeration();
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getInputStream()
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return this.getRequestData().getInputStream();
    }

    /**
     * @see javax.servlet.ServletRequestWrapper#getReader()
     */
    @Override
    public BufferedReader getReader() throws UnsupportedEncodingException,
            IOException {
        return this.getRequestData().getReader();
    }

    /**
     * @see javax.servlet.http.HttpServletRequestWrapper#getUserPrincipal()
     */
    @Override
    public Principal getUserPrincipal() {
        Principal principal = getResourceResolver().adaptTo(Principal.class);
        if (principal != null) {
            return principal;
        }
        //fallback to the userid
        String remoteUser = getRemoteUser();
        return (remoteUser != null) ? new UserPrincipal(remoteUser) : null;
    }

    /**
     * @see javax.servlet.http.HttpServletRequestWrapper#isUserInRole(String)
     */
    @Override
    public boolean isUserInRole(String role) {
        Object authorization = getAttribute(HttpContext.AUTHORIZATION);
        return (authorization instanceof Authorization)
                ? ((Authorization) authorization).hasRole(role)
                : false;
    }

    /**
     * Always returns the empty string since the actual servlet registered with
     * the servlet container (the HttpService actually) is registered as if
     * the servlet path is "/*".
     */
    @Override
    public String getServletPath() {
        return "";
    }

    /**
     * Returns the part of the request URL without the leading servlet context
     * path.
     */
    @Override
    public String getPathInfo() {
        return pathInfo;
    }

    public Part getPart(String name) {
        return (Part) this.getParameterSupport().getPart(name);
    }

    @SuppressWarnings("unchecked")
    public Collection<Part> getParts() {
        return (Collection<Part>) this.getParameterSupport().getParts();
    }

    /**
     * A UserPrincipal ...
     */
    private static class UserPrincipal implements Principal, Serializable {

        private final String name;

        /**
         * Creates a UserPrincipal with the given name.
         *
         * @param name the name of this principal
         * @throws IllegalArgumentException if name is null.
         */
        public UserPrincipal(String name) throws IllegalArgumentException {
            if (name == null) {
                throw new IllegalArgumentException("name can not be null");
            }
            this.name = name;
        }

        @Override
        public String toString() {
            return ("UserPrincipal: " + name);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof UserPrincipal) {
                UserPrincipal other = (UserPrincipal) obj;
                return name.equals(other.name);
            }
            return false;
        }

        @Override
        public int hashCode() {
            return name.hashCode();
        }

        //------------------------------------------------------------< Principal >
        /**
         * {@inheritDoc}
         */
        @Override
        public String getName() {
            return name;
        }
    }

}

## 内容3
### 文件路径：
src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
### 代码内容：
/*
 * 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.sling.engine.impl;

import static org.apache.sling.api.SlingConstants.ERROR_SERVLET_NAME;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.SlingServletException;
import org.apache.sling.api.adapter.AdapterManager;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceNotFoundException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.engine.SlingRequestProcessor;
import org.apache.sling.engine.impl.debug.RequestInfoProviderImpl;
import org.apache.sling.engine.impl.filter.ErrorFilterChainStatus;
import org.apache.sling.engine.impl.filter.ErrorFilterChainThrowable;
import org.apache.sling.engine.impl.filter.FilterHandle;
import org.apache.sling.engine.impl.filter.RequestSlingFilterChain;
import org.apache.sling.engine.impl.filter.ServletFilterManager;
import org.apache.sling.engine.impl.filter.ServletFilterManager.FilterChainType;
import org.apache.sling.engine.impl.helper.SlingServletContext;
import org.apache.sling.engine.impl.filter.SlingComponentFilterChain;
import org.apache.sling.engine.impl.parameters.ParameterSupport;
import org.apache.sling.engine.impl.request.ContentData;
import org.apache.sling.engine.impl.request.RequestData;
import org.apache.sling.engine.servlets.ErrorHandler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(service = {SlingRequestProcessor.class, SlingRequestProcessorImpl.class},
    configurationPid = Config.PID)
public class SlingRequestProcessorImpl implements SlingRequestProcessor {

    /** default log */
    private final Logger log = LoggerFactory.getLogger(SlingRequestProcessorImpl.class);

    @Reference
    private ServletResolver servletResolver;

    @Reference
    private ServletFilterManager filterManager;

    @Reference
    private RequestProcessorMBeanImpl mbean;

    @Reference(target = SlingServletContext.TARGET)
    private ServletContext slingServletContext;

    @Reference(cardinality=ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
    private volatile AdapterManager adapterManager;

    /**
     * Resolves MIME types
     *
     * @see #getMimeType(String)
     */
    @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL)
    private volatile MimeTypeService mimeTypeService;

    private final DefaultErrorHandler errorHandler = new DefaultErrorHandler();

    private volatile int maxCallCounter = Config.DEFAULT_MAX_CALL_COUNTER;

    private volatile int maxInclusionCounter = Config.DEFAULT_MAX_INCLUSION_COUNTER;

    private volatile List<StaticResponseHeader> additionalResponseHeaders = Collections.emptyList();

    @Activate
    public void activate(final Config config) {
        this.errorHandler.setServerInfo(this.slingServletContext.getServerInfo());
        this.modified(config);
    }

    @Modified
    public void modified(final Config config) {
        final List<StaticResponseHeader> mappings = new ArrayList<>();
        final String[] props = config.sling_additional_response_headers();
        if ( props != null ) {
            for (final String prop : props) {
                if (prop != null && prop.trim().length() > 0 ) {
                    try {
                        final StaticResponseHeader mapping = new StaticResponseHeader(prop.trim());
                        mappings.add(mapping);
                    } catch (final IllegalArgumentException iae) {
                        log.info("configure: Ignoring '{}': {}", prop, iae.getMessage());
                    }
                }
            }
        }
        this.additionalResponseHeaders = mappings;

        // configure the request limits
        this.maxInclusionCounter = config.sling_max_inclusions();
        this.maxCallCounter = config.sling_max_calls();
    }

    @Reference(name = "ErrorHandler", cardinality=ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, unbind = "unsetErrorHandler")
    void setErrorHandler(final ErrorHandler errorHandler) {
        this.errorHandler.setDelegate(errorHandler);
    }

    void unsetErrorHandler(final ErrorHandler errorHandler) {
        this.errorHandler.setDelegate(null);
    }

    public int getMaxCallCounter() {
        return maxCallCounter;
    }

    public int getMaxIncludeCounter() {
        return maxInclusionCounter;
    }

    public List<StaticResponseHeader> getAdditionalResponseHeaders() {
        return this.additionalResponseHeaders;
    }

    public <Type> Type adaptTo(Object object, Class<Type> type) {
        final AdapterManager adapterManager = this.adapterManager;
        if (adapterManager != null) {
            return adapterManager.getAdapter(object, type);
        }

        // no adapter manager, nothing to adapt to
        return null;
    }

    /**
     * This method is directly called by the Sling main servlet.
     */
    public void doProcessRequest(final HttpServletRequest servletRequest,
            final HttpServletResponse servletResponse,
            final ResourceResolver resourceResolver) throws IOException {
        final ServletResolver sr = this.servletResolver;

        // check that we have all required services
        if (resourceResolver == null || sr == null) {
            // Dependencies are missing
            // In this case we must not use the Sling error handling infrastructure but
            // just return a 503 status response handled by the servlet container environment

            final int status = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
            String errorMessage = "Required service missing (";
            if ( resourceResolver == null ) {
                errorMessage = errorMessage.concat("ResourceResolver");
                if ( sr == null ) {
                    errorMessage = errorMessage.concat(", ");
                }
            }
            if ( sr == null ) {
                errorMessage = errorMessage.concat("ServletResolver");
            }
            log.debug("{}), cannot service requests, sending status {}", errorMessage, status);
            servletResponse.sendError(status, errorMessage);
            return;
        }

        // setting the Sling request and response
        final RequestData requestData = new RequestData(this, servletRequest, servletResponse);
        final SlingHttpServletRequest request = requestData.getSlingRequest();
        final SlingHttpServletResponse response = requestData.getSlingResponse();

        final boolean isInclude = request.getAttribute(SlingConstants.ATTR_INCLUDE_CONTEXT_PATH) != null;
        try {
            // initialize the request data - resolve resource and servlet
            final Resource resource = requestData.initResource(resourceResolver);
            requestData.initServlet(resource, sr);

            final FilterHandle[] filters = filterManager.getFilters(FilterChainType.REQUEST);
            final FilterChain processor = new RequestSlingFilterChain(this, filters);

            request.getRequestProgressTracker().log("Applying ".concat(FilterChainType.REQUEST.name()).concat("filters"));

            processor.doFilter(request, response);

        } catch ( final SlingHttpServletResponseImpl.WriterAlreadyClosedException wace ) {
            // this is an exception case, log as error
            log.error("Writer has already been closed.", wace);

        } catch (final ResourceNotFoundException rnfe) {
            // send this exception as a 404 status
            log.debug("service: Resource {} not found", rnfe.getResource());

            if ( isInclude ) {
                throw rnfe;
            }
            handleError(HttpServletResponse.SC_NOT_FOUND, rnfe.getMessage(), request, response);

        } catch (final SlingException se) {

            if ( isInclude ) {
                throw se;
            }
            // if we have request data and a non-null active servlet name
            // we assume, that this is the name of the causing servlet
            if (requestData.getActiveServletName() != null) {
                request.setAttribute(ERROR_SERVLET_NAME,
                    requestData.getActiveServletName());
            }

            // send this exception as is (albeit unwrapping and wrapped
            // exception.
            Throwable t = se;
            while ( t instanceof SlingException && t.getCause() != null ) {
                t = t.getCause();
            }
            log.error("service: Uncaught SlingException ", t);
            handleError(t, request, response);

        } catch (final AccessControlException ace) {

            if ( isInclude ) {
                throw ace;
            }
            // SLING-319 if anything goes wrong, send 403/FORBIDDEN
            log.debug(
                "service: Authenticated user {} does not have enough rights to executed requested action",
                request.getRemoteUser());
            handleError(HttpServletResponse.SC_FORBIDDEN, null, request,
                response);

        } catch (final IOException ioe) {

            // forward IOException up the call chain to properly handle it
            throw ioe;

        } catch (final Throwable t) {

            if ( isInclude ) {
                if ( t instanceof RuntimeException ) {
                    throw (RuntimeException)t;
                }
                if ( t instanceof Error ) {
                    throw (Error)t;
                }
                throw new SlingException(t.getMessage(), t);
            }

            // if we have request data and a non-null active servlet name
            // we assume, that this is the name of the causing servlet
            if (requestData.getActiveServletName() != null) {
                request.setAttribute(ERROR_SERVLET_NAME,
                    requestData.getActiveServletName());
            }

            log.error("service: Uncaught Throwable", t);
            handleError(t, request, response);

        } finally {
            // record the request for the web console and info provider
            RequestInfoProviderImpl.recordRequest(request);

            if (mbean != null) {
                mbean.addRequestData(requestData);
            }
        }
    }

    // ---------- SlingRequestProcessor interface

    /**
     * @see org.apache.sling.engine.SlingRequestProcessor#processRequest(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.apache.sling.api.resource.ResourceResolver)
     */
    @Override
    public void processRequest(final HttpServletRequest servletRequest,
            final HttpServletResponse servletResponse,
            final ResourceResolver resourceResolver) throws IOException {
        // set the marker for the parameter support
        final Object oldValue = servletRequest.getAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING);
        servletRequest.setAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING, Boolean.TRUE);
        try {
            this.doProcessRequest(servletRequest, servletResponse, resourceResolver);
        } finally {
            // restore the old value
            if ( oldValue != null ) {
                servletRequest.setAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING, oldValue);
            } else {
                servletRequest.removeAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING);
            }
        }
    }

    /**
     * Renders the component defined by the RequestData's current ComponentData
     * instance after calling all filters of the given
     * {@link org.apache.sling.engine.impl.filter.ServletFilterManager.FilterChainType
     * filterChainType}.
     *
     * @param request
     * @param response
     * @param filterChainType
     * @throws IOException
     * @throws ServletException
     */

    public void processComponent(SlingHttpServletRequest request,
            SlingHttpServletResponse response,
            final FilterChainType filterChainType) throws IOException,
            ServletException {

        final FilterHandle filters[] = filterManager.getFilters(filterChainType);

        FilterChain processor = new SlingComponentFilterChain(filters);
        request.getRequestProgressTracker().log(
            "Applying " + filterChainType + "filters");
        processor.doFilter(request, response);
    }

    // ---------- Generic Content Request processor ----------------------------

    /**
     * Dispatches the request on behalf of the
     * {@link org.apache.sling.engine.impl.request.SlingRequestDispatcher}.
     * @param request The request
     * @param response The response
     * @param resource The resource
     * @param resolvedURL Request path info
     * @param include Is this an include (or forward) ?
     * @param protectHeadersOnInclude Should the headers be protected on include?
     */
    public void dispatchRequest(final ServletRequest request,
            final ServletResponse response, final Resource resource,
            final RequestPathInfo resolvedURL,
            final boolean include,
            final boolean protectHeadersOnInclude) throws IOException, ServletException {

        // we need a SlingHttpServletRequest/SlingHttpServletResponse tupel
        // to continue
        final SlingHttpServletRequest cRequest = RequestData.toSlingHttpServletRequest(request);
        final SlingHttpServletResponse cResponse = RequestData.toSlingHttpServletResponse(response);

        // get the request data (and btw check the correct type)
        final RequestData requestData = RequestData.getRequestData(cRequest);
        final ContentData oldContentData = requestData.getContentData();
        final ContentData contentData = requestData.setContent(resource, resolvedURL);

        try {
            // resolve the servlet
            Servlet servlet = servletResolver.resolveServlet(cRequest);
            contentData.setServlet(servlet);

            FilterChainType type = include
                    ? FilterChainType.INCLUDE
                    : FilterChainType.FORWARD;

            processComponent(cRequest, include && protectHeadersOnInclude ? new IncludeResponseWrapper(cResponse) : cResponse, type);
        } finally {
            requestData.resetContent(oldContentData);
        }
    }

    // ---------- Error Handling with Filters

    private void handleError(final FilterChain errorFilterChain,
            final SlingHttpServletRequest request,
            final SlingHttpServletResponse response)
    throws IOException {
        request.getRequestProgressTracker().log("Applying " + FilterChainType.ERROR + " filters");

        try {
            // wrap the response ensuring getWriter will fall back to wrapping
            // the response output stream if reset does not reset this
            errorFilterChain.doFilter(request, new ErrorResponseWrapper(response));
        } catch (final ServletException se) {
            throw new SlingServletException(se);
        }
    }

    void handleError(final int status, final String message,
            final SlingHttpServletRequest request,
            final SlingHttpServletResponse response) throws IOException {
        final FilterHandle[] filters = filterManager.getFilters(FilterChainType.ERROR);
        final FilterChain processor = new ErrorFilterChainStatus(filters, errorHandler, status, message);
        this.handleError(processor, request, response);
    }

    private void handleError(final Throwable throwable,
            final SlingHttpServletRequest request,
            final SlingHttpServletResponse response) throws IOException {
        final FilterHandle[] filters = filterManager.getFilters(FilterChainType.ERROR);
        final FilterChain processor = new ErrorFilterChainThrowable(filters, errorHandler, throwable);
        this.handleError(processor, request, response);
    }

    private static class ErrorResponseWrapper extends
            SlingHttpServletResponseWrapper {

        private PrintWriter writer;

        public ErrorResponseWrapper(SlingHttpServletResponse wrappedResponse) {
            super(wrappedResponse);
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            if (writer == null) {
                try {
                    writer = super.getWriter();
                } catch (IllegalStateException ise) {
                    // resetting the response did not reset the output channel
                    // status and we have to create a writer based on the output
                    // stream using the character encoding already set on the
                    // response, defaulting to ISO-8859-1
                    OutputStream out = getOutputStream();
                    String encoding = getCharacterEncoding();
                    if (encoding == null) {
                        encoding = "ISO-8859-1";
                        setCharacterEncoding(encoding);
                    }
                    Writer w = new OutputStreamWriter(out, encoding);
                    writer = new PrintWriter(w);
                }
            }
            return writer;
        }

        /**
         * Flush the writer if the {@link #getWriter()} method was called
         * to potentially wrap an OuputStream still existing in the response.
         */
        @Override
        public void flushBuffer() throws IOException {
            if (writer != null) {
                writer.flush();
            }
            super.flushBuffer();
        }
    }

    /**
     * Returns the MIME type as resolved by the MimeTypeService or
     * null if the service is not available.
     */
    public String getMimeType(final String name) {
        MimeTypeService mtservice = mimeTypeService;
        if (mtservice != null) {
            return mtservice.getMimeType(name);
        }

        log.debug(
            "getMimeType: MimeTypeService not available, cannot resolve mime type for {}",
            name);
        return null;
    }
}

## 内容4
### 文件路径：
src/main/java/org/apache/sling/engine/impl/helper/SlingServletContext.java
### 代码内容：
/*
 * 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.sling.engine.impl.helper;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;

import org.apache.sling.engine.impl.Config;
import org.apache.sling.engine.impl.ProductInfoProvider;
import org.apache.sling.engine.impl.SlingHttpContext;
import org.apache.sling.engine.impl.SlingMainServlet;
import org.apache.sling.engine.impl.request.SlingRequestDispatcher;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardContextSelect;
import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The SlingServletContext class is the ServletContext
 * which is registered as a service usable by servlets and helpers inside Sling.
 * Most methods just call into the servlet context in which the
 * {@link SlingMainServlet} is running.
 *

 *
MIME Type Mapping

 *
Just forwards to the servlet context of the {@link SlingMainServlet} for
 * MIME type mapping.

 *
Resources

 *
This class provides access to the resources in the web application by
 * means of the respective resource accessor methods. These are not the same
 * resources as available through the ResourceResolver.

 *
Request Dispatcher

 *
The {@link #getRequestDispatcher(String)} method returns a
 * {@link SlingRequestDispatcher} which may dispatch a request inside sling
 * without going through the servlet container. The
 * {@link #getNamedDispatcher(String)} method returns a servlet container
 * request dispatcher which always goes through the servlet container.

 *
Parameters and Attributes

 *
Initialization parameters and context attributes are shared with the
 * servlet context in which the {@link SlingMainServlet} is running.

 *
Logging

 *
Logging is diverted to a logger whose name is the fully qualified name of
 * this class.

 *

 *

 * This class implements the Servlet API 3.0 {@code ServletContext} interface.
 */
@Component(service = ServletContextListener.class,
    configurationPid = Config.PID)
@HttpWhiteboardContextSelect("(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + SlingHttpContext.SERVLET_CONTEXT_NAME + ")")
@HttpWhiteboardListener
public class SlingServletContext implements ServletContext, ServletContextListener {

    public static final String TARGET = "(name=" + SlingHttpContext.SERVLET_CONTEXT_NAME + ")";

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    private final ProductInfoProvider productInfoProvider;

    private final BundleContext bundleContext;

    /**
     * The server information to report in the {@link #getServerInfo()} method.
     * By default this is just the {@link #PRODUCT_NAME} (same as
     * {@link #productInfo}. During {@link #activate(BundleContext, Map, Config)}
     * activation} the field is updated with the full {@link #productInfo} value
     * as well as the operating system and java version it is running on.
     * Finally during servlet initialization the product information from the
     * servlet container's server info is added to the comment section.
     */
    private volatile String serverInfo;

    private volatile String configuredServerInfo;

    private volatile ServletContext servletContext;

    private volatile ServiceRegistration<ServletContext> registration;

    @Activate
    public SlingServletContext(final Config config,
        final BundleContext bundleContext,
        @Reference final ProductInfoProvider infoProvider) {
        this.bundleContext = bundleContext;
        this.productInfoProvider = infoProvider;
        this.setup(config);
    }

    @Modified
    protected void modified(final Config config) {
        setup(config);
    }

    private void setup(final Config config) {
        if (config.sling_serverinfo() != null && !config.sling_serverinfo().isEmpty()) {
            this.configuredServerInfo = config.sling_serverinfo();
        } else {
            this.configuredServerInfo = null;
        }

        this.setServerInfo();
    }

    /**
     * Sets up the server info to be returned for the
     * ServletContext.getServerInfo() method for servlets and
     * filters deployed inside Sling. The {@link SlingRequestProcessor} instance
     * is also updated with the server information.
     *

     * This server info is either configured through an OSGi configuration or
     * it is made up of the following components:
     *

     *
The {@link #productInfo} field as the primary product information

     *
The primary product information of the servlet container into which
     * the Sling Main Servlet is deployed. If the servlet has not yet been
     * deployed this will show as unregistered. If the servlet container
     * does not provide a server info this will show as unknown.

     *
The name and version of the Java VM as reported by the
     * java.vm.name and java.vm.version system
     * properties

     *
The name, version, and architecture of the OS platform as reported by
     * the os.name, os.version, and
     * os.arch system properties

     *

     */
    private void setServerInfo() {
        if ( this.configuredServerInfo != null ) {
            this.serverInfo = this.configuredServerInfo;
        } else {
            final String containerProductInfo;
            if (getServletContext() == null) {
                containerProductInfo = "unregistered";
            } else {
                final String containerInfo = getServletContext().getServerInfo();
                if (containerInfo != null && containerInfo.length() > 0) {
                    int lbrace = containerInfo.indexOf('(');
                    if (lbrace < 0) {
                        lbrace = containerInfo.length();
                    }
                    containerProductInfo = containerInfo.substring(0, lbrace).trim();
                } else {
                    containerProductInfo = "unknown";
                }
            }

            this.serverInfo = String.format("%s (%s, %s %s, %s %s %s)",
                this.productInfoProvider.getProductInfo(), containerProductInfo,
                System.getProperty("java.vm.name"),
                System.getProperty("java.version"), System.getProperty("os.name"),
                System.getProperty("os.version"), System.getProperty("os.arch"));
        }
    }

    @Override
    public void contextDestroyed(final ServletContextEvent sce) {
        synchronized ( this ) {
            this.servletContext = null;
            this.setServerInfo();
            if ( this.registration != null ) {
                this.registration.unregister();
                this.registration = null;
            }
        }
    }

    @Override
    public void contextInitialized(final ServletContextEvent sce) {
        this.servletContext = sce.getServletContext();
        this.setServerInfo();
        // async registreation
        final Thread thread = new Thread("SlingServletContext registration") {
            @Override
            public void run() {
                synchronized (SlingServletContext.this) {
                    if ( servletContext != null ) {
                        final Dictionary<String, Object> props = new Hashtable<String, Object>();
                        props.put("name", SlingHttpContext.SERVLET_CONTEXT_NAME); // property to identify this context
                        registration = bundleContext.registerService(ServletContext.class, SlingServletContext.this, props);
                    }
                }
            }
        };
        thread.setDaemon(true);
        thread.start();
    }

    /**
     * Returns the name of the servlet context in which Sling is configured.
     * This method calls on the ServletContext in which the
     * {@link SlingMainServlet} is running.
     */
    @Override
    public String getServletContextName() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getServletContextName();
        }

        return null;
    }

    /** Returns the context path of the web application. (Servlet API 2.5) */
    @Override
    public String getContextPath() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getContextPath();
        }

        return null;
    }

    /**
     * Returns the init-param of the servlet context in which Sling is
     * configured. This method calls on the ServletContext in
     * which the {@link SlingMainServlet} is running.
     */
    @Override
    public String getInitParameter(String name) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getInitParameter(name);
        }

        return null;
    }

    /**
     * Returns the names of the init-params of the servlet context in which
     * Sling is configured. This method calls on the ServletContext
     * in which the {@link SlingMainServlet} is running.
     */
    @Override
    public Enumeration<String> getInitParameterNames() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getInitParameterNames();
        }

        return null;
    }

    // ---------- attributes ---------------------------------------------------

    /**
     * Returns the named servlet context attribute. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public Object getAttribute(String name) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getAttribute(name);
        }

        return null;
    }

    /**
     * Returns the names of all servlet context attributes. This method calls on
     * the ServletContext in which the {@link SlingMainServlet}
     * is running.
     */
    @Override
    public Enumeration<String> getAttributeNames() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getAttributeNames();
        }

        return Collections.enumeration(Collections.<String>emptyList());
    }

    /**
     * Removes the named servlet context attribute. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public void removeAttribute(String name) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            delegatee.removeAttribute(name);
        }
    }

    /**
     * Sets the name servlet context attribute to the requested value. This
     * method calls on the ServletContext in which the
     * {@link SlingMainServlet} is running.
     */
    @Override
    public void setAttribute(String name, Object object) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            delegatee.setAttribute(name, object);
        }
    }

    // ---------- Servlet Container information --------------------------------

    /**
     * Returns the Sling server info string. This is not the same server info
     * string as returned by the servlet context in which Sling is configured.
     */
    @Override
    public String getServerInfo() {
        return this.serverInfo;
    }

    /**
     * Returns the major version number of the Servlet API supported by the
     * servlet container in which Sling is running. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public int getMajorVersion() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getMajorVersion();
        }

        return 3; // hard coded major version as fall back
    }

    /**
     * Returns the minor version number of the Servlet API supported by the
     * servlet container in which Sling is running. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public int getMinorVersion() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getMinorVersion();
        }

        return 0; // hard coded minor version as fall back
    }

    // ---------- MIME type mapping --------------------------------------------

    /**
     * Returns a MIME type for the extension of the given file name. This method
     * calls on the ServletContext in which the
     * {@link SlingMainServlet} is running.
     */
    @Override
    public String getMimeType(String file) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getMimeType(file);
        }

        return null;
    }

    // ---------- Request Dispatcher -------------------------------------------

    /**
     * Returns a {@link SlingRequestDispatcher} for the given path if not
     * null. Otherwise null is returned.
     */
    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        // return no dispatcher if content is null
        if (path == null) {
            log.error("getRequestDispatcher: No path, cannot create request dispatcher");
            return null;
        }

        return new SlingRequestDispatcher(path, null);
    }

    /**
     * Returns a servlet container request dispatcher for the named servlet.
     * This method calls on the ServletContext in which the
     * {@link SlingMainServlet} is running.
     */
    @Override
    public RequestDispatcher getNamedDispatcher(String name) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getNamedDispatcher(name);
        }

        return null;
    }

    // ---------- Resource Access ----------------------------------------------

    /**
     * Returns the URI for the given path. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public URL getResource(String path) throws MalformedURLException {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getResource(path);
        }

        return null;
    }

    /**
     * Returns an input stream to the given path. This method calls on the
     * ServletContext in which the {@link SlingMainServlet} is
     * running.
     */
    @Override
    public InputStream getResourceAsStream(String path) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getResourceAsStream(path);
        }

        return null;
    }

    /**
     * Returns a set of names for path entries considered children of the given
     * path. This method calls on the ServletContext in which the
     * {@link SlingMainServlet} is running.
     */
    @Override
    public Set<String> getResourcePaths(String parentPath) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getResourcePaths(parentPath);
        }

        return null;
    }

    /**
     * Returns the real file inside the web application to which the given path
     * maps or null if no such file exists. This method calls on
     * the ServletContext in which the {@link SlingMainServlet}
     * is running.
     */
    @Override
    public String getRealPath(String path) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getRealPath(path);
        }

        return null;
    }

    // ---------- logging ------------------------------------------------------

    /** Logs the message and optional throwable at error level to the logger */
    @Override
    public void log(String message, Throwable throwable) {
        log.error(message, throwable);
    }

    /** Logs the message at info level to the logger */
    @Override
    public void log(String message) {
        log.info(message);
    }

    /** Logs the message and optional exception at error level to the logger */
    @Override
    @Deprecated
    public void log(Exception exception, String message) {
        log(message, exception);
    }

    // ---------- foreign Servlets ---------------------------------------------

    /**
     * Returns the servlet context from the servlet container in which sling is
     * running. This method calls on the ServletContext in which
     * the {@link SlingMainServlet} is running.
     */
    @Override
    public ServletContext getContext(String uripath) {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            ServletContext otherContext = delegatee.getContext(uripath);
            if (otherContext != null && otherContext != delegatee) {
                return wrapServletContext(otherContext);
            }
        }

        return null;
    }

    /** Returns null as defined in Servlet API 2.4 */
    @Override
    @Deprecated
    public Servlet getServlet(String name) {
        return null;
    }

    /** Returns an empty enumeration as defined in Servlet API 2.4 */
    @Override
    @Deprecated
    public Enumeration<String> getServletNames() {
        return Collections.enumeration(Collections.<String>emptyList());
    }

    /** Returns an empty enumeration as defined in Servlet API 2.4 */
    @Override
    @Deprecated
    public Enumeration<Servlet> getServlets() {
        return Collections.enumeration(Collections.<Servlet>emptyList());
    }

    @Override
    public int getEffectiveMajorVersion() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getEffectiveMajorVersion();
        }
        return 3;
    }

    @Override
    public int getEffectiveMinorVersion() {
        ServletContext delegatee = getServletContext();
        if (delegatee != null) {
            return delegatee.getEffectiveMinorVersion();
        }
        return 0;
    }

    @Override
    public boolean setInitParameter(String name, String value) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public SessionCookieConfig getSessionCookieConfig() {
        // result in NPE if context is not set anymore
        return getServletContext().getSessionCookieConfig();
    }

    @Override
    public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
        // result in NPE if context is not set anymore
        return getServletContext().getDefaultSessionTrackingModes();
    }

    @Override
    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
        // result in NPE if context is not set anymore
        return getServletContext().getEffectiveSessionTrackingModes();
    }

    @Override
    public JspConfigDescriptor getJspConfigDescriptor() {
        // result in NPE if context is not set anymore
        return getServletContext().getJspConfigDescriptor();
    }

    @Override
    public ClassLoader getClassLoader() {
        // we don't allow access to any class loader here since we are
        // running in the OSGi Framework and we don't want code to fiddle
        // with class laoders obtained from the ServletContext
        throw new SecurityException();
    }

    @Override
    public void declareRoles(String... roleNames) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    // Servlet API 3.0, Section 4.4 Configuration methods

    @Override
    public Dynamic addServlet(String servletName, String className) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public Dynamic addServlet(String servletName, Servlet servlet) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public <T extends Servlet> T createServlet(Class<T> clazz) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public ServletRegistration getServletRegistration(String servletName) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public Map<String, ? extends ServletRegistration> getServletRegistrations() {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public <T extends Filter> T createFilter(Class<T> clazz) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public FilterRegistration getFilterRegistration(String filterName) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public void addListener(String className) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public <T extends EventListener> void addListener(T t) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public void addListener(Class<? extends EventListener> listenerClass) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public <T extends EventListener> T createListener(Class<T> clazz) {
        // only supported in ServletContextListener.contextInitialized or
        // ServletContainerInitializer.onStartuo
        throw new IllegalStateException();
    }

    @Override
    public String getVirtualServerName() {
        return getServletContext().getVirtualServerName();
    }

    // ---------- internal -----------------------------------------------------

    /**
     * Returns the real servlet context of the servlet container in which the
     * Sling Servlet is running.
     *
     * @return the servlet context
     */
    protected ServletContext getServletContext() {
        return this.servletContext;
    }

    protected ServletContext wrapServletContext(final ServletContext context) {
        return new ExternalServletContextWrapper(context);
    }
}

## 内容5
### 文件路径：
src/main/java/org/apache/sling/engine/impl/request/RequestData.java
### 代码内容：
/*
 * 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.sling.engine.impl.request;

import static org.apache.sling.api.SlingConstants.SLING_CURRENT_SERVLET_NAME;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RecursionTooDeepException;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.request.RequestProgressTracker;
import org.apache.sling.api.request.RequestUtil;
import org.apache.sling.api.request.TooManyCallsException;
import org.apache.sling.api.request.builder.Builders;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.engine.impl.SlingHttpServletRequestImpl;
import org.apache.sling.engine.impl.SlingHttpServletResponseImpl;
import org.apache.sling.engine.impl.SlingMainServlet;
import org.apache.sling.engine.impl.SlingRequestProcessorImpl;
import org.apache.sling.engine.impl.adapter.SlingServletRequestAdapter;
import org.apache.sling.engine.impl.adapter.SlingServletResponseAdapter;
import org.apache.sling.engine.impl.parameters.ParameterSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The RequestData class provides access to objects which are set
 * on a Servlet Request wide basis such as the repository session, the
 * persistence manager, etc.
 *
 * The setup order is:
 *

 *
Invoke constructor

 *
Invoke initResource()

 *
Invoke initServlet()

 *

 * @see ContentData
 */
public class RequestData {

    /** Logger - use static as a new object is created with every request */
    private static final Logger log = LoggerFactory.getLogger(RequestData.class);

    /**
     * The name of the request attribute providing the resource addressed by the
     * request URL.
     */
    public static final String REQUEST_RESOURCE_PATH_ATTR = "$$sling.request.resource$$";

    /**
     * The name of the request attribute to override the max call number (-1 for infinite or integer value).
     */
    private static String REQUEST_MAX_CALL_OVERRIDE = "sling.max.calls";

    /** The request processor used for request dispatching and other stuff */
    private final SlingRequestProcessorImpl slingRequestProcessor;

    private final long startTimestamp;

    /** The original servlet Servlet Request Object */
    private final HttpServletRequest servletRequest;

    /** The original servlet Servlet Response object */
    private final HttpServletResponse servletResponse;

    /** The original servlet Servlet Request Object */
    private final SlingHttpServletRequest slingRequest;

    /** The original servlet Servlet Response object */
    private final SlingHttpServletResponse slingResponse;

    /** The parameter support class */
    private ParameterSupport parameterSupport;

    private ResourceResolver resourceResolver;

    private final RequestProgressTracker requestProgressTracker;

    /** the current ContentData */
    private ContentData currentContentData;

    /**
     * the number of servlets called by
     * {@link #service(SlingHttpServletRequest, SlingHttpServletResponse)}
     */
    private int servletCallCounter;

    /**
     * The name of the currently active serlvet.
     *
     * @see #setActiveServletName(String)
     * @see #getActiveServletName()
     */
    private String activeServletName;

    /**
     * Recursion depth
     */
    private int recursionDepth;

    /**
     * The peak value for the recursion depth.
     */
    private int peakRecusionDepth;

    /**
     * Prevent traversal using '/../' or '/..' even if '[' or '}' is used in-between
     */
    private static final Set<Character> SKIPPED_TRAVERSAL_CHARS = new HashSet<>();
    static {
        SKIPPED_TRAVERSAL_CHARS.add('[');
        SKIPPED_TRAVERSAL_CHARS.add('}');
    }

    public RequestData(SlingRequestProcessorImpl slingRequestProcessor,
            HttpServletRequest request, HttpServletResponse response) {
        this.startTimestamp = System.currentTimeMillis();

        this.slingRequestProcessor = slingRequestProcessor;

        this.servletRequest = request;
        this.servletResponse = response;

        this.slingRequest = new SlingHttpServletRequestImpl(this, this.servletRequest);

        this.slingResponse = new SlingHttpServletResponseImpl(this, this.servletResponse);

        // Use tracker from SlingHttpServletRequest
        if ( request instanceof SlingHttpServletRequest ) {
            this.requestProgressTracker = ((SlingHttpServletRequest)request).getRequestProgressTracker();
        } else {
            // Getting the RequestProgressTracker from the request attributes like
            // this should not be generally used, it's just a way to pass it from
            // its creation point to here, so it's made available via
            // the Sling request's getRequestProgressTracker method.
            final Object o = request.getAttribute(RequestProgressTracker.class.getName());
            if (o instanceof RequestProgressTracker) {
                this.requestProgressTracker = (RequestProgressTracker)o;
            } else {
                log.warn("RequestProgressTracker not found in request attributes");
                this.requestProgressTracker = Builders.newRequestProgressTracker();
                this.requestProgressTracker.log("Method={0}, PathInfo={1}", request.getMethod(), request.getPathInfo());
            }
        }
    }

    public Resource initResource(ResourceResolver resourceResolver) {
        // keep the resource resolver for request processing
        this.resourceResolver = resourceResolver;

        // resolve the resource
        requestProgressTracker.startTimer("ResourceResolution");
        final SlingHttpServletRequest request = getSlingRequest();

        StringBuffer requestURL = servletRequest.getRequestURL();
        String path = request.getPathInfo();
        if (requestURL.indexOf(";") > -1 && !path.contains(";")) {
            try {
                final URL rUrl = new URL(requestURL.toString());
                final String prefix = request.getContextPath().concat(request.getServletPath());
                path = rUrl.getPath().substring(prefix.length());
            } catch ( final MalformedURLException e) {
                // ignore
            }
        }

        Resource resource = resourceResolver.resolve(request, path);
        if (request.getAttribute(REQUEST_RESOURCE_PATH_ATTR) == null) {
            request.setAttribute(REQUEST_RESOURCE_PATH_ATTR, resource.getPath());
        }
        requestProgressTracker.logTimer("ResourceResolution",
            "URI={0} resolves to Resource={1}",
            getServletRequest().getRequestURI(), resource);
        return resource;
    }

    public void initServlet(final Resource resource,
            final ServletResolver sr) {
        // the resource and the request path info, will never be null
        RequestPathInfo requestPathInfo = new SlingRequestPathInfo(resource);
        ContentData contentData = setContent(resource, requestPathInfo);

	    requestProgressTracker.log("Resource Path Info: {0}", requestPathInfo);

        // finally resolve the servlet for the resource
        requestProgressTracker.startTimer("ServletResolution");
        Servlet servlet = sr.resolveServlet(slingRequest);
        requestProgressTracker.logTimer("ServletResolution",
            "URI={0} handled by Servlet={1}",
            getServletRequest().getRequestURI(), (servlet == null ? "-none-" : RequestUtil.getServletName(servlet)));
        contentData.setServlet(servlet);
    }

    public SlingRequestProcessorImpl getSlingRequestProcessor() {
        return slingRequestProcessor;
    }

    public HttpServletRequest getServletRequest() {
        return servletRequest;
    }

    public HttpServletResponse getServletResponse() {
        return servletResponse;
    }

    public SlingHttpServletRequest getSlingRequest() {
        return slingRequest;
    }

    public SlingHttpServletResponse getSlingResponse() {
        return slingResponse;
    }

    // ---------- Request Helper

    /**
     * Unwraps the ServletRequest to a SlingHttpServletRequest.
     *
     * @param request the request
     * @return the unwrapped request
     * @throws IllegalArgumentException If the request is not a
     *             SlingHttpServletRequest and not a
     *             ServletRequestWrapper wrapping a
     *             SlingHttpServletRequest.
     */
    public static SlingHttpServletRequest unwrap(ServletRequest request) {

        // early check for most cases
        if (request instanceof SlingHttpServletRequest) {
            return (SlingHttpServletRequest) request;
        }

        // unwrap wrappers
        while (request instanceof ServletRequestWrapper) {
            request = ((ServletRequestWrapper) request).getRequest();

            // immediate termination if we found one
            if (request instanceof SlingHttpServletRequest) {
                return (SlingHttpServletRequest) request;
            }
        }

        // if we unwrapped everything and did not find a
        // SlingHttpServletRequest, we lost
        throw new IllegalArgumentException(
            "ServletRequest not wrapping SlingHttpServletRequest");
    }

    /**
     * Unwraps the SlingHttpServletRequest to a SlingHttpServletRequestImpl
     *
     * @param request the request
     * @return the unwrapped request
     * @throws IllegalArgumentException If request is not a
     *             SlingHttpServletRequestImpl and not
     *             SlingHttpServletRequestWrapper wrapping a
     *             SlingHttpServletRequestImpl.
     */
    public static SlingHttpServletRequestImpl unwrap(
            SlingHttpServletRequest request) {
        while (request instanceof SlingHttpServletRequestWrapper) {
            request = ((SlingHttpServletRequestWrapper) request).getSlingRequest();
        }

        if (request instanceof SlingHttpServletRequestImpl) {
            return (SlingHttpServletRequestImpl) request;
        }

        throw new IllegalArgumentException(
            "SlingHttpServletRequest not of correct type");
    }

    /**
     * Unwraps the ServletRequest to a SlingHttpServletRequest.
     *
     * @param response the response
     * @return the unwrapped response
     * @throws IllegalArgumentException If the response is not a
     *             SlingHttpServletResponse and not a
     *             ServletResponseWrapper wrapping a
     *             SlingHttpServletResponse.
     */
    public static SlingHttpServletResponse unwrap(ServletResponse response) {

        // early check for most cases
        if (response instanceof SlingHttpServletResponse) {
            return (SlingHttpServletResponse) response;
        }

        // unwrap wrappers
        while (response instanceof ServletResponseWrapper) {
            response = ((ServletResponseWrapper) response).getResponse();

            // immediate termination if we found one
            if (response instanceof SlingHttpServletResponse) {
                return (SlingHttpServletResponse) response;
            }
        }

        // if we unwrapped everything and did not find a
        // SlingHttpServletResponse, we lost
        throw new IllegalArgumentException(
            "ServletResponse not wrapping SlingHttpServletResponse");
    }

    /**
     * Unwraps a SlingHttpServletResponse to a SlingHttpServletResponseImpl
     *
     * @param response the response
     * @return the unwrapped response
     * @throws IllegalArgumentException If response is not a
     *             SlingHttpServletResponseImpl and not
     *             SlingHttpServletResponseWrapper wrapping a
     *             SlingHttpServletResponseImpl.
     */
    public static SlingHttpServletResponseImpl unwrap(
            SlingHttpServletResponse response) {
        while (response instanceof SlingHttpServletResponseWrapper) {
            response = ((SlingHttpServletResponseWrapper) response).getSlingResponse();
        }

        if (response instanceof SlingHttpServletResponseImpl) {
            return (SlingHttpServletResponseImpl) response;
        }

        throw new IllegalArgumentException(
            "SlingHttpServletResponse not of correct type");
    }

    /**
     * @param request the request
     * @return the request data
     * @throws IllegalArgumentException If the request is not a
     *             SlingHttpServletRequest and not a
     *             ServletRequestWrapper wrapping a
     *             SlingHttpServletRequest.
     */
    public static RequestData getRequestData(ServletRequest request) {
        return unwrap(unwrap(request)).getRequestData();
    }

    /**
     * @param request the request
     * @return the request data
     * @throws IllegalArgumentException If request is not a
     *             SlingHttpServletRequestImpl and not
     *             SlingHttpServletRequestWrapper wrapping a
     *             SlingHttpServletRequestImpl.
     */
    public static RequestData getRequestData(SlingHttpServletRequest request) {
        return unwrap(request).getRequestData();
    }

    /**
     * @param request the request
     * @return the sling http servlet request
     * @throws IllegalArgumentException if request is not a
     *             HttpServletRequest of if request
     *             is not backed by SlingHttpServletRequestImpl.
     */
    public static SlingHttpServletRequest toSlingHttpServletRequest(
            ServletRequest request) {

        // unwrap to SlingHttpServletRequest, may throw if no
        // SlingHttpServletRequest is wrapped in request
        SlingHttpServletRequest cRequest = unwrap(request);

        // ensure the SlingHttpServletRequest is backed by
        // SlingHttpServletRequestImpl
        RequestData.unwrap(cRequest);

        // if the request is not wrapper at all, we are done
        if (cRequest == request) {
            return cRequest;
        }

        // ensure the request is a HTTP request
        if (!(request instanceof HttpServletRequest)) {
            throw new IllegalArgumentException("Request is not an HTTP request");
        }

        // otherwise, we create a new response wrapping the servlet response
        // and unwrapped component response
        return new SlingServletRequestAdapter(cRequest,
            (HttpServletRequest) request);
    }

    /**
     * @param response the response
     * @return the sling http servlet response
     * @throws IllegalArgumentException if response is not a
     *             HttpServletResponse of if
     *             response is not backed by
     *             SlingHttpServletResponseImpl.
     */
    public static SlingHttpServletResponse toSlingHttpServletResponse(
            ServletResponse response) {

        // unwrap to SlingHttpServletResponse
        SlingHttpServletResponse cResponse = unwrap(response);

        // if the servlet response is actually the SlingHttpServletResponse, we
        // are done
        if (cResponse == response) {
            return cResponse;
        }

        // ensure the response is a HTTP response
        if (!(response instanceof HttpServletResponse)) {
            throw new IllegalArgumentException(
                "Response is not an HTTP response");
        }

        // otherwise, we create a new response wrapping the servlet response
        // and unwrapped component response
        return new SlingServletResponseAdapter(cResponse,
            (HttpServletResponse) response);
    }

    /**
     * Helper method to call the servlet for the current content data. If the
     * current content data has no servlet, NOT_FOUND (404) error is
     * sent and the method terminates.
     *

     * If the the servlet exists, the
     * {@link org.apache.sling.api.SlingConstants#SLING_CURRENT_SERVLET_NAME} request attribute is set
     * to the name of that servlet and that servlet name is also set as the
     * {@link #setActiveServletName(String) currently active servlet}. After
     * the termination of the servlet (normal or throwing a Throwable) the
     * request attribute is reset to the previous value. The name of the
     * currently active servlet is only reset to the previous value if the
     * servlet terminates normally. In case of a Throwable, the active servlet
     * name is not reset and indicates which servlet caused the potential abort
     * of the request.
     *
     * @param request The request object for the service method
     * @param response The response object for the service method
     * @throws IOException May be thrown by the servlet's service method
     * @throws ServletException May be thrown by the servlet's service method
     */
    public static void service(SlingHttpServletRequest request,
            SlingHttpServletResponse response) throws IOException,
            ServletException {

        if (!isValidRequest(request.getRequestPathInfo().getResourcePath(), request.getRequestPathInfo().getSelectors())) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
                    "Malformed request syntax");
            return;
        }

        RequestData requestData = RequestData.getRequestData(request);
        Servlet servlet = requestData.getContentData().getServlet();
        if (servlet == null) {

            response.sendError(HttpServletResponse.SC_NOT_FOUND,
                "No Servlet to handle request");

        } else {

            String name = RequestUtil.getServletName(servlet);

            // verify the number of service calls in this request
            if (requestData.hasServletMaxCallCount(request)) {
                throw new TooManyCallsException(name);
            }

            // replace the current servlet name in the request
            Object oldValue = request.getAttribute(SLING_CURRENT_SERVLET_NAME);
            request.setAttribute(SLING_CURRENT_SERVLET_NAME, name);

            // setup the tracker for this service call
            String timerName = name + "#" + requestData.servletCallCounter;
            requestData.servletCallCounter++;
            requestData.getRequestProgressTracker().startTimer(timerName);

            try {

                String callerServlet = requestData.setActiveServletName(name);

                servlet.service(request, response);

                requestData.setActiveServletName(callerServlet);

            } finally {

                request.setAttribute(SLING_CURRENT_SERVLET_NAME, oldValue);

                requestData.getRequestProgressTracker().logTimer(timerName);

            }
        }
    }

    /*
     * Don't allow path segments that contain only dots or a mix of dots and %5B.
     * Additionally, check that we didn't have an empty selector from a dot replacement.
     */
    static boolean isValidRequest(String resourcePath, String... selectors) {
       for (String selector : selectors) {
            if (selector.trim().isEmpty()) {
                return false;
            }
        }
        return resourcePath == null || !traversesParentPath(resourcePath);
    }

    // ---------- Content inclusion stacking -----------------------------------

    public ContentData setContent(final Resource resource,
            final RequestPathInfo requestPathInfo) {
        if ( this.recursionDepth >=  this.slingRequestProcessor.getMaxIncludeCounter()) {
            throw new RecursionTooDeepException(requestPathInfo.getResourcePath());
        }
        this.recursionDepth++;
        if (this.recursionDepth > this.peakRecusionDepth) {
            this.peakRecusionDepth = this.recursionDepth;
        }
        currentContentData = new ContentData(resource, requestPathInfo);
        return currentContentData;
    }

    public void resetContent(final ContentData data) {
        this.recursionDepth--;
        currentContentData = data;
    }

    public ContentData getContentData() {
        return currentContentData;
    }

    public ResourceResolver getResourceResolver() {
        return resourceResolver;
    }

    public RequestProgressTracker getRequestProgressTracker() {
        return requestProgressTracker;
    }

    public int getPeakRecusionDepth() {
        return peakRecusionDepth;
    }

    public int getServletCallCount() {
        return servletCallCounter;
    }

    /**
     * Returns {@code true} if the number of {@code RequestDispatcher.include}
     * calls has been reached within the given request. That maximum number may
     * either be defined by the {@link #REQUEST_MAX_CALL_OVERRIDE} request
     * attribute or the {@link SlingMainServlet#PROP_MAX_CALL_COUNTER}
     * configuration of the {@link SlingMainServlet}.
     *
     * @param request The request to check
     * @return {@code true} if the maximum number of calls has been reached (or
     *         surpassed)
     */
    private boolean hasServletMaxCallCount(final ServletRequest request) {
        // verify the number of service calls in this request
        log.debug("Servlet call counter : {}", getServletCallCount());

        // max number of calls can be overriden with a request attribute (-1 for
        // infinite or integer value)
        int maxCallCounter = this.slingRequestProcessor.getMaxCallCounter();
        Object reqMaxOverride = request.getAttribute(REQUEST_MAX_CALL_OVERRIDE);
        if (reqMaxOverride instanceof Number) {
            maxCallCounter = ((Number) reqMaxOverride).intValue();
        }

        return (maxCallCounter >= 0) && getServletCallCount() >= maxCallCounter;
    }

    public long getElapsedTimeMsec() {
        return System.currentTimeMillis() - startTimestamp;
    }

    /**
     * Sets the name of the currently active servlet and returns the name of the
     * previously active servlet.
     *
     * @param servletName the servlet name
     * @return the previous servlet name
     */
    public String setActiveServletName(String servletName) {
        String old = activeServletName;
        activeServletName = servletName;
        return old;
    }

    /**
     * Returns the name of the currently active servlet. If this name is not
     * null at the end of request processing, more precisly in
     * the case of an uncaught Throwable at the end of request
     * processing, this is the name of the servlet causing the uncaught
     * Throwable.
     *
     * @return the current servlet name
     */
    public String getActiveServletName() {
        return activeServletName;
    }

    // ---------- Parameter support -------------------------------------------

    public ServletInputStream getInputStream() throws IOException {
        if (parameterSupport != null && parameterSupport.requestDataUsed()) {
            throw new IllegalStateException(
                "Request Data has already been read");
        }

        // may throw IllegalStateException if the reader has already been
        // acquired
        return getServletRequest().getInputStream();
    }

    public BufferedReader getReader() throws UnsupportedEncodingException,
            IOException {
        if (parameterSupport != null && parameterSupport.requestDataUsed()) {
            throw new IllegalStateException(
                "Request Data has already been read");
        }

        // may throw IllegalStateException if the input stream has already been
        // acquired
        return getServletRequest().getReader();
    }

    public ParameterSupport getParameterSupport() {
        if (parameterSupport == null) {
            parameterSupport = ParameterSupport.getInstance(getServletRequest());
        }

        return parameterSupport;
    }

    /*
    * Traverses the path segment wise and checks
    * if there is any path with only dots (".")
    * skipping SKIPPED_TRAVERSAL_CHARS characters in segment.
    */
    private static boolean traversesParentPath(String path) {
        int index = 0;
        while (index < path.length()) {
            int charCount = 0;
            int dotCount = 0;
            // count dots (".") and total chars in each path segment (between two '/')
            while (index < path.length() && path.charAt(index) != '/') {
                char c = path.charAt(index);
                if (!SKIPPED_TRAVERSAL_CHARS.contains(c)) {
                    if (c == '.') {
                        dotCount++;
                    }
                    charCount++;
                }
                index++;
            }
            // if all chars are dots (".")
            // path is traversing the parent directory
            if (charCount > 1 && dotCount == charCount) {
                return true;
            }
            index++;
        }
        return false;
    }

}

## 内容6
### 文件路径：
src/main/java/org/apache/sling/engine/impl/request/SlingRequestDispatcher.java
### 代码内容：
/*
 * 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.sling.engine.impl.request;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestDispatcherOptions;
import org.apache.sling.api.request.RequestProgressTracker;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SlingRequestDispatcher implements RequestDispatcher {

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    private Resource resource;

    private RequestDispatcherOptions options;

    private String path;

    public SlingRequestDispatcher(String path, RequestDispatcherOptions options) {
        this.path = path;
        this.options = options;
        this.resource = null;
    }

    public SlingRequestDispatcher(Resource resource,
            RequestDispatcherOptions options) {

        this.resource = resource;
        this.options = options;
        this.path = resource.getPath();
    }

    @Override
    public void include(ServletRequest request, ServletResponse sResponse)
            throws ServletException, IOException {

        // guard access to the request and content data: If the request is
        // not (wrapping) a SlingHttpServletRequest, accessing the request Data
        // throws an IllegalArgumentException and we cannot continue
        final ContentData cd;
        try {
            cd = RequestData.getRequestData(request).getContentData();
        } catch (IllegalArgumentException iae) {
            throw new ServletException(iae.getMessage());
        }

        // ClassCastException is not expected here because we operate in
        // HTTP requests only (it cannot be excluded though if some client
        // code uses a ServletRequestWrapper rather than an
        // HttpServletRequestWrapper ...)
        final HttpServletRequest hRequest = (HttpServletRequest) request;

        // set the inclusion request attributes from the current request
        final Object v1 = setAttribute(request,
            SlingConstants.ATTR_REQUEST_CONTENT, cd.getResource());
        final Object v2 = setAttribute(request,
            SlingConstants.ATTR_REQUEST_SERVLET, cd.getServlet());
        final Object v3 = setAttribute(request,
            SlingConstants.ATTR_REQUEST_PATH_INFO, cd.getRequestPathInfo());
        final Object v4 = setAttribute(request,
            SlingConstants.ATTR_INCLUDE_CONTEXT_PATH, hRequest.getContextPath());
        final Object v5 = setAttribute(request,
            SlingConstants.ATTR_INCLUDE_PATH_INFO, hRequest.getPathInfo());
        final Object v6 = setAttribute(request,
            SlingConstants.ATTR_INCLUDE_QUERY_STRING, hRequest.getQueryString());
        final Object v7 = setAttribute(request,
            SlingConstants.ATTR_INCLUDE_REQUEST_URI, hRequest.getRequestURI());
        final Object v8 = setAttribute(request,
            SlingConstants.ATTR_INCLUDE_SERVLET_PATH, hRequest.getServletPath());

        try {

            dispatch(request, sResponse, true);

        } finally {

            // reset inclusion request attributes to previous values
            request.setAttribute(SlingConstants.ATTR_REQUEST_CONTENT, v1);
            request.setAttribute(SlingConstants.ATTR_REQUEST_SERVLET, v2);
            request.setAttribute(SlingConstants.ATTR_REQUEST_PATH_INFO, v3);
            request.setAttribute(SlingConstants.ATTR_INCLUDE_CONTEXT_PATH, v4);
            request.setAttribute(SlingConstants.ATTR_INCLUDE_PATH_INFO, v5);
            request.setAttribute(SlingConstants.ATTR_INCLUDE_QUERY_STRING, v6);
            request.setAttribute(SlingConstants.ATTR_INCLUDE_REQUEST_URI, v7);
            request.setAttribute(SlingConstants.ATTR_INCLUDE_SERVLET_PATH, v8);

        }
    }

    @Override
    public void forward(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {

        // fail forwarding if the response has already been committed
        if (response.isCommitted()) {
            throw new IllegalStateException("Response already committed");
        }

        // reset the response, will throw an IllegalStateException
        // if already committed, which will not be the case because
        // we already tested for this condition
        response.resetBuffer();

        // ensure inclusion information attributes are not set
        request.removeAttribute(SlingConstants.ATTR_REQUEST_CONTENT);
        request.removeAttribute(SlingConstants.ATTR_REQUEST_SERVLET);
        request.removeAttribute(SlingConstants.ATTR_REQUEST_PATH_INFO);
        request.removeAttribute(SlingConstants.ATTR_INCLUDE_CONTEXT_PATH);
        request.removeAttribute(SlingConstants.ATTR_INCLUDE_PATH_INFO);
        request.removeAttribute(SlingConstants.ATTR_INCLUDE_QUERY_STRING);
        request.removeAttribute(SlingConstants.ATTR_INCLUDE_REQUEST_URI);
        request.removeAttribute(SlingConstants.ATTR_INCLUDE_SERVLET_PATH);

        // now just include as normal
        dispatch(request, response, false);

        // finally, we would have to ensure the response is committed
        // and closed. Let's just flush the buffer and thus commit the
        // response for now
        response.flushBuffer();
    }

    private String getAbsolutePath(SlingHttpServletRequest request, String path) {
        // path is already absolute
        if (path.startsWith("/")) {
            return path;
        }

        // get parent of current request
        String uri = request.getResource().getPath();
        int lastSlash = uri.lastIndexOf('/');
        if (lastSlash >= 0) {
            uri = uri.substring(0, lastSlash);
        }

        // append relative path to parent
        return uri + '/' + path;
    }

    /**
     * Dispatch the request
     * @param request The request
     * @param response The response
     * @param include Is this an include (or forward)
     */
    private void dispatch(final ServletRequest request, final ServletResponse response,
            final boolean include) throws ServletException, IOException {
        SlingHttpServletRequest cRequest = RequestData.unwrap(request);
        RequestData rd = RequestData.getRequestData(cRequest);
        String absPath = getAbsolutePath(cRequest, path);
        RequestProgressTracker requestProgressTracker = cRequest.getRequestProgressTracker();

        // if the response is not an HttpServletResponse, fail gracefully not
        // doing anything
        if (!(response instanceof HttpServletResponse)) {
            log.error("include: Failed to include {}, response has wrong type",
                absPath);
            return;
        }

        if (resource == null) {
            String timerName = "resolveIncludedResource(" + absPath + ")";
            requestProgressTracker.startTimer(timerName);

            // resolve the absolute path in the resource resolver, using
            // only those parts of the path as if it would be request path
            resource = cRequest.getResourceResolver().resolve(absPath);

            // if the resource could not be resolved, fail gracefully
            if (resource == null) {
                log.error(
                    "include: Could not resolve {} to a resource, not including",
                    absPath);
                return;
            }

            requestProgressTracker.logTimer(timerName,
                    "path={0} resolves to Resource={1}",
                    absPath, resource);
        }

        // ensure request path info and optional merges
        SlingRequestPathInfo info = getMergedRequestPathInfo(cRequest);
        requestProgressTracker.log(
            "Including resource {0} ({1})", resource, info);
        final boolean protectHeaders = this.options != null ? this.options.isProtectHeadersOnInclude() : false;
        rd.getSlingRequestProcessor().dispatchRequest(request, response, resource,
            info, include, protectHeaders);
    }

    /**
     * Returns a {@link SlingRequestPathInfo} object to use to select the
     * servlet or script to call to render the resource to be dispatched to.
     *

     * Note: If this request dispatcher has been created with resource
     * type overwriting request dispatcher options, the resource to dispatch to
     * may be wrapped with a {@link TypeOverwritingResourceWrapper} as a result
     * of calling this method.
     */
    private SlingRequestPathInfo getMergedRequestPathInfo(
            final SlingHttpServletRequest cRequest) {
        SlingRequestPathInfo info = new SlingRequestPathInfo(resource);
        info = info.merge(cRequest.getRequestPathInfo());

        // merge request dispatcher options and resource type overwrite
        if (options != null) {
            info = info.merge(options);

            // ensure overwritten resource type
            String rtOverwrite = options.getForceResourceType();
            if (rtOverwrite != null
                && !rtOverwrite.equals(resource.getResourceType())) {
                resource = new TypeOverwritingResourceWrapper(resource,
                    rtOverwrite);
            }
        }

        return info;
    }

    private Object setAttribute(final ServletRequest request,
            final String name, final Object value) {
        final Object oldValue = request.getAttribute(name);
        request.setAttribute(name, value);
        return oldValue;
    }

    private static class TypeOverwritingResourceWrapper extends ResourceWrapper {

        private final String resourceType;

        TypeOverwritingResourceWrapper(Resource delegatee, String resourceType) {
            super(delegatee);
            this.resourceType = resourceType;
        }

        @Override
        public String getResourceType() {
            return resourceType;
        }

        /**
         * Overwrite this here because the wrapped resource will return null as
         * a super type instead of the resource type overwritten here
         */
        @Override
        public String getResourceSuperType() {
            return null;
        }

        @Override
        public boolean isResourceType(final String resourceType) {
            return this.getResourceResolver().isResourceType(this, resourceType);
        }

    }
}

Output:
【漏洞类型】路径遍历漏洞
【严重性】High
【漏洞摘要】代码中存在路径遍历漏洞，根源在于`SlingRequestDispatcher`类的`dispatch`方法中对`absPath`的处理不充分。具体表现为，如果`path`参数包含特定的字符（如“..”或“%5B”），仍然可能解析出上级目录的资源，从而导致路径遍历攻击。问题行在`SlingRequestDispatcher.java`文件的`getAbsolutePath`方法中：
```java
return uri + '/' + path;
```
【关键代码模式】与路径遍历漏洞相关的关键代码模式、函数或关键词包括：
- `getAbsolutePath`方法中对`path`参数的处理。
- `dispatch`方法中使用`absPath`来解析资源。
- `SlingRequestDispatcher`类的构造方法，接收`path`参数。
- `RequestDispatcher`接口的`include`和`forward`方法。
- `HttpServletRequest`类的`getContextPath`和`getServletPath`方法。

【修复方法说明】修复方法通过增加`protectHeadersOnInclude`和`checkContentTypeOnInclude`两个配置选项，以及创建新的响应包装器`IncludeNoContentTypeOverrideResponseWrapper`，在`dispatchRequest`方法中对`RequestDispatcher.include`操作进行保护，防止头部和内容类型的更改，从而解决路径遍历漏洞问题。