content: package com.alibaba.fastjson.support.spring;
  
  import org.springframework.core.MethodParameter;
  import org.springframework.core.annotation.Order;
  import org.springframework.http.MediaType;
  import org.springframework.http.converter.HttpMessageConverter;
  import org.springframework.http.server.ServerHttpRequest;
  import org.springframework.http.server.ServerHttpResponse;
  import org.springframework.http.server.ServletServerHttpRequest;
  import org.springframework.util.Assert;
  import org.springframework.util.ObjectUtils;
  import org.springframework.web.bind.annotation.ControllerAdvice;
  import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
  
  import javax.servlet.http.HttpServletRequest;
  import java.util.regex.Pattern;
  
  /**
   * A convenient base class for {@code ResponseBodyAdvice} implementations
   * that customize the response before JSON serialization with {@link FastJsonpHttpMessageConverter4}'s concrete
   * subclasses.
   * <p>
   * Compatible Spring MVC version 4.2+
   *
   * @author Jerry.Chen
   * @see JSONPResponseBodyAdvice
   * @since 1.2.20
   */
  @Deprecated
  @Order(Integer.MIN_VALUE) //before FastJsonViewResponseBodyAdvice
  @ControllerAdvice
  public class FastJsonpResponseBodyAdvice implements ResponseBodyAdvice<Object> {
      /**
       * Pattern for validating jsonp callback parameter values.
       */
      private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
      private final String[] jsonpQueryParamNames;
      /**
       * Default JSONP query param names: callback/jsonp
       */
      public static final String[] DEFAULT_JSONP_QUERY_PARAM_NAMES = {"callback", "jsonp"};
  
      public FastJsonpResponseBodyAdvice() {
          this.jsonpQueryParamNames = DEFAULT_JSONP_QUERY_PARAM_NAMES;
      }
  
      public FastJsonpResponseBodyAdvice(String... queryParamNames) {
          Assert.isTrue(!ObjectUtils.isEmpty(queryParamNames), "At least one query param name is required");
          this.jsonpQueryParamNames = queryParamNames;
      }
  
      public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
          return FastJsonHttpMessageConverter.class.isAssignableFrom(converterType);
      }
  
      public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                    Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                    ServerHttpResponse response) {
          MappingFastJsonValue container = getOrCreateContainer(body);
          beforeBodyWriteInternal(container, selectedContentType, returnType, request, response);
          return container;
      }
  
      /**
       * Wrap the body in a {@link MappingFastJsonValue} value container (for providing
       * additional serialization instructions) or simply cast it if already wrapped.
       */
      protected MappingFastJsonValue getOrCreateContainer(Object body) {
          return (body instanceof MappingFastJsonValue ? (MappingFastJsonValue) body : new MappingFastJsonValue(body));
      }
  
      /**
       * Invoked only if the converter type is {@code FastJsonpHttpMessageConverter4}.
       */
      public void beforeBodyWriteInternal(MappingFastJsonValue bodyContainer, MediaType contentType,
                                          MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
          HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
          for (String name : this.jsonpQueryParamNames) {
              String value = servletRequest.getParameter(name);
              if (value != null) {
                  if (!isValidJsonpQueryParam(value)) {
                      continue;
                  }
                  // MediaType contentTypeToUse = getContentType(contentType, request, response);
                  // response.getHeaders().setContentType(contentTypeToUse);
                  bodyContainer.setJsonpFunction(value);
                  break;
              }
          }
      }
  
      /**
       * Validate the jsonp query parameter value. The default implementation
       * returns true if it consists of digits, letters, or "_" and ".".
       * Invalid parameter values are ignored.
       *
       * @param value the query param value, never {@code null}
       */
      protected boolean isValidJsonpQueryParam(String value) {
          return CALLBACK_PARAM_PATTERN.matcher(value).matches();
      }
  
      /**
       * Return the content type to set the response to.
       * This implementation always returns "application/javascript".
       *
       * @param contentType the content type selected through content negotiation
       * @param request     the current request
       * @param response    the current response
       * @return the content type to set the response to
       */
      protected MediaType getContentType(MediaType contentType, ServerHttpRequest request, ServerHttpResponse response) {
          return new MediaType("application", "javascript");
      }
  }
  