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
 * @since 1.2.20
 *
 * @see JSONPResponseBodyAdvice
 */
@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");
    }
}

@@ -1017,28 +1017,8 @@
 hen%0A
- * @since 1.2.20%0A *%0A
  * @
@@ -1045,16 +1045,33 @@
 yAdvice%0A
+ * @since 1.2.20%0A
  */%0A@Dep
@@ -1605,17 +1605,16 @@
 AMES = %7B
- 
 %22callbac
@@ -1624,17 +1624,16 @@
  %22jsonp%22
- 
 %7D;%0A%0A    
@@ -2284,32 +2284,54 @@
 tedContentType,%0A
+                      
             Clas
@@ -2417,16 +2417,38 @@
 equest,%0A
+                      
         
@@ -3254,32 +3254,60 @@
 pe contentType,%0A
+                            
             Meth
@@ -3380,32 +3380,32 @@
 nse response) %7B%0A
-
         HttpServ
@@ -3758,16 +3758,19 @@
         
+ //
  MediaTy
@@ -3854,16 +3854,19 @@
         
+ //
  respons
@@ -4672,16 +4672,20 @@
 request 
+    
 the curr
@@ -4719,16 +4719,19 @@
 esponse 
+   
 the curr

fix issue for #1533