@Override
protected int componentId(DefaultIssue issue) {
- Snapshot snapshot = snapshotCache.get(issue.componentKey());
+ Snapshot snapshot = getSnapshot(issue);
if (snapshot != null) {
return snapshot.getResourceId();
}
}
return resourceDto.getId().intValue();
}
+
+ @Override
+ protected int projectId(DefaultIssue issue) {
+ Snapshot snapshot = getSnapshot(issue);
+ if (snapshot != null) {
+ return snapshot.getRootProjectId();
+ }
+ throw new IllegalStateException("Unknown component: " + issue.componentKey());
+ }
+
+ private Snapshot getSnapshot(DefaultIssue issue) {
+ Snapshot snapshot = snapshotCache.get(issue.componentKey());
+ if (snapshot != null) {
+ return snapshot;
+ }
+ return null;
+ }
+
}
}
@Test
- public void should_fail_if_unknown_component() throws Exception {
- setupData("should_fail_if_unknown_component");
+ public void should_fail_to_load_component_id_if_unknown_component() throws Exception {
+ setupData("should_fail_to_load_component_id_if_unknown_component");
SnapshotCache snapshotCache = mock(SnapshotCache.class);
when(snapshotCache.get("struts:Action.java")).thenReturn(null);
}
}
+ @Test
+ public void should_load_project_id() throws Exception {
+ SnapshotCache snapshotCache = mock(SnapshotCache.class);
+ when(snapshotCache.get("struts:Action.java")).thenReturn(new Snapshot().setResourceId(123).setRootProjectId(100));
+
+ ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis()));
+ int projectId = storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java"));
+
+ assertThat(projectId).isEqualTo(100);
+ }
+
+ @Test
+ public void should_fail_to_load_project_id_if_unknown_component() throws Exception {
+ SnapshotCache snapshotCache = mock(SnapshotCache.class);
+ when(snapshotCache.get("struts:Action.java")).thenReturn(null);
+
+ ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis()));
+ try {
+ storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java"));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Unknown component: struts:Action.java");
+ }
+ }
+
static class FakeRuleFinder implements RuleFinder {
@Override
@Override
public Rule findByKey(RuleKey key) {
- Rule rule = new Rule().setRepositoryKey(key.repository()).setKey(key.rule());
+ Rule rule = Rule.create().setRepositoryKey(key.repository()).setKey(key.rule());
rule.setId(200);
return rule;
}
+++ /dev/null
-<dataset></dataset>
\ No newline at end of file
--- /dev/null
+<dataset></dataset>
\ No newline at end of file
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
private String key;
private String componentKey;
+ private String projectKey;
private RuleKey ruleKey;
private String severity;
private boolean manualSeverity = false;
return this;
}
+ public String projectKey() {
+ return projectKey;
+ }
+
+ public DefaultIssue setProjectKey(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
public RuleKey ruleKey() {
return ruleKey;
}
import org.sonar.api.rule.Severity;
import javax.annotation.Nullable;
+
import java.util.Date;
import java.util.Map;
import java.util.UUID;
public class DefaultIssueBuilder implements Issuable.IssueBuilder {
private String componentKey;
+ private String projectKey;
private RuleKey ruleKey;
private Integer line;
private String message;
return this;
}
+ public DefaultIssueBuilder projectKey(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
public DefaultIssueBuilder createdDate(@Nullable Date date) {
this.createdDate = date;
return this;
@Override
public DefaultIssue build() {
Preconditions.checkNotNull(componentKey, "Component key must be set");
+ // TODO
+ //Preconditions.checkNotNull(projectKey, "Project key must be set");
Preconditions.checkNotNull(ruleKey, "Rule key must be set");
DefaultIssue issue = new DefaultIssue();
issue.setCreationDate(date);
issue.setUpdateDate(date);
issue.setComponentKey(componentKey);
+ issue.setProjectKey(projectKey);
issue.setRuleKey(ruleKey);
issue.setMessage(message);
issue.setSeverity(Objects.firstNonNull(severity, Severity.MAJOR));
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.util.Date;
/**
private Long id;
private String kee;
private Integer resourceId;
+ private Integer projectId;
private Integer ruleId;
private String severity;
private boolean manualSeverity;
private transient String ruleKey;
private transient String ruleRepo;
private transient String componentKey;
+ private transient String projectKey;
public Long getId() {
return id;
return this;
}
+ public Integer getProjectId() {
+ return projectId;
+ }
+
+ public IssueDto setProjectId(Integer projectId) {
+ this.projectId = projectId;
+ return this;
+ }
+
public Integer getRuleId() {
return ruleId;
}
return componentKey;
}
+ public String getProjectKey() {
+ return projectKey;
+ }
+
/**
* Only for unit tests
*/
return this;
}
+ /**
+ * Only for unit tests
+ */
+ public IssueDto setProjectKey_unit_test_only(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
- public static IssueDto toDtoForInsert(DefaultIssue issue, Integer componentId, Integer ruleId, Date now) {
+ public static IssueDto toDtoForInsert(DefaultIssue issue, Integer componentId, Integer projectId, Integer ruleId, Date now) {
return new IssueDto()
.setKee(issue.key())
.setLine(issue.line())
.setAssignee(issue.assignee())
.setRuleId(ruleId)
.setResourceId(componentId)
+ .setProjectId(projectId)
.setActionPlanKey(issue.actionPlanKey())
.setIssueAttributes(issue.attributes() != null ? KeyValueFormat.format(issue.attributes()) : "")
.setAuthorLogin(issue.authorLogin())
issue.setAssignee(assignee);
issue.setAttributes(KeyValueFormat.parse(Objects.firstNonNull(issueAttributes, "")));
issue.setComponentKey(componentKey);
+ issue.setProjectKey(projectKey);
issue.setManualSeverity(manualSeverity);
issue.setRuleKey(RuleKey.of(ruleRepo, ruleKey));
issue.setActionPlanKey(actionPlanKey);
for (DefaultIssue issue : issues) {
if (issue.isNew()) {
int componentId = componentId(issue);
+ int projectId = projectId(issue);
int ruleId = ruleId(issue);
- IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, ruleId, now);
+ IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, projectId, ruleId, now);
issueMapper.insert(dto);
} else if (issue.isChanged()) {
protected abstract int componentId(DefaultIssue issue);
+ protected abstract int projectId(DefaultIssue issue);
+
private int ruleId(Issue issue) {
Rule rule = ruleFinder.findByKey(issue.ruleKey());
if (rule == null) {
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 399;
+ public static final int LAST_VERSION = 401;
public static enum Status {
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
i.id,
i.kee as kee,
i.resource_id as resourceId,
+ i.project_id as projectId,
i.rule_id as ruleId,
i.action_plan_key as actionPlanKey,
i.severity as severity,
i.updated_at as updatedAt,
r.plugin_rule_key as ruleKey,
r.plugin_name as ruleRepo,
- p.kee as componentKey
+ p.kee as componentKey,
+ root.kee as projectKey
</sql>
<sql id="sortFilter">
</sql>
<insert id="insert" parameterType="Issue" useGeneratedKeys="false" keyProperty="id">
- INSERT INTO issues (kee, resource_id, rule_id, action_plan_key, severity, manual_severity,
+ INSERT INTO issues (kee, resource_id, project_id, rule_id, action_plan_key, severity, manual_severity,
message, line, effort_to_fix, status,
resolution, checksum, reporter, assignee, author_login, issue_attributes, issue_creation_date, issue_update_date,
issue_close_date, created_at, updated_at)
- VALUES (#{kee}, #{resourceId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity},
+ VALUES (#{kee}, #{resourceId}, #{projectId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity},
#{message}, #{line}, #{effortToFix}, #{status},
#{resolution}, #{checksum}, #{reporter}, #{assignee}, #{authorLogin}, #{issueAttributes}, #{issueCreationDate},
#{issueUpdateDate}, #{issueCloseDate}, #{createdAt}, #{updatedAt})
<selectKey order="BEFORE" resultType="Long" keyProperty="id">
select issues_seq.NEXTVAL from DUAL
</selectKey>
- INSERT INTO issues (id, kee, resource_id, rule_id, action_plan_key, severity, manual_severity,
+ INSERT INTO issues (id, kee, resource_id, project_id, rule_id, action_plan_key, severity, manual_severity,
message, line, effort_to_fix, status,
resolution, checksum, reporter, assignee, author_login, issue_attributes, issue_creation_date, issue_update_date,
issue_close_date, created_at, updated_at)
- VALUES (#{id}, #{kee}, #{resourceId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity},
+ VALUES (#{id}, #{kee}, #{resourceId}, #{projectId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity},
#{message}, #{line}, #{effortToFix}, #{status},
#{resolution}, #{checksum}, #{reporter}, #{assignee}, #{authorLogin}, #{issueAttributes}, #{issueCreationDate},
#{issueUpdateDate}, #{issueCloseDate}, #{createdAt}, #{updatedAt})
<select id="selectByKey" parameterType="String" resultType="Issue">
select
<include refid="issueColumns"/>
- from issues i, rules r, projects p
- where i.kee=#{kee} and i.rule_id=r.id and p.id=i.resource_id
+ from issues i, rules r, projects p, projects root
+ where i.kee=#{kee} and i.rule_id=r.id and p.id=i.resource_id and i.project_id=root.id
</select>
<select id="selectNonClosedIssues" parameterType="int" resultType="Issue">
select distinct
<include refid="issueColumns"/>
- from issues i, rules r, projects p
+ from issues i, rules r, projects p, projects root
where i.status <> 'CLOSED'
and (p.root_id=#{id} or (p.root_id is null and p.id=#{id}))
and i.resource_id=p.id
+ and i.project_id=root.id
and r.id=i.rule_id
</select>
<select id="selectByIds" parameterType="map" resultType="Issue">
select
<include refid="issueColumns"/>
- from issues i, rules r, projects p
+ from issues i, rules r, projects p, projects root
<where>
and
<foreach collection="ids" open="i.id in (" close=")" item="list" separator=") or i.id in (">
</foreach>
and i.rule_id=r.id
and p.id=i.resource_id
+ and i.project_id=root.id
</where>
<include refid="sortFilter"/>
</select>
</select>
<sql id="selectQueryConditions">
- from issues i, projects p, rules r
+ from issues i, projects p, rules r, projects root
<if test="componentRoots != null and componentRoots.size() > 0">
, projects rootprojects, snapshots rootsnapshots, snapshots s
</if>
</if>
<where>
and i.resource_id=p.id
+ and i.project_id=root.id
and i.rule_id=r.id
<if test="componentRoots != null and componentRoots.size() > 0">
and rootprojects.enabled=${_true}
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('391');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('392');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('394');
-INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('395');
-INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('396');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('397');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('398');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('399');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('400');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('401');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"KEE" VARCHAR(50) UNIQUE NOT NULL,
"RESOURCE_ID" INTEGER NOT NULL,
+ "PROJECT_ID" INTEGER,
"RULE_ID" INTEGER,
"SEVERITY" VARCHAR(10),
"MANUAL_SEVERITY" BOOLEAN NOT NULL,
CREATE INDEX "ISSUES_RESOURCE_ID" ON "ISSUES" ("RESOURCE_ID");
+CREATE INDEX "ISSUES_PROJECT_ID" ON "ISSUES" ("PROJECT_ID");
+
CREATE INDEX "ISSUES_RULE_ID" ON "ISSUES" ("RULE_ID");
CREATE INDEX "ISSUES_SEVERITY" ON "ISSUES" ("SEVERITY");
assertThat(issue.getKee()).isEqualTo("ABCDE");
assertThat(issue.getId()).isEqualTo(100L);
assertThat(issue.getResourceId()).isEqualTo(401);
+ assertThat(issue.getProjectId()).isEqualTo(399);
assertThat(issue.getRuleId()).isEqualTo(500);
assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
assertThat(issue.isManualSeverity()).isFalse();
assertThat(issue.getRuleRepo()).isEqualTo("squid");
assertThat(issue.getRule()).isEqualTo("AvoidCycle");
assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getProjectKey()).isEqualTo("struts");
}
@Test
assertThat(issue.getRuleRepo()).isEqualTo("squid");
assertThat(issue.getRule()).isEqualTo("AvoidCycle");
assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getProjectKey()).isEqualTo("struts");
}
@Test
.setKee("100")
.setRuleId(1)
.setRuleKey_unit_test_only("squid", "AvoidCycle")
- .setComponentKey_unit_test_only("component-key")
+ .setComponentKey_unit_test_only("org.sonar.sample:Sample")
+ .setProjectKey_unit_test_only("org.sonar.sample")
.setResourceId(1)
+ .setProjectId(1)
.setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
.setEffortToFix(15.0)
DefaultIssue issue = dto.toDefaultIssue();
assertThat(issue.key()).isEqualTo("100");
assertThat(issue.ruleKey().toString()).isEqualTo("squid:AvoidCycle");
- assertThat(issue.componentKey()).isEqualTo("component-key");
+ assertThat(issue.componentKey()).isEqualTo("org.sonar.sample:Sample");
+ assertThat(issue.projectKey()).isEqualTo("org.sonar.sample");
assertThat(issue.status()).isEqualTo(Issue.STATUS_CLOSED);
assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FALSE_POSITIVE);
assertThat(issue.effortToFix()).isEqualTo(15.0);
public void testInsert() throws Exception {
IssueDto dto = new IssueDto();
dto.setResourceId(123);
+ dto.setProjectId(100);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
IssueDto dto = new IssueDto();
dto.setResourceId(123);
+ dto.setProjectId(100);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
protected int componentId(DefaultIssue issue) {
return 100;
}
+
+ @Override
+ protected int projectId(DefaultIssue issue) {
+ return 10;
+ }
}
static class FakeRuleFinder implements RuleFinder {
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
action_plan_key="ABC"
severity="BLOCKER"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
action_plan_key="ABC"
severity="BLOCKER"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
action_plan_key="DEF"
severity="BLOCKER"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="100"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="101"
resource_id="402"
+ project_id="399"
rule_id="501"
severity="MAJOR"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE"
resource_id="401"
+ project_id="399"
rule_id="500"
action_plan_key="ABC"
severity="BLOCKER"
id="101"
kee="ABCDF"
resource_id="401"
+ project_id="399"
rule_id="500"
action_plan_key="ABC"
severity="BLOCKER"
id="102"
kee="ABCDG"
resource_id="401"
+ project_id="399"
rule_id="501"
action_plan_key="[null]"
severity="BLOCKER"
id="100"
kee="ABCDE"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="100"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="101"
resource_id="402"
+ project_id="399"
rule_id="501"
severity="MAJOR"
manual_severity="[false]"
id="102"
kee="102"
resource_id="402"
+ project_id="399"
rule_id="501"
severity="MAJOR"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="MINOR"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="MAJOR"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE-1"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="101"
kee="ABCDE-2"
resource_id="401"
+ project_id="399"
rule_id="500"
severity="BLOCKER"
manual_severity="[false]"
id="102"
kee="ABCDE-3"
resource_id="401"
+ project_id="399"
rule_id="501"
severity="BLOCKER"
manual_severity="[false]"
id="100"
kee="ABCDE"
resource_id="123"
+ project_id="100"
rule_id="200"
severity="BLOCKER"
manual_severity="[false]"
-<!--
- ~ 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.
- -->
<dataset>
<issues
id="100"
kee="ABCDE"
resource_id="123"
+ project_id="100"
rule_id="200"
severity="BLOCKER"
manual_severity="[false]"
-<!--
- ~ 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.
- -->
<dataset>
<issues
id="100"
kee="ABCDE"
resource_id="123"
+ project_id="100"
rule_id="200"
severity="INFO"
manual_severity="[false]"
message="[null]"
line="5000"
resource_id="100"
+ project_id="10"
rule_id="200"
created_at="[null]"
updated_at="[null]"
message="[null]"
line="5000"
resource_id="100"
+ project_id="10"
rule_id="200"
created_at="2013-05-18"
updated_at="2013-05-18"
message="[null]"
line="3000"
resource_id="100"
+ project_id="10"
rule_id="200"
created_at="2010-01-01"
updated_at="2011-02-02"
}
return resourceDto.getId().intValue();
}
+
+ @Override
+ protected int projectId(DefaultIssue issue) {
+ ResourceDto resourceDto = resourceDao.getRootProjectByComponentKey(issue.componentKey());
+ if (resourceDto == null) {
+ throw new IllegalStateException("Unknown component: " + issue.componentKey());
+ }
+ return resourceDto.getId().intValue();
+ }
}
+++ /dev/null
-#
-# Sonar, entreprise quality control 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.
-#
-
-#
-# Sonar 3.6
-#
-class CreateIssues < ActiveRecord::Migration
-
- def self.up
- create_table :issues do |t|
- t.column :kee, :string, :null => false, :limit => 50
- t.column :resource_id, :integer, :null => false
- t.column :rule_id, :integer, :null => true
- t.column :severity, :string, :null => true, :limit => 10
- t.column :manual_severity, :boolean, :null => false
- t.column :message, :string, :null => true, :limit => 4000
- t.column :line, :integer, :null => true
- t.column :effort_to_fix, :decimal, :null => true, :precision => 30, :scale => 20
- t.column :status, :string , :null => true, :limit => 20
- t.column :resolution, :string , :null => true, :limit => 20
- t.column :checksum, :string , :null => true, :limit => 1000
- t.column :reporter, :string, :null => true, :limit => 40
- t.column :assignee, :string, :null => true, :limit => 40
- t.column :author_login, :string, :null => true, :limit => 100
- t.column :action_plan_key, :string, :null => true, :limit => 50
- t.column :issue_attributes, :string, :null => true, :limit => 4000
-
- # functional dates
- t.column :issue_creation_date, :datetime, :null => true
- t.column :issue_close_date, :datetime, :null => true
- t.column :issue_update_date, :datetime, :null => true
-
- # technical dates
- t.column :created_at, :datetime, :null => true
- t.column :updated_at, :datetime, :null => true
- end
-
- add_index :issues, :kee, :name => 'issues_kee', :unique => true
- add_index :issues, :resource_id, :name => 'issues_resource_id'
- add_index :issues, :rule_id, :name => 'issues_rule_id'
- add_index :issues, :severity, :name => 'issues_severity'
- add_index :issues, :status, :name => 'issues_status'
- add_index :issues, :assignee, :name => 'issues_assignee'
- add_index :issues, :action_plan_key, :name => 'issues_action_plan_key'
- add_index :issues, :issue_creation_date, :name => 'issues_creation_date'
- end
-
-end
-
+++ /dev/null
-#
-# Sonar, entreprise quality control 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.
-#
-
-#
-# Sonar 3.6
-#
-class CreateIssueChanges < ActiveRecord::Migration
-
- def self.up
- create_table :issue_changes do |t|
- t.column :kee, :string, :null => true, :limit => 50
- t.column :issue_key, :string, :null => false, :limit => 50
- t.column :user_login, :string, :null => true, :limit => 40
- t.column :change_type, :string, :null => true, :limit => 20
- t.column :change_data, :text, :null => true
- t.column :created_at, :datetime, :null => true
- t.column :updated_at, :datetime, :null => true
- end
-
- add_index :issue_changes, :kee, :name => 'issue_changes_kee'
- add_index :issue_changes, :issue_key, :name => 'issue_changes_issue_key'
- end
-
-end
-
--- /dev/null
+#
+# Sonar, entreprise quality control 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.
+#
+
+#
+# Sonar 3.6
+#
+class CreateIssues < ActiveRecord::Migration
+
+ def self.up
+ create_table :issues do |t|
+ t.column :kee, :string, :null => false, :limit => 50
+ t.column :resource_id, :integer, :null => false
+ t.column :project_id, :integer, :null => true
+ t.column :rule_id, :integer, :null => true
+ t.column :severity, :string, :null => true, :limit => 10
+ t.column :manual_severity, :boolean, :null => false
+ t.column :message, :string, :null => true, :limit => 4000
+ t.column :line, :integer, :null => true
+ t.column :effort_to_fix, :decimal, :null => true, :precision => 30, :scale => 20
+ t.column :status, :string , :null => true, :limit => 20
+ t.column :resolution, :string , :null => true, :limit => 20
+ t.column :checksum, :string , :null => true, :limit => 1000
+ t.column :reporter, :string, :null => true, :limit => 40
+ t.column :assignee, :string, :null => true, :limit => 40
+ t.column :author_login, :string, :null => true, :limit => 100
+ t.column :action_plan_key, :string, :null => true, :limit => 50
+ t.column :issue_attributes, :string, :null => true, :limit => 4000
+
+ # functional dates
+ t.column :issue_creation_date, :datetime, :null => true
+ t.column :issue_close_date, :datetime, :null => true
+ t.column :issue_update_date, :datetime, :null => true
+
+ # technical dates
+ t.column :created_at, :datetime, :null => true
+ t.column :updated_at, :datetime, :null => true
+ end
+
+ add_index :issues, :kee, :name => 'issues_kee', :unique => true
+ add_index :issues, :resource_id, :name => 'issues_resource_id'
+ add_index :issues, :project_id, :name => 'issues_project_id'
+ add_index :issues, :rule_id, :name => 'issues_rule_id'
+ add_index :issues, :severity, :name => 'issues_severity'
+ add_index :issues, :status, :name => 'issues_status'
+ add_index :issues, :assignee, :name => 'issues_assignee'
+ add_index :issues, :action_plan_key, :name => 'issues_action_plan_key'
+ add_index :issues, :issue_creation_date, :name => 'issues_creation_date'
+ end
+
+end
+
+++ /dev/null
-#
-# Sonar, entreprise quality control 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.
-#
-
-#
-# Sonar 3.6
-# See SONAR-4305
-#
-class DeleteReviewDuplications < ActiveRecord::Migration
-
- class Review < ActiveRecord::Base
- end
-
- def self.up
- duplicated_ids = ActiveRecord::Base.connection.select_rows('select rule_failure_permanent_id from reviews group by rule_failure_permanent_id having count(*) > 1')
- say_with_time "Removing #{duplicated_ids.size} duplicated reviews" do
- duplicated_ids.each do |id|
- reviews = Review.find(:all, :conditions => {:rule_failure_permanent_id => id})
- # delete all reviews except the last one
- reviews[0...-1].each do |review|
- Review.delete(review.id)
- end
- end
- end
- end
-end
\ No newline at end of file
--- /dev/null
+#
+# Sonar, entreprise quality control 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.
+#
+
+#
+# Sonar 3.6
+#
+class CreateIssueChanges < ActiveRecord::Migration
+
+ def self.up
+ create_table :issue_changes do |t|
+ t.column :kee, :string, :null => true, :limit => 50
+ t.column :issue_key, :string, :null => false, :limit => 50
+ t.column :user_login, :string, :null => true, :limit => 40
+ t.column :change_type, :string, :null => true, :limit => 20
+ t.column :change_data, :text, :null => true
+ t.column :created_at, :datetime, :null => true
+ t.column :updated_at, :datetime, :null => true
+ end
+
+ add_index :issue_changes, :kee, :name => 'issue_changes_kee'
+ add_index :issue_changes, :issue_key, :name => 'issue_changes_issue_key'
+ end
+
+end
+
+++ /dev/null
-#
-# Sonar, entreprise quality control 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.
-#
-
-#
-# Sonar 3.6
-# See SONAR-4305
-#
-class MigrateViolationsToIssues < ActiveRecord::Migration
-
- class RuleFailure < ActiveRecord::Base
- end
-
- class Issue < ActiveRecord::Base
- end
-
- class IssueChange < ActiveRecord::Base
- end
-
- class User < ActiveRecord::Base
- end
-
- class ActionPlan < ActiveRecord::Base
- end
-
- PRIORITY_TO_SEVERITY = {1 => 'INFO', 2 => 'MINOR', 3 => 'MAJOR', 4 => 'CRITICAL', 5 => 'BLOCKER'}
-
- def self.up
- truncate_issues
-
- violation_ids = ActiveRecord::Base.connection.select_rows('select id from rule_failures')
-
- say_with_time "Converting #{violation_ids.size} violations to issues" do
- logins_by_id = User.all.inject({}) do |result, user|
- result[user.id]=user.login
- result
- end
-
- plans_by_id = ActionPlan.all.inject({}) do |result, plan|
- result[plan.id]=plan.kee
- result
- end
-
- violation_ids.each_slice(999) do |ids|
- violations = ActiveRecord::Base.connection.select_rows(sql_select_violation(ids))
- ActiveRecord::Base.transaction do
- violations.each do |violation|
- issue_key = new_key
- review_id = violation[0]
- created_at = violation[7]
- resource_id = violation[1]
- if resource_id.present?
- issue = Issue.new(
- :kee => issue_key,
- :resource_id => violation[1],
- :rule_id => violation[2],
- :severity => PRIORITY_TO_SEVERITY[violation[3].to_i],
- :message => violation[4],
- :line => violation[5],
- :effort_to_fix => violation[6],
- :resolution => violation[13],
- :checksum => violation[8],
- :author_login => nil,
- :issue_attributes => violation[15],
- :issue_creation_date => created_at,
- :issue_close_date => nil,
- :created_at => created_at
- )
- if review_id.present?
- # has review
- issue.status=violation[11]
- issue.issue_update_date=violation[16]
- issue.updated_at=violation[16]
- issue.severity=violation[12]
- issue.manual_severity=violation[14]
- issue.reporter=logins_by_id[violation[9].to_i] if violation[9].present?
- issue.assignee=logins_by_id[violation[10].to_i] if violation[10].present?
-
- plan_id = select_plan_id(review_id)
- issue.action_plan_key=plans_by_id[plan_id.to_i] if plan_id
-
- review_comments = select_review_comments(review_id)
- review_comments.each do |review_comment|
- user_id = review_comment[2]
- login = logins_by_id[user_id.to_i]
- if login
- IssueChange.create(
- :kee => new_key,
- :issue_key => issue_key,
- :user_login => login,
- :change_type => 'comment',
- :change_data => review_comment[3],
- :created_at => review_comment[0],
- :updated_at => review_comment[1]
- )
- end
- end
-
- else
- # does not have review
- issue.status='OPEN'
- issue.issue_update_date=created_at
- issue.updated_at=created_at
- issue.manual_severity=false
- end
- issue.save
- end
- end
- end
- end
- end
-
- #TODO
- #drop_table('rule_failures')
- #drop_table('reviews')
- #drop_table('review_comments')
- #drop_table('action_plans_reviews')
- end
-
- def self.truncate_issues
- ActiveRecord::Base.connection.execute('truncate table issues')
- ActiveRecord::Base.connection.execute('truncate table issue_changes')
- end
-
- def self.sql_select_violation(ids)
- "select rev.id, s.project_id, rf.rule_id, rf.failure_level, rf.message, rf.line, rf.cost, rf.created_at,
- rf.checksum,
- rev.user_id, rev.assignee_id, rev.status, rev.severity, rev.resolution, rev.manual_severity, rev.data,
- rev.updated_at
- from rule_failures rf
- inner join snapshots s on s.id=rf.snapshot_id
- left join reviews rev on rev.rule_failure_permanent_id=rf.permanent_id
- where rf.id in (#{ids.join(',')})"
- end
-
- def self.new_key
- Java::JavaUtil::UUID.randomUUID().toString()
- end
-
- def self.select_plan_id(review_id)
- ActiveRecord::Base.connection.select_value("select action_plan_id from action_plans_reviews where review_id=#{review_id}")
- end
-
- def self.select_review_comments(review_id)
- ActiveRecord::Base.connection.select_rows "select created_at, updated_at, user_id, review_text from review_comments where review_id=#{review_id}"
- end
-end
\ No newline at end of file
--- /dev/null
+#
+# Sonar, entreprise quality control 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.
+#
+
+#
+# Sonar 3.6
+# See SONAR-4305
+#
+class DeleteReviewDuplications < ActiveRecord::Migration
+
+ class Review < ActiveRecord::Base
+ end
+
+ def self.up
+ duplicated_ids = ActiveRecord::Base.connection.select_rows('select rule_failure_permanent_id from reviews group by rule_failure_permanent_id having count(*) > 1')
+ say_with_time "Removing #{duplicated_ids.size} duplicated reviews" do
+ duplicated_ids.each do |id|
+ reviews = Review.find(:all, :conditions => {:rule_failure_permanent_id => id})
+ # delete all reviews except the last one
+ reviews[0...-1].each do |review|
+ Review.delete(review.id)
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+#
+# Sonar, entreprise quality control 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.
+#
+
+#
+# Sonar 3.6
+# See SONAR-4305
+#
+class MigrateViolationsToIssues < ActiveRecord::Migration
+
+ class RuleFailure < ActiveRecord::Base
+ end
+
+ class Issue < ActiveRecord::Base
+ end
+
+ class IssueChange < ActiveRecord::Base
+ end
+
+ class User < ActiveRecord::Base
+ end
+
+ class ActionPlan < ActiveRecord::Base
+ end
+
+ PRIORITY_TO_SEVERITY = {1 => 'INFO', 2 => 'MINOR', 3 => 'MAJOR', 4 => 'CRITICAL', 5 => 'BLOCKER'}
+
+ def self.up
+ truncate_issues
+
+ violation_ids = ActiveRecord::Base.connection.select_rows('select id from rule_failures')
+
+ say_with_time "Converting #{violation_ids.size} violations to issues" do
+ logins_by_id = User.all.inject({}) do |result, user|
+ result[user.id]=user.login
+ result
+ end
+
+ plans_by_id = ActionPlan.all.inject({}) do |result, plan|
+ result[plan.id]=plan.kee
+ result
+ end
+
+ violation_ids.each_slice(999) do |ids|
+ violations = ActiveRecord::Base.connection.select_rows(sql_select_violation(ids))
+ ActiveRecord::Base.transaction do
+ violations.each do |violation|
+ issue_key = new_key
+ review_id = violation[0]
+ created_at = violation[7]
+ resource_id = violation[1]
+ if resource_id.present?
+ issue = Issue.new(
+ :kee => issue_key,
+ :resource_id => violation[1],
+ :rule_id => violation[2],
+ :severity => PRIORITY_TO_SEVERITY[violation[3].to_i],
+ :message => violation[4],
+ :line => violation[5],
+ :effort_to_fix => violation[6],
+ :resolution => violation[13],
+ :checksum => violation[8],
+ :author_login => nil,
+ :issue_attributes => violation[15],
+ :issue_creation_date => created_at,
+ :issue_close_date => nil,
+ :created_at => created_at
+ )
+ if review_id.present?
+ # has review
+ issue.status=violation[11]
+ issue.issue_update_date=violation[16]
+ issue.updated_at=violation[16]
+ issue.severity=violation[12]
+ issue.manual_severity=violation[14]
+ issue.reporter=logins_by_id[violation[9].to_i] if violation[9].present?
+ issue.assignee=logins_by_id[violation[10].to_i] if violation[10].present?
+
+ plan_id = select_plan_id(review_id)
+ issue.action_plan_key=plans_by_id[plan_id.to_i] if plan_id
+
+ review_comments = select_review_comments(review_id)
+ review_comments.each do |review_comment|
+ user_id = review_comment[2]
+ login = logins_by_id[user_id.to_i]
+ if login
+ IssueChange.create(
+ :kee => new_key,
+ :issue_key => issue_key,
+ :user_login => login,
+ :change_type => 'comment',
+ :change_data => review_comment[3],
+ :created_at => review_comment[0],
+ :updated_at => review_comment[1]
+ )
+ end
+ end
+
+ else
+ # does not have review
+ issue.status='OPEN'
+ issue.issue_update_date=created_at
+ issue.updated_at=created_at
+ issue.manual_severity=false
+ end
+ issue.save
+ end
+ end
+ end
+ end
+ end
+
+ #TODO
+ #drop_table('rule_failures')
+ #drop_table('reviews')
+ #drop_table('review_comments')
+ #drop_table('action_plans_reviews')
+ end
+
+ def self.truncate_issues
+ ActiveRecord::Base.connection.execute('truncate table issues')
+ ActiveRecord::Base.connection.execute('truncate table issue_changes')
+ end
+
+ def self.sql_select_violation(ids)
+ "select rev.id, s.project_id, rf.rule_id, rf.failure_level, rf.message, rf.line, rf.cost, rf.created_at,
+ rf.checksum,
+ rev.user_id, rev.assignee_id, rev.status, rev.severity, rev.resolution, rev.manual_severity, rev.data,
+ rev.updated_at
+ from rule_failures rf
+ inner join snapshots s on s.id=rf.snapshot_id
+ left join reviews rev on rev.rule_failure_permanent_id=rf.permanent_id
+ where rf.id in (#{ids.join(',')})"
+ end
+
+ def self.new_key
+ Java::JavaUtil::UUID.randomUUID().toString()
+ end
+
+ def self.select_plan_id(review_id)
+ ActiveRecord::Base.connection.select_value("select action_plan_id from action_plans_reviews where review_id=#{review_id}")
+ end
+
+ def self.select_review_comments(review_id)
+ ActiveRecord::Base.connection.select_rows "select created_at, updated_at, user_id, review_text from review_comments where review_id=#{review_id}"
+ end
+end
\ No newline at end of file
--- /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.server.issue;
+
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RuleQuery;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.resource.ResourceDao;
+
+import java.util.Collection;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ServerIssueStorageTest extends AbstractDaoTestCase {
+
+ @Test
+ public void should_load_component_id_from_db() throws Exception {
+ setupData("should_load_component_id_from_db");
+
+ ServerIssueStorage storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), new ResourceDao(getMyBatis()));
+ int componentId = storage.componentId(new DefaultIssue().setComponentKey("struts:Action.java"));
+
+ assertThat(componentId).isEqualTo(123);
+ }
+
+ @Test
+ public void should_fail_to_load_component_id_if_unknown_component() throws Exception {
+ setupData("should_fail_to_load_component_id_if_unknown_component");
+
+ ServerIssueStorage storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), new ResourceDao(getMyBatis()));
+ try {
+ storage.componentId(new DefaultIssue().setComponentKey("struts:Action.java"));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Unknown component: struts:Action.java");
+ }
+ }
+
+ @Test
+ public void should_load_project_id_from_db() throws Exception {
+ setupData("should_load_project_id_from_db");
+
+ ServerIssueStorage storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), new ResourceDao(getMyBatis()));
+ int projectId = storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java"));
+
+ assertThat(projectId).isEqualTo(1);
+ }
+
+ @Test
+ public void should_fail_to_load_project_id_if_unknown_component() throws Exception {
+ setupData("should_fail_to_load_project_id_if_unknown_component");
+
+ ServerIssueStorage storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), new ResourceDao(getMyBatis()));
+ try {
+ storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java"));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Unknown component: struts:Action.java");
+ }
+ }
+
+ static class FakeRuleFinder implements RuleFinder {
+
+ @Override
+ public Rule findById(int ruleId) {
+ return null;
+ }
+
+ @Override
+ public Rule findByKey(String repositoryKey, String key) {
+ return null;
+ }
+
+ @Override
+ public Rule findByKey(RuleKey key) {
+ Rule rule = Rule.create().setRepositoryKey(key.repository()).setKey(key.rule());
+ rule.setId(200);
+ return rule;
+ }
+
+ @Override
+ public Rule find(RuleQuery query) {
+ return null;
+ }
+
+ @Override
+ public Collection<Rule> findAll(RuleQuery query) {
+ return null;
+ }
+ }
+}
--- /dev/null
+<dataset></dataset>
\ No newline at end of file
--- /dev/null
+<dataset></dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+ <projects id="123" kee="struts:Action.java" />
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+ <projects id="1" kee="struts" root_id="[null]"/>
+ <projects id="2" kee="struts:Action.java" root_id="1"/>
+
+ <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" />
+ <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" />
+</dataset>
\ No newline at end of file