From 01084bd6dff4b699cc88fa624c784aa54cf74bbb Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 13 May 2013 18:14:00 +0200 Subject: [PATCH] SONAR-4321 export components --- .../org/sonar/core/issue/db/IssueMapper.xml | 3 ++ .../app/controllers/api/issues_controller.rb | 11 ++++ .../sonar/wsclient/component/Component.java | 50 +++++++++++++++++++ .../org/sonar/wsclient/issue/IssueParser.java | 8 +++ .../java/org/sonar/wsclient/issue/Issues.java | 16 ++++++ .../sonar/wsclient/issue/IssueParserTest.java | 17 ++++++- .../issue-with-components.json | 49 ++++++++++++++++++ 7 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/component/Component.java create mode 100644 sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index c049a8fa13e..137ca53966c 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -234,6 +234,9 @@ and i.issue_creation_date < #{createdBefore} + + order by i.id + order by diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb index 753997bbb12..fc481b2394b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb @@ -33,6 +33,7 @@ class Api::IssuesController < Api::ApiController :securityExclusions => results.securityExclusions, :paging => paging_to_hash(results.paging), :issues => results.issues.map { |issue| Issue.to_hash(issue) }, + :components => results.components.map { |component| component_to_hash(component) }, :rules => results.rules.map { |rule| Rule.to_hash(rule) }, :users => results.users.map { |user| User.to_hash(user) } } @@ -220,6 +221,16 @@ class Api::IssuesController < Api::ApiController private + def component_to_hash(component) + hash = { + :key => component.key, + :qualifier => component.qualifier + } + hash[:name] = component.name if component.name + hash[:longName] = component.longName if component.longName + hash + end + def paging_to_hash(paging) { :pageIndex => paging.pageIndex, diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/component/Component.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/component/Component.java new file mode 100644 index 00000000000..1a1114836bc --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/component/Component.java @@ -0,0 +1,50 @@ +/* + * 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.component; + +import org.sonar.wsclient.unmarshallers.JsonUtils; + +import javax.annotation.CheckForNull; +import java.util.Map; + +public class Component { + private final Map json; + + public Component(Map json) { + this.json = json; + } + + public String qualifier() { + return JsonUtils.getString(json, "qualifier"); + } + + public String key() { + return JsonUtils.getString(json, "key"); + } + + public String name() { + return JsonUtils.getString(json, "name"); + } + + @CheckForNull + public String longName() { + return JsonUtils.getString(json, "longName"); + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java index 76650508778..1bde473d793 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java @@ -20,6 +20,7 @@ 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; @@ -57,6 +58,13 @@ class IssueParser { } } + List jsonComponents = (List) jsonRoot.get("components"); + if (jsonComponents != null) { + for (Map jsonComponent : jsonComponents) { + result.add(new Component(jsonComponent)); + } + } + Map paging = (Map) jsonRoot.get("paging"); result.setPaging(new Paging(paging)); result.setSecurityExclusions(JsonUtils.getBoolean(jsonRoot, "securityExclusions")); diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java index 1b821df20b0..f3d57ebf99c 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java @@ -19,6 +19,7 @@ */ package org.sonar.wsclient.issue; +import org.sonar.wsclient.component.Component; import org.sonar.wsclient.rule.Rule; import org.sonar.wsclient.user.User; @@ -33,6 +34,7 @@ public class Issues { private final List list = new ArrayList(); private final Map rulesByKey = new HashMap(); private final Map usersByKey = new HashMap(); + private final Map componentsByKey = new HashMap(); private Paging paging; private Boolean securityExclusions; @@ -61,6 +63,15 @@ public class Issues { return usersByKey.get(login); } + public Collection components() { + return componentsByKey.values(); + } + + @CheckForNull + public Component component(Issue issue) { + return componentsByKey.get(issue.componentKey()); + } + public Paging paging() { return paging; } @@ -84,6 +95,11 @@ public class Issues { return this; } + Issues add(Component c) { + componentsByKey.put(c.key(), c); + return this; + } + Issues setPaging(Paging paging) { this.paging = paging; return this; diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java index 803da3cf185..8ac410e59e3 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java @@ -20,11 +20,10 @@ package org.sonar.wsclient.issue; import org.apache.commons.io.IOUtils; -import org.apache.http.impl.cookie.DateUtils; import org.junit.Test; +import org.sonar.wsclient.component.Component; import org.sonar.wsclient.user.User; -import java.util.Date; import java.util.List; import static org.fest.assertions.Assertions.assertThat; @@ -142,4 +141,18 @@ public class IssueParserTest { 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 IssueParser().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"); + } } diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json new file mode 100644 index 00000000000..0eae0aca856 --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-components.json @@ -0,0 +1,49 @@ +{ + "issues": [ + { + "key": "ABCDE", + "component": "struts:Action.java", + "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": "

\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

\n" + + } + ], + "components": [ + { + "key": "struts:Action.java", + "name": "Action", + "qualifier": "CLA", + "longName": "org.struts.Action" + } + ], + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 2, + "pages": 1 + }, + "securityExclusions": true +} \ No newline at end of file -- 2.39.5