1   package com.atlassian.plugins.rest.module.jersey;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.sal.api.net.Request;
5   import com.atlassian.sal.api.net.Response;
6   import com.atlassian.sal.api.net.ResponseException;
7   import com.atlassian.sal.api.net.ResponseHandler;
8   import com.atlassian.sal.api.net.ReturningResponseHandler;
9   import com.atlassian.sal.api.net.auth.Authenticator;
10  
11  import java.io.IOException;
12  import java.nio.charset.Charset;
13  import java.util.List;
14  import java.util.Map;
15  import javax.ws.rs.core.HttpHeaders;
16  import javax.ws.rs.core.MediaType;
17  
18  import static org.apache.commons.lang.Validate.notNull;
19  
20  public class JerseyRequest implements Request<JerseyRequest, JerseyResponse>
21  {
22      private final Request delegateRequest;
23      private final JerseyEntityHandler jerseyEntityHandler;
24      private final Plugin plugin;
25  
26      private Object entity;
27  
28      public JerseyRequest(final Request delegateRequest, final JerseyEntityHandler jerseyEntityHandler, Plugin plugin)
29      {
30          this.delegateRequest = delegateRequest;
31          this.jerseyEntityHandler = jerseyEntityHandler;
32          this.plugin = plugin;
33      }
34  
35      public JerseyRequest setEntity(final Object entity)
36      {
37          notNull(entity);
38          this.entity = entity;
39          return this;
40      }
41  
42      public JerseyRequest setConnectionTimeout(final int i)
43      {
44          delegateRequest.setConnectionTimeout(i);
45          return this;
46      }
47  
48      public JerseyRequest setSoTimeout(final int i)
49      {
50          delegateRequest.setSoTimeout(i);
51          return this;
52      }
53  
54      public JerseyRequest setUrl(final String s)
55      {
56          delegateRequest.setUrl(s);
57          return this;
58      }
59  
60      public JerseyRequest setRequestBody(final String s)
61      {
62          delegateRequest.setRequestBody(s);
63          return this;
64      }
65  
66      public JerseyRequest setRequestContentType(final String s)
67      {
68          delegateRequest.setRequestContentType(s);
69          return this;
70      }
71  
72      public JerseyRequest addRequestParameters(final String... strings)
73      {
74          delegateRequest.addRequestParameters(strings);
75          return this;
76      }
77  
78      public JerseyRequest addAuthentication(final Authenticator authenticator)
79      {
80          delegateRequest.addAuthentication(authenticator);
81          return this;
82      }
83  
84      public JerseyRequest addTrustedTokenAuthentication()
85      {
86          delegateRequest.addTrustedTokenAuthentication();
87          return this;
88      }
89  
90      public JerseyRequest addTrustedTokenAuthentication(final String s)
91      {
92          delegateRequest.addTrustedTokenAuthentication(s);
93          return this;
94      }
95  
96      public JerseyRequest addBasicAuthentication(final String s, final String s1)
97      {
98          delegateRequest.addBasicAuthentication(s, s1);
99          return this;
100     }
101 
102     public JerseyRequest addSeraphAuthentication(final String s, final String s1)
103     {
104         delegateRequest.addSeraphAuthentication(s, s1);
105         return this;
106     }
107 
108     public JerseyRequest addHeader(final String s, final String s1)
109     {
110         delegateRequest.addHeader(s, s1);
111         return this;
112     }
113 
114     public JerseyRequest setHeader(final String s, final String s1)
115     {
116         delegateRequest.setHeader(s, s1);
117         return this;
118     }
119 	
120 	public JerseyRequest setFollowRedirects(final boolean follow)
121     {
122         delegateRequest.setFollowRedirects(follow);
123         return this;
124     }
125 
126     public Map<String, List<String>> getHeaders()
127     {
128         return delegateRequest.getHeaders();
129     }
130 
131     public void execute(final ResponseHandler<JerseyResponse> responseHandler)
132             throws ResponseException
133     {
134         executeAndReturn(new ReturningResponseHandler<JerseyResponse, Void>()
135         {
136             public Void handle(JerseyResponse jerseyResponse) throws ResponseException
137             {
138                 responseHandler.handle(jerseyResponse);
139                 return null;
140             }
141         });
142     }
143 
144     public String execute()
145             throws ResponseException
146     {
147         marshallEntity();
148         return delegateRequest.execute();
149     }
150 
151     public <RET> RET executeAndReturn(final ReturningResponseHandler<JerseyResponse, RET> responseHandler) throws ResponseException
152     {
153         marshallEntity();
154         final Object result = delegateRequest.executeAndReturn(new ReturningResponseHandler<Response, RET>()
155         {
156             public RET handle(final Response response) throws ResponseException
157             {
158                 JerseyResponse res = new JerseyResponse(response, jerseyEntityHandler, plugin);
159                 return responseHandler.handle(res);
160             }
161         });
162 
163         return (RET)result;
164     }
165 
166     private void marshallEntity() throws EntityConversionException
167     {
168         if (entity != null)
169         {
170             String contentType = getOrSetSingleHeaderValue(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
171             String encoding = getOrSetSingleHeaderValue(HttpHeaders.CONTENT_ENCODING, "UTF-8");
172             getOrSetSingleHeaderValue(HttpHeaders.ACCEPT, contentType);
173             Charset charset = Charset.forName(encoding);
174             MediaType type;
175             try
176             {
177                 type = MediaType.valueOf(contentType);
178             }
179             catch (IllegalArgumentException e)
180             {
181                 throw new UnsupportedContentTypeException(e.getMessage(), e);
182             }
183 
184             try
185             {
186                 String body = jerseyEntityHandler.marshall(entity, type, charset);
187                 setRequestBody(body);
188                 setRequestContentType(contentType);
189             }
190             catch (IOException e)
191             {
192                 throw new EntityConversionException(e);
193             }
194         }
195     }
196 
197     /**
198      * Retrieve the specified header value, or set it to the supplied defaultValue if the header is currently unset.
199      */
200     private String getOrSetSingleHeaderValue(final String headerName, final String defaultValue)
201     {
202         String value = defaultValue;
203         List<String> headers = getHeaders().get(headerName);
204         if (headers != null && !headers.isEmpty())
205         {
206             if (headers.size() == 1)
207             {
208                 value = headers.get(0);
209             }
210         }
211         else
212         {
213             setHeader(headerName, defaultValue);
214         }
215         return value;
216     }
217 
218 }