// --------------------------------------------------------- Public methods
  @Override
  public void doFilter(
      final ServletRequest servletRequest,
      final ServletResponse servletResponse,
      final FilterChain filterChain)
      throws IOException, ServletException {
    if (!(servletRequest instanceof HttpServletRequest)
        || !(servletResponse instanceof HttpServletResponse)) {
      String message = "CORS doesn't support non-HTTP request or response.";
      throw new ServletException(message);
    }

    // Safe to downcast at this point.
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;

    // Determines the CORS request type.
    CORSFilter.CORSRequestType requestType = checkRequestType(request);

    // Adds CORS specific attributes to request.
    if (decorateRequest) {
      CORSFilter.decorateCORSProperties(request, requestType);
    }
    switch (requestType) {
      case SIMPLE:
        // Handles a Simple CORS request.
        this.handleSimpleCORS(request, response, filterChain);
        break;
      case ACTUAL:
        // Handles an Actual CORS request.
        this.handleSimpleCORS(request, response, filterChain);
        break;
      case PRE_FLIGHT:
        // Handles a Pre-flight CORS request.
        this.handlePreflightCORS(request, response, filterChain);
        break;
      case NOT_CORS:
        // Handles a Normal request that is not a cross-origin request.
        this.handleNonCORS(request, response, filterChain);
        break;
      default:
        // Handles a CORS request that violates specification.
        this.handleInvalidCORS(request, response, filterChain);
        break;
    }
  }