1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.atlassian.jira.rest.client.internal.jersey;
18
19 import com.atlassian.jira.rest.client.ProgressMonitor;
20 import com.atlassian.jira.rest.client.RestClientException;
21 import com.atlassian.jira.rest.client.internal.json.JsonArrayParser;
22 import com.atlassian.jira.rest.client.internal.json.JsonParseUtil;
23 import com.atlassian.jira.rest.client.internal.json.JsonParser;
24 import com.atlassian.jira.rest.client.internal.json.gen.JsonGenerator;
25 import com.sun.jersey.api.client.UniformInterfaceException;
26 import com.sun.jersey.api.client.WebResource;
27 import com.sun.jersey.client.apache.ApacheHttpClient;
28 import org.codehaus.jettison.json.JSONArray;
29 import org.codehaus.jettison.json.JSONException;
30 import org.codehaus.jettison.json.JSONObject;
31
32 import javax.annotation.Nullable;
33 import java.net.URI;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.concurrent.Callable;
37
38
39
40
41
42
43 public abstract class AbstractJerseyRestClient {
44 protected final ApacheHttpClient client;
45 protected final URI baseUri;
46
47 public AbstractJerseyRestClient(URI baseUri, ApacheHttpClient client) {
48 this.baseUri = baseUri;
49 this.client = client;
50 }
51
52 protected <T> T invoke(Callable<T> callable) throws RestClientException {
53 try {
54 return callable.call();
55 } catch (UniformInterfaceException e) {
56
57
58
59
60
61
62
63
64
65 try {
66 final String body = e.getResponse().getEntity(String.class);
67 final Collection<String> errorMessages = extractErrors(body);
68 throw new RestClientException(errorMessages, e);
69 } catch (JSONException e1) {
70 throw new RestClientException(e);
71 }
72 } catch (RestClientException e) {
73 throw e;
74 } catch (Exception e) {
75 throw new RestClientException(e);
76 }
77 }
78
79 protected <T> T getAndParse(final URI uri, final JsonParser<T> parser, ProgressMonitor progressMonitor) {
80 return invoke(new Callable<T>() {
81 @Override
82 public T call() throws Exception {
83 final WebResource webResource = client.resource(uri);
84 final JSONObject s = webResource.get(JSONObject.class);
85 return parser.parse(s);
86 }
87 });
88
89 }
90
91 protected <T> T getAndParse(final URI uri, final JsonArrayParser<T> parser, ProgressMonitor progressMonitor) {
92 return invoke(new Callable<T>() {
93 @Override
94 public T call() throws Exception {
95 final WebResource webResource = client.resource(uri);
96 final JSONArray jsonArray = webResource.get(JSONArray.class);
97 return parser.parse(jsonArray);
98 }
99 });
100 }
101
102 protected void delete(final URI uri, ProgressMonitor progressMonitor) {
103 invoke(new Callable<Void>() {
104 @Override
105 public Void call() throws Exception {
106 final WebResource webResource = client.resource(uri);
107 webResource.delete();
108 return null;
109 }
110 });
111 }
112
113 protected <T> T postAndParse(final URI uri, @Nullable final JSONObject postEntity, final JsonParser<T> parser, ProgressMonitor progressMonitor) {
114 return invoke(new Callable<T>() {
115 @Override
116 public T call() throws Exception {
117 final WebResource webResource = client.resource(uri);
118 final JSONObject s = postEntity != null ? webResource.post(JSONObject.class, postEntity) : webResource.post(JSONObject.class);
119 return parser.parse(s);
120 }
121 });
122 }
123
124 protected void post(final URI uri, @Nullable final JSONObject postEntity, ProgressMonitor progressMonitor) {
125 post(uri, new Callable<JSONObject>() {
126 @Override
127 public JSONObject call() throws Exception {
128 return postEntity;
129
130 }
131 }, progressMonitor);
132 }
133
134 protected void post(final URI uri, final Callable<JSONObject> callable, ProgressMonitor progressMonitor) {
135 invoke(new Callable<Void>() {
136 @Override
137 public Void call() throws Exception {
138 final WebResource webResource = client.resource(uri);
139 final JSONObject postEntity = callable.call();
140 if (postEntity != null) {
141 webResource.post(postEntity);
142 } else {
143 webResource.post();
144 }
145 return null;
146 }
147 });
148
149 }
150
151 protected <T> T postAndParse(final URI uri, final Callable<JSONObject> callable, final JsonParser<T> parser, ProgressMonitor progressMonitor) {
152 return impl(uri, Method.POST, callable, parser);
153 }
154
155 protected <T> T putAndParse(final URI uri, final Callable<JSONObject> callable, final JsonParser<T> parser, ProgressMonitor progressMonitor) {
156 return impl(uri, Method.PUT, callable, parser);
157 }
158
159 enum Method {
160 PUT, POST
161 }
162
163 private <T> T impl(final URI uri, final Method method, final Callable<JSONObject> callable, final JsonParser<T> parser) {
164 return invoke(new Callable<T>() {
165 @Override
166 public T call() throws Exception {
167 final WebResource webResource = client.resource(uri);
168 final JSONObject postEntity = callable.call();
169 final JSONObject s;
170 s = doHttpMethod(webResource, postEntity, method);
171 return parser.parse(s);
172 }
173 });
174 }
175
176 private JSONObject doHttpMethod(WebResource webResource, @Nullable JSONObject postEntity, Method method) {
177 if (postEntity != null) {
178 if (method == Method.POST) {
179 return webResource.post(JSONObject.class, postEntity);
180 } else {
181 return webResource.put(JSONObject.class, postEntity);
182 }
183 } else {
184 if (method == Method.POST) {
185 return webResource.post(JSONObject.class);
186 } else {
187 return webResource.put(JSONObject.class);
188 }
189 }
190 }
191
192
193 static Collection<String> extractErrors(String body) throws JSONException {
194 JSONObject jsonObject = new JSONObject(body);
195 final Collection<String> errorMessages = new ArrayList<String>();
196 final JSONArray errorMessagesJsonArray = jsonObject.optJSONArray("errorMessages");
197 if (errorMessagesJsonArray != null) {
198 errorMessages.addAll(JsonParseUtil.toStringCollection(errorMessagesJsonArray));
199 }
200 final JSONObject errorJsonObject = jsonObject.optJSONObject("errors");
201 if (errorJsonObject != null) {
202 final JSONArray valuesJsonArray = errorJsonObject.toJSONArray(errorJsonObject.names());
203 if (valuesJsonArray != null) {
204 errorMessages.addAll(JsonParseUtil.toStringCollection(valuesJsonArray));
205 }
206 }
207 return errorMessages;
208 }
209
210
211 protected static class InputGeneratorCallable<T> implements Callable<JSONObject> {
212
213 private final JsonGenerator<T> generator;
214 private final T bean;
215
216 public static <T> InputGeneratorCallable<T> create(JsonGenerator<T> generator, T bean) {
217 return new InputGeneratorCallable<T>(generator, bean);
218 }
219
220 public InputGeneratorCallable(JsonGenerator<T> generator, T bean) {
221 this.generator = generator;
222 this.bean = bean;
223 }
224
225 @Override
226 public JSONObject call() throws Exception {
227 return generator.generate(bean);
228 }
229 }
230
231
232 }