1   package com.atlassian.plugins.rest.module.json;
2   
3   import com.sun.jersey.spi.container.ContainerRequest;
4   import com.sun.jersey.spi.container.ContainerResponse;
5   import com.sun.jersey.spi.container.ContainerResponseFilter;
6   import org.apache.commons.lang.StringUtils;
7   import org.apache.commons.lang.Validate;
8   
9   import static javax.ws.rs.core.HttpHeaders.*;
10  import javax.ws.rs.core.MediaType;
11  import javax.ws.rs.core.MultivaluedMap;
12  import javax.ws.rs.ext.Provider;
13  
14  @Provider
15  public class JsonWithPaddingResponseFilter implements ContainerResponseFilter
16  {
17      private final String callbackFunctionParameterName;
18  
19      public JsonWithPaddingResponseFilter()
20      {
21          this("jsonp-callback");
22      }
23  
24      public JsonWithPaddingResponseFilter(String callbackFunctionParameterName)
25      {
26          Validate.notEmpty(callbackFunctionParameterName);
27          this.callbackFunctionParameterName = callbackFunctionParameterName;
28      }
29  
30      public ContainerResponse filter(ContainerRequest request, ContainerResponse response)
31      {
32          if (isJsonWithPadding(request, response))
33          {
34              response.setContainerResponseWriter(new JsonWithPaddingResponseAdapter(getCallbackFunction(request), response.getContainerResponseWriter()));
35          }
36          return response;
37      }
38  
39      private boolean isJsonWithPadding(ContainerRequest request, ContainerResponse response)
40      {
41          return isJsonResponse(response) && isCallbackRequest(request);
42      }
43  
44      private boolean isCallbackRequest(ContainerRequest request)
45      {
46          return StringUtils.isNotBlank(getCallbackFunction(request));
47      }
48  
49      private String getCallbackFunction(ContainerRequest request)
50      {
51          return request.getQueryParameters().getFirst(callbackFunctionParameterName);
52      }
53  
54      private boolean isJsonResponse(ContainerResponse response)
55      {
56          final MultivaluedMap<String, Object> httpHeaders = response.getHttpHeaders();
57          return httpHeaders.containsKey(CONTENT_TYPE) && httpHeaders.getFirst(CONTENT_TYPE).equals(MediaType.APPLICATION_JSON_TYPE);
58      }
59  }