Showing
3 changed files
with
83 additions
and
56 deletions
1 | +package pl.com.it_crowd.youtrack.api; | ||
2 | + | ||
3 | +import java.net.URI; | ||
4 | +import java.net.URISyntaxException; | ||
5 | + | ||
6 | +public class URIUtils { | ||
7 | +// -------------------------- STATIC METHODS -------------------------- | ||
8 | + | ||
9 | + public static URI buildURI(URI base, String path) | ||
10 | + { | ||
11 | + return buildURI(base, path, null); | ||
12 | + } | ||
13 | + | ||
14 | + public static URI buildURI(URI base, String path, String query) | ||
15 | + { | ||
16 | + try { | ||
17 | + return new URI(base.getScheme(), base.getHost(), base.getPath().replaceAll("/+$", "") + path, query, null); | ||
18 | + } catch (URISyntaxException e) { | ||
19 | + throw new RuntimeException(e); | ||
20 | + } | ||
21 | + } | ||
22 | +} |
1 | package pl.com.it_crowd.youtrack.api; | 1 | package pl.com.it_crowd.youtrack.api; |
2 | 2 | ||
3 | +import org.apache.commons.logging.Log; | ||
4 | +import org.apache.commons.logging.LogFactory; | ||
3 | import org.apache.http.Header; | 5 | import org.apache.http.Header; |
4 | import org.apache.http.HttpEntity; | 6 | import org.apache.http.HttpEntity; |
5 | import org.apache.http.HttpHeaders; | 7 | import org.apache.http.HttpHeaders; |
@@ -17,7 +19,6 @@ import org.apache.http.client.methods.HttpGet; | @@ -17,7 +19,6 @@ import org.apache.http.client.methods.HttpGet; | ||
17 | import org.apache.http.client.methods.HttpPost; | 19 | import org.apache.http.client.methods.HttpPost; |
18 | import org.apache.http.client.methods.HttpPut; | 20 | import org.apache.http.client.methods.HttpPut; |
19 | import org.apache.http.client.methods.HttpUriRequest; | 21 | import org.apache.http.client.methods.HttpUriRequest; |
20 | -import org.apache.http.client.utils.URIBuilder; | ||
21 | import org.apache.http.conn.ClientConnectionManager; | 22 | import org.apache.http.conn.ClientConnectionManager; |
22 | import org.apache.http.conn.scheme.Scheme; | 23 | import org.apache.http.conn.scheme.Scheme; |
23 | import org.apache.http.conn.scheme.SchemeRegistry; | 24 | import org.apache.http.conn.scheme.SchemeRegistry; |
@@ -60,6 +61,8 @@ import java.util.List; | @@ -60,6 +61,8 @@ import java.util.List; | ||
60 | import java.util.regex.Matcher; | 61 | import java.util.regex.Matcher; |
61 | import java.util.regex.Pattern; | 62 | import java.util.regex.Pattern; |
62 | 63 | ||
64 | +import static pl.com.it_crowd.youtrack.api.URIUtils.buildURI; | ||
65 | + | ||
63 | public class YoutrackAPI { | 66 | public class YoutrackAPI { |
64 | // ------------------------------ FIELDS ------------------------------ | 67 | // ------------------------------ FIELDS ------------------------------ |
65 | 68 | ||
@@ -67,10 +70,14 @@ public class YoutrackAPI { | @@ -67,10 +70,14 @@ public class YoutrackAPI { | ||
67 | 70 | ||
68 | private final static QName Issue_QNAME = new QName("", "issue"); | 71 | private final static QName Issue_QNAME = new QName("", "issue"); |
69 | 72 | ||
73 | + private static Log LOG = LogFactory.getLog(YoutrackAPI.class); | ||
74 | + | ||
70 | private HttpClient httpClient; | 75 | private HttpClient httpClient; |
71 | 76 | ||
72 | private String serviceLocation; | 77 | private String serviceLocation; |
73 | 78 | ||
79 | + private URI serviceLocationURI; | ||
80 | + | ||
74 | // -------------------------- STATIC METHODS -------------------------- | 81 | // -------------------------- STATIC METHODS -------------------------- |
75 | 82 | ||
76 | private static HttpClient getDefaultHttpClient() | 83 | private static HttpClient getDefaultHttpClient() |
@@ -134,7 +141,15 @@ public class YoutrackAPI { | @@ -134,7 +141,15 @@ public class YoutrackAPI { | ||
134 | 141 | ||
135 | public YoutrackAPI(String serviceLocation, HttpClient httpClient) | 142 | public YoutrackAPI(String serviceLocation, HttpClient httpClient) |
136 | { | 143 | { |
144 | + if (serviceLocation == null) { | ||
145 | + throw new IllegalArgumentException("serviceLocation cannot be null"); | ||
146 | + } | ||
137 | this.serviceLocation = serviceLocation; | 147 | this.serviceLocation = serviceLocation; |
148 | + try { | ||
149 | + serviceLocationURI = new URI(this.serviceLocation); | ||
150 | + } catch (URISyntaxException e) { | ||
151 | + throw new RuntimeException(e); | ||
152 | + } | ||
138 | this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; | 153 | this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; |
139 | } | 154 | } |
140 | 155 | ||
@@ -170,7 +185,7 @@ public class YoutrackAPI { | @@ -170,7 +185,7 @@ public class YoutrackAPI { | ||
170 | 185 | ||
171 | public void command(String issueId, String command, String comment, String group, Boolean disableNotifications, String runAs) throws IOException | 186 | public void command(String issueId, String command, String comment, String group, Boolean disableNotifications, String runAs) throws IOException |
172 | { | 187 | { |
173 | - final HttpPost request = new HttpPost(serviceLocation + "/rest/issue/" + issueId + "/execute"); | 188 | + final HttpPost request = new HttpPost(buildURI(serviceLocationURI, "/rest/issue/" + issueId + "/execute")); |
174 | final List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>(); | 189 | final List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>(); |
175 | parameters.add(new BasicNameValuePair("command", command)); | 190 | parameters.add(new BasicNameValuePair("command", command)); |
176 | if (!isBlank(comment)) { | 191 | if (!isBlank(comment)) { |
@@ -202,14 +217,8 @@ public class YoutrackAPI { | @@ -202,14 +217,8 @@ public class YoutrackAPI { | ||
202 | */ | 217 | */ |
203 | public String createIssue(String project, String summary, String description) throws IOException | 218 | public String createIssue(String project, String summary, String description) throws IOException |
204 | { | 219 | { |
205 | - final URI uri; | ||
206 | - try { | ||
207 | - uri = new URIBuilder(serviceLocation + "/rest/issue").build(); | ||
208 | - } catch (URISyntaxException e) { | ||
209 | - throw new RuntimeException(e); | ||
210 | - } | ||
211 | - final HttpPut request = createPutRequest(uri, new BasicNameValuePair("project", project), new BasicNameValuePair("summary", summary), | ||
212 | - new BasicNameValuePair("description", description)); | 220 | + final HttpPut request = createPutRequest(buildURI(serviceLocationURI, "/rest/issue"), new BasicNameValuePair("project", project), |
221 | + new BasicNameValuePair("summary", summary), new BasicNameValuePair("description", description)); | ||
213 | final HttpResponse response = httpClient.execute(request); | 222 | final HttpResponse response = httpClient.execute(request); |
214 | final StatusLine statusLine = response.getStatusLine(); | 223 | final StatusLine statusLine = response.getStatusLine(); |
215 | final HttpEntity entity = response.getEntity(); | 224 | final HttpEntity entity = response.getEntity(); |
@@ -230,24 +239,12 @@ public class YoutrackAPI { | @@ -230,24 +239,12 @@ public class YoutrackAPI { | ||
230 | 239 | ||
231 | public void deleteIssue(String issueId) throws IOException | 240 | public void deleteIssue(String issueId) throws IOException |
232 | { | 241 | { |
233 | - final URI uri; | ||
234 | - try { | ||
235 | - uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
236 | - } catch (URISyntaxException e) { | ||
237 | - throw new RuntimeException(e); | ||
238 | - } | ||
239 | - execute(new HttpDelete(uri)); | 242 | + execute(new HttpDelete(buildURI(serviceLocationURI, "/rest/issue/" + issueId))); |
240 | } | 243 | } |
241 | 244 | ||
242 | public AssigneeList getAssignees(String project) throws IOException, JAXBException | 245 | public AssigneeList getAssignees(String project) throws IOException, JAXBException |
243 | { | 246 | { |
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); | ||
249 | - } | ||
250 | - final String responseString = execute(new HttpGet(uri)); | 247 | + final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee"))); |
251 | final Object result = YoutrackUnmarshaller.unmarshall(responseString); | 248 | final Object result = YoutrackUnmarshaller.unmarshall(responseString); |
252 | if (result instanceof AssigneeList) { | 249 | if (result instanceof AssigneeList) { |
253 | return (AssigneeList) result; | 250 | return (AssigneeList) result; |
@@ -258,13 +255,7 @@ public class YoutrackAPI { | @@ -258,13 +255,7 @@ public class YoutrackAPI { | ||
258 | 255 | ||
259 | public Enumeration getBundle(String customField) throws IOException, JAXBException | 256 | public Enumeration getBundle(String customField) throws IOException, JAXBException |
260 | { | 257 | { |
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); | ||
266 | - } | ||
267 | - final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(uri))); | 258 | + final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/customfield/bundle/" + customField)))); |
268 | if (result instanceof Enumeration) { | 259 | if (result instanceof Enumeration) { |
269 | return (Enumeration) result; | 260 | return (Enumeration) result; |
270 | } else if (result instanceof JAXBElement) { | 261 | } else if (result instanceof JAXBElement) { |
@@ -281,13 +272,7 @@ public class YoutrackAPI { | @@ -281,13 +272,7 @@ public class YoutrackAPI { | ||
281 | 272 | ||
282 | public List<User> getIndividualAssignees(String project) throws IOException, JAXBException | 273 | public List<User> getIndividualAssignees(String project) throws IOException, JAXBException |
283 | { | 274 | { |
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); | ||
289 | - } | ||
290 | - final String responseString = execute(new HttpGet(uri)); | 275 | + final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee/individual"))); |
291 | final Object result = YoutrackUnmarshaller.unmarshall(responseString); | 276 | final Object result = YoutrackUnmarshaller.unmarshall(responseString); |
292 | if (result instanceof UserRefs) { | 277 | if (result instanceof UserRefs) { |
293 | return ((UserRefs) result).getUsers(); | 278 | return ((UserRefs) result).getUsers(); |
@@ -298,15 +283,9 @@ public class YoutrackAPI { | @@ -298,15 +283,9 @@ public class YoutrackAPI { | ||
298 | 283 | ||
299 | public IssueWrapper getIssue(String issueId) throws IOException, JAXBException | 284 | public IssueWrapper getIssue(String issueId) throws IOException, JAXBException |
300 | { | 285 | { |
301 | - final URI uri; | ||
302 | - try { | ||
303 | - uri = new URIBuilder(serviceLocation + "/rest/issue/" + issueId).build(); | ||
304 | - } catch (URISyntaxException e) { | ||
305 | - throw new RuntimeException(e); | ||
306 | - } | ||
307 | final String responseString; | 286 | final String responseString; |
308 | try { | 287 | try { |
309 | - responseString = execute(new HttpGet(uri)); | 288 | + responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue/" + issueId))); |
310 | } catch (YoutrackErrorException e) { | 289 | } catch (YoutrackErrorException e) { |
311 | if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { | 290 | if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { |
312 | throw new NoResultFoundException(e.getMessage(), e); | 291 | throw new NoResultFoundException(e.getMessage(), e); |
@@ -331,15 +310,15 @@ public class YoutrackAPI { | @@ -331,15 +310,15 @@ public class YoutrackAPI { | ||
331 | 310 | ||
332 | public void login(String username, String password) throws IOException, JAXBException | 311 | public void login(String username, String password) throws IOException, JAXBException |
333 | { | 312 | { |
334 | - final HttpPost request = new HttpPost(serviceLocation + "/rest/user/login"); | 313 | + final HttpPost request = new HttpPost(buildURI(serviceLocationURI, "/rest/user/login")); |
335 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); | 314 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); |
336 | execute(request); | 315 | execute(request); |
337 | } | 316 | } |
338 | 317 | ||
339 | public List<IssueWrapper> searchIssuesByProject(String project, Object filter) throws JAXBException, IOException | 318 | public List<IssueWrapper> searchIssuesByProject(String project, Object filter) throws JAXBException, IOException |
340 | { | 319 | { |
341 | - final String url = serviceLocation + "/rest/issue/byproject/" + project + "?filter=" + (filter == null ? "" : filter); | ||
342 | - final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(url))); | 320 | + final Object result = YoutrackUnmarshaller.unmarshall( |
321 | + execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue/byproject/" + project, "filter=" + (filter == null ? "" : filter))))); | ||
343 | if (!(result instanceof Issues)) { | 322 | if (!(result instanceof Issues)) { |
344 | throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result); | 323 | throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result); |
345 | } | 324 | } |
@@ -353,13 +332,7 @@ public class YoutrackAPI { | @@ -353,13 +332,7 @@ public class YoutrackAPI { | ||
353 | 332 | ||
354 | public void updateIssue(String issueId, String summary, String description) throws IOException | 333 | public void updateIssue(String issueId, String summary, String description) throws IOException |
355 | { | 334 | { |
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), | 335 | + final HttpPost request = createPostRequest(buildURI(serviceLocationURI, "/rest/issue/" + issueId), new BasicNameValuePair(Fields.summary.name(), summary), |
363 | new BasicNameValuePair(Fields.description.name(), description)); | 336 | new BasicNameValuePair(Fields.description.name(), description)); |
364 | final HttpResponse response = httpClient.execute(request); | 337 | final HttpResponse response = httpClient.execute(request); |
365 | final StatusLine statusLine = response.getStatusLine(); | 338 | final StatusLine statusLine = response.getStatusLine(); |
@@ -389,7 +362,7 @@ public class YoutrackAPI { | @@ -389,7 +362,7 @@ public class YoutrackAPI { | ||
389 | final String error = ErrorUnmarshaller.unmarshal(responseText); | 362 | final String error = ErrorUnmarshaller.unmarshal(responseText); |
390 | throw new YoutrackErrorException(error, statusLine.getStatusCode()); | 363 | throw new YoutrackErrorException(error, statusLine.getStatusCode()); |
391 | } catch (JAXBException e) { | 364 | } catch (JAXBException e) { |
392 | - // TODO we should log on debug level the JAXBException | 365 | + LOG.error("Cannot unmarshal following response text:\n" + responseText, e); |
393 | throw new HttpResponseException(statusLine.getStatusCode(), responseText); | 366 | throw new HttpResponseException(statusLine.getStatusCode(), responseText); |
394 | } | 367 | } |
395 | } | 368 | } |
1 | +package pl.com.it_crowd.youtrack.api.rest; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | +import pl.com.it_crowd.youtrack.api.Filter; | ||
5 | +import pl.com.it_crowd.youtrack.api.URIUtils; | ||
6 | +import pl.com.it_crowd.youtrack.api.defaults.StateValues; | ||
7 | + | ||
8 | +import java.net.URI; | ||
9 | +import java.net.URISyntaxException; | ||
10 | + | ||
11 | +import static org.junit.Assert.assertEquals; | ||
12 | + | ||
13 | +public class URIUtilsTest { | ||
14 | +// -------------------------- OTHER METHODS -------------------------- | ||
15 | + | ||
16 | + @Test | ||
17 | + public void buildURI() throws URISyntaxException | ||
18 | + { | ||
19 | +// Given | ||
20 | + final URI base = new URI("http://localhost:8080/youtrack/"); | ||
21 | + final String pathA = "/rest/admin/bundle/QA note types"; | ||
22 | + final String queryA = "q=" + Filter.stateFilter(StateValues.NotWontFix).maxResults(20); | ||
23 | + | ||
24 | +// When | ||
25 | + final URI uriA = URIUtils.buildURI(base, pathA); | ||
26 | + final URI uriB = URIUtils.buildURI(base, pathA, queryA); | ||
27 | + | ||
28 | +// Then | ||
29 | + assertEquals("http://localhost/youtrack/rest/admin/bundle/QA%20note%20types", uriA.toString()); | ||
30 | + assertEquals("http://localhost/youtrack/rest/admin/bundle/QA%20note%20types?q=state:-%257BWon%2527t+fix%257D&max=20", uriB.toString()); | ||
31 | + } | ||
32 | +} |
Please
register
or
login
to post a comment