aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-core/src/main/java/org/sonar/core/permission/GlobalPermissions.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java7
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java63
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDto.java75
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java (renamed from sonar-server/src/main/java/org/sonar/server/rule/Rules.java)45
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveruleMapper.java (renamed from sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java)9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java34
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java6
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml26
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml19
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java (renamed from sonar-server/src/test/java/org/sonar/server/rule/RulesTest.java)41
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java42
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insert-result.xml5
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insertParameter-result.xml5
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/delete-result.xml6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/insert-result.xml12
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update-result.xml9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleParam.java13
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java32
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java118
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java23
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualityprofile/RubyQProfilesService.java13
-rw-r--r--sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java14
-rw-r--r--sonar-server/src/main/java/org/sonar/server/util/RubyValidation.java47
-rw-r--r--sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java134
-rw-r--r--sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java42
-rw-r--r--sonar-server/src/test/java/org/sonar/server/qualityprofile/RubyQProfilesServiceTest.java14
31 files changed, 792 insertions, 81 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/permission/GlobalPermissions.java b/sonar-core/src/main/java/org/sonar/core/permission/GlobalPermissions.java
index 6e1e052bdc6..e76500ad6cd 100644
--- a/sonar-core/src/main/java/org/sonar/core/permission/GlobalPermissions.java
+++ b/sonar-core/src/main/java/org/sonar/core/permission/GlobalPermissions.java
@@ -42,4 +42,8 @@ public final class GlobalPermissions {
*/
public static final List<String> ALL = ImmutableList.of(SYSTEM_ADMIN, QUALITY_PROFILE_ADMIN, DASHBOARD_SHARING, SCAN_EXECUTION, DRY_RUN_EXECUTION, PROVISIONING);
+ private GlobalPermissions() {
+ // only static methods
+ }
+
}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java
index 36587a7a6d2..ada0107b857 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java
@@ -31,6 +31,7 @@ import org.sonar.core.permission.PermissionDao;
import org.sonar.core.permission.PermissionTemplateDao;
import org.sonar.core.properties.PropertiesDao;
import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.resource.ResourceIndexerDao;
@@ -54,6 +55,7 @@ public final class DaoUtils {
ActionPlanDao.class,
ActionPlanStatsDao.class,
ActiveDashboardDao.class,
+ ActiveRuleDao.class,
AuthorDao.class,
AuthorizationDao.class,
DashboardDao.class,
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
index 1a112a7de87..2fb00f2a0bc 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
@@ -55,8 +55,7 @@ import org.sonar.core.properties.PropertiesMapper;
import org.sonar.core.properties.PropertyDto;
import org.sonar.core.purge.PurgeMapper;
import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.qualityprofile.db.QualityProfileMapper;
+import org.sonar.core.qualityprofile.db.*;
import org.sonar.core.resource.*;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleMapper;
@@ -139,6 +138,8 @@ public class MyBatis implements BatchComponent, ServerComponent {
loadAlias(conf, "UserWithPermission", UserWithPermissionDto.class);
loadAlias(conf, "GroupWithPermission", GroupWithPermissionDto.class);
loadAlias(conf, "QualityProfile", QualityProfileDto.class);
+ loadAlias(conf, "ActiveRule", ActiveRuleDto.class);
+ loadAlias(conf, "ActiveRuleParam", ActiveRuleParamDto.class);
// AuthorizationMapper has to be loaded before IssueMapper because this last one used it
loadMapper(conf, "org.sonar.core.user.AuthorizationMapper");
@@ -154,7 +155,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, WidgetMapper.class, WidgetPropertyMapper.class,
MeasureMapper.class, SnapshotDataMapper.class, SnapshotSourceMapper.class, ActionPlanMapper.class, ActionPlanStatsMapper.class,
NotificationQueueMapper.class, CharacteristicMapper.class,
- GroupMembershipMapper.class, QualityProfileMapper.class
+ GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class
};
loadMappers(conf, mappers);
configureLogback(mappers);
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java
new file mode 100644
index 00000000000..2346103e655
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.qualityprofile.db;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.MyBatis;
+
+public class ActiveRuleDao implements ServerComponent {
+
+ private final MyBatis mybatis;
+
+ public ActiveRuleDao(MyBatis mybatis) {
+ this.mybatis = mybatis;
+ }
+
+ public void insert(ActiveRuleDto dto, SqlSession session) {
+ session.getMapper(ActiveRuleMapper.class).insert(dto);
+ }
+
+ public void insert(ActiveRuleDto dto) {
+ SqlSession session = mybatis.openSession();
+ try {
+ insert(dto, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void insert(ActiveRuleParamDto dto, SqlSession session) {
+ session.getMapper(ActiveRuleMapper.class).insertParameter(dto);
+ }
+
+ public void insert(ActiveRuleParamDto dto) {
+ SqlSession session = mybatis.openSession();
+ try {
+ insert(dto, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDto.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDto.java
new file mode 100644
index 00000000000..1810c6854a5
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDto.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.qualityprofile.db;
+
+public class ActiveRuleDto {
+
+ private Integer id;
+ private Integer profileId;
+ private Integer ruleId;
+ private Integer severity;
+ private String inheritance;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public ActiveRuleDto setId(Integer id) {
+ this.id = id;
+ return this;
+ }
+
+ public Integer getProfileId() {
+ return profileId;
+ }
+
+ public ActiveRuleDto setProfileId(Integer profileId) {
+ this.profileId = profileId;
+ return this;
+ }
+
+ public Integer getRulId() {
+ return ruleId;
+ }
+
+ public ActiveRuleDto setRuleId(Integer ruleId) {
+ this.ruleId = ruleId;
+ return this;
+ }
+
+ public Integer getSeverity() {
+ return severity;
+ }
+
+ public ActiveRuleDto setSeverity(Integer severity) {
+ this.severity = severity;
+ return this;
+ }
+
+ public String getInheritance() {
+ return inheritance;
+ }
+
+ public ActiveRuleDto setInheritance(String inheritance) {
+ this.inheritance = inheritance;
+ return this;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule/Rules.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java
index e17747f65d9..20dcad77895 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule/Rules.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java
@@ -18,22 +18,49 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.rule;
+package org.sonar.core.qualityprofile.db;
-import org.sonar.api.ServerComponent;
+public class ActiveRuleParamDto {
-public class Rules implements ServerComponent {
+ private Integer id;
+ private Integer activeRuleId;
+ private Integer rulesParameterId;
+ private String value;
- public void createManualRule() {
- throw new UnsupportedOperationException();
+ public Integer getId() {
+ return id;
}
- public void editManualRule() {
- throw new UnsupportedOperationException();
+ public ActiveRuleParamDto setId(Integer id) {
+ this.id = id;
+ return this;
}
- public void deleteManualRule() {
- throw new UnsupportedOperationException();
+ public Integer getActiveRuleId() {
+ return activeRuleId;
+ }
+
+ public ActiveRuleParamDto setActiveRuleId(Integer activeRuleId) {
+ this.activeRuleId = activeRuleId;
+ return this;
+ }
+
+ public Integer getRulesParameterId() {
+ return rulesParameterId;
+ }
+
+ public ActiveRuleParamDto setRulesParameterId(Integer rulesParameterId) {
+ this.rulesParameterId = rulesParameterId;
+ return this;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public ActiveRuleParamDto setValue(String value) {
+ this.value = value;
+ return this;
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveruleMapper.java
index 1d7b42bf716..e4068570c50 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveruleMapper.java
@@ -18,9 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.rule;
+package org.sonar.core.qualityprofile.db;
-import org.sonar.api.ServerComponent;
+public interface ActiveRuleMapper {
+
+ void insert(ActiveRuleDto dto);
+
+ void insertParameter(ActiveRuleParamDto dto);
-public class RuleOperations implements ServerComponent {
}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
index 8abf40b311d..fb158675c08 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
@@ -43,4 +43,38 @@ public class QualityProfileDao implements ServerComponent {
}
}
+ public void insert(QualityProfileDto dto, SqlSession session) {
+ session.getMapper(QualityProfileMapper.class).insert(dto);
+ }
+
+ public void insert(QualityProfileDto dto) {
+ SqlSession session = mybatis.openSession();
+ try {
+ insert(dto, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void update(QualityProfileDto dto) {
+ SqlSession session = mybatis.openSession();
+ try {
+ session.getMapper(QualityProfileMapper.class).update(dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void delete(Integer id) {
+ SqlSession session = mybatis.openSession();
+ try {
+ session.getMapper(QualityProfileMapper.class).delete(id);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
index 8e39c65a680..15acccf2e0e 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
@@ -26,4 +26,10 @@ public interface QualityProfileMapper {
List<QualityProfileDto> selectAll();
+ void insert(QualityProfileDto dto);
+
+ void update(QualityProfileDto dto);
+
+ void delete(Integer id);
+
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml
new file mode 100644
index 00000000000..f7178820d9d
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.qualityprofile.db.ActiveRuleMapper">
+
+ <sql id="activeRuleColumns">
+ p.id,
+ p.profile_id as profileId,
+ p.rule_id as ruleId,
+ p.failure_level as severity,
+ p.version as version,
+ p.used_profile as used
+ </sql>
+
+ <insert id="insert" parameterType="ActiveRule" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
+ INSERT INTO active_rules (profile_id, rule_id, failure_level, inheritance)
+ VALUES (#{profileId}, #{ruleId}, #{severity}, #{inheritance})
+ </insert>
+
+ <insert id="insertParameter" parameterType="ActiveRuleParam" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
+ INSERT INTO active_rule_parameters (active_rule_id, rules_parameter_id, value)
+ VALUES (#{activeRuleId}, #{rulesParameterId}, #{value})
+ </insert>
+
+</mapper>
+
diff --git a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
index 829b765e8e8..217ba29567b 100644
--- a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
@@ -17,5 +17,24 @@
from rules_profiles p
</select>
+ <insert id="insert" parameterType="QualityProfile" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
+ INSERT INTO rules_profiles (name, language, parent_name, version, used_profile)
+ VALUES (#{name}, #{language}, #{parent}, #{version}, #{used})
+ </insert>
+
+ <update id="update" parameterType="QualityProfile">
+ UPDATE rules_profiles SET
+ name=#{name},
+ language=#{language},
+ parent_name=#{parent},
+ version=#{version},
+ used_profile=#{used}
+ WHERE id=#{id}
+ </update>
+
+ <update id="delete" parameterType="Integer">
+ DELETE FROM rules_profiles WHERE id=#{id}
+ </update>
+
</mapper>
diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RulesTest.java b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java
index d7651118ef5..ddfe06f8c65 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule/RulesTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java
@@ -18,32 +18,43 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.rule;
+package org.sonar.core.qualityprofile.db;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.core.persistence.AbstractDaoTestCase;
-public class RulesTest {
+public class ActiveRuleDaoTest extends AbstractDaoTestCase {
- Rules rules;
+ ActiveRuleDao dao;
@Before
- public void setUp() throws Exception {
- rules = new Rules();
+ public void createDao() {
+ dao = new ActiveRuleDao(getMyBatis());
}
- @Test(expected = UnsupportedOperationException.class)
- public void testCreateManualRule() throws Exception {
- rules.createManualRule();
- }
+ @Test
+ public void insert() {
+ ActiveRuleDto dto = new ActiveRuleDto()
+ .setProfileId(1)
+ .setRuleId(10)
+ .setSeverity(2)
+ .setInheritance("INHERITED");
+
+ dao.insert(dto);
- @Test(expected = UnsupportedOperationException.class)
- public void testEditManualRule() throws Exception {
- rules.editManualRule();
+ checkTables("insert", "active_rules");
}
- @Test(expected = UnsupportedOperationException.class)
- public void testDeleteManualRule() throws Exception {
- rules.deleteManualRule();
+ @Test
+ public void insert_parameter() {
+ ActiveRuleParamDto dto = new ActiveRuleParamDto()
+ .setActiveRuleId(1)
+ .setRulesParameterId(1)
+ .setValue("20");
+
+ dao.insert(dto);
+
+ checkTables("insertParameter", "active_rule_parameters");
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
index 8718b7843df..315af5e11ac 100644
--- a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
@@ -62,4 +62,46 @@ public class QualityProfileDaoTest extends AbstractDaoTestCase {
assertThat(dto2.isUsed()).isFalse();
}
+ @Test
+ public void insert() {
+ setupData("shared");
+
+ QualityProfileDto dto = new QualityProfileDto()
+ .setName("Sonar Way with Findbugs")
+ .setLanguage("xoo")
+ .setParent("Sonar Way")
+ .setVersion(2)
+ .setUsed(true);
+
+ dao.insert(dto);
+
+ checkTables("insert", "rules_profiles");
+ }
+
+ @Test
+ public void update() {
+ setupData("shared");
+
+ QualityProfileDto dto = new QualityProfileDto()
+ .setId(1)
+ .setName("New Sonar Way with Findbugs")
+ .setLanguage("js")
+ .setParent("New Sonar Way")
+ .setVersion(3)
+ .setUsed(false);
+
+ dao.update(dto);
+
+ checkTables("update", "rules_profiles");
+ }
+
+ @Test
+ public void delete() {
+ setupData("shared");
+
+ dao.delete(1);
+
+ checkTables("delete", "rules_profiles");
+ }
+
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insert-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insert-result.xml
new file mode 100644
index 00000000000..0a98d012fad
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insert-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <active_rules id="1" profile_id="1" rule_id="10" failure_level="2" inheritance="INHERITED"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insertParameter-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insertParameter-result.xml
new file mode 100644
index 00000000000..69ec55f8007
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest/insertParameter-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="20"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/delete-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/delete-result.xml
new file mode 100644
index 00000000000..b43d589e9eb
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/delete-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <rules_profiles id="2" name="Sonar way" language="js" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/insert-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/insert-result.xml
new file mode 100644
index 00000000000..c0190f3a5ad
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/insert-result.xml
@@ -0,0 +1,12 @@
+<dataset>
+
+ <rules_profiles id="1" name="Sonar way" language="java" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Sonar way" language="js" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="3" name="Sonar Way with Findbugs" language="xoo" parent_name="Sonar Way" version="2"
+ used_profile="[true]"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update-result.xml
new file mode 100644
index 00000000000..4f2bff4e53d
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update-result.xml
@@ -0,0 +1,9 @@
+<dataset>
+
+ <rules_profiles id="1" name="New Sonar Way with Findbugs" language="js" parent_name="New Sonar Way" version="3"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Sonar way" language="js" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java b/sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java
index 887e5814ae8..de5c0a37ccd 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java
@@ -42,7 +42,7 @@ public abstract class ProfileImporter implements ServerExtension {
public abstract RulesProfile importProfile(Reader reader, ValidationMessages messages);
- public final String getKey() {
+ public String getKey() {
return importerKey;
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java b/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
index 344d0961be8..775f76d189e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
@@ -28,10 +28,6 @@ import java.util.List;
*/
public final class Severity {
- private Severity() {
- // utility
- }
-
public static final String INFO = "INFO";
public static final String MINOR = "MINOR";
public static final String MAJOR = "MAJOR";
@@ -42,4 +38,9 @@ public final class Severity {
* All the supported severity values, ordered from {@link #INFO} to {@link #BLOCKER}.
*/
public static final List<String> ALL = ImmutableList.of(INFO, MINOR, MAJOR, CRITICAL, BLOCKER);
+
+ private Severity() {
+ // utility
+ }
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleParam.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleParam.java
index e848d56775e..4f6815ce7e7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleParam.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleParam.java
@@ -22,14 +22,7 @@ package org.sonar.api.rules;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
+import javax.persistence.*;
@Entity
@Table(name = "rules_parameters")
@@ -74,6 +67,10 @@ public class RuleParam {
this.type = type;
}
+ public Integer getId() {
+ return id;
+ }
+
public Rule getRule() {
return rule;
}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
index 3c7fd4b6507..ef32b393b5b 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
@@ -47,6 +47,7 @@ import org.sonar.core.resource.ResourceQuery;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.user.UserSession;
import org.sonar.server.util.RubyUtils;
+import org.sonar.server.util.RubyValidation;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -70,8 +71,6 @@ public class InternalRubyIssueService implements ServerComponent {
private static final String USER_PARAM = "user";
private static final String ACTION_PLANS_ERRORS_ACTION_PLAN_DOES_NOT_EXIST_MESSAGE = "action_plans.errors.action_plan_does_not_exist";
- private static final String ERRORS_CANT_BE_EMPTY_MESSAGE = "errors.cant_be_empty";
- private static final String ERRORS_IS_TOO_LONG_MESSAGE = "errors.is_too_long";
private final IssueService issueService;
private final IssueCommentService commentService;
@@ -354,7 +353,7 @@ public class InternalRubyIssueService implements ServerComponent {
private void checkProject(String projectParam, Result<ActionPlan> result) {
if (Strings.isNullOrEmpty(projectParam)) {
- result.addError(Result.Message.ofL10n(ERRORS_CANT_BE_EMPTY_MESSAGE, PROJECT_PARAM));
+ result.addError(Result.Message.ofL10n(RubyValidation.ERRORS_CANT_BE_EMPTY_MESSAGE, PROJECT_PARAM));
} else {
ResourceDto project = resourceDao.getResource(ResourceQuery.create().setKey(projectParam));
if (project == null) {
@@ -554,12 +553,12 @@ public class InternalRubyIssueService implements ServerComponent {
boolean shared = sharedParam != null ? sharedParam : false;
if (checkId) {
- checkMandatoryParameter(id, ID_PARAM);
+ RubyValidation.checkMandatoryParameter(id, ID_PARAM);
}
if (checkUser) {
- checkMandatoryParameter(user, USER_PARAM);
+ RubyValidation.checkMandatoryParameter(user, USER_PARAM);
}
- checkMandatorySizeParameter(name, NAME_PARAM, 100);
+ RubyValidation.checkMandatorySizeParameter(name, NAME_PARAM, 100);
checkOptionalSizeParameter(description, DESCRIPTION_PARAM, 4000);
DefaultIssueFilter defaultIssueFilter = DefaultIssueFilter.create(name)
@@ -595,39 +594,26 @@ public class InternalRubyIssueService implements ServerComponent {
private void checkMandatoryParameter(String value, String paramName, Result result) {
if (Strings.isNullOrEmpty(value)) {
- result.addError(Result.Message.ofL10n(ERRORS_CANT_BE_EMPTY_MESSAGE, paramName));
+ result.addError(Result.Message.ofL10n(RubyValidation.ERRORS_CANT_BE_EMPTY_MESSAGE, paramName));
}
}
private void checkMandatorySizeParameter(String value, String paramName, Integer size, Result result) {
checkMandatoryParameter(value, paramName, result);
if (!Strings.isNullOrEmpty(value) && value.length() > size) {
- result.addError(Result.Message.ofL10n(ERRORS_IS_TOO_LONG_MESSAGE, paramName, size));
+ result.addError(Result.Message.ofL10n(RubyValidation.ERRORS_IS_TOO_LONG_MESSAGE, paramName, size));
}
}
private void checkOptionalSizeParameter(String value, String paramName, Integer size, Result result) {
if (!Strings.isNullOrEmpty(value) && value.length() > size) {
- result.addError(Result.Message.ofL10n(ERRORS_IS_TOO_LONG_MESSAGE, paramName, size));
- }
- }
-
- private void checkMandatoryParameter(String value, String paramName) {
- if (Strings.isNullOrEmpty(value)) {
- throw BadRequestException.ofL10n(ERRORS_CANT_BE_EMPTY_MESSAGE, paramName);
- }
- }
-
- private void checkMandatorySizeParameter(String value, String paramName, Integer size) {
- checkMandatoryParameter(value, paramName);
- if (!Strings.isNullOrEmpty(value) && value.length() > size) {
- throw BadRequestException.ofL10n(ERRORS_IS_TOO_LONG_MESSAGE, paramName, size);
+ result.addError(Result.Message.ofL10n(RubyValidation.ERRORS_IS_TOO_LONG_MESSAGE, paramName, size));
}
}
private void checkOptionalSizeParameter(String value, String paramName, Integer size) {
if (!Strings.isNullOrEmpty(value) && value.length() > size) {
- throw BadRequestException.ofL10n(ERRORS_IS_TOO_LONG_MESSAGE, paramName, size);
+ throw BadRequestException.ofL10n(RubyValidation.ERRORS_IS_TOO_LONG_MESSAGE, paramName, size);
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 1c6017766e2..e5d27bd2efd 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -90,6 +90,7 @@ import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.InternalPermissionTemplateService;
import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.plugins.*;
+import org.sonar.server.qualityprofile.QProfileOperations;
import org.sonar.server.qualityprofile.QProfileSearch;
import org.sonar.server.qualityprofile.QProfiles;
import org.sonar.server.qualityprofile.RubyQProfilesService;
@@ -271,6 +272,7 @@ public final class Platform {
// quality profiles
servicesContainer.addSingleton(QProfiles.class);
servicesContainer.addSingleton(QProfileSearch.class);
+ servicesContainer.addSingleton(QProfileOperations.class);
servicesContainer.addSingleton(RubyQProfilesService.class);
// users
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
index 03cd68cf176..59af8af48c2 100644
--- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
+++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
@@ -20,7 +20,125 @@
package org.sonar.server.qualityprofile;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ibatis.session.SqlSession;
import org.sonar.api.ServerComponent;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.ActiveRuleParam;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.*;
+import org.sonar.server.issue.Result;
+import org.sonar.server.user.UserSession;
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
public class QProfileOperations implements ServerComponent {
+
+ private final MyBatis myBatis;
+ private final QualityProfileDao dao;
+ private final ActiveRuleDao activeRuleDao;
+ private final List<ProfileExporter> exporters;
+ private final List<ProfileImporter> importers;
+
+ public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao) {
+ this(myBatis, dao, activeRuleDao, Lists.<ProfileExporter>newArrayList(), Lists.<ProfileImporter>newArrayList());
+ }
+
+ public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, List<ProfileExporter> exporters, List<ProfileImporter> importers) {
+ this.myBatis = myBatis;
+ this.dao = dao;
+ this.activeRuleDao = activeRuleDao;
+ this.exporters = exporters;
+ this.importers = importers;
+ }
+
+ public Result<QProfile> newProfile(String name, String language, UserSession userSession) {
+ userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ QualityProfileDto dto = new QualityProfileDto().setName(name).setLanguage(language);
+ dao.insert(dto);
+ return Result.of(QProfile.from(dto));
+ }
+
+ public Result<QProfile> newProfile(String name, String language, Map<String, String> xmlProfilesByPlugin, UserSession userSession) {
+ userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ // TODO check name not already exists
+
+ SqlSession sqlSession = myBatis.openSession();
+ Result<QProfile> result = Result.of();
+ try {
+ QualityProfileDto dto = new QualityProfileDto().setName(name).setLanguage(language);
+ dao.insert(dto, sqlSession);
+ for (Map.Entry<String, String> entry : xmlProfilesByPlugin.entrySet()) {
+ importProfile(dto, entry.getKey(), entry.getValue(), result, sqlSession);
+ }
+ result.set(QProfile.from(dto));
+ } finally {
+ sqlSession.commit();
+ return result;
+ }
+ }
+
+ private void importProfile(QualityProfileDto qualityProfileDto, String pluginKey, String xmlProfile, Result<QProfile> result, SqlSession sqlSession) {
+ ProfileImporter importer = getProfileImporter(pluginKey);
+ ValidationMessages messages = ValidationMessages.create();
+ RulesProfile profile = importer.importProfile(new StringReader(xmlProfile), messages);
+ completeErrorResult(result, messages);
+
+ if (result.ok()) {
+ for (ActiveRule activeRule : profile.getActiveRules()) {
+ ActiveRuleDto activeRuleDto = toActiveRuleDto(activeRule, qualityProfileDto);
+ activeRuleDao.insert(activeRuleDto, sqlSession);
+ for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
+ activeRuleDao.insert(toActiveRuleParamDto(activeRuleParam, activeRuleDto), sqlSession);
+ }
+ }
+ }
+ }
+
+ public ProfileImporter getProfileImporter(String exporterKey) {
+ for (ProfileImporter importer : importers) {
+ if (StringUtils.equals(exporterKey, importer.getKey())) {
+ return importer;
+ }
+ }
+ return null;
+ }
+
+ private void completeErrorResult(Result<QProfile> result, ValidationMessages messages) {
+ for (String error : messages.getErrors()) {
+ result.addError(error);
+ }
+ for (String warning : messages.getWarnings()) {
+ result.addError(warning);
+ }
+ }
+
+ private ActiveRuleDto toActiveRuleDto(ActiveRule activeRule, QualityProfileDto dto) {
+ return new ActiveRuleDto()
+ .setProfileId(dto.getId())
+ .setRuleId(activeRule.getRule().getId())
+ .setSeverity(toSeverityLevel(activeRule.getSeverity()));
+ }
+
+ private Integer toSeverityLevel(RulePriority rulePriority) {
+ return rulePriority.ordinal() + 1;
+ }
+
+ private ActiveRuleParamDto toActiveRuleParamDto(ActiveRuleParam activeRuleParam, ActiveRuleDto activeRuleDto) {
+ return new ActiveRuleParamDto()
+ .setActiveRuleId(activeRuleDto.getId())
+ .setRulesParameterId(activeRuleParam.getRuleParam().getId())
+ .setValue(activeRuleParam.getValue());
+ }
+
}
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java
index 829b648af97..89def5ce300 100644
--- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java
+++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java
@@ -22,15 +22,18 @@ package org.sonar.server.qualityprofile;
import org.sonar.api.ServerComponent;
import org.sonar.api.rule.RuleKey;
+import org.sonar.server.user.UserSession;
import java.util.List;
public class QProfiles implements ServerComponent {
private final QProfileSearch search;
+ private final QProfileOperations operations;
- public QProfiles(QProfileSearch search) {
+ public QProfiles(QProfileSearch search, QProfileOperations operations) {
this.search = search;
+ this.operations = operations;
}
public List<QProfile> searchProfiles() {
@@ -41,8 +44,8 @@ public class QProfiles implements ServerComponent {
throw new UnsupportedOperationException();
}
- public void newProfile() {
- throw new UnsupportedOperationException();
+ public void newProfile(String name, String language, UserSession userSession) {
+ operations.newProfile(name, language, userSession);
}
public void deleteProfile() {
@@ -125,4 +128,18 @@ public class QProfiles implements ServerComponent {
throw new UnsupportedOperationException();
}
+ // TEMPLATE RULES
+
+ public void createTemplateRule() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void editTemplateRule() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void deleteTemplateRule() {
+ throw new UnsupportedOperationException();
+ }
+
}
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/RubyQProfilesService.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/RubyQProfilesService.java
index 5d83361a7a5..218a3894b55 100644
--- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/RubyQProfilesService.java
+++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/RubyQProfilesService.java
@@ -21,8 +21,11 @@
package org.sonar.server.qualityprofile;
import org.sonar.api.ServerComponent;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.util.RubyValidation;
import java.util.List;
+import java.util.Map;
public class RubyQProfilesService implements ServerComponent {
@@ -35,4 +38,14 @@ public class RubyQProfilesService implements ServerComponent {
public List<QProfile> searchProfiles() {
return qProfiles.searchProfiles();
}
+
+ public void newProfile(Map<String, Object> params) {
+ String name = (String) params.get("name");
+ String language = (String) params.get("language");
+// RubyUtils.toStrings()
+
+ RubyValidation.checkMandatoryParameter(name, "name");
+ RubyValidation.checkMandatoryParameter(language, "language");
+ qProfiles.newProfile(name, language, UserSession.get());
+ }
}
diff --git a/sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java b/sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java
index 2e46eecb29a..ad7fcee4ed6 100644
--- a/sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java
+++ b/sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java
@@ -27,6 +27,7 @@ import org.sonar.api.utils.DateUtils;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.util.Date;
import java.util.List;
@@ -52,6 +53,19 @@ public class RubyUtils {
return result;
}
+// public static Map<String, String> toMap(@Nullable Object o) {
+// Map<String, String> result = null;
+// if (o != null) {
+// if (o instanceof List) {
+// // assume that it contains only strings
+// result = (List) o;
+// } else if (o instanceof CharSequence) {
+// result = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().split((CharSequence) o));
+// }
+// }
+// return result;
+// }
+
@CheckForNull
public static Integer toInteger(@Nullable Object o) {
if (o == null) {
diff --git a/sonar-server/src/main/java/org/sonar/server/util/RubyValidation.java b/sonar-server/src/main/java/org/sonar/server/util/RubyValidation.java
new file mode 100644
index 00000000000..11acc05fa65
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/util/RubyValidation.java
@@ -0,0 +1,47 @@
+/*
+ * 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.util;
+
+import com.google.common.base.Strings;
+import org.sonar.server.exceptions.BadRequestException;
+
+public class RubyValidation {
+
+ public static final String ERRORS_CANT_BE_EMPTY_MESSAGE = "errors.cant_be_empty";
+ public static final String ERRORS_IS_TOO_LONG_MESSAGE = "errors.is_too_long";
+
+ private RubyValidation() {
+ // only static methods
+ }
+
+ public static void checkMandatoryParameter(String value, String paramName) {
+ if (Strings.isNullOrEmpty(value)) {
+ throw BadRequestException.ofL10n(RubyValidation.ERRORS_CANT_BE_EMPTY_MESSAGE, paramName);
+ }
+ }
+
+ public static void checkMandatorySizeParameter(String value, String paramName, Integer size) {
+ checkMandatoryParameter(value, paramName);
+ if (!Strings.isNullOrEmpty(value) && value.length() > size) {
+ throw BadRequestException.ofL10n(RubyValidation.ERRORS_IS_TOO_LONG_MESSAGE, paramName, size);
+ }
+ }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java
new file mode 100644
index 00000000000..60847640338
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.qualityprofile;
+
+import org.apache.ibatis.session.SqlSession;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.*;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.MockUserSession;
+
+import java.io.Reader;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class QProfileOperationsTest {
+
+ @Mock
+ MyBatis myBatis;
+
+ @Mock
+ SqlSession session;
+
+ @Mock
+ QualityProfileDao dao;
+
+ @Mock
+ ActiveRuleDao activeRuleDao;
+
+ List<ProfileExporter> exporters = newArrayList();
+
+ List<ProfileImporter> importers = newArrayList();
+
+ QProfileOperations operations;
+
+ @Before
+ public void setUp() throws Exception {
+ when(myBatis.openSession()).thenReturn(session);
+ operations = new QProfileOperations(myBatis, dao, activeRuleDao, exporters, importers);
+ }
+
+ @Test
+ public void new_profile() throws Exception {
+ operations.newProfile("Default", "java", MockUserSession.create().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN));
+
+ ArgumentCaptor<QualityProfileDto> argument = ArgumentCaptor.forClass(QualityProfileDto.class);
+ verify(dao).insert(argument.capture());
+ assertThat(argument.getValue().getName()).isEqualTo("Default");
+ assertThat(argument.getValue().getLanguage()).isEqualTo("java");
+ }
+
+ @Test
+ public void fail_to_create_new_profile_without_profile_admin_permission() throws Exception {
+ try {
+ operations.newProfile("Default", "java", MockUserSession.create());
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(ForbiddenException.class);
+ }
+ verifyNoMoreInteractions(dao);
+ }
+
+ @Test
+ public void new_profile_from_xml_plugn() throws Exception {
+ RulesProfile profile = RulesProfile.create("Default", "java");
+ Rule rule = Rule.create("pmd", "rule1");
+ rule.createParameter("paramKey");
+ rule.setId(10);
+ ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER);
+ activeRule.setParameter("paramKey", "paramValue");
+
+ Map<String, String> xmlProfilesByPlugin = newHashMap();
+ xmlProfilesByPlugin.put("pmd", "<xml/>");
+ ProfileImporter importer = mock(ProfileImporter.class);
+ when(importer.getKey()).thenReturn("pmd");
+ when(importer.importProfile(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
+ importers.add(importer);
+
+ operations.newProfile("Default", "java", xmlProfilesByPlugin, MockUserSession.create().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN));
+ verify(session).commit();
+
+ ArgumentCaptor<QualityProfileDto> profileArgument = ArgumentCaptor.forClass(QualityProfileDto.class);
+ verify(dao).insert(profileArgument.capture(), eq(session));
+ assertThat(profileArgument.getValue().getName()).isEqualTo("Default");
+ assertThat(profileArgument.getValue().getLanguage()).isEqualTo("java");
+
+ ArgumentCaptor<ActiveRuleDto> activeRuleArgument = ArgumentCaptor.forClass(ActiveRuleDto.class);
+ verify(activeRuleDao).insert(activeRuleArgument.capture(), eq(session));
+ assertThat(activeRuleArgument.getValue().getRulId()).isEqualTo(10);
+ assertThat(activeRuleArgument.getValue().getSeverity()).isEqualTo(5);
+
+ ArgumentCaptor<ActiveRuleParamDto> activeRuleParamArgument = ArgumentCaptor.forClass(ActiveRuleParamDto.class);
+ verify(activeRuleDao).insert(activeRuleParamArgument.capture(), eq(session));
+ assertThat(activeRuleParamArgument.getValue().getValue()).isEqualTo("paramValue");
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java
index 0000f971e36..dae6b16760e 100644
--- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java
@@ -25,10 +25,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.UserSession;
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class QProfilesTest {
@@ -36,20 +38,20 @@ public class QProfilesTest {
@Mock
QProfileSearch search;
+ @Mock
+ QProfileOperations operations;
+
QProfiles qProfiles;
@Before
public void setUp() throws Exception {
- qProfiles = new QProfiles(search);
+ qProfiles = new QProfiles(search, operations);
}
@Test
public void search_profiles() throws Exception {
- when(qProfiles.searchProfiles()).thenReturn(newArrayList(
- new QProfile().setId(1).setName("Sonar Way with Findbugs").setLanguage("java").setParent("Sonar Way").setVersion(1).setUsed(false)
- ));
-
- assertThat(qProfiles.searchProfiles()).hasSize(1);
+ qProfiles.searchProfiles();
+ verify(search).searchProfiles();
}
@Test(expected = UnsupportedOperationException.class)
@@ -57,9 +59,10 @@ public class QProfilesTest {
qProfiles.searchProfile(null);
}
- @Test(expected = UnsupportedOperationException.class)
- public void testNewProfile() throws Exception {
- qProfiles.newProfile();
+ @Test
+ public void new_profile() throws Exception {
+ qProfiles.newProfile("Default", "java", MockUserSession.create());
+ verify(operations).newProfile(eq("Default"), eq("java"), any(UserSession.class));
}
@Test(expected = UnsupportedOperationException.class)
@@ -151,4 +154,19 @@ public class QProfilesTest {
public void testDeactiveRule() throws Exception {
qProfiles.deactiveRule(null, null);
}
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void createTemplateRule() throws Exception {
+ qProfiles.createTemplateRule();;
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void editTemplateRule() throws Exception {
+ qProfiles.editTemplateRule();
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void deleteTemplateRule() throws Exception {
+ qProfiles.deleteTemplateRule();
+ }
}
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/RubyQProfilesServiceTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/RubyQProfilesServiceTest.java
index ad973ae7e98..69a83d7ff4b 100644
--- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/RubyQProfilesServiceTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/RubyQProfilesServiceTest.java
@@ -20,14 +20,19 @@
package org.sonar.server.qualityprofile;
+import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.server.user.UserSession;
import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
@@ -51,4 +56,13 @@ public class RubyQProfilesServiceTest {
assertThat(service.searchProfiles()).hasSize(1);
}
+
+ @Test
+ public void new_profile() throws Exception {
+ service.newProfile(ImmutableMap.<String, Object>of(
+ "name", "Default",
+ "language", "java")
+ );
+ verify(qProfiles).newProfile(eq("Default"), eq("java"), any(UserSession.class));
+ }
}