Showing
1 changed file
with
311 additions
and
299 deletions
@@ -11,6 +11,7 @@ import org.apache.http.client.ClientProtocolException; | @@ -11,6 +11,7 @@ import org.apache.http.client.ClientProtocolException; | ||
11 | import org.apache.http.client.HttpClient; | 11 | import org.apache.http.client.HttpClient; |
12 | import org.apache.http.client.HttpResponseException; | 12 | import org.apache.http.client.HttpResponseException; |
13 | import org.apache.http.client.entity.UrlEncodedFormEntity; | 13 | import org.apache.http.client.entity.UrlEncodedFormEntity; |
14 | +import org.apache.http.client.methods.HttpDelete; | ||
14 | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; | 15 | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; |
15 | import org.apache.http.client.methods.HttpGet; | 16 | import org.apache.http.client.methods.HttpGet; |
16 | import org.apache.http.client.methods.HttpPost; | 17 | import org.apache.http.client.methods.HttpPost; |
@@ -62,343 +63,354 @@ import java.util.regex.Pattern; | @@ -62,343 +63,354 @@ import java.util.regex.Pattern; | ||
62 | public class YoutrackAPI { | 63 | public class YoutrackAPI { |
63 | // ------------------------------ FIELDS ------------------------------ | 64 | // ------------------------------ FIELDS ------------------------------ |
64 | 65 | ||
65 | - private final static QName Enumeration_QNAME = new QName("", "enumeration"); | 66 | + private final static QName Enumeration_QNAME = new QName("", "enumeration"); |
66 | 67 | ||
67 | - private final static QName Issue_QNAME = new QName("", "issue"); | 68 | + private final static QName Issue_QNAME = new QName("", "issue"); |
68 | 69 | ||
69 | - private HttpClient httpClient; | 70 | + private HttpClient httpClient; |
70 | 71 | ||
71 | - private String serviceLocation; | 72 | + private String serviceLocation; |
72 | 73 | ||
73 | // -------------------------- STATIC METHODS -------------------------- | 74 | // -------------------------- STATIC METHODS -------------------------- |
74 | 75 | ||
75 | - private static HttpClient getDefaultHttpClient() | ||
76 | - { | ||
77 | - SSLContext sslContext; | ||
78 | - try { | ||
79 | - sslContext = SSLContext.getInstance("SSL"); | ||
80 | - } catch (NoSuchAlgorithmException e) { | ||
81 | - throw new RuntimeException(e); | ||
82 | - } | ||
83 | - // set up a TrustManager that trusts everything | ||
84 | - try { | ||
85 | - sslContext.init(null, new TrustManager[]{new X509TrustManager() { | ||
86 | - public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException | ||
87 | - { | ||
88 | - } | ||
89 | - | ||
90 | - public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException | ||
91 | - { | ||
92 | - } | ||
93 | - | ||
94 | - public X509Certificate[] getAcceptedIssuers() | ||
95 | - { | ||
96 | - return new X509Certificate[0]; | ||
97 | - } | ||
98 | - }}, new SecureRandom()); | ||
99 | - } catch (KeyManagementException e) { | ||
100 | - throw new RuntimeException(e); | 76 | + private static HttpClient getDefaultHttpClient() |
77 | + { | ||
78 | + SSLContext sslContext; | ||
79 | + try { | ||
80 | + sslContext = SSLContext.getInstance("SSL"); | ||
81 | + } catch (NoSuchAlgorithmException e) { | ||
82 | + throw new RuntimeException(e); | ||
83 | + } | ||
84 | + // set up a TrustManager that trusts everything | ||
85 | + try { | ||
86 | + sslContext.init(null, new TrustManager[]{new X509TrustManager() { | ||
87 | + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException | ||
88 | + { | ||
101 | } | 89 | } |
102 | 90 | ||
103 | - SSLSocketFactory sf = new SSLSocketFactory(sslContext); | ||
104 | - Scheme httpsScheme = new Scheme("https", 443, sf); | ||
105 | - SchemeRegistry schemeRegistry = SchemeRegistryFactory.createDefault(); | ||
106 | - schemeRegistry.register(schemeRegistry.unregister("https")); | ||
107 | - schemeRegistry.register(httpsScheme); | 91 | + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException |
92 | + { | ||
93 | + } | ||
108 | 94 | ||
109 | - ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); | ||
110 | - return new DefaultHttpClient(cm); | 95 | + public X509Certificate[] getAcceptedIssuers() |
96 | + { | ||
97 | + return new X509Certificate[0]; | ||
98 | + } | ||
99 | + }}, new SecureRandom()); | ||
100 | + } catch (KeyManagementException e) { | ||
101 | + throw new RuntimeException(e); | ||
111 | } | 102 | } |
112 | 103 | ||
113 | - private static boolean isBlank(String str) | ||
114 | - { | ||
115 | - int strLen; | ||
116 | - if (str == null || (strLen = str.length()) == 0) { | ||
117 | - return true; | ||
118 | - } | ||
119 | - for (int i = 0; i < strLen; i++) { | ||
120 | - if ((!Character.isWhitespace(str.charAt(i)))) { | ||
121 | - return false; | ||
122 | - } | ||
123 | - } | ||
124 | - return true; | 104 | + SSLSocketFactory sf = new SSLSocketFactory(sslContext); |
105 | + Scheme httpsScheme = new Scheme("https", 443, sf); | ||
106 | + SchemeRegistry schemeRegistry = SchemeRegistryFactory.createDefault(); | ||
107 | + schemeRegistry.register(schemeRegistry.unregister("https")); | ||
108 | + schemeRegistry.register(httpsScheme); | ||
109 | + | ||
110 | + ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); | ||
111 | + return new DefaultHttpClient(cm); | ||
112 | + } | ||
113 | + | ||
114 | + private static boolean isBlank(String str) | ||
115 | + { | ||
116 | + int strLen; | ||
117 | + if (str == null || (strLen = str.length()) == 0) { | ||
118 | + return true; | ||
119 | + } | ||
120 | + for (int i = 0; i < strLen; i++) { | ||
121 | + if ((!Character.isWhitespace(str.charAt(i)))) { | ||
122 | + return false; | ||
123 | + } | ||
125 | } | 124 | } |
125 | + return true; | ||
126 | + } | ||
126 | 127 | ||
127 | // --------------------------- CONSTRUCTORS --------------------------- | 128 | // --------------------------- CONSTRUCTORS --------------------------- |
128 | 129 | ||
129 | - public YoutrackAPI(String serviceLocation) | ||
130 | - { | ||
131 | - this(serviceLocation, null); | ||
132 | - } | 130 | + public YoutrackAPI(String serviceLocation) |
131 | + { | ||
132 | + this(serviceLocation, null); | ||
133 | + } | ||
133 | 134 | ||
134 | - public YoutrackAPI(String serviceLocation, HttpClient httpClient) | ||
135 | - { | ||
136 | - this.serviceLocation = serviceLocation; | ||
137 | - this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; | ||
138 | - } | 135 | + public YoutrackAPI(String serviceLocation, HttpClient httpClient) |
136 | + { | ||
137 | + this.serviceLocation = serviceLocation; | ||
138 | + this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; | ||
139 | + } | ||
139 | 140 | ||
140 | - public YoutrackAPI(String serviceLocation, String username, String password) throws IOException, JAXBException | ||
141 | - { | ||
142 | - this(serviceLocation, null, username, password); | ||
143 | - } | 141 | + public YoutrackAPI(String serviceLocation, String username, String password) throws IOException, JAXBException |
142 | + { | ||
143 | + this(serviceLocation, null, username, password); | ||
144 | + } | ||
144 | 145 | ||
145 | - public YoutrackAPI(String serviceLocation, HttpClient httpClient, String username, String password) throws IOException, JAXBException | ||
146 | - { | ||
147 | - this(serviceLocation, httpClient); | ||
148 | - login(username, password); | ||
149 | - } | 146 | + public YoutrackAPI(String serviceLocation, HttpClient httpClient, String username, String password) throws IOException, JAXBException |
147 | + { | ||
148 | + this(serviceLocation, httpClient); | ||
149 | + login(username, password); | ||
150 | + } | ||
150 | 151 | ||
151 | // --------------------- GETTER / SETTER METHODS --------------------- | 152 | // --------------------- GETTER / SETTER METHODS --------------------- |
152 | 153 | ||
153 | - public String getServiceLocation() | ||
154 | - { | ||
155 | - return serviceLocation; | ||
156 | - } | 154 | + public String getServiceLocation() |
155 | + { | ||
156 | + return serviceLocation; | ||
157 | + } | ||
157 | 158 | ||
158 | // -------------------------- OTHER METHODS -------------------------- | 159 | // -------------------------- OTHER METHODS -------------------------- |
159 | 160 | ||
160 | - public void command(String issueId, String command) throws IOException | ||
161 | - { | ||
162 | - command(issueId, command, null, null, null, null); | 161 | + public void command(String issueId, String command) throws IOException |
162 | + { | ||
163 | + command(issueId, command, null, null, null, null); | ||
164 | + } | ||
165 | + | ||
166 | + public void command(String issueId, Command command) throws IOException | ||
167 | + { | ||
168 | + command(issueId, command.toString()); | ||
169 | + } | ||
170 | + | ||
171 | + public void command(String issueId, String command, String comment, String group, Boolean disableNotifications, String runAs) throws IOException | ||
172 | + { | ||
173 | + final HttpPost request = new HttpPost(serviceLocation + "/rest/issue/" + issueId + "/execute"); | ||
174 | + final List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>(); | ||
175 | + parameters.add(new BasicNameValuePair("command", command)); | ||
176 | + if (!isBlank(comment)) { | ||
177 | + parameters.add(new BasicNameValuePair("comment", comment)); | ||
163 | } | 178 | } |
164 | - | ||
165 | - public void command(String issueId, Command command) throws IOException | ||
166 | - { | ||
167 | - command(issueId, command.toString()); | 179 | + if (!isBlank(group)) { |
180 | + parameters.add(new BasicNameValuePair("group", group)); | ||
168 | } | 181 | } |
169 | - | ||
170 | - public void command(String issueId, String command, String comment, String group, Boolean disableNotifications, String runAs) throws IOException | ||
171 | - { | ||
172 | - final HttpPost request = new HttpPost(serviceLocation + "/rest/issue/" + issueId + "/execute"); | ||
173 | - final List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>(); | ||
174 | - parameters.add(new BasicNameValuePair("command", command)); | ||
175 | - if (!isBlank(comment)) { | ||
176 | - parameters.add(new BasicNameValuePair("comment", comment)); | ||
177 | - } | ||
178 | - if (!isBlank(group)) { | ||
179 | - parameters.add(new BasicNameValuePair("group", group)); | ||
180 | - } | ||
181 | - if (disableNotifications != null) { | ||
182 | - parameters.add(new BasicNameValuePair("disableNotifications", disableNotifications.toString())); | ||
183 | - } | ||
184 | - if (!isBlank(runAs)) { | ||
185 | - parameters.add(new BasicNameValuePair("runAs", runAs)); | ||
186 | - } | ||
187 | - request.setEntity(new UrlEncodedFormEntity(parameters)); | ||
188 | - execute(request); | 182 | + if (disableNotifications != null) { |
183 | + parameters.add(new BasicNameValuePair("disableNotifications", disableNotifications.toString())); | ||
189 | } | 184 | } |
190 | - | ||
191 | - /** | ||
192 | - * Creates new issue on Youtrack. | ||
193 | - * | ||
194 | - * @param project project to create issue in | ||
195 | - * @param summary summary of the issue | ||
196 | - * @param description longer description of the issue | ||
197 | - * | ||
198 | - * @return issue id of created issue | ||
199 | - * | ||
200 | - * @throws IOException in case of communication problems | ||
201 | - */ | ||
202 | - public String createIssue(String project, String summary, String description) throws IOException | ||
203 | - { | ||
204 | - final URI uri; | ||
205 | - try { | ||
206 | - uri = new URIBuilder(serviceLocation + "/rest/issue").build(); | ||
207 | - } catch (URISyntaxException e) { | ||
208 | - throw new RuntimeException(e); | ||
209 | - } | ||
210 | - final HttpPut request = createPutRequest(uri, new BasicNameValuePair("project", project), new BasicNameValuePair("summary", summary), | ||
211 | - new BasicNameValuePair("description", description)); | ||
212 | - final HttpResponse response = httpClient.execute(request); | ||
213 | - final StatusLine statusLine = response.getStatusLine(); | ||
214 | - final HttpEntity entity = response.getEntity(); | ||
215 | - final String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
216 | - throwExceptionsIfNeeded(statusLine, responseText); | ||
217 | - | ||
218 | - final Header header = response.getFirstHeader(HttpHeaders.LOCATION); | ||
219 | - if (header == null) { | ||
220 | - throw new YoutrackAPIException("Missing location header despite positive status code: " + statusLine.getStatusCode()); | ||
221 | - } | ||
222 | - final String issueURL = header.getValue(); | ||
223 | - final Matcher matcher = Pattern.compile(".*(" + project + "-\\d+)").matcher(issueURL); | ||
224 | - if (!matcher.find() || matcher.groupCount() < 1) { | ||
225 | - throw new YoutrackAPIException("Cannot extract issue id from issue URL: " + issueURL); | ||
226 | - } | ||
227 | - return matcher.group(1); | 185 | + if (!isBlank(runAs)) { |
186 | + parameters.add(new BasicNameValuePair("runAs", runAs)); | ||
228 | } | 187 | } |
229 | - | ||
230 | - public AssigneeList getAssignees(String project) throws IOException, JAXBException | ||
231 | - { | ||
232 | - final URI uri; | ||
233 | - try { | ||
234 | - uri = new URIBuilder(serviceLocation + "/rest/admin/project/" + project + "/assignee").build(); | ||
235 | - } catch (URISyntaxException e) { | ||
236 | - throw new RuntimeException(e); | ||
237 | - } | ||
238 | - final String responseString = execute(new HttpGet(uri)); | ||
239 | - final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
240 | - if (result instanceof AssigneeList) { | ||
241 | - return (AssigneeList) result; | ||
242 | - } else { | ||
243 | - throw new YoutrackAPIException("Unexpected type: " + result); | ||
244 | - } | 188 | + request.setEntity(new UrlEncodedFormEntity(parameters)); |
189 | + execute(request); | ||
190 | + } | ||
191 | + | ||
192 | + /** | ||
193 | + * Creates new issue on Youtrack. | ||
194 | + * | ||
195 | + * @param project project to create issue in | ||
196 | + * @param summary summary of the issue | ||
197 | + * @param description longer description of the issue | ||
198 | + * | ||
199 | + * @return issue id of created issue | ||
200 | + * | ||
201 | + * @throws IOException in case of communication problems | ||
202 | + */ | ||
203 | + public String createIssue(String project, String summary, String description) throws IOException | ||
204 | + { | ||
205 | + final URI uri; | ||
206 | + try { | ||
207 | + uri = new URIBuilder(serviceLocation + "/rest/issue").build(); | ||
208 | + } catch (URISyntaxException e) { | ||
209 | + throw new RuntimeException(e); | ||
245 | } | 210 | } |
246 | - | ||
247 | - public Enumeration getBundle(String customField) throws IOException, JAXBException | ||
248 | - { | ||
249 | - final URI uri; | ||
250 | - try { | ||
251 | - uri = new URIBuilder(serviceLocation + "/rest/admin/customfield/bundle/" + customField).build(); | ||
252 | - } catch (URISyntaxException e) { | ||
253 | - throw new RuntimeException(e); | ||
254 | - } | ||
255 | - final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(uri))); | ||
256 | - if (result instanceof Enumeration) { | ||
257 | - return (Enumeration) result; | ||
258 | - } else if (result instanceof JAXBElement) { | ||
259 | - final JAXBElement jaxbElement = (JAXBElement) result; | ||
260 | - if (Enumeration_QNAME.equals(jaxbElement.getName())) { | ||
261 | - return (Enumeration) ((JAXBElement) result).getValue(); | ||
262 | - } else { | ||
263 | - throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); | ||
264 | - } | ||
265 | - } else { | ||
266 | - throw new YoutrackAPIException("Unexpected type: " + result); | ||
267 | - } | 211 | + final HttpPut request = createPutRequest(uri, new BasicNameValuePair("project", project), new BasicNameValuePair("summary", summary), |
212 | + new BasicNameValuePair("description", description)); | ||
213 | + final HttpResponse response = httpClient.execute(request); | ||
214 | + final StatusLine statusLine = response.getStatusLine(); | ||
215 | + final HttpEntity entity = response.getEntity(); | ||
216 | + final String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
217 | + throwExceptionsIfNeeded(statusLine, responseText); | ||
218 | + | ||
219 | + final Header header = response.getFirstHeader(HttpHeaders.LOCATION); | ||
220 | + if (header == null) { | ||
221 | + throw new YoutrackAPIException("Missing location header despite positive status code: " + statusLine.getStatusCode()); | ||
268 | } | 222 | } |
269 | - | ||
270 | - public List<User> getIndividualAssignees(String project) throws IOException, JAXBException | ||
271 | - { | ||
272 | - final URI uri; | ||
273 | - try { | ||
274 | - uri = new URIBuilder(serviceLocation + "/rest/admin/project/" + project + "/assignee/individual").build(); | ||
275 | - } catch (URISyntaxException e) { | ||
276 | - throw new RuntimeException(e); | ||
277 | - } | ||
278 | - final String responseString = execute(new HttpGet(uri)); | ||
279 | - final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
280 | - if (result instanceof UserRefs) { | ||
281 | - return ((UserRefs) result).getUsers(); | ||
282 | - } else { | ||
283 | - throw new YoutrackAPIException("Unexpected type: " + result); | ||
284 | - } | 223 | + final String issueURL = header.getValue(); |
224 | + final Matcher matcher = Pattern.compile(".*(" + project + "-\\d+)").matcher(issueURL); | ||
225 | + if (!matcher.find() || matcher.groupCount() < 1) { | ||
226 | + throw new YoutrackAPIException("Cannot extract issue id from issue URL: " + issueURL); | ||
285 | } | 227 | } |
286 | - | ||
287 | - public IssueWrapper getIssue(String issueId) throws IOException, JAXBException | ||
288 | - { | ||
289 | - final URI uri; | ||
290 | - try { | ||
291 | - uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
292 | - } catch (URISyntaxException e) { | ||
293 | - throw new RuntimeException(e); | ||
294 | - } | ||
295 | - final String responseString; | ||
296 | - try { | ||
297 | - responseString = execute(new HttpGet(uri)); | ||
298 | - } catch (YoutrackErrorException e) { | ||
299 | - if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { | ||
300 | - throw new NoResultFoundException(e.getMessage(), e); | ||
301 | - } else { | ||
302 | - throw e; | ||
303 | - } | ||
304 | - } | ||
305 | - final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
306 | - if (result instanceof pl.com.it_crowd.youtrack.api.rest.Issue) { | ||
307 | - return new IssueWrapper((Issue) result); | ||
308 | - } else if (result instanceof JAXBElement) { | ||
309 | - final JAXBElement jaxbElement = (JAXBElement) result; | ||
310 | - if (Issue_QNAME.equals(jaxbElement.getName())) { | ||
311 | - return new IssueWrapper((Issue) jaxbElement.getValue()); | ||
312 | - } else { | ||
313 | - throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); | ||
314 | - } | ||
315 | - } else { | ||
316 | - throw new YoutrackAPIException("Unexpected type " + result); | ||
317 | - } | 228 | + return matcher.group(1); |
229 | + } | ||
230 | + | ||
231 | + public void deleteIssue(String issueId) throws IOException | ||
232 | + { | ||
233 | + final URI uri; | ||
234 | + try { | ||
235 | + uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
236 | + } catch (URISyntaxException e) { | ||
237 | + throw new RuntimeException(e); | ||
318 | } | 238 | } |
319 | - | ||
320 | - public void login(String username, String password) throws IOException, JAXBException | ||
321 | - { | ||
322 | - final HttpPost request = new HttpPost(serviceLocation + "/rest/user/login"); | ||
323 | - request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); | ||
324 | - execute(request); | 239 | + execute(new HttpDelete(uri)); |
240 | + } | ||
241 | + | ||
242 | + public AssigneeList getAssignees(String project) throws IOException, JAXBException | ||
243 | + { | ||
244 | + final URI uri; | ||
245 | + try { | ||
246 | + uri = new URIBuilder(serviceLocation + "/rest/admin/project/" + project + "/assignee").build(); | ||
247 | + } catch (URISyntaxException e) { | ||
248 | + throw new RuntimeException(e); | ||
325 | } | 249 | } |
326 | - | ||
327 | - public List<IssueWrapper> searchIssuesByProject(String project, Object filter) throws JAXBException, IOException | ||
328 | - { | ||
329 | - final String url = serviceLocation + "/rest/issue/byproject/" + project + "?filter=" + (filter == null ? "" : filter); | ||
330 | - final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(url))); | ||
331 | - if (!(result instanceof Issues)) { | ||
332 | - throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result); | ||
333 | - } | ||
334 | - List<Issue> issues = ((Issues) result).getIssues(); | ||
335 | - List<IssueWrapper> wrappedIssues = new ArrayList<IssueWrapper>(); | ||
336 | - for (Issue issue : issues) { | ||
337 | - wrappedIssues.add(new IssueWrapper(issue)); | ||
338 | - } | ||
339 | - return wrappedIssues; | 250 | + final String responseString = execute(new HttpGet(uri)); |
251 | + final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
252 | + if (result instanceof AssigneeList) { | ||
253 | + return (AssigneeList) result; | ||
254 | + } else { | ||
255 | + throw new YoutrackAPIException("Unexpected type: " + result); | ||
340 | } | 256 | } |
341 | - | ||
342 | - public void updateIssue(String issueId, String summary, String description) throws IOException | ||
343 | - { | ||
344 | - final URI uri; | ||
345 | - try { | ||
346 | - uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
347 | - } catch (URISyntaxException e) { | ||
348 | - throw new RuntimeException(e); | ||
349 | - } | ||
350 | - final HttpPost request = createPostRequest(uri, new BasicNameValuePair(Fields.summary.name(), summary), | ||
351 | - new BasicNameValuePair(Fields.description.name(), description)); | ||
352 | - final HttpResponse response = httpClient.execute(request); | ||
353 | - final StatusLine statusLine = response.getStatusLine(); | ||
354 | - final HttpEntity entity = response.getEntity(); | ||
355 | - final String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
356 | - throwExceptionsIfNeeded(statusLine, responseText); | 257 | + } |
258 | + | ||
259 | + public Enumeration getBundle(String customField) throws IOException, JAXBException | ||
260 | + { | ||
261 | + final URI uri; | ||
262 | + try { | ||
263 | + uri = new URIBuilder(serviceLocation + "/rest/admin/customfield/bundle/" + customField).build(); | ||
264 | + } catch (URISyntaxException e) { | ||
265 | + throw new RuntimeException(e); | ||
357 | } | 266 | } |
358 | - | ||
359 | - private HttpPost createPostRequest(URI uri, NameValuePair... nameValuePair) throws UnsupportedEncodingException | ||
360 | - { | ||
361 | - return setEntity(new HttpPost(uri), nameValuePair); | 267 | + final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(uri))); |
268 | + if (result instanceof Enumeration) { | ||
269 | + return (Enumeration) result; | ||
270 | + } else if (result instanceof JAXBElement) { | ||
271 | + final JAXBElement jaxbElement = (JAXBElement) result; | ||
272 | + if (Enumeration_QNAME.equals(jaxbElement.getName())) { | ||
273 | + return (Enumeration) ((JAXBElement) result).getValue(); | ||
274 | + } else { | ||
275 | + throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); | ||
276 | + } | ||
277 | + } else { | ||
278 | + throw new YoutrackAPIException("Unexpected type: " + result); | ||
362 | } | 279 | } |
363 | - | ||
364 | - private HttpPut createPutRequest(URI uri, NameValuePair... nameValuePair) throws UnsupportedEncodingException | ||
365 | - { | ||
366 | - return setEntity(new HttpPut(uri), nameValuePair); | 280 | + } |
281 | + | ||
282 | + public List<User> getIndividualAssignees(String project) throws IOException, JAXBException | ||
283 | + { | ||
284 | + final URI uri; | ||
285 | + try { | ||
286 | + uri = new URIBuilder(serviceLocation + "/rest/admin/project/" + project + "/assignee/individual").build(); | ||
287 | + } catch (URISyntaxException e) { | ||
288 | + throw new RuntimeException(e); | ||
367 | } | 289 | } |
368 | - | ||
369 | - private String execute(HttpUriRequest request) throws IOException | ||
370 | - { | ||
371 | - final HttpResponse response = httpClient.execute(request); | ||
372 | - final StatusLine statusLine = response.getStatusLine(); | ||
373 | - final HttpEntity entity = response.getEntity(); | ||
374 | - String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
375 | - if (statusLine.getStatusCode() >= 300) { | ||
376 | - try { | ||
377 | - final String error = ErrorUnmarshaller.unmarshal(responseText); | ||
378 | - throw new YoutrackErrorException(error, statusLine.getStatusCode()); | ||
379 | - } catch (JAXBException e) { | ||
380 | - // TODO we should log on debug level the JAXBException | ||
381 | - throw new HttpResponseException(statusLine.getStatusCode(), responseText); | ||
382 | - } | ||
383 | - } | ||
384 | - if (entity == null) { | ||
385 | - throw new ClientProtocolException("Response contains no content"); | ||
386 | - } | ||
387 | - return responseText; | 290 | + final String responseString = execute(new HttpGet(uri)); |
291 | + final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
292 | + if (result instanceof UserRefs) { | ||
293 | + return ((UserRefs) result).getUsers(); | ||
294 | + } else { | ||
295 | + throw new YoutrackAPIException("Unexpected type: " + result); | ||
388 | } | 296 | } |
389 | - | ||
390 | - private <T extends HttpEntityEnclosingRequestBase> T setEntity(T request, NameValuePair[] nameValuePair) throws UnsupportedEncodingException | ||
391 | - { | ||
392 | - final ArrayList<NameValuePair> list = new ArrayList<NameValuePair>(); | ||
393 | - Collections.addAll(list, nameValuePair); | ||
394 | - request.setEntity(new UrlEncodedFormEntity(list)); | ||
395 | - return request; | 297 | + } |
298 | + | ||
299 | + public IssueWrapper getIssue(String issueId) throws IOException, JAXBException | ||
300 | + { | ||
301 | + final URI uri; | ||
302 | + try { | ||
303 | + uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
304 | + } catch (URISyntaxException e) { | ||
305 | + throw new RuntimeException(e); | ||
396 | } | 306 | } |
397 | - | ||
398 | - private void throwExceptionsIfNeeded(StatusLine statusLine, String responseText) throws IOException | ||
399 | - { | ||
400 | - if (statusLine.getStatusCode() >= 300) { | ||
401 | - throw new HttpResponseException(statusLine.getStatusCode(), responseText); | ||
402 | - } | 307 | + final String responseString; |
308 | + try { | ||
309 | + responseString = execute(new HttpGet(uri)); | ||
310 | + } catch (YoutrackErrorException e) { | ||
311 | + if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { | ||
312 | + throw new NoResultFoundException(e.getMessage(), e); | ||
313 | + } else { | ||
314 | + throw e; | ||
315 | + } | ||
316 | + } | ||
317 | + final Object result = YoutrackUnmarshaller.unmarshall(responseString); | ||
318 | + if (result instanceof pl.com.it_crowd.youtrack.api.rest.Issue) { | ||
319 | + return new IssueWrapper((Issue) result); | ||
320 | + } else if (result instanceof JAXBElement) { | ||
321 | + final JAXBElement jaxbElement = (JAXBElement) result; | ||
322 | + if (Issue_QNAME.equals(jaxbElement.getName())) { | ||
323 | + return new IssueWrapper((Issue) jaxbElement.getValue()); | ||
324 | + } else { | ||
325 | + throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); | ||
326 | + } | ||
327 | + } else { | ||
328 | + throw new YoutrackAPIException("Unexpected type " + result); | ||
329 | + } | ||
330 | + } | ||
331 | + | ||
332 | + public void login(String username, String password) throws IOException, JAXBException | ||
333 | + { | ||
334 | + final HttpPost request = new HttpPost(serviceLocation + "/rest/user/login"); | ||
335 | + request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); | ||
336 | + execute(request); | ||
337 | + } | ||
338 | + | ||
339 | + public List<IssueWrapper> searchIssuesByProject(String project, Object filter) throws JAXBException, IOException | ||
340 | + { | ||
341 | + final String url = serviceLocation + "/rest/issue/byproject/" + project + "?filter=" + (filter == null ? "" : filter); | ||
342 | + final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(url))); | ||
343 | + if (!(result instanceof Issues)) { | ||
344 | + throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result); | ||
345 | + } | ||
346 | + List<Issue> issues = ((Issues) result).getIssues(); | ||
347 | + List<IssueWrapper> wrappedIssues = new ArrayList<IssueWrapper>(); | ||
348 | + for (Issue issue : issues) { | ||
349 | + wrappedIssues.add(new IssueWrapper(issue)); | ||
350 | + } | ||
351 | + return wrappedIssues; | ||
352 | + } | ||
353 | + | ||
354 | + public void updateIssue(String issueId, String summary, String description) throws IOException | ||
355 | + { | ||
356 | + final URI uri; | ||
357 | + try { | ||
358 | + uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
359 | + } catch (URISyntaxException e) { | ||
360 | + throw new RuntimeException(e); | ||
361 | + } | ||
362 | + final HttpPost request = createPostRequest(uri, new BasicNameValuePair(Fields.summary.name(), summary), | ||
363 | + new BasicNameValuePair(Fields.description.name(), description)); | ||
364 | + final HttpResponse response = httpClient.execute(request); | ||
365 | + final StatusLine statusLine = response.getStatusLine(); | ||
366 | + final HttpEntity entity = response.getEntity(); | ||
367 | + final String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
368 | + throwExceptionsIfNeeded(statusLine, responseText); | ||
369 | + } | ||
370 | + | ||
371 | + private HttpPost createPostRequest(URI uri, NameValuePair... nameValuePair) throws UnsupportedEncodingException | ||
372 | + { | ||
373 | + return setEntity(new HttpPost(uri), nameValuePair); | ||
374 | + } | ||
375 | + | ||
376 | + private HttpPut createPutRequest(URI uri, NameValuePair... nameValuePair) throws UnsupportedEncodingException | ||
377 | + { | ||
378 | + return setEntity(new HttpPut(uri), nameValuePair); | ||
379 | + } | ||
380 | + | ||
381 | + private String execute(HttpUriRequest request) throws IOException | ||
382 | + { | ||
383 | + final HttpResponse response = httpClient.execute(request); | ||
384 | + final StatusLine statusLine = response.getStatusLine(); | ||
385 | + final HttpEntity entity = response.getEntity(); | ||
386 | + String responseText = entity == null ? null : EntityUtils.toString(entity); | ||
387 | + if (statusLine.getStatusCode() >= 300) { | ||
388 | + try { | ||
389 | + final String error = ErrorUnmarshaller.unmarshal(responseText); | ||
390 | + throw new YoutrackErrorException(error, statusLine.getStatusCode()); | ||
391 | + } catch (JAXBException e) { | ||
392 | + // TODO we should log on debug level the JAXBException | ||
393 | + throw new HttpResponseException(statusLine.getStatusCode(), responseText); | ||
394 | + } | ||
395 | + } | ||
396 | + if (entity == null) { | ||
397 | + throw new ClientProtocolException("Response contains no content"); | ||
398 | + } | ||
399 | + return responseText; | ||
400 | + } | ||
401 | + | ||
402 | + private <T extends HttpEntityEnclosingRequestBase> T setEntity(T request, NameValuePair[] nameValuePair) throws UnsupportedEncodingException | ||
403 | + { | ||
404 | + final ArrayList<NameValuePair> list = new ArrayList<NameValuePair>(); | ||
405 | + Collections.addAll(list, nameValuePair); | ||
406 | + request.setEntity(new UrlEncodedFormEntity(list)); | ||
407 | + return request; | ||
408 | + } | ||
409 | + | ||
410 | + private void throwExceptionsIfNeeded(StatusLine statusLine, String responseText) throws IOException | ||
411 | + { | ||
412 | + if (statusLine.getStatusCode() >= 300) { | ||
413 | + throw new HttpResponseException(statusLine.getStatusCode(), responseText); | ||
403 | } | 414 | } |
415 | + } | ||
404 | } | 416 | } |
Please
register
or
login
to post a comment