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