aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
diff options
context:
space:
mode:
authorGodin <mandrikov@gmail.com>2010-12-08 14:53:08 +0000
committerGodin <mandrikov@gmail.com>2010-12-08 14:53:08 +0000
commit1ba217e3e27485a9c4e7176a04acf4cfdd10ac6b (patch)
tree4400d173987d88c001155c9d1351905930d2756c /sonar-server
parent74c4ac9a4a5c9df13116862dd5dca982cc3f84bd (diff)
downloadsonarqube-1ba217e3e27485a9c4e7176a04acf4cfdd10ac6b.tar.gz
sonarqube-1ba217e3e27485a9c4e7176a04acf4cfdd10ac6b.zip
SONAR-1987: Backup/restore user rules
Diffstat (limited to 'sonar-server')
-rw-r--r--sonar-server/src/main/java/org/sonar/server/configuration/Backup.java10
-rw-r--r--sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java13
-rw-r--r--sonar-server/src/main/java/org/sonar/server/configuration/RulesBackup.java193
-rw-r--r--sonar-server/src/main/java/org/sonar/server/configuration/SonarConfig.java12
-rw-r--r--sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/configuration/RulesBackupTest.java55
6 files changed, 278 insertions, 13 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java b/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java
index a8ed347761e..eba4e481083 100644
--- a/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java
+++ b/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java
@@ -56,6 +56,8 @@ public class Backup {
backupables.add(new MetricsBackup(session));
backupables.add(new PropertiesBackup(session));
+ // Note that order is important, because profile can have reference to rule
+ backupables.add(new RulesBackup(session));
backupables.add(new ProfilesBackup(session));
}
@@ -149,11 +151,9 @@ public class Backup {
protected void writeText(QuickWriter writer, String text) {
writer.write("<![CDATA[");
/*
- * See http://jira.codehaus.org/browse/SONAR-1605
- * According to XML specification ( http://www.w3.org/TR/REC-xml/#sec-cdata-sect )
- * CData section may contain everything except of sequence ']]>'
- * so we will split all occurrences of this sequence into two CDATA
- * first one would contain ']]' and second '>'
+ * See http://jira.codehaus.org/browse/SONAR-1605 According to XML specification (
+ * http://www.w3.org/TR/REC-xml/#sec-cdata-sect ) CData section may contain everything except of sequence ']]>' so we will
+ * split all occurrences of this sequence into two CDATA first one would contain ']]' and second '>'
*/
text = StringUtils.replace(text, "]]>", "]]]]><![CDATA[>");
writer.write(text);
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java
index 16f84aad306..3149e62923c 100644
--- a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java
+++ b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java
@@ -111,9 +111,10 @@ public class ProfilesBackup implements Backupable {
for (Iterator<ActiveRule> iar = profile.getActiveRules().iterator(); iar.hasNext();) {
ActiveRule activeRule = iar.next();
Rule unMarshalledRule = activeRule.getRule();
- Rule matchingRuleInDb = rulesDao.getRuleByKey(unMarshalledRule.getPluginName(), unMarshalledRule.getKey());
+ Rule matchingRuleInDb = rulesDao.getRuleByKey(unMarshalledRule.getRepositoryKey(), unMarshalledRule.getKey());
if (matchingRuleInDb == null) {
- LoggerFactory.getLogger(getClass()).error("Unable to find active rule " + unMarshalledRule.getPluginName() + ":" + unMarshalledRule.getKey());
+ LoggerFactory.getLogger(getClass()).error(
+ "Unable to find active rule " + unMarshalledRule.getRepositoryKey() + ":" + unMarshalledRule.getKey());
iar.remove();
continue;
}
@@ -148,7 +149,8 @@ public class ProfilesBackup implements Backupable {
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Map<String, String> values = readNode(reader);
- return new Alert(null, new Metric(values.get("metric-key")), values.get("operator"), values.get("value-error"), values.get("value-warning"));
+ return new Alert(null, new Metric(values.get("metric-key")), values.get("operator"), values.get("value-error"),
+ values.get("value-warning"));
}
public boolean canConvert(Class type) {
@@ -163,7 +165,7 @@ public class ProfilesBackup implements Backupable {
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
ActiveRule rule = (ActiveRule) source;
writeNode(writer, "key", rule.getRule().getKey());
- writeNode(writer, "plugin", rule.getRule().getPluginName());
+ writeNode(writer, "plugin", rule.getRule().getRepositoryKey());
writeNode(writer, "level", rule.getSeverity().name());
if (!rule.getActiveRuleParams().isEmpty()) {
@@ -188,7 +190,8 @@ public class ProfilesBackup implements Backupable {
while (reader.hasMoreChildren()) {
reader.moveDown();
Map<String, String> valuesParam = readNode(reader);
- ActiveRuleParam activeRuleParam = new ActiveRuleParam(null, new RuleParam(null, valuesParam.get("key"), null, null), valuesParam.get("value"));
+ ActiveRuleParam activeRuleParam = new ActiveRuleParam(null, new RuleParam(null, valuesParam.get("key"), null, null),
+ valuesParam.get("value"));
params.add(activeRuleParam);
reader.moveUp();
}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/RulesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/RulesBackup.java
new file mode 100644
index 00000000000..62382851002
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/configuration/RulesBackup.java
@@ -0,0 +1,193 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.server.configuration;
+
+import com.google.common.collect.Lists;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import org.apache.commons.collections.CollectionUtils;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleParam;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.jpa.dao.RulesDao;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RulesBackup implements Backupable {
+ private Collection<Rule> rules;
+ private RulesDao rulesDao;
+ private DatabaseSession session;
+
+ public RulesBackup(DatabaseSession session) {
+ this.rulesDao = new RulesDao(session);
+ this.session = session;
+ }
+
+ /**
+ * For tests.
+ */
+ RulesBackup(Collection<Rule> rules) {
+ this.rules = rules;
+ }
+
+ public void exportXml(SonarConfig sonarConfig) {
+ if (rules == null) {
+ rules = getUserRules();
+ }
+ sonarConfig.setRules(rules);
+ }
+
+ public void importXml(SonarConfig sonarConfig) {
+ disableUserRules();
+ if (CollectionUtils.isNotEmpty(sonarConfig.getRules())) {
+ registerUserRules(sonarConfig.getRules());
+ }
+ }
+
+ private List<Rule> getUserRules() {
+ List<Rule> rules = rulesDao.getRules();
+ List<Rule> userRules = Lists.newArrayList();
+ for (Rule rule : rules) {
+ if (rule.getParent() != null) {
+ userRules.add(rule);
+ }
+ }
+ return userRules;
+ }
+
+ private void disableUserRules() {
+ for (Rule rule : getUserRules()) {
+ rule.setEnabled(false);
+ session.save(rule);
+ }
+ }
+
+ private void registerUserRules(Collection<Rule> rules) {
+ for (Rule rule : rules) {
+ Rule parent = rule.getParent();
+ Rule matchingParentRuleInDb = rulesDao.getRuleByKey(parent.getRepositoryKey(), parent.getKey());
+ if (matchingParentRuleInDb == null) {
+ LoggerFactory.getLogger(getClass()).error("Unable to find parent rule " + parent.getRepositoryKey() + ":" + parent.getKey());
+ continue;
+ }
+ rule.setParent(matchingParentRuleInDb);
+ Rule matchingRuleInDb = rulesDao.getRuleByKey(rule.getRepositoryKey(), rule.getKey());
+ if (matchingRuleInDb != null) {
+ matchingRuleInDb.setName(rule.getName());
+ matchingRuleInDb.setDescription(rule.getDescription());
+ matchingRuleInDb.setSeverity(rule.getSeverity());
+ matchingRuleInDb.setParams(rule.getParams());
+ matchingRuleInDb.setEnabled(true);
+ session.save(matchingRuleInDb);
+ } else {
+ rule.setEnabled(true);
+ session.save(rule);
+ }
+ }
+ }
+
+ public void configure(XStream xStream) {
+ xStream.alias("rule", Rule.class);
+ xStream.registerConverter(new Converter() {
+ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+ Rule rule = (Rule) source;
+ writeNode(writer, "parentRepositoryKey", rule.getParent().getRepositoryKey());
+ writeNode(writer, "parentKey", rule.getParent().getKey());
+ writeNode(writer, "repositoryKey", rule.getRepositoryKey());
+ writeNode(writer, "key", rule.getKey());
+ writeNode(writer, "level", rule.getSeverity().name());
+ writeNode(writer, "name", rule.getName());
+ writeNode(writer, "description", rule.getDescription());
+
+ if (!rule.getParams().isEmpty()) {
+ writer.startNode("params");
+ for (RuleParam ruleParam : rule.getParams()) {
+ writer.startNode("param");
+ writeNode(writer, "key", ruleParam.getKey());
+ writeNode(writer, "value", ruleParam.getDefaultValue());
+ writer.endNode();
+ }
+ writer.endNode();
+ }
+ }
+
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ Rule rule = Rule.create();
+
+ Map<String, String> valuesRule = new HashMap<String, String>();
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ valuesRule.put(reader.getNodeName(), reader.getValue());
+ if (reader.getNodeName().equals("params")) {
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ Map<String, String> valuesParam = readNode(reader);
+ rule.createParameter()
+ .setKey(valuesParam.get("key"))
+ .setDefaultValue(valuesParam.get("value"));
+ reader.moveUp();
+ }
+ }
+ reader.moveUp();
+ }
+
+ Rule parent = Rule.create()
+ .setRepositoryKey(valuesRule.get("parentRepositoryKey"))
+ .setKey(valuesRule.get("parentKey"));
+ rule.setParent(parent)
+ .setRepositoryKey(valuesRule.get("repositoryKey"))
+ .setKey(valuesRule.get("key"))
+ .setName(valuesRule.get("name"))
+ .setDescription(valuesRule.get("description"))
+ .setSeverity(RulePriority.valueOf(valuesRule.get("level")));
+ return rule;
+ }
+
+ public boolean canConvert(Class type) {
+ return Rule.class.equals(type);
+ }
+ });
+ }
+
+ private void writeNode(HierarchicalStreamWriter writer, String name, String value) {
+ writer.startNode(name);
+ writer.setValue(value);
+ writer.endNode();
+ }
+
+ private Map<String, String> readNode(HierarchicalStreamReader reader) {
+ Map<String, String> values = new HashMap<String, String>();
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ values.put(reader.getNodeName(), reader.getValue());
+ reader.moveUp();
+ }
+ return values;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/SonarConfig.java b/sonar-server/src/main/java/org/sonar/server/configuration/SonarConfig.java
index 0426ed45b76..123fc534b54 100644
--- a/sonar-server/src/main/java/org/sonar/server/configuration/SonarConfig.java
+++ b/sonar-server/src/main/java/org/sonar/server/configuration/SonarConfig.java
@@ -24,6 +24,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
import org.sonar.api.database.configuration.Property;
import org.sonar.api.measures.Metric;
import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.Rule;
import java.util.Collection;
import java.util.Date;
@@ -41,6 +42,8 @@ public class SonarConfig {
private Collection<RulesProfile> profiles;
+ private Collection<Rule> rules;
+
public SonarConfig() {
}
@@ -89,6 +92,14 @@ public class SonarConfig {
this.profiles = profiles;
}
+ public Collection<Rule> getRules() {
+ return rules;
+ }
+
+ public void setRules(Collection<Rule> rules) {
+ this.rules = rules;
+ }
+
@Override
public String toString() {
return new ToStringBuilder(this)
@@ -99,4 +110,5 @@ public class SonarConfig {
.append("profiles", profiles)
.toString();
}
+
}
diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java
index 4d6e66d7a0f..6b28a22366e 100644
--- a/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java
@@ -65,7 +65,8 @@ public class BackupTest {
@Test
public void shouldReturnAValidXml() throws Exception {
- Backup backup = new Backup(Arrays.asList(new MetricsBackup(null), new PropertiesBackup(null), new ProfilesBackup((DatabaseSession) null)));
+ Backup backup = new Backup(Arrays.asList(new MetricsBackup(null), new PropertiesBackup(null),
+ new ProfilesBackup((DatabaseSession) null)));
SonarConfig sonarConfig = getSonarConfig();
sonarConfig.setMetrics(getMetrics());
sonarConfig.setProperties(getProperties());
@@ -97,7 +98,8 @@ public class BackupTest {
@Test
public void shouldImportXml() {
- Backup backup = new Backup(Arrays.asList(new MetricsBackup(null), new PropertiesBackup(null), new ProfilesBackup((DatabaseSession) null)));
+ Backup backup = new Backup(Arrays.asList(new MetricsBackup(null), new PropertiesBackup(null),
+ new ProfilesBackup((DatabaseSession) null)));
String xml = getFileFromClasspath("backup-restore-valid.xml");
SonarConfig sonarConfig = backup.getSonarConfigFromXml(xml);
@@ -124,7 +126,7 @@ public class BackupTest {
assertEquals(RulePriority.MAJOR, testActiveRule.getSeverity());
assertNotNull(testActiveRule.getRule());
assertEquals("test key", testActiveRule.getRule().getKey());
- assertEquals("test plugin", testActiveRule.getRule().getPluginName());
+ assertEquals("test plugin", testActiveRule.getRule().getRepositoryKey());
assertEquals(1, testActiveRule.getActiveRuleParams().size());
ActiveRuleParam testActiveRuleParam = testActiveRule.getActiveRuleParams().get(0);
diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/RulesBackupTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/RulesBackupTest.java
new file mode 100644
index 00000000000..9886fdc5bf0
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/configuration/RulesBackupTest.java
@@ -0,0 +1,55 @@
+package org.sonar.server.configuration;
+
+import org.junit.Test;
+import org.sonar.api.rules.Rule;
+import org.sonar.jpa.dao.RulesDao;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class RulesBackupTest extends AbstractDbUnitTestCase {
+
+ @Test
+ public void shouldExportRules() {
+ SonarConfig sonarConfig = new SonarConfig();
+
+ Rule rule = Rule.create("repo", "key", "name").setDescription("description");
+
+ Rule userRule = Rule.create("repo", "key2", "name2").setDescription("description2");
+ userRule.setParent(rule);
+ userRule.createParameter("param").setDefaultValue("value");
+
+ RulesBackup rulesBackup = new RulesBackup(Arrays.asList(userRule));
+ rulesBackup.exportXml(sonarConfig);
+
+ assertThat(sonarConfig.getRules().size(), is(1));
+ assertTrue(sonarConfig.getRules().iterator().next() == userRule);
+ }
+
+ @Test
+ public void shouldImportRules() {
+ RulesDao rulesDao = getDao().getRulesDao();
+
+ RulesBackup rulesBackup = new RulesBackup(getSession());
+ SonarConfig sonarConfig = new SonarConfig();
+
+ Rule rule = Rule.create("repo", "key", "name").setDescription("description");
+
+ Rule userRule = Rule.create("repo", "key2", "name2").setDescription("description2");
+ userRule.setParent(rule);
+ userRule.createParameter("param").setDefaultValue("value");
+
+ getSession().save(rule);
+
+ sonarConfig.setRules(Arrays.asList(userRule));
+ rulesBackup.importXml(sonarConfig);
+
+ List<Rule> rules = rulesDao.getRules();
+ assertThat(rules.size(), is(2));
+ }
+}