summaryrefslogtreecommitdiffstats
path: root/sonar-ws-client
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2013-06-12 23:28:00 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2013-06-13 15:46:48 +0200
commit9678ebc554ee2c2581268c956040e3ebc7adcb12 (patch)
tree379f934e4c31d598bc08ea91310e52a4a39ca5c0 /sonar-ws-client
parent92b4d736ed08613824523d2acd033cc39b56b412 (diff)
downloadsonarqube-9678ebc554ee2c2581268c956040e3ebc7adcb12.tar.gz
sonarqube-9678ebc554ee2c2581268c956040e3ebc7adcb12.zip
Improve error handling of ws-client
Diffstat (limited to 'sonar-ws-client')
-rw-r--r--sonar-ws-client/pom.xml6
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java44
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/base/HttpException.java43
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/base/Paging.java (renamed from sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Paging.java)8
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java2
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java32
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlan.java60
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlanQuery.java2
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java112
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java19
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueComment.java31
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java6
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java120
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewActionPlan.java3
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java4
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/UpdateActionPlan.java3
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlan.java94
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClient.java (renamed from sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultActionPlanClient.java)49
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java155
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueClient.java (renamed from sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java)84
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueComment.java53
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssues.java146
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/IssueJsonParser.java (renamed from sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java)40
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/package-info.java21
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java9
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java4
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/base/HttpExceptionTest.java34
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java57
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java12
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClientTest.java (renamed from sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultActionPlanClientTest.java)13
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java (renamed from sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java)13
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java (renamed from sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java)24
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/DefaultIssueClientTest/add_comment_result.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/DefaultIssueClientTest/add_comment_result.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/empty.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/empty.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/getTransitions.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/getTransitions.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-action-plans.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-comments.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-comments.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-components.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-projects.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-projects.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-users.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-users.json)0
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json (renamed from sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json)0
41 files changed, 860 insertions, 443 deletions
diff --git a/sonar-ws-client/pom.xml b/sonar-ws-client/pom.xml
index 2b307d7c435..7b9135ea8e7 100644
--- a/sonar-ws-client/pom.xml
+++ b/sonar-ws-client/pom.xml
@@ -10,7 +10,7 @@
<artifactId>sonar-ws-client</artifactId>
<packaging>jar</packaging>
<name>Sonar :: Web Service Client</name>
- <description>Java library to request Sonar web services</description>
+ <description>Java Client Library for Sonar Web Services</description>
<properties>
<httpclient4.version>4.2.2</httpclient4.version>
@@ -133,10 +133,12 @@
org.apache.httpcomponents.httpcore;bundle-version="${httpclient4.version}";optional="true"
</Require-Bundle>
<Export-Package>!.,org.sonar.wsclient,
+ org.sonar.wsclient.component,
org.sonar.wsclient.connectors,
org.sonar.wsclient.services,
org.sonar.wsclient.issue,
- org.sonar.wsclient.rule
+ org.sonar.wsclient.rule,
+ org.sonar.wsclient.user
</Export-Package>
<Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment>
</instructions>
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java
index 1ecc19f01ab..767070141e1 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java
@@ -21,8 +21,8 @@ package org.sonar.wsclient;
import org.sonar.wsclient.internal.HttpRequestFactory;
import org.sonar.wsclient.issue.ActionPlanClient;
-import org.sonar.wsclient.issue.DefaultActionPlanClient;
-import org.sonar.wsclient.issue.DefaultIssueClient;
+import org.sonar.wsclient.issue.internal.DefaultActionPlanClient;
+import org.sonar.wsclient.issue.internal.DefaultIssueClient;
import org.sonar.wsclient.issue.IssueClient;
import org.sonar.wsclient.user.DefaultUserClient;
import org.sonar.wsclient.user.UserClient;
@@ -30,6 +30,14 @@ import org.sonar.wsclient.user.UserClient;
import javax.annotation.Nullable;
/**
+ * Entry point of the Java Client for Sonar Web Services. It does not support all web services yet.
+ * <p/>
+ * Example:
+ * <pre>
+ * SonarClient client = SonarClient.create("http://localhost:9000");
+ * IssueClient issueClient = client.issueClient();
+ * </pre>
+ *
* @since 3.6
*/
public class SonarClient {
@@ -54,24 +62,37 @@ public class SonarClient {
.setReadTimeoutInMilliseconds(builder.readTimeoutMs);
}
+ /**
+ * New client to interact with web services related to issues
+ */
public IssueClient issueClient() {
return new DefaultIssueClient(requestFactory);
}
+ /**
+ * New client to interact with web services related to issue action plans
+ */
public ActionPlanClient actionPlanClient() {
return new DefaultActionPlanClient(requestFactory);
}
+ /**
+ * New client to interact with web services related to users
+ */
public UserClient userClient() {
return new DefaultUserClient(requestFactory);
}
+ /**
+ * Create a builder of {@link SonarClient}s.
+ */
public static Builder builder() {
return new Builder();
}
/**
- * Create a client with default configuration. Use {@link #builder()} to define a custom configuration.
+ * Create a client with default configuration. Use {@link #builder()} to define
+ * a custom configuration (credentials, HTTP proxy, HTTP timeouts).
*/
public static SonarClient create(String serverUrl) {
return builder().url(serverUrl).build();
@@ -85,22 +106,34 @@ public class SonarClient {
private Builder() {
}
+ /**
+ * Mandatory HTTP server URL, eg "http://localhost:9000"
+ */
public Builder url(String url) {
this.url = url;
return this;
}
+ /**
+ * Optional login, for example "admin"
+ */
public Builder login(@Nullable String login) {
this.login = login;
return this;
}
+ /**
+ * Optional password related to {@link #login(String)}, for example "admin"
+ */
public Builder password(@Nullable String password) {
this.password = password;
return this;
}
- public Builder proxy(String proxyHost, int proxyPort) {
+ /**
+ * Host and port of the optional HTTP proxy
+ */
+ public Builder proxy(@Nullable String proxyHost, int proxyPort) {
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
return this;
@@ -134,6 +167,9 @@ public class SonarClient {
return this;
}
+ /**
+ * Build a new client
+ */
public SonarClient build() {
if (url == null || "".equals(url)) {
throw new IllegalStateException("Server URL must be set");
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/base/HttpException.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/base/HttpException.java
new file mode 100644
index 00000000000..94d9bfbcead
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/base/HttpException.java
@@ -0,0 +1,43 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.base;
+
+/**
+ * @since 3.6
+ */
+public class HttpException extends RuntimeException {
+
+ private final String url;
+ private final int status;
+
+ public HttpException(String url, int status) {
+ super(String.format("Error %d on %s", status, url));
+ this.url = url;
+ this.status = status;
+ }
+
+ public String url() {
+ return url;
+ }
+
+ public int status() {
+ return status;
+ }
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Paging.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/base/Paging.java
index cd24f2beaf4..d803bdd956a 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Paging.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/base/Paging.java
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.base;
import org.sonar.wsclient.unmarshallers.JsonUtils;
@@ -26,13 +26,15 @@ import java.util.Map;
/**
* @since 3.6
- * TODO move outside this package
*/
public class Paging {
private final Map json;
- Paging(Map json) {
+ /**
+ * For internal use
+ */
+ public Paging(Map json) {
this.json = json;
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java
index 698500541ec..99be0b4af2f 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java
@@ -25,7 +25,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
- * Not an API, please do not directly use this class.
+ * Not an API. Please do not use this class, except maybe for unit tests.
*/
public class EncodingUtils {
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java
index a601df34efc..e454a585448 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java
@@ -20,13 +20,13 @@
package org.sonar.wsclient.internal;
import com.github.kevinsawicki.http.HttpRequest;
+import org.sonar.wsclient.base.HttpException;
import javax.annotation.Nullable;
-
import java.util.Map;
/**
- * Not an API, please do not directly use this class.
+ * Not an API. Please do not use this class, except maybe for unit tests.
*/
public class HttpRequestFactory {
@@ -116,17 +116,34 @@ public class HttpRequestFactory {
return readTimeoutInMilliseconds;
}
- public HttpRequest get(String wsUrl, Map<String, Object> queryParams) {
+ public String get(String wsUrl, Map<String, Object> queryParams) {
HttpRequest request = HttpRequest.get(baseUrl + wsUrl, queryParams, true);
- return prepare(request);
+ return execute(request);
}
- public HttpRequest post(String wsUrl, Map<String, Object> queryParams) {
+ public String post(String wsUrl, Map<String, Object> queryParams) {
HttpRequest request = HttpRequest.post(baseUrl + wsUrl, queryParams, true);
- return prepare(request);
+ return execute(request);
+ }
+
+ private String execute(HttpRequest request) {
+ try {
+ prepare(request);
+ if (request.ok()) {
+ return request.body("UTF-8");
+ }
+ // TODO handle error messages
+ throw new HttpException(request.url().toString(), request.code());
+
+ } catch (HttpException e) {
+ throw e;
+
+ } catch (HttpRequest.HttpRequestException e) {
+ throw new IllegalStateException(e.getCause());
+ }
}
- private HttpRequest prepare(HttpRequest request) {
+ private void prepare(HttpRequest request) {
if (proxyHost != null) {
request.useProxy(proxyHost, proxyPort);
if (proxyLogin != null) {
@@ -145,6 +162,5 @@ public class HttpRequestFactory {
if (login != null) {
request.basic(login, password);
}
- return request;
}
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlan.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlan.java
index d7c40630111..daf45ba7124 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlan.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlan.java
@@ -11,84 +11,52 @@
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * Lesser General License for more details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You should have received a copy of the GNU Lesser General License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.wsclient.issue;
-import org.sonar.wsclient.unmarshallers.JsonUtils;
-
import javax.annotation.CheckForNull;
-
import java.util.Date;
-import java.util.Map;
/**
* @since 3.6
*/
-public class ActionPlan {
-
- private final Map json;
-
- ActionPlan(Map json) {
- this.json = json;
- }
+public interface ActionPlan {
/**
* Unique key
*/
- public String key() {
- return JsonUtils.getString(json, "key");
- }
+ String key();
- public String project() {
- return JsonUtils.getString(json, "project");
- }
+ String project();
- public String name() {
- return JsonUtils.getString(json, "name");
- }
+ String name();
@CheckForNull
- public String description() {
- return JsonUtils.getString(json, "desc");
- }
+ String description();
- public String status() {
- return JsonUtils.getString(json, "status");
- }
+ String status();
/**
* Login of the user who created the action plan.
*/
- public String userLogin() {
- return JsonUtils.getString(json, "userLogin");
- }
+ String userLogin();
@CheckForNull
- public Date deadLine() {
- return JsonUtils.getDateTime(json, "deadLine");
- }
+ Date deadLine();
- public Date createdAt() {
- return JsonUtils.getDateTime(json, "createdAt");
- }
+ Date createdAt();
- public Date updatedAt() {
- return JsonUtils.getDateTime(json, "updatedAt");
- }
+ Date updatedAt();
@CheckForNull
- public Integer totalIssues() {
- return JsonUtils.getInteger(json, "totalIssues");
- }
+ Integer totalIssues();
@CheckForNull
- public Integer unresolvedIssues() {
- return JsonUtils.getInteger(json, "unresolvedIssues");
- }
+ Integer unresolvedIssues();
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlanQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlanQuery.java
index aa7124f5cd0..3f77468b783 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlanQuery.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/ActionPlanQuery.java
@@ -27,7 +27,7 @@ import java.util.Map;
*/
public class ActionPlanQuery {
- static final String BASE_URL = "/api/action_plans/search";
+ public static final String BASE_URL = "/api/action_plans/search";
private final Map<String, Object> params = new HashMap<String, Object>();
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java
index b5b555087e5..3294fa81f65 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java
@@ -11,144 +11,86 @@
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * Lesser General License for more details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You should have received a copy of the GNU Lesser General License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.wsclient.issue;
-import org.sonar.wsclient.unmarshallers.JsonUtils;
-
import javax.annotation.CheckForNull;
-
-import java.util.*;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
/**
* @since 3.6
*/
-public class Issue {
-
- private final Map json;
-
- Issue(Map json) {
- this.json = json;
- }
+public interface Issue {
/**
* Unique key
*/
- public String key() {
- return JsonUtils.getString(json, "key");
- }
+ String key();
- public String componentKey() {
- return JsonUtils.getString(json, "component");
- }
+ String componentKey();
- public String projectKey() {
- return JsonUtils.getString(json, "project");
- }
+ String projectKey();
- public String ruleKey() {
- return JsonUtils.getString(json, "rule");
- }
+ String ruleKey();
- public String severity() {
- return JsonUtils.getString(json, "severity");
- }
+ String severity();
@CheckForNull
- public String message() {
- return JsonUtils.getString(json, "message");
- }
+ String message();
@CheckForNull
- public Integer line() {
- return JsonUtils.getInteger(json, "line");
- }
+ Integer line();
@CheckForNull
- public Double effortToFix() {
- return JsonUtils.getDouble(json, "effortToFix");
- }
+ Double effortToFix();
- public String status() {
- return JsonUtils.getString(json, "status");
- }
+ String status();
/**
* The resolution type. Null if the issue is not resolved.
*/
@CheckForNull
- public String resolution() {
- return JsonUtils.getString(json, "resolution");
- }
+ String resolution();
@CheckForNull
- public String reporter() {
- return JsonUtils.getString(json, "reporter");
- }
+ String reporter();
/**
* Login of assignee. Null if issue is not assigned.
*/
@CheckForNull
- public String assignee() {
- return JsonUtils.getString(json, "assignee");
- }
+ String assignee();
/**
* SCM account
*/
@CheckForNull
- public String author() {
- return JsonUtils.getString(json, "author");
- }
+ String author();
@CheckForNull
- public String actionPlan() {
- return JsonUtils.getString(json, "actionPlan");
- }
+ String actionPlan();
- public Date creationDate() {
- return JsonUtils.getDateTime(json, "creationDate");
- }
+ Date creationDate();
- public Date updateDate() {
- return JsonUtils.getDateTime(json, "updateDate");
- }
+ Date updateDate();
@CheckForNull
- public Date closeDate() {
- return JsonUtils.getDateTime(json, "closeDate");
- }
+ Date closeDate();
@CheckForNull
- public String attribute(String key) {
- return attributes().get(key);
- }
-
- public Map<String, String> attributes() {
- Map<String, String> attr = (Map) json.get("attr");
- if (attr == null) {
- return Collections.emptyMap();
- }
- return attr;
- }
+ String attribute(String key);
+
+ Map<String, String> attributes();
/**
* Non-null list of comments
*/
- public List<IssueComment> comments() {
- List<IssueComment> comments = new ArrayList();
- List<Map> jsonComments = (List<Map>) json.get("comments");
- if (jsonComments != null) {
- for (Map jsonComment : jsonComments) {
- comments.add(new IssueComment(jsonComment));
- }
- }
- return comments;
- }
+ List<IssueComment> comments();
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java
index 3527938710a..1e1fd52df4f 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java
@@ -24,16 +24,35 @@ import javax.annotation.Nullable;
import java.util.List;
/**
+ * This client is a wrapper over the web services related to issues
+ *
* @since 3.6
*/
public interface IssueClient {
+ /**
+ * Wrap the web service /api/issues/search in order to search for issues.
+ */
Issues find(IssueQuery query);
+ /**
+ * Assign an existing issue to a user. A null assignee removes the assignee.
+ *
+ * @return the updated issue
+ */
Issue assign(String issueKey, @Nullable String assignee);
+ /**
+ * Change the severity of an existing issue. Supported values are "INFO", "MINOR",
+ * "MAJOR", "CRITICAL" and "BLOCKER".
+ *
+ * @return the updated issue
+ */
Issue setSeverity(String issueKey, String severity);
+ /**
+ * Link an existing issue to an action plan. A null action plan unlinks the issue.
+ */
Issue plan(String issueKey, @Nullable String actionPlan);
IssueComment addComment(String issueKey, String markdownText);
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueComment.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueComment.java
index f649d573b8f..2ce101d0ac7 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueComment.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueComment.java
@@ -11,42 +11,25 @@
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * Lesser General License for more details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You should have received a copy of the GNU Lesser General License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.wsclient.issue;
-import org.sonar.wsclient.unmarshallers.JsonUtils;
-
import java.util.Date;
-import java.util.Map;
/**
* @since 3.6
*/
-public class IssueComment {
- private final Map json;
-
- IssueComment(Map json) {
- this.json = json;
- }
-
- public String key() {
- return JsonUtils.getString(json, "key");
- }
+public interface IssueComment {
+ String key();
- public String htmlText() {
- return JsonUtils.getString(json, "htmlText");
- }
+ String htmlText();
- public String login() {
- return JsonUtils.getString(json, "login");
- }
+ String login();
- public Date createdAt() {
- return JsonUtils.getDateTime(json, "createdAt");
- }
+ Date createdAt();
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
index db597021e08..f291d31051a 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
@@ -30,7 +30,6 @@ import java.util.Map;
*/
public class IssueQuery {
- static final String BASE_URL = "/api/issues/search";
private final Map<String, Object> params = new HashMap<String, Object>();
private IssueQuery() {
@@ -40,7 +39,10 @@ public class IssueQuery {
return new IssueQuery();
}
- Map<String, Object> urlParams() {
+ /**
+ * URL query string, for internal use
+ */
+ public Map<String, Object> urlParams() {
return params;
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java
index ff761f26cdf..43d5cf687ac 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java
@@ -11,133 +11,57 @@
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * Lesser General License for more details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You should have received a copy of the GNU Lesser General License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.wsclient.issue;
+import org.sonar.wsclient.base.Paging;
import org.sonar.wsclient.component.Component;
import org.sonar.wsclient.rule.Rule;
import org.sonar.wsclient.user.User;
import javax.annotation.CheckForNull;
-
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
/**
* @since 3.6
*/
-public class Issues {
+public interface Issues {
+ List<Issue> list();
- private final List<Issue> list = new ArrayList<Issue>();
- private final Map<String, Rule> rulesByKey = new HashMap<String, Rule>();
- private final Map<String, User> usersByKey = new HashMap<String, User>();
- private final Map<String, Component> componentsByKey = new HashMap<String, Component>();
- private final Map<String, Component> projectsByKey = new HashMap<String, Component>();
- private final Map<String, ActionPlan> actionPlansByKey = new HashMap<String, ActionPlan>();
- private Paging paging;
- private Boolean maxResultsReached;
+ int size();
- public List<Issue> list() {
- return list;
- }
+ Collection<Rule> rules();
- public int size() {
- return list.size();
- }
+ Rule rule(Issue issue);
- public Collection<Rule> rules() {
- return rulesByKey.values();
- }
+ Collection<User> users();
- public Rule rule(Issue issue) {
- return rulesByKey.get(issue.ruleKey());
- }
+ @CheckForNull
+ User user(String login);
- public Collection<User> users() {
- return usersByKey.values();
- }
+ Collection<Component> components();
@CheckForNull
- public User user(String login) {
- return usersByKey.get(login);
- }
+ Component component(Issue issue);
- public Collection<Component> components() {
- return componentsByKey.values();
- }
+ Collection<Component> projects();
@CheckForNull
- public Component component(Issue issue) {
- return componentsByKey.get(issue.componentKey());
- }
+ Component project(Issue issue);
- public Collection<Component> projects() {
- return projectsByKey.values();
- }
+ Collection<ActionPlan> actionPlans();
@CheckForNull
- public Component project(Issue issue) {
- return projectsByKey.get(issue.projectKey());
- }
+ ActionPlan actionPlans(Issue issue);
- public Collection<ActionPlan> actionPlans() {
- return actionPlansByKey.values();
- }
+ Paging paging();
+
+ Boolean maxResultsReached();
- @CheckForNull
- public ActionPlan actionPlans(Issue issue) {
- return actionPlansByKey.get(issue.actionPlan());
- }
-
- public Paging paging() {
- return paging;
- }
-
- public Boolean maxResultsReached() {
- return maxResultsReached;
- }
-
- Issues add(Issue issue) {
- list.add(issue);
- return this;
- }
-
- Issues add(Rule rule) {
- rulesByKey.put(rule.key(), rule);
- return this;
- }
-
- Issues add(User user) {
- usersByKey.put(user.login(), user);
- return this;
- }
-
- Issues add(ActionPlan actionPlan) {
- actionPlansByKey.put(actionPlan.key(), actionPlan);
- return this;
- }
-
- Issues addComponent(Component c) {
- componentsByKey.put(c.key(), c);
- return this;
- }
-
- Issues addProject(Component c) {
- projectsByKey.put(c.key(), c);
- return this;
- }
-
- Issues setPaging(Paging paging) {
- this.paging = paging;
- return this;
- }
-
- Issues setMaxResultsReached(Boolean maxResultsReached) {
- this.maxResultsReached = maxResultsReached;
- return this;
- }
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewActionPlan.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewActionPlan.java
index 74c92acbfe8..19655b9edeb 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewActionPlan.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewActionPlan.java
@@ -30,7 +30,6 @@ import java.util.Map;
*/
public class NewActionPlan {
- static final String BASE_URL = "/api/action_plans/create";
private final Map<String, Object> params = new HashMap<String, Object>();
private NewActionPlan() {
@@ -40,7 +39,7 @@ public class NewActionPlan {
return new NewActionPlan();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java
index 4b8932c2a11..8bda9a02fc2 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java
@@ -27,7 +27,7 @@ import java.util.Map;
* @since 3.6
*/
public class NewIssue {
- static final String BASE_URL = "/api/issues/create";
+
private final Map<String, Object> params = new HashMap<String, Object>();
private NewIssue() {
@@ -37,7 +37,7 @@ public class NewIssue {
return new NewIssue();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/UpdateActionPlan.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/UpdateActionPlan.java
index 2ca316217b3..c8aace9c92c 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/UpdateActionPlan.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/UpdateActionPlan.java
@@ -30,7 +30,6 @@ import java.util.Map;
*/
public class UpdateActionPlan {
- static final String BASE_URL = "/api/action_plans/update";
private final Map<String, Object> params = new HashMap<String, Object>();
private UpdateActionPlan() {
@@ -40,7 +39,7 @@ public class UpdateActionPlan {
return new UpdateActionPlan();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlan.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlan.java
new file mode 100644
index 00000000000..afa077b47b7
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlan.java
@@ -0,0 +1,94 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.issue.internal;
+
+import org.sonar.wsclient.issue.ActionPlan;
+import org.sonar.wsclient.unmarshallers.JsonUtils;
+
+import javax.annotation.CheckForNull;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class DefaultActionPlan implements ActionPlan {
+
+ private final Map json;
+
+ DefaultActionPlan(Map json) {
+ this.json = json;
+ }
+
+ /**
+ * Unique key
+ */
+ public String key() {
+ return JsonUtils.getString(json, "key");
+ }
+
+ public String project() {
+ return JsonUtils.getString(json, "project");
+ }
+
+ public String name() {
+ return JsonUtils.getString(json, "name");
+ }
+
+ @CheckForNull
+ public String description() {
+ return JsonUtils.getString(json, "desc");
+ }
+
+ public String status() {
+ return JsonUtils.getString(json, "status");
+ }
+
+ /**
+ * Login of the user who created the action plan.
+ */
+ public String userLogin() {
+ return JsonUtils.getString(json, "userLogin");
+ }
+
+ @CheckForNull
+ public Date deadLine() {
+ return JsonUtils.getDateTime(json, "deadLine");
+ }
+
+ public Date createdAt() {
+ return JsonUtils.getDateTime(json, "createdAt");
+ }
+
+ public Date updatedAt() {
+ return JsonUtils.getDateTime(json, "updatedAt");
+ }
+
+ @CheckForNull
+ public Integer totalIssues() {
+ return JsonUtils.getInteger(json, "totalIssues");
+ }
+
+ @CheckForNull
+ public Integer unresolvedIssues() {
+ return JsonUtils.getInteger(json, "unresolvedIssues");
+ }
+
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultActionPlanClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClient.java
index 651800edeff..3a187b1d3e6 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultActionPlanClient.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClient.java
@@ -17,12 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
-import com.github.kevinsawicki.http.HttpRequest;
import org.json.simple.JSONValue;
import org.sonar.wsclient.internal.EncodingUtils;
import org.sonar.wsclient.internal.HttpRequestFactory;
+import org.sonar.wsclient.issue.*;
import java.util.ArrayList;
import java.util.List;
@@ -44,17 +44,13 @@ public class DefaultActionPlanClient implements ActionPlanClient {
@Override
public List<ActionPlan> find(String projectKey) {
- HttpRequest request = requestFactory.get(ActionPlanQuery.BASE_URL, EncodingUtils.toMap("project", projectKey));
- if (!request.ok()) {
- throw new IllegalStateException("Fail to search for action plans. Bad HTTP response status: " + request.code());
- }
+ String json = requestFactory.get(ActionPlanQuery.BASE_URL, EncodingUtils.toMap("project", projectKey));
List<ActionPlan> result = new ArrayList<ActionPlan>();
- String json = request.body("UTF-8");
Map jsonRoot = (Map) JSONValue.parse(json);
- List<Map> jsonActionPlans = (List) jsonRoot.get("actionPlans");
+ List<Map> jsonActionPlans = (List<Map>) jsonRoot.get("actionPlans");
if (jsonActionPlans != null) {
for (Map jsonActionPlan : jsonActionPlans) {
- result.add(new ActionPlan(jsonActionPlan));
+ result.add(new DefaultActionPlan(jsonActionPlan));
}
}
return result;
@@ -62,20 +58,14 @@ public class DefaultActionPlanClient implements ActionPlanClient {
@Override
public ActionPlan create(NewActionPlan newActionPlan) {
- HttpRequest request = requestFactory.post(NewActionPlan.BASE_URL, newActionPlan.urlParams());
- if (!request.ok()) {
- throw new IllegalStateException("Fail to create action plan. Bad HTTP response status: " + request.code());
- }
- return createActionPlanResult(request);
+ String json = requestFactory.post("/api/action_plans/create", newActionPlan.urlParams());
+ return createActionPlanResult(json);
}
@Override
public ActionPlan update(UpdateActionPlan updateActionPlan) {
- HttpRequest request = requestFactory.post(UpdateActionPlan.BASE_URL, updateActionPlan.urlParams());
- if (!request.ok()) {
- throw new IllegalStateException("Fail to update action plan. Bad HTTP response status: " + request.code());
- }
- return createActionPlanResult(request);
+ String json = requestFactory.post("/api/action_plans/update", updateActionPlan.urlParams());
+ return createActionPlanResult(json);
}
@Override
@@ -85,28 +75,23 @@ public class DefaultActionPlanClient implements ActionPlanClient {
@Override
public ActionPlan open(String actionPlanKey) {
- HttpRequest request = executeSimpleAction(actionPlanKey, "open");
- return createActionPlanResult(request);
+ String json = executeSimpleAction(actionPlanKey, "open");
+ return createActionPlanResult(json);
}
@Override
public ActionPlan close(String actionPlanKey) {
- HttpRequest request = executeSimpleAction(actionPlanKey, "close");
- return createActionPlanResult(request);
+ String json = executeSimpleAction(actionPlanKey, "close");
+ return createActionPlanResult(json);
}
- private HttpRequest executeSimpleAction(String actionPlanKey, String action) {
- HttpRequest request = requestFactory.post("/api/action_plans/" + action, EncodingUtils.toMap("key", actionPlanKey));
- if (!request.ok()) {
- throw new IllegalStateException("Fail to " + action + " action plan. Bad HTTP response status: " + request.code());
- }
- return request;
+ private String executeSimpleAction(String actionPlanKey, String action) {
+ return requestFactory.post("/api/action_plans/" + action, EncodingUtils.toMap("key", actionPlanKey));
}
- private ActionPlan createActionPlanResult(HttpRequest request){
- String json = request.body("UTF-8");
+ private ActionPlan createActionPlanResult(String json) {
Map jsonRoot = (Map) JSONValue.parse(json);
- return new ActionPlan((Map) jsonRoot.get("actionPlan"));
+ return new DefaultActionPlan((Map) jsonRoot.get("actionPlan"));
}
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java
new file mode 100644
index 00000000000..36f25bc8d30
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java
@@ -0,0 +1,155 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.issue.internal;
+
+import org.sonar.wsclient.issue.Issue;
+import org.sonar.wsclient.issue.IssueComment;
+import org.sonar.wsclient.unmarshallers.JsonUtils;
+
+import javax.annotation.CheckForNull;
+import java.util.*;
+
+/**
+ * @since 3.6
+ */
+public class DefaultIssue implements Issue {
+
+ private final Map json;
+
+ DefaultIssue(Map json) {
+ this.json = json;
+ }
+
+ /**
+ * Unique key
+ */
+ public String key() {
+ return JsonUtils.getString(json, "key");
+ }
+
+ public String componentKey() {
+ return JsonUtils.getString(json, "component");
+ }
+
+ public String projectKey() {
+ return JsonUtils.getString(json, "project");
+ }
+
+ public String ruleKey() {
+ return JsonUtils.getString(json, "rule");
+ }
+
+ public String severity() {
+ return JsonUtils.getString(json, "severity");
+ }
+
+ @CheckForNull
+ public String message() {
+ return JsonUtils.getString(json, "message");
+ }
+
+ @CheckForNull
+ public Integer line() {
+ return JsonUtils.getInteger(json, "line");
+ }
+
+ @CheckForNull
+ public Double effortToFix() {
+ return JsonUtils.getDouble(json, "effortToFix");
+ }
+
+ public String status() {
+ return JsonUtils.getString(json, "status");
+ }
+
+ /**
+ * The resolution type. Null if the issue is not resolved.
+ */
+ @CheckForNull
+ public String resolution() {
+ return JsonUtils.getString(json, "resolution");
+ }
+
+ @CheckForNull
+ public String reporter() {
+ return JsonUtils.getString(json, "reporter");
+ }
+
+ /**
+ * Login of assignee. Null if issue is not assigned.
+ */
+ @CheckForNull
+ public String assignee() {
+ return JsonUtils.getString(json, "assignee");
+ }
+
+ /**
+ * SCM account
+ */
+ @CheckForNull
+ public String author() {
+ return JsonUtils.getString(json, "author");
+ }
+
+ @CheckForNull
+ public String actionPlan() {
+ return JsonUtils.getString(json, "actionPlan");
+ }
+
+ public Date creationDate() {
+ return JsonUtils.getDateTime(json, "creationDate");
+ }
+
+ public Date updateDate() {
+ return JsonUtils.getDateTime(json, "updateDate");
+ }
+
+ @CheckForNull
+ public Date closeDate() {
+ return JsonUtils.getDateTime(json, "closeDate");
+ }
+
+ @CheckForNull
+ public String attribute(String key) {
+ return attributes().get(key);
+ }
+
+ public Map<String, String> attributes() {
+ Map<String, String> attr = (Map<String,String>) json.get("attr");
+ if (attr == null) {
+ return Collections.emptyMap();
+ }
+ return attr;
+ }
+
+ /**
+ * Non-null list of comments
+ */
+ public List<IssueComment> comments() {
+ List<IssueComment> comments = new ArrayList<IssueComment>();
+ List<Map> jsonComments = (List<Map>) json.get("comments");
+ if (jsonComments != null) {
+ for (Map jsonComment : jsonComments) {
+ comments.add(new DefaultIssueComment(jsonComment));
+ }
+ }
+ return comments;
+ }
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueClient.java
index 4dd1972e2ba..c4b2f326555 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueClient.java
@@ -17,15 +17,14 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
-import com.github.kevinsawicki.http.HttpRequest;
import org.json.simple.JSONValue;
import org.sonar.wsclient.internal.EncodingUtils;
import org.sonar.wsclient.internal.HttpRequestFactory;
+import org.sonar.wsclient.issue.*;
import javax.annotation.Nullable;
-
import java.util.List;
import java.util.Map;
@@ -34,122 +33,87 @@ import java.util.Map;
*/
public class DefaultIssueClient implements IssueClient {
+ private static final String SEARCH_URL = "/api/issues/search";
+
private final HttpRequestFactory requestFactory;
private final IssueJsonParser parser;
- /**
- * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance.
- */
public DefaultIssueClient(HttpRequestFactory requestFactory) {
this.requestFactory = requestFactory;
this.parser = new IssueJsonParser();
}
public Issues find(IssueQuery query) {
- HttpRequest request = requestFactory.get(IssueQuery.BASE_URL, query.urlParams());
- if (!request.ok()) {
- throw new IllegalStateException("Fail to search for issues. Bad HTTP response status: " + request.code());
- }
- String json = request.body("UTF-8");
+ String json = requestFactory.get(SEARCH_URL, query.urlParams());
return parser.parseIssues(json);
}
@Override
public Issue create(NewIssue newIssue) {
- HttpRequest request = requestFactory.post(NewIssue.BASE_URL, newIssue.urlParams());
- if (!request.ok()) {
- throw new IllegalStateException("Fail to create issue. Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/create", newIssue.urlParams());
+ return jsonToIssue(json);
}
@Override
public Issue setSeverity(String issueKey, String severity) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "severity", severity);
- HttpRequest request = requestFactory.post("/api/issues/set_severity", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to set severity. Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/set_severity", params);
+ return jsonToIssue(json);
}
@Override
public Issue assign(String issueKey, @Nullable String assignee) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "assignee", assignee);
- HttpRequest request = requestFactory.post("/api/issues/assign", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to assign issue to user. Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/assign", params);
+ return jsonToIssue(json);
}
@Override
public Issue plan(String issueKey, @Nullable String actionPlanKey) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "plan", actionPlanKey);
- HttpRequest request = requestFactory.post("/api/issues/plan", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to link action plan. Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/plan", params);
+ return jsonToIssue(json);
}
@Override
public IssueComment addComment(String issueKey, String markdownText) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "text", markdownText);
- HttpRequest request = requestFactory.post("/api/issues/add_comment", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to add issue comment. Bad HTTP response status: " + request.code());
- }
- Map rootJson = (Map) JSONValue.parse(request.body());
- return new IssueComment((Map)rootJson.get("comment"));
+ String json = requestFactory.post("/api/issues/add_comment", params);
+ Map rootJson = (Map) JSONValue.parse(json);
+ return new DefaultIssueComment((Map) rootJson.get("comment"));
}
@Override
public List<String> transitions(String issueKey) {
Map<String, Object> queryParams = EncodingUtils.toMap("issue", issueKey);
- HttpRequest request = requestFactory.get("/api/issues/transitions", queryParams);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to return transitions for issue. Bad HTTP response status: " + request.code());
- }
- String json = request.body("UTF-8");
+ String json = requestFactory.get("/api/issues/transitions", queryParams);
return parser.parseTransitions(json);
}
@Override
public Issue doTransition(String issueKey, String transition) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "transition", transition);
- HttpRequest request = requestFactory.post("/api/issues/do_transition", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to execute transition on issue " + issueKey + ".Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/do_transition", params);
+ return jsonToIssue(json);
}
@Override
public List<String> actions(String issueKey) {
Map<String, Object> queryParams = EncodingUtils.toMap("issue", issueKey);
- HttpRequest request = requestFactory.get("/api/issues/actions", queryParams);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to return actions for issue. Bad HTTP response status: " + request.code());
- }
- String json = request.body("UTF-8");
+ String json = requestFactory.get("/api/issues/actions", queryParams);
return parser.parseActions(json);
}
@Override
public Issue doAction(String issueKey, String action) {
Map<String, Object> params = EncodingUtils.toMap("issue", issueKey, "actionKey", action);
- HttpRequest request = requestFactory.post("/api/issues/do_action", params);
- if (!request.ok()) {
- throw new IllegalStateException("Fail to execute action on issue " + issueKey + ".Bad HTTP response status: " + request.code());
- }
- return createIssueResult(request);
+ String json = requestFactory.post("/api/issues/do_action", params);
+ return jsonToIssue(json);
}
- private Issue createIssueResult(HttpRequest request){
- String json = request.body("UTF-8");
+ private Issue jsonToIssue(String json) {
Map jsonRoot = (Map) JSONValue.parse(json);
- return new Issue((Map) jsonRoot.get("issue"));
+ return new DefaultIssue((Map) jsonRoot.get("issue"));
}
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueComment.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueComment.java
new file mode 100644
index 00000000000..bcd42560403
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssueComment.java
@@ -0,0 +1,53 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.issue.internal;
+
+import org.sonar.wsclient.issue.IssueComment;
+import org.sonar.wsclient.unmarshallers.JsonUtils;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class DefaultIssueComment implements IssueComment {
+ private final Map json;
+
+ DefaultIssueComment(Map json) {
+ this.json = json;
+ }
+
+ public String key() {
+ return JsonUtils.getString(json, "key");
+ }
+
+ public String htmlText() {
+ return JsonUtils.getString(json, "htmlText");
+ }
+
+ public String login() {
+ return JsonUtils.getString(json, "login");
+ }
+
+ public Date createdAt() {
+ return JsonUtils.getDateTime(json, "createdAt");
+ }
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssues.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssues.java
new file mode 100644
index 00000000000..37b5348fa88
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssues.java
@@ -0,0 +1,146 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.issue.internal;
+
+import org.sonar.wsclient.component.Component;
+import org.sonar.wsclient.issue.ActionPlan;
+import org.sonar.wsclient.issue.Issue;
+import org.sonar.wsclient.issue.Issues;
+import org.sonar.wsclient.base.Paging;
+import org.sonar.wsclient.rule.Rule;
+import org.sonar.wsclient.user.User;
+
+import javax.annotation.CheckForNull;
+import java.util.*;
+
+/**
+ * @since 3.6
+ */
+public class DefaultIssues implements Issues {
+
+ private final List<Issue> list = new ArrayList<Issue>();
+ private final Map<String, Rule> rulesByKey = new HashMap<String, Rule>();
+ private final Map<String, User> usersByKey = new HashMap<String, User>();
+ private final Map<String, Component> componentsByKey = new HashMap<String, Component>();
+ private final Map<String, Component> projectsByKey = new HashMap<String, Component>();
+ private final Map<String, ActionPlan> actionPlansByKey = new HashMap<String, ActionPlan>();
+ private Paging paging;
+ private Boolean maxResultsReached;
+
+ public List<Issue> list() {
+ return list;
+ }
+
+ public int size() {
+ return list.size();
+ }
+
+ public Collection<Rule> rules() {
+ return rulesByKey.values();
+ }
+
+ public Rule rule(Issue issue) {
+ return rulesByKey.get(issue.ruleKey());
+ }
+
+ public Collection<User> users() {
+ return usersByKey.values();
+ }
+
+ @CheckForNull
+ public User user(String login) {
+ return usersByKey.get(login);
+ }
+
+ public Collection<Component> components() {
+ return componentsByKey.values();
+ }
+
+ @CheckForNull
+ public Component component(Issue issue) {
+ return componentsByKey.get(issue.componentKey());
+ }
+
+ public Collection<Component> projects() {
+ return projectsByKey.values();
+ }
+
+ @CheckForNull
+ public Component project(Issue issue) {
+ return projectsByKey.get(issue.projectKey());
+ }
+
+ public Collection<ActionPlan> actionPlans() {
+ return actionPlansByKey.values();
+ }
+
+ @CheckForNull
+ public ActionPlan actionPlans(Issue issue) {
+ return actionPlansByKey.get(issue.actionPlan());
+ }
+
+ public Paging paging() {
+ return paging;
+ }
+
+ public Boolean maxResultsReached() {
+ return maxResultsReached;
+ }
+
+ DefaultIssues add(Issue issue) {
+ list.add(issue);
+ return this;
+ }
+
+ DefaultIssues add(Rule rule) {
+ rulesByKey.put(rule.key(), rule);
+ return this;
+ }
+
+ DefaultIssues add(User user) {
+ usersByKey.put(user.login(), user);
+ return this;
+ }
+
+ DefaultIssues add(ActionPlan actionPlan) {
+ actionPlansByKey.put(actionPlan.key(), actionPlan);
+ return this;
+ }
+
+ DefaultIssues addComponent(Component c) {
+ componentsByKey.put(c.key(), c);
+ return this;
+ }
+
+ DefaultIssues addProject(Component c) {
+ projectsByKey.put(c.key(), c);
+ return this;
+ }
+
+ DefaultIssues setPaging(Paging paging) {
+ this.paging = paging;
+ return this;
+ }
+
+ DefaultIssues setMaxResultsReached(Boolean maxResultsReached) {
+ this.maxResultsReached = maxResultsReached;
+ return this;
+ }
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/IssueJsonParser.java
index 906929ce308..d123e9779cb 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/IssueJsonParser.java
@@ -17,10 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
import org.json.simple.JSONValue;
import org.sonar.wsclient.component.Component;
+import org.sonar.wsclient.issue.Issues;
+import org.sonar.wsclient.base.Paging;
import org.sonar.wsclient.rule.Rule;
import org.sonar.wsclient.unmarshallers.JsonUtils;
import org.sonar.wsclient.user.User;
@@ -32,15 +34,15 @@ import java.util.Map;
/**
* @since 3.6
*/
-class IssueJsonParser {
+public class IssueJsonParser {
- Issues parseIssues(String json) {
- Issues result = new Issues();
+ public Issues parseIssues(String json) {
+ DefaultIssues result = new DefaultIssues();
Map jsonRoot = (Map) JSONValue.parse(json);
- List<Map> jsonIssues = (List) jsonRoot.get("issues");
+ List<Map> jsonIssues = (List<Map>) jsonRoot.get("issues");
if (jsonIssues != null) {
for (Map jsonIssue : jsonIssues) {
- result.add(new Issue(jsonIssue));
+ result.add(new DefaultIssue(jsonIssue));
}
}
parseRules(result, jsonRoot);
@@ -52,14 +54,14 @@ class IssueJsonParser {
return result;
}
- private void parsePaging(Issues result, Map jsonRoot) {
+ private void parsePaging(DefaultIssues result, Map jsonRoot) {
Map paging = (Map) jsonRoot.get("paging");
result.setPaging(new Paging(paging));
result.setMaxResultsReached(JsonUtils.getBoolean(jsonRoot, "maxResultsReached"));
}
- private void parseProjects(Issues result, Map jsonRoot) {
- List<Map> jsonProjects = (List) jsonRoot.get("projects");
+ private void parseProjects(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonProjects = (List<Map>) jsonRoot.get("projects");
if (jsonProjects != null) {
for (Map jsonProject : jsonProjects) {
result.addProject(new Component(jsonProject));
@@ -67,8 +69,8 @@ class IssueJsonParser {
}
}
- private void parseComponents(Issues result, Map jsonRoot) {
- List<Map> jsonComponents = (List) jsonRoot.get("components");
+ private void parseComponents(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonComponents = (List<Map>) jsonRoot.get("components");
if (jsonComponents != null) {
for (Map jsonComponent : jsonComponents) {
result.addComponent(new Component(jsonComponent));
@@ -76,8 +78,8 @@ class IssueJsonParser {
}
}
- private void parseUsers(Issues result, Map jsonRoot) {
- List<Map> jsonUsers = (List) jsonRoot.get("users");
+ private void parseUsers(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonUsers = (List<Map>) jsonRoot.get("users");
if (jsonUsers != null) {
for (Map jsonUser : jsonUsers) {
result.add(new User(jsonUser));
@@ -85,8 +87,8 @@ class IssueJsonParser {
}
}
- private void parseRules(Issues result, Map jsonRoot) {
- List<Map> jsonRules = (List) jsonRoot.get("rules");
+ private void parseRules(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonRules = (List<Map>) jsonRoot.get("rules");
if (jsonRules != null) {
for (Map jsonRule : jsonRules) {
result.add(new Rule(jsonRule));
@@ -94,11 +96,11 @@ class IssueJsonParser {
}
}
- private void parseActionPlans(Issues result, Map jsonRoot) {
+ private void parseActionPlans(DefaultIssues result, Map jsonRoot) {
List<Map> jsonRules = (List) jsonRoot.get("actionPlans");
if (jsonRules != null) {
for (Map jsonRule : jsonRules) {
- result.add(new ActionPlan(jsonRule));
+ result.add(new DefaultActionPlan(jsonRule));
}
}
}
@@ -106,7 +108,7 @@ class IssueJsonParser {
List<String> parseTransitions(String json) {
List<String> transitions = new ArrayList<String>();
Map jRoot = (Map) JSONValue.parse(json);
- List<String> jTransitions = (List) jRoot.get("transitions");
+ List<String> jTransitions = (List<String>) jRoot.get("transitions");
for (String jTransition : jTransitions) {
transitions.add(jTransition);
}
@@ -116,7 +118,7 @@ class IssueJsonParser {
List<String> parseActions(String json) {
List<String> actions = new ArrayList<String>();
Map jRoot = (Map) JSONValue.parse(json);
- List<String> jActions = (List) jRoot.get("actions");
+ List<String> jActions = (List<String>) jRoot.get("actions");
for (String jAction : jActions) {
actions.add(jAction);
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/package-info.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/package-info.java
new file mode 100644
index 00000000000..bd54aab693e
--- /dev/null
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.wsclient.issue.internal; \ No newline at end of file
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java
index fd842df823c..b7c60866991 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java
@@ -19,7 +19,6 @@
*/
package org.sonar.wsclient.user;
-import com.github.kevinsawicki.http.HttpRequest;
import org.json.simple.JSONValue;
import org.sonar.wsclient.internal.HttpRequestFactory;
@@ -43,14 +42,10 @@ public class DefaultUserClient implements UserClient {
@Override
public List<User> find(UserQuery query) {
- HttpRequest request = requestFactory.get(UserQuery.BASE_URL, query.urlParams());
- if (!request.ok()) {
- throw new IllegalStateException("Fail to search for users. Bad HTTP response status: " + request.code());
- }
+ String json = requestFactory.get(UserQuery.BASE_URL, query.urlParams());
List<User> result = new ArrayList<User>();
- String json = request.body("UTF-8");
Map jsonRoot = (Map) JSONValue.parse(json);
- List<Map> jsonUsers = (List) jsonRoot.get("users");
+ List<Map> jsonUsers = (List<Map>) jsonRoot.get("users");
if (jsonUsers != null) {
for (Map jsonUser : jsonUsers) {
result.add(new User(jsonUser));
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java
index 8216d88767e..74b601c3f3d 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java
@@ -20,8 +20,8 @@
package org.sonar.wsclient;
import org.junit.Test;
-import org.sonar.wsclient.issue.DefaultActionPlanClient;
-import org.sonar.wsclient.issue.DefaultIssueClient;
+import org.sonar.wsclient.issue.internal.DefaultActionPlanClient;
+import org.sonar.wsclient.issue.internal.DefaultIssueClient;
import org.sonar.wsclient.user.DefaultUserClient;
import static org.fest.assertions.Assertions.assertThat;
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/base/HttpExceptionTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/base/HttpExceptionTest.java
new file mode 100644
index 00000000000..d0a41a02cf2
--- /dev/null
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/base/HttpExceptionTest.java
@@ -0,0 +1,34 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.wsclient.base;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class HttpExceptionTest {
+ @Test
+ public void test_exception() throws Exception {
+ HttpException exception = new HttpException("http://localhost:9000/api/search", 500);
+ assertThat(exception.status()).isEqualTo(500);
+ assertThat(exception.url()).isEqualTo("http://localhost:9000/api/search");
+ assertThat(exception.getMessage()).isEqualTo("Error 500 on http://localhost:9000/api/search");
+ }
+}
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java
index 0006ad7295b..9969090a1ee 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java
@@ -19,20 +19,21 @@
*/
package org.sonar.wsclient.internal;
-import com.github.kevinsawicki.http.HttpRequest;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.MockHttpServerInterceptor;
-import org.sonar.wsclient.issue.DefaultIssueClient;
import org.sonar.wsclient.issue.IssueClient;
import org.sonar.wsclient.issue.IssueQuery;
+import org.sonar.wsclient.issue.internal.DefaultIssueClient;
+import java.net.ConnectException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
public class HttpRequestFactoryTest {
@Rule
@@ -40,56 +41,62 @@ public class HttpRequestFactoryTest {
@Test
public void test_get() {
- httpServer.doReturnStatus(200).doReturnBody("list of issues");
+ httpServer.doReturnStatus(200).doReturnBody("{'issues': []}");
HttpRequestFactory factory = new HttpRequestFactory(httpServer.url());
- HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
+ String json = factory.get("/api/issues", Collections.<String, Object>emptyMap());
- assertThat(request.method()).isEqualTo("GET");
- assertThat(request.body()).isEqualTo("list of issues");
- assertThat(request.code()).isEqualTo(200);
+ assertThat(json).isEqualTo("{'issues': []}");
assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
}
@Test
+ public void should_throw_illegal_state_exc_if_connect_exception() {
+ HttpRequestFactory factory = new HttpRequestFactory("http://localhost:1");
+ try {
+ factory.get("/api/issues", Collections.<String, Object>emptyMap());
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class);
+ assertThat(e).hasMessage("java.net.ConnectException: Connection refused");
+ }
+ }
+
+ @Test
public void test_post() {
- httpServer.doReturnStatus(200);
+ httpServer.doReturnStatus(200).doReturnBody("{}");
HttpRequestFactory factory = new HttpRequestFactory(httpServer.url());
- HttpRequest request = factory.post("/api/issues/change", Collections.<String, Object>emptyMap());
+ String json = factory.post("/api/issues/change", Collections.<String, Object>emptyMap());
- assertThat(request.method()).isEqualTo("POST");
- assertThat(request.code()).isEqualTo(200);
+ assertThat(json).isEqualTo("{}");
assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/change");
}
@Test
public void test_authentication() {
- httpServer.doReturnStatus(200).doReturnBody("list of issues");
+ httpServer.doReturnStatus(200).doReturnBody("{}");
HttpRequestFactory factory = new HttpRequestFactory(httpServer.url()).setLogin("karadoc").setPassword("legrascestlavie");
- HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
+ String json = factory.get("/api/issues", Collections.<String, Object>emptyMap());
- assertThat(request.body()).isEqualTo("list of issues");
- assertThat(request.code()).isEqualTo(200);
+ assertThat(json).isEqualTo("{}");
assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
assertThat(httpServer.requestHeaders().get("Authorization")).isEqualTo("Basic a2FyYWRvYzpsZWdyYXNjZXN0bGF2aWU=");
}
@Test
public void test_proxy() throws Exception {
- HttpRequestFactory factory = new HttpRequestFactory(httpServer.url()).setProxyHost("localhost").setProxyPort(5020);
- HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
- // it's not possible to check that the proxy is correctly configured
- }
-
- @Test
- public void test_proxy_credentials() throws Exception {
HttpRequestFactory factory = new HttpRequestFactory(httpServer.url())
- .setProxyHost("localhost").setProxyPort(5020)
+ .setProxyHost("localhost").setProxyPort(1)
.setProxyLogin("john").setProxyPassword("smith");
- HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
- // it's not possible to check that the proxy is correctly configured
+ try {
+ factory.get("/api/issues", Collections.<String, Object>emptyMap());
+ fail();
+ } catch (IllegalStateException e) {
+ // it's not possible to check that the proxy is correctly configured
+ assertThat(e.getCause()).isInstanceOf(ConnectException.class);
+ }
}
@Test
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
index bd1ddc18e01..941894aee78 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
@@ -21,6 +21,9 @@ package org.sonar.wsclient.issue;
import org.junit.Test;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.MapAssert.entry;
@@ -32,7 +35,8 @@ public class IssueQueryTest {
}
@Test
- public void get_all_issues_by_parameter() {
+ public void get_all_issues_by_parameter() throws ParseException {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
IssueQuery query = IssueQuery.create()
.issues("ABCDE", "FGHIJ")
.assignees("arthur", "perceval")
@@ -47,12 +51,14 @@ public class IssueQueryTest {
.statuses("OPEN", "CLOSED")
.severities("BLOCKER", "INFO")
.reporters("login1", "login2")
+ .createdBefore(df.parse("2015-12-13T05:59"))
+ .createdAfter(df.parse("2012-01-23T13:40"))
.sort("ASSIGNEE")
.asc(false)
.pageSize(5)
.pageIndex(4);
- assertThat(query.urlParams()).hasSize(17);
+ assertThat(query.urlParams()).hasSize(19);
assertThat(query.urlParams()).includes(entry("issues", "ABCDE,FGHIJ"));
assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval"));
assertThat(query.urlParams()).includes(entry("assigned", true));
@@ -66,6 +72,8 @@ public class IssueQueryTest {
assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED"));
assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO"));
assertThat(query.urlParams()).includes(entry("reporters", "login1,login2"));
+ assertThat((String)query.urlParams().get("createdBefore")).startsWith("2015-12-13T05:59");
+ assertThat((String)query.urlParams().get("createdAfter")).startsWith("2012-01-23T13:40:00");
assertThat(query.urlParams()).includes(entry("sort", "ASSIGNEE"));
assertThat(query.urlParams()).includes(entry("asc", false));
assertThat(query.urlParams()).includes(entry("pageSize", 5));
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultActionPlanClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClientTest.java
index e56572fc2b1..2e74730df14 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultActionPlanClientTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultActionPlanClientTest.java
@@ -18,12 +18,17 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.MockHttpServerInterceptor;
+import org.sonar.wsclient.base.HttpException;
import org.sonar.wsclient.internal.HttpRequestFactory;
+import org.sonar.wsclient.issue.ActionPlan;
+import org.sonar.wsclient.issue.ActionPlanClient;
+import org.sonar.wsclient.issue.NewActionPlan;
+import org.sonar.wsclient.issue.UpdateActionPlan;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -115,8 +120,10 @@ public class DefaultActionPlanClientTest {
try {
client.delete("382f6f2e-ad9d-424a-b973-9b065e04348a");
fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("Fail to delete action plan. Bad HTTP response status: 500");
+ } catch (HttpException e) {
+ assertThat(e.status()).isEqualTo(500);
+ assertThat(e.url()).startsWith("http://localhost");
+ assertThat(e.url()).endsWith("/api/action_plans/delete?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
}
}
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java
index 7ad6f6df3c8..d262073e26e 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java
@@ -17,13 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.MockHttpServerInterceptor;
+import org.sonar.wsclient.base.HttpException;
import org.sonar.wsclient.internal.HttpRequestFactory;
+import org.sonar.wsclient.issue.*;
+import org.sonar.wsclient.issue.internal.DefaultIssueClient;
import java.util.List;
@@ -57,8 +60,10 @@ public class DefaultIssueClientTest {
try {
client.find(IssueQuery.create());
fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("Fail to search for issues. Bad HTTP response status: 500");
+ } catch (HttpException e) {
+ assertThat(e.status()).isEqualTo(500);
+ assertThat(e.url()).startsWith("http://localhost");
+ assertThat(e.url()).endsWith("/api/issues/search");
}
}
@@ -167,7 +172,7 @@ public class DefaultIssueClientTest {
@Test
public void should_add_comment() throws Exception {
HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody(IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/DefaultIssueClientTest/add_comment_result.json")));
+ httpServer.doReturnBody(IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/DefaultIssueClientTest/add_comment_result.json")));
IssueClient client = new DefaultIssueClient(requestFactory);
IssueComment comment = client.addComment("ISSUE-1", "this is my comment");
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java
index 09cb3941742..c84bfe8c001 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java
@@ -17,11 +17,17 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.wsclient.issue;
+package org.sonar.wsclient.issue.internal;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
+import org.sonar.wsclient.base.Paging;
import org.sonar.wsclient.component.Component;
+import org.sonar.wsclient.issue.ActionPlan;
+import org.sonar.wsclient.issue.Issue;
+import org.sonar.wsclient.issue.IssueComment;
+import org.sonar.wsclient.issue.Issues;
+import org.sonar.wsclient.issue.internal.IssueJsonParser;
import org.sonar.wsclient.user.User;
import java.util.List;
@@ -31,7 +37,7 @@ import static org.fest.assertions.Assertions.assertThat;
public class IssueJsonParserTest {
@Test
public void test_GET_search() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/search.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues).isNotNull();
List<Issue> list = issues.list();
@@ -86,7 +92,7 @@ public class IssueJsonParserTest {
@Test
public void test_GET_empty_search() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/empty.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/empty.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues).isNotNull();
assertThat(issues.list()).isEmpty();
@@ -96,7 +102,7 @@ public class IssueJsonParserTest {
@Test
public void test_GET_transitions() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/getTransitions.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/getTransitions.json"));
List<String> transitions = new IssueJsonParser().parseTransitions(json);
assertThat(transitions).isNotNull();
@@ -106,7 +112,7 @@ public class IssueJsonParserTest {
@Test
public void should_parse_comments() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-comments.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-comments.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues.size()).isEqualTo(1);
@@ -128,7 +134,7 @@ public class IssueJsonParserTest {
@Test
public void should_parse_users() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-users.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-users.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues.users()).hasSize(2);
@@ -148,7 +154,7 @@ public class IssueJsonParserTest {
@Test
public void should_parse_components() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-components.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues.components()).hasSize(1);
@@ -162,7 +168,7 @@ public class IssueJsonParserTest {
@Test
public void should_parse_projects() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-projects.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-projects.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues.projects()).hasSize(1);
@@ -176,7 +182,7 @@ public class IssueJsonParserTest {
@Test
public void should_parse_action_plans() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json"));
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-action-plans.json"));
Issues issues = new IssueJsonParser().parseIssues(json);
assertThat(issues.actionPlans()).hasSize(1);
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/DefaultIssueClientTest/add_comment_result.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/DefaultIssueClientTest/add_comment_result.json
index 7329cc86d24..7329cc86d24 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/DefaultIssueClientTest/add_comment_result.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/DefaultIssueClientTest/add_comment_result.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/empty.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/empty.json
index b3712e0d503..b3712e0d503 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/empty.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/empty.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/getTransitions.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/getTransitions.json
index 0451945c9d1..0451945c9d1 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/getTransitions.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/getTransitions.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-action-plans.json
index 46718d5b39f..46718d5b39f 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-action-plans.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-comments.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-comments.json
index 5118aaee009..5118aaee009 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-comments.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-comments.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-components.json
index 2f331712d3c..2f331712d3c 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-components.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-projects.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-projects.json
index a5e4ea7cd9d..a5e4ea7cd9d 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-projects.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-projects.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-users.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-users.json
index 7d8bc6586a4..7d8bc6586a4 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-users.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-users.json
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json
index 8c8505f5d73..8c8505f5d73 100644
--- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json