<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>
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>
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;
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 {
.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();
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;
return this;
}
+ /**
+ * Build a new client
+ */
public SonarClient build() {
if (url == null || "".equals(url)) {
throw new IllegalStateException("Server URL must be set");
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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.sonar.wsclient.unmarshallers.JsonUtils;
+
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class Paging {
+
+ private final Map json;
+
+ /**
+ * For internal use
+ */
+ public Paging(Map json) {
+ this.json = json;
+ }
+
+ public Integer pageSize() {
+ return JsonUtils.getInteger(json, "pageSize");
+ }
+
+ public Integer pageIndex() {
+ return JsonUtils.getInteger(json, "pageIndex");
+ }
+
+ public Integer total() {
+ return JsonUtils.getInteger(json, "total");
+ }
+
+ public Integer pages() {
+ return JsonUtils.getInteger(json, "pages");
+ }
+
+}
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 {
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 {
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) {
if (login != null) {
request.basic(login, password);
}
- return request;
}
}
* 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();
}
*/
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>();
+++ /dev/null
-/*
- * 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;
-
-import com.github.kevinsawicki.http.HttpRequest;
-import org.json.simple.JSONValue;
-import org.sonar.wsclient.internal.EncodingUtils;
-import org.sonar.wsclient.internal.HttpRequestFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#actionPlanClient()}.
- */
-public class DefaultActionPlanClient implements ActionPlanClient {
-
- private final HttpRequestFactory requestFactory;
-
- /**
- * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance.
- */
- public DefaultActionPlanClient(HttpRequestFactory requestFactory) {
- this.requestFactory = requestFactory;
- }
-
- @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());
- }
- 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");
- if (jsonActionPlans != null) {
- for (Map jsonActionPlan : jsonActionPlans) {
- result.add(new ActionPlan(jsonActionPlan));
- }
- }
- return result;
- }
-
- @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);
- }
-
- @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);
- }
-
- @Override
- public void delete(String actionPlanKey) {
- executeSimpleAction(actionPlanKey, "delete");
- }
-
- @Override
- public ActionPlan open(String actionPlanKey) {
- HttpRequest request = executeSimpleAction(actionPlanKey, "open");
- return createActionPlanResult(request);
- }
-
- @Override
- public ActionPlan close(String actionPlanKey) {
- HttpRequest request = executeSimpleAction(actionPlanKey, "close");
- return createActionPlanResult(request);
- }
-
- 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 ActionPlan createActionPlanResult(HttpRequest request){
- String json = request.body("UTF-8");
- Map jsonRoot = (Map) JSONValue.parse(json);
- return new ActionPlan((Map) jsonRoot.get("actionPlan"));
- }
-
-}
+++ /dev/null
-/*
- * 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;
-
-import com.github.kevinsawicki.http.HttpRequest;
-import org.json.simple.JSONValue;
-import org.sonar.wsclient.internal.EncodingUtils;
-import org.sonar.wsclient.internal.HttpRequestFactory;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#issueClient()}.
- */
-public class DefaultIssueClient implements IssueClient {
-
- 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");
- 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);
- }
-
- @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);
- }
-
- @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);
- }
-
- @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);
- }
-
- @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"));
- }
-
- @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");
- 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);
- }
-
- @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");
- 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);
- }
-
- private Issue createIssueResult(HttpRequest request){
- String json = request.body("UTF-8");
- Map jsonRoot = (Map) JSONValue.parse(json);
- return new Issue((Map) jsonRoot.get("issue"));
- }
-
-}
* 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();
}
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);
* 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();
}
+++ /dev/null
-/*
- * 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;
-
-import org.json.simple.JSONValue;
-import org.sonar.wsclient.component.Component;
-import org.sonar.wsclient.rule.Rule;
-import org.sonar.wsclient.unmarshallers.JsonUtils;
-import org.sonar.wsclient.user.User;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @since 3.6
- */
-class IssueJsonParser {
-
- Issues parseIssues(String json) {
- Issues result = new Issues();
- Map jsonRoot = (Map) JSONValue.parse(json);
- List<Map> jsonIssues = (List) jsonRoot.get("issues");
- if (jsonIssues != null) {
- for (Map jsonIssue : jsonIssues) {
- result.add(new Issue(jsonIssue));
- }
- }
- parseRules(result, jsonRoot);
- parseUsers(result, jsonRoot);
- parseComponents(result, jsonRoot);
- parseProjects(result, jsonRoot);
- parseActionPlans(result, jsonRoot);
- parsePaging(result, jsonRoot);
- return result;
- }
-
- private void parsePaging(Issues 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");
- if (jsonProjects != null) {
- for (Map jsonProject : jsonProjects) {
- result.addProject(new Component(jsonProject));
- }
- }
- }
-
- private void parseComponents(Issues result, Map jsonRoot) {
- List<Map> jsonComponents = (List) jsonRoot.get("components");
- if (jsonComponents != null) {
- for (Map jsonComponent : jsonComponents) {
- result.addComponent(new Component(jsonComponent));
- }
- }
- }
-
- private void parseUsers(Issues result, Map jsonRoot) {
- List<Map> jsonUsers = (List) jsonRoot.get("users");
- if (jsonUsers != null) {
- for (Map jsonUser : jsonUsers) {
- result.add(new User(jsonUser));
- }
- }
- }
-
- private void parseRules(Issues result, Map jsonRoot) {
- List<Map> jsonRules = (List) jsonRoot.get("rules");
- if (jsonRules != null) {
- for (Map jsonRule : jsonRules) {
- result.add(new Rule(jsonRule));
- }
- }
- }
-
- private void parseActionPlans(Issues result, Map jsonRoot) {
- List<Map> jsonRules = (List) jsonRoot.get("actionPlans");
- if (jsonRules != null) {
- for (Map jsonRule : jsonRules) {
- result.add(new ActionPlan(jsonRule));
- }
- }
- }
-
- List<String> parseTransitions(String json) {
- List<String> transitions = new ArrayList<String>();
- Map jRoot = (Map) JSONValue.parse(json);
- List<String> jTransitions = (List) jRoot.get("transitions");
- for (String jTransition : jTransitions) {
- transitions.add(jTransition);
- }
- return transitions;
- }
-
- List<String> parseActions(String json) {
- List<String> actions = new ArrayList<String>();
- Map jRoot = (Map) JSONValue.parse(json);
- List<String> jActions = (List) jRoot.get("actions");
- for (String jAction : jActions) {
- actions.add(jAction);
- }
- return actions;
- }
-}
*/
public class IssueQuery {
- static final String BASE_URL = "/api/issues/search";
private final Map<String, Object> params = new HashMap<String, Object>();
private IssueQuery() {
return new IssueQuery();
}
- Map<String, Object> urlParams() {
+ /**
+ * URL query string, for internal use
+ */
+ public Map<String, Object> urlParams() {
return params;
}
* 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;
- }
}
*/
public class NewActionPlan {
- static final String BASE_URL = "/api/action_plans/create";
private final Map<String, Object> params = new HashMap<String, Object>();
private NewActionPlan() {
return new NewActionPlan();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
* @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() {
return new NewIssue();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
+++ /dev/null
-/*
- * 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;
-
-import org.sonar.wsclient.unmarshallers.JsonUtils;
-
-import java.util.Map;
-
-/**
- * @since 3.6
- * TODO move outside this package
- */
-public class Paging {
-
- private final Map json;
-
- Paging(Map json) {
- this.json = json;
- }
-
- public Integer pageSize() {
- return JsonUtils.getInteger(json, "pageSize");
- }
-
- public Integer pageIndex() {
- return JsonUtils.getInteger(json, "pageIndex");
- }
-
- public Integer total() {
- return JsonUtils.getInteger(json, "total");
- }
-
- public Integer pages() {
- return JsonUtils.getInteger(json, "pages");
- }
-
-}
*/
public class UpdateActionPlan {
- static final String BASE_URL = "/api/action_plans/update";
private final Map<String, Object> params = new HashMap<String, Object>();
private UpdateActionPlan() {
return new UpdateActionPlan();
}
- Map<String, Object> urlParams() {
+ public Map<String, Object> urlParams() {
return params;
}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
--- /dev/null
+/*
+ * 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.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;
+import java.util.Map;
+
+/**
+ * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#actionPlanClient()}.
+ */
+public class DefaultActionPlanClient implements ActionPlanClient {
+
+ private final HttpRequestFactory requestFactory;
+
+ /**
+ * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance.
+ */
+ public DefaultActionPlanClient(HttpRequestFactory requestFactory) {
+ this.requestFactory = requestFactory;
+ }
+
+ @Override
+ public List<ActionPlan> find(String projectKey) {
+ String json = requestFactory.get(ActionPlanQuery.BASE_URL, EncodingUtils.toMap("project", projectKey));
+ List<ActionPlan> result = new ArrayList<ActionPlan>();
+ Map jsonRoot = (Map) JSONValue.parse(json);
+ List<Map> jsonActionPlans = (List<Map>) jsonRoot.get("actionPlans");
+ if (jsonActionPlans != null) {
+ for (Map jsonActionPlan : jsonActionPlans) {
+ result.add(new DefaultActionPlan(jsonActionPlan));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public ActionPlan create(NewActionPlan newActionPlan) {
+ String json = requestFactory.post("/api/action_plans/create", newActionPlan.urlParams());
+ return createActionPlanResult(json);
+ }
+
+ @Override
+ public ActionPlan update(UpdateActionPlan updateActionPlan) {
+ String json = requestFactory.post("/api/action_plans/update", updateActionPlan.urlParams());
+ return createActionPlanResult(json);
+ }
+
+ @Override
+ public void delete(String actionPlanKey) {
+ executeSimpleAction(actionPlanKey, "delete");
+ }
+
+ @Override
+ public ActionPlan open(String actionPlanKey) {
+ String json = executeSimpleAction(actionPlanKey, "open");
+ return createActionPlanResult(json);
+ }
+
+ @Override
+ public ActionPlan close(String actionPlanKey) {
+ String json = executeSimpleAction(actionPlanKey, "close");
+ return createActionPlanResult(json);
+ }
+
+ private String executeSimpleAction(String actionPlanKey, String action) {
+ return requestFactory.post("/api/action_plans/" + action, EncodingUtils.toMap("key", actionPlanKey));
+ }
+
+ private ActionPlan createActionPlanResult(String json) {
+ Map jsonRoot = (Map) JSONValue.parse(json);
+ return new DefaultActionPlan((Map) jsonRoot.get("actionPlan"));
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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.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;
+
+/**
+ * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#issueClient()}.
+ */
+public class DefaultIssueClient implements IssueClient {
+
+ private static final String SEARCH_URL = "/api/issues/search";
+
+ private final HttpRequestFactory requestFactory;
+ private final IssueJsonParser parser;
+
+ public DefaultIssueClient(HttpRequestFactory requestFactory) {
+ this.requestFactory = requestFactory;
+ this.parser = new IssueJsonParser();
+ }
+
+ public Issues find(IssueQuery query) {
+ String json = requestFactory.get(SEARCH_URL, query.urlParams());
+ return parser.parseIssues(json);
+ }
+
+ @Override
+ public Issue create(NewIssue newIssue) {
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ String json = requestFactory.post("/api/issues/do_action", params);
+ return jsonToIssue(json);
+ }
+
+ private Issue jsonToIssue(String json) {
+ Map jsonRoot = (Map) JSONValue.parse(json);
+ return new DefaultIssue((Map) jsonRoot.get("issue"));
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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.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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class IssueJsonParser {
+
+ public Issues parseIssues(String json) {
+ DefaultIssues result = new DefaultIssues();
+ Map jsonRoot = (Map) JSONValue.parse(json);
+ List<Map> jsonIssues = (List<Map>) jsonRoot.get("issues");
+ if (jsonIssues != null) {
+ for (Map jsonIssue : jsonIssues) {
+ result.add(new DefaultIssue(jsonIssue));
+ }
+ }
+ parseRules(result, jsonRoot);
+ parseUsers(result, jsonRoot);
+ parseComponents(result, jsonRoot);
+ parseProjects(result, jsonRoot);
+ parseActionPlans(result, jsonRoot);
+ parsePaging(result, jsonRoot);
+ return result;
+ }
+
+ 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(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonProjects = (List<Map>) jsonRoot.get("projects");
+ if (jsonProjects != null) {
+ for (Map jsonProject : jsonProjects) {
+ result.addProject(new Component(jsonProject));
+ }
+ }
+ }
+
+ 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));
+ }
+ }
+ }
+
+ 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));
+ }
+ }
+ }
+
+ 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));
+ }
+ }
+ }
+
+ private void parseActionPlans(DefaultIssues result, Map jsonRoot) {
+ List<Map> jsonRules = (List) jsonRoot.get("actionPlans");
+ if (jsonRules != null) {
+ for (Map jsonRule : jsonRules) {
+ result.add(new DefaultActionPlan(jsonRule));
+ }
+ }
+ }
+
+ List<String> parseTransitions(String json) {
+ List<String> transitions = new ArrayList<String>();
+ Map jRoot = (Map) JSONValue.parse(json);
+ List<String> jTransitions = (List<String>) jRoot.get("transitions");
+ for (String jTransition : jTransitions) {
+ transitions.add(jTransition);
+ }
+ return transitions;
+ }
+
+ List<String> parseActions(String json) {
+ List<String> actions = new ArrayList<String>();
+ Map jRoot = (Map) JSONValue.parse(json);
+ List<String> jActions = (List<String>) jRoot.get("actions");
+ for (String jAction : jActions) {
+ actions.add(jAction);
+ }
+ return actions;
+ }
+}
--- /dev/null
+/*
+ * 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
*/
package org.sonar.wsclient.user;
-import com.github.kevinsawicki.http.HttpRequest;
import org.json.simple.JSONValue;
import org.sonar.wsclient.internal.HttpRequestFactory;
@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));
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;
--- /dev/null
+/*
+ * 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");
+ }
+}
*/
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
@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
+++ /dev/null
-/*
- * 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;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.wsclient.MockHttpServerInterceptor;
-import org.sonar.wsclient.internal.HttpRequestFactory;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class DefaultActionPlanClientTest {
-
- @Rule
- public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
-
- @Test
- public void should_find_action_plans() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"actionPlans\": [{\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\",\n" +
- "\"name\": \"Long term\",\n" +
- "\"status\": \"CLOSED\",\n" +
- "\"project\": \"com.sonarsource.it.samples:simple-sample\",\n" +
- "\"userLogin\": \"admin\",\n" +
- "\"deadLine\": \"2013-05-30T00:00:00+0200\",\n" +
- "\"totalIssues\": 3,\n" +
- "\"unresolvedIssues\": 2,\n" +
- "\"createdAt\": \"2013-05-13T12:50:29+0200\",\n" +
- "\"updatedAt\": \"2013-05-13T12:50:44+0200\"}]}");
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- List<ActionPlan> actionPlans = client.find("com.sonarsource.it.samples:simple-sample");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/search?project=com.sonarsource.it.samples:simple-sample");
- assertThat(actionPlans).hasSize(1);
- ActionPlan actionPlan = actionPlans.get(0);
- assertThat(actionPlan.key()).isEqualTo("382f6f2e-ad9d-424a-b973-9b065e04348a");
- assertThat(actionPlan.name()).isEqualTo("Long term");
- assertThat(actionPlan.project()).isEqualTo("com.sonarsource.it.samples:simple-sample");
- assertThat(actionPlan.status()).isEqualTo("CLOSED");
- assertThat(actionPlan.userLogin()).isEqualTo("admin");
- assertThat(actionPlan.deadLine()).isNotNull();
- assertThat(actionPlan.totalIssues()).isEqualTo(3);
- assertThat(actionPlan.unresolvedIssues()).isEqualTo(2);
- assertThat(actionPlan.createdAt()).isNotNull();
- assertThat(actionPlan.updatedAt()).isNotNull();
- }
-
- @Test
- public void should_create_action_plan() throws Exception {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- ActionPlan result = client.create(
- NewActionPlan.create().name("Short term").project("org.sonar.Sample").description("Short term issues").deadLine(stringToDate("2014-01-01")));
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/create?project=org.sonar.Sample&description=Short%20term%20issues&name=Short%20term&deadLine=2014-01-01");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_update_action_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- ActionPlan result = client.update(
- UpdateActionPlan.create().key("382f6f2e-ad9d-424a-b973-9b065e04348a").name("Short term").description("Short term issues").deadLine(stringToDate("2014-01-01")));
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/update?description=Short%20term%20issues&name=Short%20term&deadLine=2014-01-01&key=382f6f2e-ad9d-424a-b973-9b065e04348a");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_delete_action_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- client.delete("382f6f2e-ad9d-424a-b973-9b065e04348a");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/delete?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
- }
-
- @Test
- public void should_fail_to_delete_action_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnStatus(500);
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- 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");
- }
- }
-
- @Test
- public void should_open_action_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- ActionPlan result = client.open("382f6f2e-ad9d-424a-b973-9b065e04348a");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/open?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_close_action_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
-
- ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
- ActionPlan result = client.close("382f6f2e-ad9d-424a-b973-9b065e04348a");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/close?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
- assertThat(result).isNotNull();
- }
-
- private static Date stringToDate(String sDate) {
- try {
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-dd-MM");
- return sdf.parse(sDate);
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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;
-
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.wsclient.MockHttpServerInterceptor;
-import org.sonar.wsclient.internal.HttpRequestFactory;
-
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class DefaultIssueClientTest {
- @Rule
- public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
-
- @Test
- public void should_find_issues() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issues\": [{\"key\": \"ABCDE\"}]}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- IssueQuery query = IssueQuery.create().issues("ABCDE");
- Issues issues = client.find(query);
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/search?issues=ABCDE");
- assertThat(issues.list()).hasSize(1);
- assertThat(issues.list().get(0).key()).isEqualTo("ABCDE");
- }
-
- @Test
- public void should_fail_to_find_issues() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnStatus(500);
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- try {
- client.find(IssueQuery.create());
- fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("Fail to search for issues. Bad HTTP response status: 500");
- }
- }
-
- @Test
- public void should_set_severity() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.setSeverity("ABCDE", "BLOCKER");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/set_severity?issue=ABCDE&severity=BLOCKER");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_assign() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.assign("ABCDE", "emmerik");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/assign?issue=ABCDE&assignee=emmerik");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_unassign() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.assign("ABCDE", null);
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/assign?issue=ABCDE");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_plan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.plan("ABCDE", "DEFGH");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/plan?issue=ABCDE&plan=DEFGH");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_unplan() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.plan("ABCDE", null);
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/plan?issue=ABCDE");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_create_issue() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.create(NewIssue.create().component("Action.java").rule("squid:AvoidCycle"));
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/create?component=Action.java&rule=squid:AvoidCycle");
- assertThat(result).isNotNull();
- }
-
- @Test
- public void should_get_transitions() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\n" +
- " \"transitions\": [\n" +
- " \"resolve\",\n" +
- " \"falsepositive\"\n" +
- " ]\n" +
- "}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- List<String> transitions = client.transitions("ABCDE");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/transitions?issue=ABCDE");
- assertThat(transitions).hasSize(2);
- assertThat(transitions).containsOnly("resolve", "falsepositive");
- }
-
- @Test
- public void should_apply_transition() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.doTransition("ABCDE", "resolve");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/do_transition?issue=ABCDE&transition=resolve");
- assertThat(result).isNotNull();
- }
-
- @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")));
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- IssueComment comment = client.addComment("ISSUE-1", "this is my comment");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/add_comment?issue=ISSUE-1&text=this%20is%20my%20comment");
- assertThat(comment).isNotNull();
- assertThat(comment.key()).isEqualTo("COMMENT-123");
- assertThat(comment.htmlText()).isEqualTo("this is my comment");
- assertThat(comment.login()).isEqualTo("admin");
- assertThat(comment.createdAt().getDate()).isEqualTo(18);
- }
-
- @Test
- public void should_get_actions() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\n" +
- " \"actions\": [\n" +
- " \"link-to-jira\",\n" +
- " \"tweet\"\n" +
- " ]\n" +
- "}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- List<String> actions = client.actions("ABCDE");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/actions?issue=ABCDE");
- assertThat(actions).hasSize(2);
- assertThat(actions).containsOnly("link-to-jira", "tweet");
- }
-
- @Test
- public void should_apply_action() {
- HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
- httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
-
- IssueClient client = new DefaultIssueClient(requestFactory);
- Issue result = client.doAction("ABCDE", "tweet");
-
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/do_action?issue=ABCDE&actionKey=tweet");
- assertThat(result).isNotNull();
- }
-}
+++ /dev/null
-/*
- * 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;
-
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.sonar.wsclient.component.Component;
-import org.sonar.wsclient.user.User;
-
-import java.util.List;
-
-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"));
- Issues issues = new IssueJsonParser().parseIssues(json);
- assertThat(issues).isNotNull();
- List<Issue> list = issues.list();
- assertThat(list).hasSize(2);
- Issue first = list.get(0);
- assertThat(first.key()).isEqualTo("ABCDE");
- assertThat(first.componentKey()).isEqualTo("Action.java");
- assertThat(first.projectKey()).isEqualTo("struts");
- assertThat(first.ruleKey()).isEqualTo("squid:CycleBetweenPackages");
- assertThat(first.severity()).isEqualTo("CRITICAL");
- assertThat(first.line()).isEqualTo(10);
- assertThat(first.resolution()).isEqualTo("FIXED");
- assertThat(first.status()).isEqualTo("OPEN");
- assertThat(first.assignee()).isEqualTo("karadoc");
- assertThat(first.message()).isEqualTo("the message");
- assertThat(first.effortToFix()).isEqualTo(4.2);
- assertThat(first.reporter()).isEqualTo("perceval");
- assertThat(first.author()).isEqualTo("pirlouis");
- assertThat(first.actionPlan()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491");
- assertThat(first.creationDate()).isNotNull();
- assertThat(first.updateDate()).isNotNull();
- assertThat(first.closeDate()).isNotNull();
- assertThat(first.attribute("JIRA")).isEqualTo("FOO-1234");
- assertThat(first.attribute("OTHER")).isNull();
- assertThat(first.attributes()).hasSize(1);
- assertThat(first.comments()).isEmpty();
-
- Issue second = list.get(1);
- assertThat(second.key()).isEqualTo("FGHIJ");
- assertThat(second.line()).isNull();
- assertThat(second.effortToFix()).isNull();
- assertThat(second.reporter()).isNull();
- assertThat(second.author()).isNull();
- assertThat(second.attribute("JIRA")).isNull();
- assertThat(second.attributes()).isEmpty();
- assertThat(second.comments()).isEmpty();
-
- assertThat(issues.rules()).hasSize(2);
- assertThat(issues.rule(first).key()).isEqualTo("squid:CycleBetweenPackages");
- assertThat(issues.rule(first).name()).isEqualTo("Avoid cycle between java packages");
- assertThat(issues.rule(first).description()).contains("When several packages");
-
- assertThat(issues.paging()).isNotNull();
- Paging paging = issues.paging();
- assertThat(paging.pageIndex()).isEqualTo(1);
- assertThat(paging.pageSize()).isEqualTo(100);
- assertThat(paging.pages()).isEqualTo(1);
- assertThat(paging.total()).isEqualTo(2);
-
- assertThat(issues.maxResultsReached()).isTrue();
- }
-
- @Test
- public void test_GET_empty_search() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/empty.json"));
- Issues issues = new IssueJsonParser().parseIssues(json);
- assertThat(issues).isNotNull();
- assertThat(issues.list()).isEmpty();
- assertThat(issues.rules()).isEmpty();
- assertThat(issues.maxResultsReached()).isFalse();
- }
-
- @Test
- public void test_GET_transitions() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/getTransitions.json"));
- List<String> transitions = new IssueJsonParser().parseTransitions(json);
-
- assertThat(transitions).isNotNull();
- assertThat(transitions).hasSize(2);
- assertThat(transitions).containsOnly("resolve", "falsepositive");
- }
-
- @Test
- public void should_parse_comments() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-comments.json"));
- Issues issues = new IssueJsonParser().parseIssues(json);
- assertThat(issues.size()).isEqualTo(1);
-
- Issue issue = issues.list().get(0);
- assertThat(issue.comments()).hasSize(2);
-
- IssueComment firstComment = issue.comments().get(0);
- assertThat(firstComment.key()).isEqualTo("COMMENT-1");
- assertThat(firstComment.login()).isEqualTo("morgan");
- assertThat(firstComment.htmlText()).isEqualTo("the first comment");
- assertThat(firstComment.createdAt().getDate()).isEqualTo(18);
-
- IssueComment secondComment = issue.comments().get(1);
- assertThat(secondComment.key()).isEqualTo("COMMENT-2");
- assertThat(secondComment.login()).isEqualTo("arthur");
- assertThat(secondComment.htmlText()).isEqualTo("the second comment");
- assertThat(secondComment.createdAt().getDate()).isEqualTo(19);
- }
-
- @Test
- public void should_parse_users() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-users.json"));
- Issues issues = new IssueJsonParser().parseIssues(json);
-
- assertThat(issues.users()).hasSize(2);
-
- User morgan = issues.user("morgan");
- assertThat(morgan.login()).isEqualTo("morgan");
- assertThat(morgan.name()).isEqualTo("Morgan");
- assertThat(morgan.active()).isTrue();
- assertThat(morgan.email()).isEqualTo("mor@gan.bzh");
-
- User arthur = issues.user("arthur");
- assertThat(arthur.login()).isEqualTo("arthur");
- assertThat(arthur.name()).isEqualTo("Arthur");
- assertThat(arthur.active()).isFalse();
- assertThat(arthur.email()).isEqualTo("ar@thur.bzh");
- }
-
- @Test
- public void should_parse_components() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json"));
- Issues issues = new IssueJsonParser().parseIssues(json);
-
- assertThat(issues.components()).hasSize(1);
-
- Component component = issues.component(issues.list().get(0));
- assertThat(component.key()).isEqualTo("struts:Action.java");
- assertThat(component.qualifier()).isEqualTo("CLA");
- assertThat(component.name()).isEqualTo("Action");
- assertThat(component.longName()).isEqualTo("org.struts.Action");
- }
-
- @Test
- public void should_parse_projects() throws Exception {
- String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-projects.json"));
- Issues issues = new IssueJsonParser().parseIssues(json);
-
- assertThat(issues.projects()).hasSize(1);
-
- Component component = issues.project(issues.list().get(0));
- assertThat(component.key()).isEqualTo("struts");
- assertThat(component.qualifier()).isEqualTo("TRK");
- assertThat(component.name()).isEqualTo("Struts");
- assertThat(component.longName()).isEqualTo("org.struts");
- }
-
- @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"));
- Issues issues = new IssueJsonParser().parseIssues(json);
-
- assertThat(issues.actionPlans()).hasSize(1);
-
- ActionPlan actionPlan = issues.actionPlans(issues.list().get(0));
- assertThat(actionPlan.key()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491");
- assertThat(actionPlan.name()).isEqualTo("3.6");
- assertThat(actionPlan.status()).isEqualTo("OPEN");
- assertThat(actionPlan.project()).isEqualTo("struts");
- assertThat(actionPlan.deadLine().getTime()).isEqualTo(1369951200000l);
- assertThat(actionPlan.createdAt().getTime()).isEqualTo(1369828520000l);
- assertThat(actionPlan.updatedAt().getTime()).isEqualTo(1369828520000l);
- }
-}
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;
}
@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")
.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));
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));
--- /dev/null
+/*
+ * 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.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;
+import java.util.Date;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultActionPlanClientTest {
+
+ @Rule
+ public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
+
+ @Test
+ public void should_find_action_plans() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"actionPlans\": [{\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\",\n" +
+ "\"name\": \"Long term\",\n" +
+ "\"status\": \"CLOSED\",\n" +
+ "\"project\": \"com.sonarsource.it.samples:simple-sample\",\n" +
+ "\"userLogin\": \"admin\",\n" +
+ "\"deadLine\": \"2013-05-30T00:00:00+0200\",\n" +
+ "\"totalIssues\": 3,\n" +
+ "\"unresolvedIssues\": 2,\n" +
+ "\"createdAt\": \"2013-05-13T12:50:29+0200\",\n" +
+ "\"updatedAt\": \"2013-05-13T12:50:44+0200\"}]}");
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ List<ActionPlan> actionPlans = client.find("com.sonarsource.it.samples:simple-sample");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/search?project=com.sonarsource.it.samples:simple-sample");
+ assertThat(actionPlans).hasSize(1);
+ ActionPlan actionPlan = actionPlans.get(0);
+ assertThat(actionPlan.key()).isEqualTo("382f6f2e-ad9d-424a-b973-9b065e04348a");
+ assertThat(actionPlan.name()).isEqualTo("Long term");
+ assertThat(actionPlan.project()).isEqualTo("com.sonarsource.it.samples:simple-sample");
+ assertThat(actionPlan.status()).isEqualTo("CLOSED");
+ assertThat(actionPlan.userLogin()).isEqualTo("admin");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ assertThat(actionPlan.totalIssues()).isEqualTo(3);
+ assertThat(actionPlan.unresolvedIssues()).isEqualTo(2);
+ assertThat(actionPlan.createdAt()).isNotNull();
+ assertThat(actionPlan.updatedAt()).isNotNull();
+ }
+
+ @Test
+ public void should_create_action_plan() throws Exception {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ ActionPlan result = client.create(
+ NewActionPlan.create().name("Short term").project("org.sonar.Sample").description("Short term issues").deadLine(stringToDate("2014-01-01")));
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/create?project=org.sonar.Sample&description=Short%20term%20issues&name=Short%20term&deadLine=2014-01-01");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_update_action_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ ActionPlan result = client.update(
+ UpdateActionPlan.create().key("382f6f2e-ad9d-424a-b973-9b065e04348a").name("Short term").description("Short term issues").deadLine(stringToDate("2014-01-01")));
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/update?description=Short%20term%20issues&name=Short%20term&deadLine=2014-01-01&key=382f6f2e-ad9d-424a-b973-9b065e04348a");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_delete_action_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ client.delete("382f6f2e-ad9d-424a-b973-9b065e04348a");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/delete?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
+ }
+
+ @Test
+ public void should_fail_to_delete_action_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnStatus(500);
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ try {
+ client.delete("382f6f2e-ad9d-424a-b973-9b065e04348a");
+ fail();
+ } 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");
+ }
+ }
+
+ @Test
+ public void should_open_action_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ ActionPlan result = client.open("382f6f2e-ad9d-424a-b973-9b065e04348a");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/open?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_close_action_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"actionPlan\": {\"key\": \"382f6f2e-ad9d-424a-b973-9b065e04348a\"}}");
+
+ ActionPlanClient client = new DefaultActionPlanClient(requestFactory);
+ ActionPlan result = client.close("382f6f2e-ad9d-424a-b973-9b065e04348a");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/action_plans/close?key=382f6f2e-ad9d-424a-b973-9b065e04348a");
+ assertThat(result).isNotNull();
+ }
+
+ private static Date stringToDate(String sDate) {
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-dd-MM");
+ return sdf.parse(sDate);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.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;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultIssueClientTest {
+ @Rule
+ public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
+
+ @Test
+ public void should_find_issues() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issues\": [{\"key\": \"ABCDE\"}]}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ IssueQuery query = IssueQuery.create().issues("ABCDE");
+ Issues issues = client.find(query);
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/search?issues=ABCDE");
+ assertThat(issues.list()).hasSize(1);
+ assertThat(issues.list().get(0).key()).isEqualTo("ABCDE");
+ }
+
+ @Test
+ public void should_fail_to_find_issues() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnStatus(500);
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ try {
+ client.find(IssueQuery.create());
+ fail();
+ } catch (HttpException e) {
+ assertThat(e.status()).isEqualTo(500);
+ assertThat(e.url()).startsWith("http://localhost");
+ assertThat(e.url()).endsWith("/api/issues/search");
+ }
+ }
+
+ @Test
+ public void should_set_severity() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.setSeverity("ABCDE", "BLOCKER");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/set_severity?issue=ABCDE&severity=BLOCKER");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_assign() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.assign("ABCDE", "emmerik");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/assign?issue=ABCDE&assignee=emmerik");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_unassign() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.assign("ABCDE", null);
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/assign?issue=ABCDE");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_plan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.plan("ABCDE", "DEFGH");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/plan?issue=ABCDE&plan=DEFGH");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_unplan() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.plan("ABCDE", null);
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/plan?issue=ABCDE");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_create_issue() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.create(NewIssue.create().component("Action.java").rule("squid:AvoidCycle"));
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/create?component=Action.java&rule=squid:AvoidCycle");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_get_transitions() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\n" +
+ " \"transitions\": [\n" +
+ " \"resolve\",\n" +
+ " \"falsepositive\"\n" +
+ " ]\n" +
+ "}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ List<String> transitions = client.transitions("ABCDE");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/transitions?issue=ABCDE");
+ assertThat(transitions).hasSize(2);
+ assertThat(transitions).containsOnly("resolve", "falsepositive");
+ }
+
+ @Test
+ public void should_apply_transition() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.doTransition("ABCDE", "resolve");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/do_transition?issue=ABCDE&transition=resolve");
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void should_add_comment() throws Exception {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ 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");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/add_comment?issue=ISSUE-1&text=this%20is%20my%20comment");
+ assertThat(comment).isNotNull();
+ assertThat(comment.key()).isEqualTo("COMMENT-123");
+ assertThat(comment.htmlText()).isEqualTo("this is my comment");
+ assertThat(comment.login()).isEqualTo("admin");
+ assertThat(comment.createdAt().getDate()).isEqualTo(18);
+ }
+
+ @Test
+ public void should_get_actions() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\n" +
+ " \"actions\": [\n" +
+ " \"link-to-jira\",\n" +
+ " \"tweet\"\n" +
+ " ]\n" +
+ "}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ List<String> actions = client.actions("ABCDE");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/actions?issue=ABCDE");
+ assertThat(actions).hasSize(2);
+ assertThat(actions).containsOnly("link-to-jira", "tweet");
+ }
+
+ @Test
+ public void should_apply_action() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url());
+ httpServer.doReturnBody("{\"issue\": {\"key\": \"ABCDE\"}}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ Issue result = client.doAction("ABCDE", "tweet");
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/do_action?issue=ABCDE&actionKey=tweet");
+ assertThat(result).isNotNull();
+ }
+}
--- /dev/null
+/*
+ * 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.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;
+
+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/internal/IssueJsonParserTest/search.json"));
+ Issues issues = new IssueJsonParser().parseIssues(json);
+ assertThat(issues).isNotNull();
+ List<Issue> list = issues.list();
+ assertThat(list).hasSize(2);
+ Issue first = list.get(0);
+ assertThat(first.key()).isEqualTo("ABCDE");
+ assertThat(first.componentKey()).isEqualTo("Action.java");
+ assertThat(first.projectKey()).isEqualTo("struts");
+ assertThat(first.ruleKey()).isEqualTo("squid:CycleBetweenPackages");
+ assertThat(first.severity()).isEqualTo("CRITICAL");
+ assertThat(first.line()).isEqualTo(10);
+ assertThat(first.resolution()).isEqualTo("FIXED");
+ assertThat(first.status()).isEqualTo("OPEN");
+ assertThat(first.assignee()).isEqualTo("karadoc");
+ assertThat(first.message()).isEqualTo("the message");
+ assertThat(first.effortToFix()).isEqualTo(4.2);
+ assertThat(first.reporter()).isEqualTo("perceval");
+ assertThat(first.author()).isEqualTo("pirlouis");
+ assertThat(first.actionPlan()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491");
+ assertThat(first.creationDate()).isNotNull();
+ assertThat(first.updateDate()).isNotNull();
+ assertThat(first.closeDate()).isNotNull();
+ assertThat(first.attribute("JIRA")).isEqualTo("FOO-1234");
+ assertThat(first.attribute("OTHER")).isNull();
+ assertThat(first.attributes()).hasSize(1);
+ assertThat(first.comments()).isEmpty();
+
+ Issue second = list.get(1);
+ assertThat(second.key()).isEqualTo("FGHIJ");
+ assertThat(second.line()).isNull();
+ assertThat(second.effortToFix()).isNull();
+ assertThat(second.reporter()).isNull();
+ assertThat(second.author()).isNull();
+ assertThat(second.attribute("JIRA")).isNull();
+ assertThat(second.attributes()).isEmpty();
+ assertThat(second.comments()).isEmpty();
+
+ assertThat(issues.rules()).hasSize(2);
+ assertThat(issues.rule(first).key()).isEqualTo("squid:CycleBetweenPackages");
+ assertThat(issues.rule(first).name()).isEqualTo("Avoid cycle between java packages");
+ assertThat(issues.rule(first).description()).contains("When several packages");
+
+ assertThat(issues.paging()).isNotNull();
+ Paging paging = issues.paging();
+ assertThat(paging.pageIndex()).isEqualTo(1);
+ assertThat(paging.pageSize()).isEqualTo(100);
+ assertThat(paging.pages()).isEqualTo(1);
+ assertThat(paging.total()).isEqualTo(2);
+
+ assertThat(issues.maxResultsReached()).isTrue();
+ }
+
+ @Test
+ public void test_GET_empty_search() throws Exception {
+ 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();
+ assertThat(issues.rules()).isEmpty();
+ assertThat(issues.maxResultsReached()).isFalse();
+ }
+
+ @Test
+ public void test_GET_transitions() throws Exception {
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/getTransitions.json"));
+ List<String> transitions = new IssueJsonParser().parseTransitions(json);
+
+ assertThat(transitions).isNotNull();
+ assertThat(transitions).hasSize(2);
+ assertThat(transitions).containsOnly("resolve", "falsepositive");
+ }
+
+ @Test
+ public void should_parse_comments() throws Exception {
+ 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);
+
+ Issue issue = issues.list().get(0);
+ assertThat(issue.comments()).hasSize(2);
+
+ IssueComment firstComment = issue.comments().get(0);
+ assertThat(firstComment.key()).isEqualTo("COMMENT-1");
+ assertThat(firstComment.login()).isEqualTo("morgan");
+ assertThat(firstComment.htmlText()).isEqualTo("the first comment");
+ assertThat(firstComment.createdAt().getDate()).isEqualTo(18);
+
+ IssueComment secondComment = issue.comments().get(1);
+ assertThat(secondComment.key()).isEqualTo("COMMENT-2");
+ assertThat(secondComment.login()).isEqualTo("arthur");
+ assertThat(secondComment.htmlText()).isEqualTo("the second comment");
+ assertThat(secondComment.createdAt().getDate()).isEqualTo(19);
+ }
+
+ @Test
+ public void should_parse_users() throws Exception {
+ 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);
+
+ User morgan = issues.user("morgan");
+ assertThat(morgan.login()).isEqualTo("morgan");
+ assertThat(morgan.name()).isEqualTo("Morgan");
+ assertThat(morgan.active()).isTrue();
+ assertThat(morgan.email()).isEqualTo("mor@gan.bzh");
+
+ User arthur = issues.user("arthur");
+ assertThat(arthur.login()).isEqualTo("arthur");
+ assertThat(arthur.name()).isEqualTo("Arthur");
+ assertThat(arthur.active()).isFalse();
+ assertThat(arthur.email()).isEqualTo("ar@thur.bzh");
+ }
+
+ @Test
+ public void should_parse_components() throws Exception {
+ 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);
+
+ Component component = issues.component(issues.list().get(0));
+ assertThat(component.key()).isEqualTo("struts:Action.java");
+ assertThat(component.qualifier()).isEqualTo("CLA");
+ assertThat(component.name()).isEqualTo("Action");
+ assertThat(component.longName()).isEqualTo("org.struts.Action");
+ }
+
+ @Test
+ public void should_parse_projects() throws Exception {
+ 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);
+
+ Component component = issues.project(issues.list().get(0));
+ assertThat(component.key()).isEqualTo("struts");
+ assertThat(component.qualifier()).isEqualTo("TRK");
+ assertThat(component.name()).isEqualTo("Struts");
+ assertThat(component.longName()).isEqualTo("org.struts");
+ }
+
+ @Test
+ public void should_parse_action_plans() throws Exception {
+ 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);
+
+ ActionPlan actionPlan = issues.actionPlans(issues.list().get(0));
+ assertThat(actionPlan.key()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491");
+ assertThat(actionPlan.name()).isEqualTo("3.6");
+ assertThat(actionPlan.status()).isEqualTo("OPEN");
+ assertThat(actionPlan.project()).isEqualTo("struts");
+ assertThat(actionPlan.deadLine().getTime()).isEqualTo(1369951200000l);
+ assertThat(actionPlan.createdAt().getTime()).isEqualTo(1369828520000l);
+ assertThat(actionPlan.updatedAt().getTime()).isEqualTo(1369828520000l);
+ }
+}
+++ /dev/null
-{
- "comment": {
- "key": "COMMENT-123",
- "htmlText": "this is my comment",
- "login": "admin",
- "createdAt": "2013-05-18T13:45:34+0200"
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 0,
- "pages": 0
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "transitions": [
- "resolve",
- "falsepositive"
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "struts:Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "status": "OPEN",
- "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491",
- "comments": [
- {
- "key": "COMMENT-1",
- "login": "morgan",
- "htmlText": "the first comment",
- "createdAt": "2013-05-18T13:45:34+0200"
- },
- {
- "key": "COMMENT-2",
- "login": "arthur",
- "htmlText": "the second comment",
- "createdAt": "2013-06-19T00:02:03+0100"
- }
- ]
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- }
- ],
- "components": [
- {
- "key": "struts:Action.java",
- "name": "Action",
- "qualifier": "CLA",
- "longName": "org.struts.Action"
- }
- ],
- "projects": [
- {
- "key": "struts",
- "name": "Struts",
- "qualifier": "TRK",
- "longName": "org.struts"
- }
- ],
- "actionPlans": [
- {
- "key": "9450b10c-e725-48b8-bf01-acdec751c491",
- "name": "3.6",
- "status": "OPEN",
- "project": "struts",
- "userLogin": "arthur",
- "deadLine": "2013-05-31T00:00:00+0200",
- "createdAt": "2013-05-29T13:55:20+0200",
- "updatedAt": "2013-05-29T13:55:20+0200"
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "status": "OPEN",
- "comments": [
- {
- "key": "COMMENT-1",
- "login": "morgan",
- "htmlText": "the first comment",
- "createdAt": "2013-05-18T13:45:34+0200"
- },
- {
- "key": "COMMENT-2",
- "login": "arthur",
- "htmlText": "the second comment",
- "createdAt": "2013-06-19T00:02:03+0100"
- }
- ]
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "struts:Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "status": "OPEN",
- "comments": [
- {
- "key": "COMMENT-1",
- "login": "morgan",
- "htmlText": "the first comment",
- "createdAt": "2013-05-18T13:45:34+0200"
- },
- {
- "key": "COMMENT-2",
- "login": "arthur",
- "htmlText": "the second comment",
- "createdAt": "2013-06-19T00:02:03+0100"
- }
- ]
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- }
- ],
- "components": [
- {
- "key": "struts:Action.java",
- "name": "Action",
- "qualifier": "CLA",
- "longName": "org.struts.Action"
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "struts:Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "status": "OPEN",
- "comments": [
- {
- "key": "COMMENT-1",
- "login": "morgan",
- "htmlText": "the first comment",
- "createdAt": "2013-05-18T13:45:34+0200"
- },
- {
- "key": "COMMENT-2",
- "login": "arthur",
- "htmlText": "the second comment",
- "createdAt": "2013-06-19T00:02:03+0100"
- }
- ]
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- }
- ],
- "components": [
- {
- "key": "struts:Action.java",
- "name": "Action",
- "qualifier": "CLA",
- "longName": "org.struts.Action"
- }
- ],
- "projects": [
- {
- "key": "struts",
- "name": "Struts",
- "qualifier": "TRK",
- "longName": "org.struts"
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "status": "OPEN",
- "comments": [
- {
- "key": "COMMENT-1",
- "login": "morgan",
- "htmlText": "the first comment",
- "createdAt": "2013-05-18T13:45:34+0200"
- },
- {
- "key": "COMMENT-2",
- "login": "arthur",
- "htmlText": "the second comment",
- "createdAt": "2013-06-19T00:02:03+0100"
- }
- ]
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- }
- ],
- "users": [
- {
- "login": "morgan",
- "name": "Morgan",
- "active": true,
- "email": "mor@gan.bzh"
- },
- {
- "login": "arthur",
- "name": "Arthur",
- "active": false,
- "email": "ar@thur.bzh"
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": false
-}
\ No newline at end of file
+++ /dev/null
-{
- "issues": [
- {
- "key": "ABCDE",
- "component": "Action.java",
- "project": "struts",
- "rule": "squid:CycleBetweenPackages",
- "severity": "CRITICAL",
- "line": 10,
- "resolution": "FIXED",
- "status": "OPEN",
- "assignee": "karadoc",
- "effortToFix": 4.2,
- "message": "the message",
- "title": "the title",
- "reporter": "perceval",
- "author": "pirlouis",
- "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491",
- "creationDate": "2013-05-18T12:45:34+0200",
- "updateDate": "2013-05-18T13:45:34+0200",
- "closeDate": "2013-05-18T14:45:34+0200",
- "attr": {
- "JIRA": "FOO-1234"
- }
- },
- {
- "key": "FGHIJ",
- "component": "Filter.java",
- "project": "struts",
- "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck",
- "severity": "BLOCKER",
- "resolution": "FIXED",
- "status": "OPEN"
- }
- ],
- "rules": [
- {
-
- "key": "squid:CycleBetweenPackages",
- "name": "Avoid cycle between java packages",
- "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
-
- },
- {
- "key": "checkstyle:com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck",
- "name": "Unused Imports",
- "desc": "Checks for unused import statements."
- }
- ],
- "paging": {
- "pageIndex": 1,
- "pageSize": 100,
- "total": 2,
- "pages": 1
- },
- "maxResultsReached": true
-}
\ No newline at end of file
--- /dev/null
+{
+ "comment": {
+ "key": "COMMENT-123",
+ "htmlText": "this is my comment",
+ "login": "admin",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 0,
+ "pages": 0
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "transitions": [
+ "resolve",
+ "falsepositive"
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "struts:Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "status": "OPEN",
+ "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491",
+ "comments": [
+ {
+ "key": "COMMENT-1",
+ "login": "morgan",
+ "htmlText": "the first comment",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ },
+ {
+ "key": "COMMENT-2",
+ "login": "arthur",
+ "htmlText": "the second comment",
+ "createdAt": "2013-06-19T00:02:03+0100"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ }
+ ],
+ "components": [
+ {
+ "key": "struts:Action.java",
+ "name": "Action",
+ "qualifier": "CLA",
+ "longName": "org.struts.Action"
+ }
+ ],
+ "projects": [
+ {
+ "key": "struts",
+ "name": "Struts",
+ "qualifier": "TRK",
+ "longName": "org.struts"
+ }
+ ],
+ "actionPlans": [
+ {
+ "key": "9450b10c-e725-48b8-bf01-acdec751c491",
+ "name": "3.6",
+ "status": "OPEN",
+ "project": "struts",
+ "userLogin": "arthur",
+ "deadLine": "2013-05-31T00:00:00+0200",
+ "createdAt": "2013-05-29T13:55:20+0200",
+ "updatedAt": "2013-05-29T13:55:20+0200"
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "status": "OPEN",
+ "comments": [
+ {
+ "key": "COMMENT-1",
+ "login": "morgan",
+ "htmlText": "the first comment",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ },
+ {
+ "key": "COMMENT-2",
+ "login": "arthur",
+ "htmlText": "the second comment",
+ "createdAt": "2013-06-19T00:02:03+0100"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "struts:Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "status": "OPEN",
+ "comments": [
+ {
+ "key": "COMMENT-1",
+ "login": "morgan",
+ "htmlText": "the first comment",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ },
+ {
+ "key": "COMMENT-2",
+ "login": "arthur",
+ "htmlText": "the second comment",
+ "createdAt": "2013-06-19T00:02:03+0100"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ }
+ ],
+ "components": [
+ {
+ "key": "struts:Action.java",
+ "name": "Action",
+ "qualifier": "CLA",
+ "longName": "org.struts.Action"
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "struts:Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "status": "OPEN",
+ "comments": [
+ {
+ "key": "COMMENT-1",
+ "login": "morgan",
+ "htmlText": "the first comment",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ },
+ {
+ "key": "COMMENT-2",
+ "login": "arthur",
+ "htmlText": "the second comment",
+ "createdAt": "2013-06-19T00:02:03+0100"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ }
+ ],
+ "components": [
+ {
+ "key": "struts:Action.java",
+ "name": "Action",
+ "qualifier": "CLA",
+ "longName": "org.struts.Action"
+ }
+ ],
+ "projects": [
+ {
+ "key": "struts",
+ "name": "Struts",
+ "qualifier": "TRK",
+ "longName": "org.struts"
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "status": "OPEN",
+ "comments": [
+ {
+ "key": "COMMENT-1",
+ "login": "morgan",
+ "htmlText": "the first comment",
+ "createdAt": "2013-05-18T13:45:34+0200"
+ },
+ {
+ "key": "COMMENT-2",
+ "login": "arthur",
+ "htmlText": "the second comment",
+ "createdAt": "2013-06-19T00:02:03+0100"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ }
+ ],
+ "users": [
+ {
+ "login": "morgan",
+ "name": "Morgan",
+ "active": true,
+ "email": "mor@gan.bzh"
+ },
+ {
+ "login": "arthur",
+ "name": "Arthur",
+ "active": false,
+ "email": "ar@thur.bzh"
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": false
+}
\ No newline at end of file
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "Action.java",
+ "project": "struts",
+ "rule": "squid:CycleBetweenPackages",
+ "severity": "CRITICAL",
+ "line": 10,
+ "resolution": "FIXED",
+ "status": "OPEN",
+ "assignee": "karadoc",
+ "effortToFix": 4.2,
+ "message": "the message",
+ "title": "the title",
+ "reporter": "perceval",
+ "author": "pirlouis",
+ "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491",
+ "creationDate": "2013-05-18T12:45:34+0200",
+ "updateDate": "2013-05-18T13:45:34+0200",
+ "closeDate": "2013-05-18T14:45:34+0200",
+ "attr": {
+ "JIRA": "FOO-1234"
+ }
+ },
+ {
+ "key": "FGHIJ",
+ "component": "Filter.java",
+ "project": "struts",
+ "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck",
+ "severity": "BLOCKER",
+ "resolution": "FIXED",
+ "status": "OPEN"
+ }
+ ],
+ "rules": [
+ {
+
+ "key": "squid:CycleBetweenPackages",
+ "name": "Avoid cycle between java packages",
+ "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n"
+
+ },
+ {
+ "key": "checkstyle:com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck",
+ "name": "Unused Imports",
+ "desc": "Checks for unused import statements."
+ }
+ ],
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 2,
+ "pages": 1
+ },
+ "maxResultsReached": true
+}
\ No newline at end of file