Commit 1d7db5f915d99f1842ce2e9d0f6e4d133954c7a5

Authored by bernard
1 parent f211190c

Safer URI building.

  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 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 5 import org.apache.http.Header;
4 6 import org.apache.http.HttpEntity;
5 7 import org.apache.http.HttpHeaders;
... ... @@ -17,7 +19,6 @@ import org.apache.http.client.methods.HttpGet;
17 19 import org.apache.http.client.methods.HttpPost;
18 20 import org.apache.http.client.methods.HttpPut;
19 21 import org.apache.http.client.methods.HttpUriRequest;
20   -import org.apache.http.client.utils.URIBuilder;
21 22 import org.apache.http.conn.ClientConnectionManager;
22 23 import org.apache.http.conn.scheme.Scheme;
23 24 import org.apache.http.conn.scheme.SchemeRegistry;
... ... @@ -60,6 +61,8 @@ import java.util.List;
60 61 import java.util.regex.Matcher;
61 62 import java.util.regex.Pattern;
62 63
  64 +import static pl.com.it_crowd.youtrack.api.URIUtils.buildURI;
  65 +
63 66 public class YoutrackAPI {
64 67 // ------------------------------ FIELDS ------------------------------
65 68
... ... @@ -67,10 +70,14 @@ public class YoutrackAPI {
67 70
68 71 private final static QName Issue_QNAME = new QName("", "issue");
69 72
  73 + private static Log LOG = LogFactory.getLog(YoutrackAPI.class);
  74 +
70 75 private HttpClient httpClient;
71 76
72 77 private String serviceLocation;
73 78
  79 + private URI serviceLocationURI;
  80 +
74 81 // -------------------------- STATIC METHODS --------------------------
75 82
76 83 private static HttpClient getDefaultHttpClient()
... ... @@ -134,7 +141,15 @@ public class YoutrackAPI {
134 141
135 142 public YoutrackAPI(String serviceLocation, HttpClient httpClient)
136 143 {
  144 + if (serviceLocation == null) {
  145 + throw new IllegalArgumentException("serviceLocation cannot be null");
  146 + }
137 147 this.serviceLocation = serviceLocation;
  148 + try {
  149 + serviceLocationURI = new URI(this.serviceLocation);
  150 + } catch (URISyntaxException e) {
  151 + throw new RuntimeException(e);
  152 + }
138 153 this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient;
139 154 }
140 155
... ... @@ -170,7 +185,7 @@ public class YoutrackAPI {
170 185
171 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 189 final List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
175 190 parameters.add(new BasicNameValuePair("command", command));
176 191 if (!isBlank(comment)) {
... ... @@ -202,14 +217,8 @@ public class YoutrackAPI {
202 217 */
203 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 222 final HttpResponse response = httpClient.execute(request);
214 223 final StatusLine statusLine = response.getStatusLine();
215 224 final HttpEntity entity = response.getEntity();
... ... @@ -230,24 +239,12 @@ public class YoutrackAPI {
230 239
231 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 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 248 final Object result = YoutrackUnmarshaller.unmarshall(responseString);
252 249 if (result instanceof AssigneeList) {
253 250 return (AssigneeList) result;
... ... @@ -258,13 +255,7 @@ public class YoutrackAPI {
258 255
259 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 259 if (result instanceof Enumeration) {
269 260 return (Enumeration) result;
270 261 } else if (result instanceof JAXBElement) {
... ... @@ -281,13 +272,7 @@ public class YoutrackAPI {
281 272
282 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 276 final Object result = YoutrackUnmarshaller.unmarshall(responseString);
292 277 if (result instanceof UserRefs) {
293 278 return ((UserRefs) result).getUsers();
... ... @@ -298,15 +283,9 @@ public class YoutrackAPI {
298 283
299 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 286 final String responseString;
308 287 try {
309   - responseString = execute(new HttpGet(uri));
  288 + responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue/" + issueId)));
310 289 } catch (YoutrackErrorException e) {
311 290 if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
312 291 throw new NoResultFoundException(e.getMessage(), e);
... ... @@ -331,15 +310,15 @@ public class YoutrackAPI {
331 310
332 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 314 request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password))));
336 315 execute(request);
337 316 }
338 317
339 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 322 if (!(result instanceof Issues)) {
344 323 throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result);
345 324 }
... ... @@ -353,13 +332,7 @@ public class YoutrackAPI {
353 332
354 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 336 new BasicNameValuePair(Fields.description.name(), description));
364 337 final HttpResponse response = httpClient.execute(request);
365 338 final StatusLine statusLine = response.getStatusLine();
... ... @@ -389,7 +362,7 @@ public class YoutrackAPI {
389 362 final String error = ErrorUnmarshaller.unmarshal(responseText);
390 363 throw new YoutrackErrorException(error, statusLine.getStatusCode());
391 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 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