]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5673 Creating a new profile from a configuration file is not working
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 13 Oct 2014 10:40:37 +0000 (12:40 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 13 Oct 2014 10:57:27 +0000 (12:57 +0200)
19 files changed:
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivatorContextFactory.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb
server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb

index 3477fab825c1b8cfa8656df33d6b05825b5e3ec7..8715210be75a04cc597e302b92d489f554b1a1a9 100644 (file)
 package org.sonar.xoo;
 
 import org.sonar.api.SonarPlugin;
-import org.sonar.xoo.lang.MeasureSensor;
-import org.sonar.xoo.lang.ScmActivitySensor;
-import org.sonar.xoo.lang.SymbolReferencesSensor;
-import org.sonar.xoo.lang.SyntaxHighlightingSensor;
-import org.sonar.xoo.lang.XooTokenizerSensor;
-import org.sonar.xoo.rule.CreateIssueByInternalKeySensor;
-import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor;
-import org.sonar.xoo.rule.OneIssuePerLineSensor;
-import org.sonar.xoo.rule.XooQualityProfile;
-import org.sonar.xoo.rule.XooRulesDefinition;
+import org.sonar.xoo.lang.*;
+import org.sonar.xoo.rule.*;
 
 import java.util.Arrays;
 import java.util.List;
@@ -49,6 +41,10 @@ public class XooPlugin extends SonarPlugin {
       XooRulesDefinition.class,
       XooQualityProfile.class,
 
+      XooFakeExporter.class,
+      XooFakeImporter.class,
+      XooFakeImporterWithMessages.class,
+
       // sensors
       MeasureSensor.class,
       ScmActivitySensor.class,
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java
new file mode 100644 (file)
index 0000000..b8375db
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.xoo.rule;
+
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.xoo.Xoo;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Fake exporter just for test
+ */
+public class XooFakeExporter extends ProfileExporter {
+  public XooFakeExporter() {
+    super("XooFakeExporter", "Xoo Fake Exporter");
+  }
+
+  @Override
+  public String[] getSupportedLanguages() {
+    return new String[]{Xoo.KEY};
+  }
+
+  @Override
+  public String getMimeType() {
+    return "plain/custom";
+  }
+
+  @Override
+  public void exportProfile(RulesProfile profile, Writer writer) {
+    try {
+      writer.write("xoo -> " + profile.getName() + " -> " + profile.getActiveRules().size());
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java
new file mode 100644 (file)
index 0000000..867c111
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.xoo.rule;
+
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.xoo.Xoo;
+
+import java.io.Reader;
+
+/**
+ * Fake importer just for test, it will NOT take into account the given file but will create some hard-coded rules
+ */
+public class XooFakeImporter extends ProfileImporter {
+  public XooFakeImporter() {
+    super("XooProfileImporter", "Xoo Profile Importer");
+  }
+
+  @Override
+  public String[] getSupportedLanguages() {
+    return new String[] {Xoo.KEY};
+  }
+
+  @Override
+  public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+    RulesProfile rulesProfile = RulesProfile.create();
+    rulesProfile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, "x1"), RulePriority.CRITICAL);
+    return rulesProfile;
+  }
+}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java
new file mode 100644 (file)
index 0000000..a11e3a2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.xoo.rule;
+
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.utils.ValidationMessages;
+
+import java.io.Reader;
+
+/**
+ * Fake importer just for test, it will NOT take into account the given file but will display some info and warning messages
+ */
+public class XooFakeImporterWithMessages extends ProfileImporter {
+  public XooFakeImporterWithMessages() {
+    super("XooFakeImporterWithMessages", "Xoo Profile Importer With Messages");
+  }
+
+  @Override
+  public String[] getSupportedLanguages() {
+    return new String[] {};
+  }
+
+  @Override
+  public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+    messages.addWarningText("a warning");
+    messages.addInfoText("an info");
+    return RulesProfile.create();
+  }
+}
index bfe1fd99afa64f225fe06b75f05610e0080cf502..e8100740345f8eee92ff3c483677cd170956cfe6 100644 (file)
@@ -27,6 +27,6 @@ public class XooPluginTest {
 
   @Test
   public void provide_extensions() {
-    assertThat(new XooPlugin().getExtensions()).hasSize(11);
+    assertThat(new XooPlugin().getExtensions()).hasSize(14);
   }
 }
index 148f27a2b3665ee46917c18deea15b4b88d20d7b..0041a742d923c7b21998e5377a8d437d2e82994e 100644 (file)
@@ -320,7 +320,6 @@ class ServerComponents {
     pico.addSingleton(QProfileLookup.class);
     pico.addSingleton(QProfileProjectOperations.class);
     pico.addSingleton(QProfileProjectLookup.class);
-    pico.addSingleton(QProfileRepositoryExporter.class);
     pico.addSingleton(BuiltInProfiles.class);
     pico.addSingleton(QProfileRestoreBuiltInAction.class);
     pico.addSingleton(QProfilesWs.class);
index d8a224f89577d243b4e178f48e2dd37a43095f91..0651346fcd434d97a9a93981d86683bd3799fee4 100644 (file)
 package org.sonar.server.qualityprofile;
 
 import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
 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.ActiveRuleParam;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.persistence.DbSession;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 
+import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
@@ -39,16 +46,20 @@ public class QProfileExporters implements ServerComponent {
 
   private final QProfileLoader loader;
   private final RuleFinder ruleFinder;
+  private final RuleActivator ruleActivator;
   private final ProfileExporter[] exporters;
+  private final ProfileImporter[] importers;
 
-  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, ProfileExporter[] exporters) {
+  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, RuleActivator ruleActivator, ProfileExporter[] exporters, ProfileImporter[] importers) {
     this.loader = loader;
     this.ruleFinder = ruleFinder;
+    this.ruleActivator = ruleActivator;
     this.exporters = exporters;
+    this.importers = importers;
   }
 
-  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder) {
-    this(loader, ruleFinder, new ProfileExporter[0]);
+  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, RuleActivator ruleActivator) {
+    this(loader, ruleFinder, ruleActivator, new ProfileExporter[0], new ProfileImporter[0]);
   }
 
   public List<ProfileExporter> exportersForLanguage(String language) {
@@ -104,4 +115,60 @@ public class QProfileExporters implements ServerComponent {
     }
     throw new NotFoundException("Unknown quality profile exporter: " + exporterKey);
   }
+
+  /**
+   * Used by rails
+   */
+  public List<ProfileImporter> findProfileImportersForLanguage(String language) {
+    List<ProfileImporter> result = new ArrayList<ProfileImporter>();
+    for (ProfileImporter importer : importers) {
+      if (importer.getSupportedLanguages() == null || importer.getSupportedLanguages().length == 0 || ArrayUtils.contains(importer.getSupportedLanguages(), language)) {
+        result.add(importer);
+      }
+    }
+    return result;
+  }
+
+  public QProfileResult importXml(QualityProfileDto profileDto, String importerKey, String xml, DbSession dbSession) {
+    QProfileResult result = new QProfileResult();
+    ValidationMessages messages = ValidationMessages.create();
+    ProfileImporter importer = getProfileImporter(importerKey);
+    RulesProfile rulesProfile = importer.importProfile(new StringReader(xml), messages);
+    importProfile(profileDto, rulesProfile, dbSession);
+    processValidationMessages(messages, result);
+    return result;
+  }
+
+  private void importProfile(QualityProfileDto profileDto, RulesProfile rulesProfile, DbSession dbSession) {
+    for (org.sonar.api.rules.ActiveRule activeRule : rulesProfile.getActiveRules()) {
+      ruleActivator.activate(dbSession, toRuleActivation(activeRule), profileDto);
+    }
+  }
+
+  private ProfileImporter getProfileImporter(String importerKey) {
+    for (ProfileImporter importer : importers) {
+      if (StringUtils.equals(importerKey, importer.getKey())) {
+        return importer;
+      }
+    }
+    throw new BadRequestException("No such importer : " + importerKey);
+  }
+
+  private void processValidationMessages(ValidationMessages messages, QProfileResult result) {
+    if (!messages.getErrors().isEmpty()) {
+      throw new BadRequestException(messages);
+    }
+    result.addWarnings(messages.getWarnings());
+    result.addInfos(messages.getInfos());
+  }
+
+  private RuleActivation toRuleActivation(org.sonar.api.rules.ActiveRule activeRule) {
+    RuleActivation ruleActivation = new RuleActivation(activeRule.getRule().ruleKey());
+    ruleActivation.setSeverity(activeRule.getSeverity().name());
+    for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
+      ruleActivation.setParameter(activeRuleParam.getKey(), activeRuleParam.getValue());
+    }
+    return ruleActivation;
+  }
+
 }
index ae09c899cd542f3bb084c1f7a673c4bb56df34ee..d794058ea979101c3ad703048ecb610446cc44bf 100644 (file)
@@ -37,6 +37,10 @@ public class QProfileName {
     return name;
   }
 
+  public static QProfileName createFor(String lang, String name){
+    return new QProfileName(lang, name);
+  }
+
   @Override
   public boolean equals(@Nullable Object o) {
     if (this == o) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java
deleted file mode 100644 (file)
index 883d056..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.ServerComponent;
-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.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
-import org.sonar.server.exceptions.BadRequestException;
-
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-
-/**
- * Used through ruby code <pre>Internal.profile_exporter</pre>
- */
-public class QProfileRepositoryExporter implements ServerComponent {
-
-  private final ActiveRuleDao activeRuleDao;
-  private final List<ProfileImporter> importers;
-
-  /**
-   * Used by pico when no plugin provide profile exporter / importer
-   */
-  public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao) {
-    this(activeRuleDao, Lists.<ProfileImporter>newArrayList());
-  }
-
-  public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao, List<ProfileImporter> importers) {
-    this.activeRuleDao = activeRuleDao;
-    this.importers = importers;
-  }
-
-  public QProfileResult importXml(QProfile profile, String pluginKey, String xml, SqlSession session) {
-    QProfileResult result = new QProfileResult();
-    ValidationMessages messages = ValidationMessages.create();
-    ProfileImporter importer = getProfileImporter(pluginKey);
-    RulesProfile rulesProfile = importer.importProfile(new StringReader(xml), messages);
-    importProfile(profile.id(), rulesProfile, session);
-    processValidationMessages(messages, result);
-    return result;
-  }
-
-  private void importProfile(int profileId, RulesProfile rulesProfile, SqlSession sqlSession) {
-    List<ActiveRuleDto> activeRuleDtos = newArrayList();
-    Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
-    for (ActiveRule activeRule : rulesProfile.getActiveRules()) {
-      ActiveRuleDto activeRuleDto = toActiveRuleDto(activeRule, profileId);
-      activeRuleDao.insert(activeRuleDto, sqlSession);
-      activeRuleDtos.add(activeRuleDto);
-      for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
-        ActiveRuleParamDto activeRuleParamDto = toActiveRuleParamDto(activeRuleParam, activeRuleDto);
-        activeRuleDao.insert(activeRuleParamDto, sqlSession);
-        paramsByActiveRule.put(activeRuleDto.getId(), activeRuleParamDto);
-      }
-    }
-    // TODO use RuleActivator to benefit from changelog and preview cache cleanup
-  }
-
-  private void processValidationMessages(ValidationMessages messages, QProfileResult result) {
-    if (!messages.getErrors().isEmpty()) {
-      throw new BadRequestException(messages);
-    }
-    result.addWarnings(messages.getWarnings());
-    result.addInfos(messages.getInfos());
-  }
-
-  private ActiveRuleDto toActiveRuleDto(ActiveRule activeRule, int profileId) {
-    return new ActiveRuleDto()
-      .setProfileId(profileId)
-      .setRuleId(activeRule.getRule().getId())
-      .setSeverity(toSeverityLevel(activeRule.getSeverity()));
-  }
-
-  private String toSeverityLevel(RulePriority rulePriority) {
-    return rulePriority.name();
-  }
-
-  private ActiveRuleParamDto toActiveRuleParamDto(ActiveRuleParam activeRuleParam, ActiveRuleDto activeRuleDto) {
-    return new ActiveRuleParamDto()
-      .setActiveRuleId(activeRuleDto.getId())
-      .setRulesParameterId(activeRuleParam.getRuleParam().getId())
-      .setKey(activeRuleParam.getKey())
-      .setValue(activeRuleParam.getValue());
-  }
-
-  private ProfileImporter getProfileImporter(String importerKey) {
-    for (ProfileImporter importer : importers) {
-      if (StringUtils.equals(importerKey, importer.getKey())) {
-        return importer;
-      }
-    }
-    throw new BadRequestException("No such importer : " + importerKey);
-  }
-
-  public List<ProfileImporter> getProfileImportersForLanguage(String language) {
-    List<ProfileImporter> result = new ArrayList<ProfileImporter>();
-    for (ProfileImporter importer : importers) {
-      if (importer.getSupportedLanguages() == null || importer.getSupportedLanguages().length == 0 || ArrayUtils.contains(importer.getSupportedLanguages(), language)) {
-        result.add(importer);
-      }
-    }
-    return result;
-  }
-
-}
index 81fbb63faa39a733ff269f07184c90466529c31d..5873862f58d0f1b3976814f3e45d1bbd427f3dc7 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.sonar.server.qualityprofile;
 
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+
 import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -29,7 +31,7 @@ public class QProfileResult {
   private List<String> warnings;
   private List<String> infos;
 
-  private QProfile profile;
+  private QualityProfileDto profile;
 
   public QProfileResult() {
     warnings = newArrayList();
@@ -54,11 +56,11 @@ public class QProfileResult {
     return this;
   }
 
-  public QProfile profile() {
+  public QualityProfileDto profile() {
     return profile;
   }
 
-  public QProfileResult setProfile(QProfile profile) {
+  public QProfileResult setProfile(QualityProfileDto profile) {
     this.profile = profile;
     return this;
   }
index fde5a90ed2f7344d44725992d9b8cdfdd55ff85f..d67cb2db9d25fcc797827bbfa850fdc15fd6a81b 100644 (file)
@@ -48,6 +48,7 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 public class QProfileService implements ServerComponent {
 
@@ -58,9 +59,10 @@ public class QProfileService implements ServerComponent {
   private final QProfileBackuper backuper;
   private final QProfileCopier copier;
   private final QProfileReset reset;
+  private final QProfileExporters exporters;
 
   public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory,
-    QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset) {
+                         QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset, QProfileExporters exporters) {
     this.db = db;
     this.index = index;
     this.ruleActivator = ruleActivator;
@@ -68,15 +70,23 @@ public class QProfileService implements ServerComponent {
     this.backuper = backuper;
     this.copier = copier;
     this.reset = reset;
+    this.exporters = exporters;
   }
 
-  public QualityProfileDto create(QProfileName name) {
+  public QProfileResult create(QProfileName name, @Nullable Map<String, String> xmlQProfilesByPlugin) {
     verifyAdminPermission();
     DbSession dbSession = db.openSession(false);
     try {
+      QProfileResult result = new QProfileResult();
       QualityProfileDto profile = factory.create(dbSession, name);
+      result.setProfile(profile);
+      if (xmlQProfilesByPlugin != null) {
+        for (Map.Entry<String, String> entry : xmlQProfilesByPlugin.entrySet()) {
+          result.add(exporters.importXml(profile, entry.getKey(), entry.getValue(), dbSession));
+        }
+      }
       dbSession.commit();
-      return profile;
+      return result;
     } finally {
       dbSession.close();
     }
index 2fb2b565d6dccf07e63b59dd9ca35e07a39184b5..a456b77eea904a27e147ffd50601fd2444767b18 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.qualityprofile;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
-import org.apache.commons.lang.StringUtils;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.core.activity.Activity;
@@ -89,6 +88,11 @@ public class RuleActivator implements ServerComponent {
     return doActivate(dbSession, activation, context);
   }
 
+  List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, QualityProfileDto profileDto) {
+    RuleActivatorContext context = contextFactory.create(profileDto, activation.getRuleKey(), dbSession);
+    return doActivate(dbSession, activation, context);
+  }
+
   private List<ActiveRuleChange> doActivate(DbSession dbSession, RuleActivation activation, RuleActivatorContext context) {
     context.verifyForActivation();
     List<ActiveRuleChange> changes = Lists.newArrayList();
index 1854942476b36e777f3aec3abbcb956324254c03..184d3fdf187f8f134f1fae34413e11095a3c80db 100644 (file)
@@ -47,7 +47,7 @@ public class RuleActivatorContextFactory implements ServerComponent {
       throw new BadRequestException("Quality profile not found: " + profileKey);
     }
     context.setProfile(profile);
-    return create(profile, ruleKey, session, context);
+    return create(ruleKey, session, context);
   }
 
   RuleActivatorContext create(QProfileName profileName, RuleKey ruleKey, DbSession session) {
@@ -57,13 +57,17 @@ public class RuleActivatorContextFactory implements ServerComponent {
       throw new BadRequestException("Quality profile not found: " + profileName);
     }
     context.setProfile(profile);
-    return create(profile, ruleKey, session, context);
+    return create(ruleKey, session, context);
   }
 
-  private RuleActivatorContext create(QualityProfileDto profile, RuleKey ruleKey, DbSession session, RuleActivatorContext context) {
+  RuleActivatorContext create(QualityProfileDto profile, RuleKey ruleKey, DbSession session) {
+    return create(ruleKey, session, new RuleActivatorContext().setProfile(profile));
+  }
+
+  private RuleActivatorContext create(RuleKey ruleKey, DbSession session, RuleActivatorContext context) {
     initRule(ruleKey, context, session);
-    initActiveRules(profile.getKey(), ruleKey, context, session, false);
-    String parentKee = profile.getParentKee();
+    initActiveRules(context.profile().getKey(), ruleKey, context, session, false);
+    String parentKee = context.profile().getParentKee();
     if (parentKee != null) {
       initActiveRules(parentKee, ruleKey, context, session, true);
     }
index fd8a87a9dd2bfda5f4edf7b0a6a83df5c4281dcc..8c0f19312c80e4f86467d6a00808a48606c976f5 100644 (file)
  */
 package org.sonar.server.qualityprofile;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.sonar.api.profiles.ProfileDefinition;
 import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.ProfileImporter;
 import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.api.server.rule.RulesDefinition;
 import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.persistence.DbSession;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.ServerTester;
 
 import java.io.IOException;
+import java.io.Reader;
 import java.io.Writer;
+import java.util.List;
 
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.Fail.fail;
@@ -45,9 +54,26 @@ public class QProfileExportersTest {
   @ClassRule
   public static ServerTester tester = new ServerTester().addXoo().addComponents(
     XooRulesDefinition.class, XooProfileDefinition.class,
-    XooExporter.class, StandardExporter.class);
+    XooExporter.class, StandardExporter.class,
+    XooProfileImporter.class, XooProfileImporterWithMessages.class, XooProfileImporterWithError.class);
 
-  QProfileExporters exporters = tester.get(QProfileExporters.class);
+  DbClient db;
+  DbSession dbSession;
+  QProfileExporters exporters;
+  QProfileLoader loader;
+
+  @Before
+  public void before() {
+    db = tester.get(DbClient.class);
+    dbSession = db.openSession(false);
+    exporters = tester.get(QProfileExporters.class);
+    loader = tester.get(QProfileLoader.class);
+  }
+
+  @After
+  public void after() throws Exception {
+    dbSession.close();
+  }
 
   @Test
   public void exportersForLanguage() throws Exception {
@@ -92,6 +118,58 @@ public class QProfileExportersTest {
     }
   }
 
+  @Test
+  public void profile_importers_for_language() throws Exception {
+    assertThat(exporters.findProfileImportersForLanguage("xoo")).hasSize(3);
+  }
+
+  @Test
+  public void import_xml() throws Exception {
+    QualityProfileDto profileDto = QProfileTesting.newDto(QProfileName.createFor("xoo", "import_xml"), "import_xml");
+    db.qualityProfileDao().insert(dbSession, profileDto);
+    dbSession.commit();
+
+    assertThat(loader.findActiveRulesByProfile(profileDto.getKey())).isEmpty();
+
+    exporters.importXml(profileDto, "XooProfileImporter", "<xml/>", dbSession);
+    dbSession.commit();
+
+    List<ActiveRule> activeRules = loader.findActiveRulesByProfile(profileDto.getKey());
+    assertThat(activeRules).hasSize(1);
+    ActiveRule activeRule = activeRules.get(0);
+    assertThat(activeRule.key().ruleKey()).isEqualTo(RuleKey.of("xoo", "R1"));
+    assertThat(activeRule.severity()).isEqualTo(Severity.CRITICAL);
+  }
+
+  @Test
+  public void import_xml_return_messages() throws Exception {
+    QProfileResult result = exporters.importXml(QProfileTesting.newXooP1(), "XooProfileImporterWithMessages", "<xml/>", dbSession);
+    dbSession.commit();
+
+    assertThat(result.infos()).containsOnly("an info");
+    assertThat(result.warnings()).containsOnly("a warning");
+  }
+
+  @Test
+  public void fail_to_import_xml_when_error_in_importer() throws Exception {
+    try {
+      exporters.importXml(QProfileTesting.newXooP1(), "XooProfileImporterWithError", "<xml/>", dbSession);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("error!");
+    }
+  }
+
+  @Test
+  public void fail_to_import_xml_on_unknown_importer() throws Exception {
+    try {
+      exporters.importXml(QProfileTesting.newXooP1(), "Unknown", "<xml/>", dbSession);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such importer : Unknown");
+    }
+  }
+
   public static class XooExporter extends ProfileExporter {
     public XooExporter() {
       super("xootool", "Xoo Tool");
@@ -157,4 +235,52 @@ public class QProfileExportersTest {
     }
   }
 
+  public static class XooProfileImporter extends ProfileImporter {
+    public XooProfileImporter() {
+      super("XooProfileImporter", "Xoo Profile Importer");
+    }
+
+    @Override
+    public String[] getSupportedLanguages() {
+      return new String[] {"xoo"};
+    }
+
+    @Override
+    public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+      RulesProfile rulesProfile = RulesProfile.create();
+      rulesProfile.activateRule(Rule.create("xoo", "R1"), RulePriority.CRITICAL);
+      return rulesProfile;
+    }
+  }
+
+  public static class XooProfileImporterWithMessages extends ProfileImporter {
+    public XooProfileImporterWithMessages() {
+      super("XooProfileImporterWithMessages", "Xoo Profile Importer With Message");
+    }
+
+    @Override
+    public String[] getSupportedLanguages() {
+      return new String[] {};
+    }
+
+    @Override
+    public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+      messages.addWarningText("a warning");
+      messages.addInfoText("an info");
+      return RulesProfile.create();
+    }
+  }
+
+  public static class XooProfileImporterWithError extends ProfileImporter {
+    public XooProfileImporterWithError() {
+      super("XooProfileImporterWithError", "Xoo Profile Importer With Error");
+    }
+
+    @Override
+    public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+      messages.addErrorText("error!");
+      return RulesProfile.create();
+    }
+  }
+
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java
deleted file mode 100644 (file)
index cdbc9ca..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.invocation.InvocationOnMock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.profiles.ProfileImporter;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rule.Severity;
-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.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
-import org.sonar.server.exceptions.BadRequestException;
-
-import java.io.Reader;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QProfileRepositoryExporterTest {
-
-  @Mock
-  SqlSession session;
-
-  @Mock
-  DatabaseSession hibernateSession;
-
-  @Mock
-  ActiveRuleDao activeRuleDao;
-
-  List<ProfileImporter> importers = newArrayList();
-
-  Integer currentId = 1;
-
-  QProfileRepositoryExporter operations;
-
-  @Before
-  public void setUp() throws Exception {
-    // Associate an id when inserting an object to simulate the db id generator
-    doAnswer(new Answer() {
-      public Object answer(InvocationOnMock invocation) {
-        Object[] args = invocation.getArguments();
-        ActiveRuleDto dto = (ActiveRuleDto) args[0];
-        dto.setId(currentId++);
-        return null;
-      }
-    }).when(activeRuleDao).insert(any(ActiveRuleDto.class), any(SqlSession.class));
-
-    operations = new QProfileRepositoryExporter(activeRuleDao, importers);
-  }
-
-  @Test
-  public void import_from_xml_plugin() throws Exception {
-    RulesProfile profile = RulesProfile.create("Default", "java");
-    Rule rule = Rule.create("pmd", "rule1");
-    rule.createParameter("max");
-    rule.setId(10);
-    ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER);
-    activeRule.setParameter("max", "10");
-
-    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.importXml(new QProfile().setId(1), "pmd", "<xml/>", session);
-
-    verify(importer).importProfile(any(Reader.class), any(ValidationMessages.class));
-
-    ArgumentCaptor<ActiveRuleDto> activeRuleArgument = ArgumentCaptor.forClass(ActiveRuleDto.class);
-    verify(activeRuleDao).insert(activeRuleArgument.capture(), eq(session));
-    assertThat(activeRuleArgument.getValue().getRuleId()).isEqualTo(10);
-    assertThat(activeRuleArgument.getValue().getSeverityString()).isEqualTo(Severity.BLOCKER);
-
-    ArgumentCaptor<ActiveRuleParamDto> activeRuleParamArgument = ArgumentCaptor.forClass(ActiveRuleParamDto.class);
-    verify(activeRuleDao).insert(activeRuleParamArgument.capture(), eq(session));
-    assertThat(activeRuleParamArgument.getValue().getKey()).isEqualTo("max");
-    assertThat(activeRuleParamArgument.getValue().getValue()).isEqualTo("10");
-  }
-
-  @Test
-  public void import_from_xml_plugin_add_infos_and_warnings() throws Exception {
-    final RulesProfile profile = RulesProfile.create("Default", "java");
-    Rule rule = Rule.create("pmd", "rule1");
-    rule.createParameter("max");
-    rule.setId(10);
-    ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER);
-    activeRule.setParameter("max", "10");
-
-    ProfileImporter importer = mock(ProfileImporter.class);
-    when(importer.getKey()).thenReturn("pmd");
-    doAnswer(new Answer() {
-      public Object answer(InvocationOnMock invocation) {
-        Object[] args = invocation.getArguments();
-        ValidationMessages validationMessages = (ValidationMessages) args[1];
-        validationMessages.addInfoText("an info message");
-        validationMessages.addWarningText("a warning message");
-        return profile;
-      }
-    }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class));
-    importers.add(importer);
-
-    QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "<xml/>", session);
-    ;
-    assertThat(result.infos()).hasSize(1);
-    assertThat(result.warnings()).hasSize(1);
-  }
-
-  @Test
-  public void fail_to_import_profile_from_xml_plugin_if_error() throws Exception {
-    final RulesProfile profile = RulesProfile.create("Default", "java");
-    Rule rule = Rule.create("pmd", "rule1");
-    rule.createParameter("max");
-    rule.setId(10);
-    ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER);
-    activeRule.setParameter("max", "10");
-
-    ProfileImporter importer = mock(ProfileImporter.class);
-    when(importer.getKey()).thenReturn("pmd");
-    importers.add(importer);
-
-    doAnswer(new Answer() {
-      public Object answer(InvocationOnMock invocation) {
-        Object[] args = invocation.getArguments();
-        ValidationMessages validationMessages = (ValidationMessages) args[1];
-        validationMessages.addErrorText("error!");
-        return profile;
-      }
-    }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class));
-
-    try {
-      operations.importXml(new QProfile().setId(1), "pmd", "<xml/>", session);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(BadRequestException.class);
-    }
-  }
-
-  @Test
-  public void fail_to_import_profile_when_missing_importer() throws Exception {
-    final RulesProfile profile = RulesProfile.create("Default", "java");
-    Rule rule = Rule.create("pmd", "rule1");
-    rule.createParameter("max");
-    rule.setId(10);
-    ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER);
-    activeRule.setParameter("max", "10");
-
-    ProfileImporter importer = mock(ProfileImporter.class);
-    when(importer.getKey()).thenReturn("pmd");
-    importers.add(importer);
-
-    when(importer.importProfile(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
-
-    try {
-      operations.importXml(new QProfile().setId(1), "unknown", "<xml/>", session);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such importer : unknown");
-    }
-    verify(importer, never()).importProfile(any(Reader.class), any(ValidationMessages.class));
-  }
-
-  @Test
-  public void get_profile_importers_for_language() throws Exception {
-    // 2 importers not declaring supported languages -> match all languages -> to be include in result
-    ProfileImporter importersWithEmptySupportedLanguagesList = mock(ProfileImporter.class);
-    when(importersWithEmptySupportedLanguagesList.getSupportedLanguages()).thenReturn(new String[] {});
-    importers.add(importersWithEmptySupportedLanguagesList);
-    importers.add(mock(ProfileImporter.class));
-
-    // 1 importers supporting the java language -> to be include in result
-    ProfileImporter importerSupportingJava = mock(ProfileImporter.class);
-    when(importerSupportingJava.getSupportedLanguages()).thenReturn(new String[] {"java"});
-    importers.add(importerSupportingJava);
-
-    // 1 importers supporting another language -> not to be include in result
-    ProfileImporter importerSupportingAnotherLanguage = mock(ProfileImporter.class);
-    when(importerSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[] {"js"});
-    importers.add(importerSupportingAnotherLanguage);
-
-    assertThat(operations.getProfileImportersForLanguage("java")).hasSize(3);
-  }
-
-}
index 6985b4815dfef118a97fbca20d3918227cc2246e..6f7d04c23284f6a71a420eb8e74d7bb207bc2567 100644 (file)
  */
 package org.sonar.server.qualityprofile;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
 import org.sonar.core.activity.Activity;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.user.UserDto;
 import org.sonar.server.activity.ActivityService;
@@ -44,6 +52,9 @@ import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -55,7 +66,7 @@ import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P2_KEY;
 public class QProfileServiceMediumTest {
 
   @ClassRule
-  public static ServerTester tester = new ServerTester();
+  public static ServerTester tester = new ServerTester().addComponents(XooProfileImporter.class, XooExporter.class);
 
   DbClient db;
   DbSession dbSession;
@@ -87,6 +98,35 @@ public class QProfileServiceMediumTest {
     dbSession.close();
   }
 
+  @Test
+  public void create_profile() throws Exception {
+    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
+
+    QualityProfileDto profile = service.create(QProfileName.createFor("xoo", "New Profile"), null).profile();
+
+    assertThat(loader.getByKey(profile.getKey())).isNotNull();
+    assertThat(loader.getByKey(profile.getKey()).getLanguage()).isEqualTo("xoo");
+    assertThat(loader.getByKey(profile.getKey()).getName()).isEqualTo("New Profile");
+  }
+
+  @Test
+  public void create_profile_with_xml() throws Exception {
+    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
+
+    db.ruleDao().insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "R1")).setLanguage("xoo").setSeverity("MINOR"));
+    dbSession.commit();
+
+    QProfileResult result = service.create(QProfileName.createFor("xoo", "New Profile"), ImmutableMap.of("XooProfileImporter", "<xml/>"));
+    QualityProfileDto profile = result.profile();
+
+    assertThat(loader.getByKey(profile.getKey())).isNotNull();
+    assertThat(loader.getByKey(profile.getKey()).getLanguage()).isEqualTo("xoo");
+    assertThat(loader.getByKey(profile.getKey()).getName()).isEqualTo("New Profile");
+
+    List<ActiveRule> activeRules = loader.findActiveRulesByProfile(profile.getKey());
+    assertThat(activeRules).hasSize(1);
+  }
+
   @Test
   public void count_by_all_profiles() throws Exception {
     MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
@@ -294,4 +334,51 @@ public class QProfileServiceMediumTest {
     assertThat(service.getDefault("xoo").getKey()).isEqualTo(XOO_P1_KEY);
   }
 
+
+  public static class XooExporter extends ProfileExporter {
+    public XooExporter() {
+      super("xootool", "Xoo Tool");
+    }
+
+    @Override
+    public String[] getSupportedLanguages() {
+      return new String[]{"xoo"};
+    }
+
+    @Override
+    public String getMimeType() {
+      return "plain/custom";
+    }
+
+    @Override
+    public void exportProfile(RulesProfile profile, Writer writer) {
+      try {
+        writer.write("xoo -> " + profile.getName() + " -> " + profile.getActiveRules().size());
+      } catch (IOException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+  public static class XooProfileImporter extends ProfileImporter {
+    public XooProfileImporter() {
+      super("XooProfileImporter", "Xoo Profile Importer");
+    }
+
+    @Override
+    public String[] getSupportedLanguages() {
+      return new String[]{"xoo"};
+    }
+
+    @Override
+    public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+      RulesProfile rulesProfile = RulesProfile.create();
+      Rule rule = Rule.create("xoo", "R1");
+      rule.createParameter("acceptWhitespace");
+      org.sonar.api.rules.ActiveRule activeRule = rulesProfile.activateRule(rule, RulePriority.CRITICAL);
+      activeRule.setParameter("acceptWhitespace", "true");
+      return rulesProfile;
+    }
+  }
+
 }
index cf4cd585bff6bd8670f5a59b3b671b765fb483f2..c93870cf723f8a99e929dfa1a1d5fde484c4f83f 100644 (file)
 package org.sonar.server.qualityprofile;
 
 import com.google.common.collect.ImmutableMap;
-import org.junit.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
@@ -29,6 +32,7 @@ import org.sonar.core.persistence.DbSession;
 import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.rule.RuleParamDto;
 import org.sonar.server.db.DbClient;
@@ -66,6 +70,8 @@ public class RuleActivatorMediumTest {
   RuleActivator ruleActivator;
   ActiveRuleIndex index;
 
+  QualityProfileDto profileDto;
+
   @Before
   public void before() {
     tester.clearDbAndIndexes();
@@ -97,7 +103,8 @@ public class RuleActivatorMediumTest {
       .setName("format").setDefaultValue("txt").setType(RuleParamType.STRING.type()));
 
     // create pre-defined profile P1
-    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1());
+    profileDto = QProfileTesting.newXooP1();
+    db.qualityProfileDao().insert(dbSession, profileDto);
     dbSession.commit();
     dbSession.clearCache();
   }
@@ -124,6 +131,23 @@ public class RuleActivatorMediumTest {
     assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED);
   }
 
+  @Test
+  public void activate_with_profile_dto() throws Exception {
+    RuleActivation activation = new RuleActivation(RuleTesting.XOO_X1);
+    activation.setSeverity(Severity.BLOCKER);
+    activation.setParameter("max", "7");
+    activation.setParameter("min", "3");
+    List<ActiveRuleChange> changes = ruleActivator.activate(dbSession, activation, profileDto);
+    dbSession.commit();
+    dbSession.clearCache();
+
+    assertThat(countActiveRules(XOO_P1_KEY)).isEqualTo(1);
+    verifyHasActiveRule(ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.BLOCKER, null,
+      ImmutableMap.of("max", "7", "min", "3"));
+    assertThat(changes).hasSize(1);
+    assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED);
+  }
+
   @Test
   public void activate_with_default_severity_and_parameter() throws Exception {
     activate(new RuleActivation(RuleTesting.XOO_X1), XOO_P1_KEY);
index b6a5ba9f4e227c30c71fdc5cf6ec9f21e21a3c01..6956a1287ebb143f733185c7805cea136dcb560e 100644 (file)
@@ -71,10 +71,9 @@ class ProfilesController < ApplicationController
         end
       end
       profile_name = Java::OrgSonarServerQualityprofile::QProfileName.new(params[:language], params[:name])
-      Internal.qprofile_service.create(profile_name)
-      # TODO use files_by_key
-      #flash[:notice] = message('quality_profiles.profile_x_created', :params => result.profile.name)
-      #flash_result(result)
+      result = Internal.qprofile_service.create(profile_name, files_by_key)
+      flash[:notice] = message('quality_profiles.profile_x_created', :params => result.profile().getName())
+      flash_result(result)
     end
     redirect_to :action => 'index'
   end
@@ -530,7 +529,7 @@ class ProfilesController < ApplicationController
   def flash_result(result)
     # only 4 messages are kept each time to avoid cookie overflow.
     unless result.infos.empty?
-      flash[:notice] += result.infos.to_a[0...4].join('<br/>')
+      flash[:notice] += '<br/>' + result.infos.to_a[0...4].join('<br/>')
     end
     unless result.warnings.empty?
       flash[:warning] = result.warnings.to_a[0...4].join('<br/>')
index 328e2af6add5fcdb1d932b0a31132db5efc8bd89..a003c054478797d224cea4dd075488293a0a91e4 100644 (file)
@@ -1,6 +1,6 @@
 <%
    language = controller.java_facade.getLanguages().find { |l| l.getKey()==language_key }
-   importers = Internal.component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class).getProfileImportersForLanguage(language_key)
+   importers = Internal.component(Java::OrgSonarServerQualityprofile::QProfileExporters.java_class).findProfileImportersForLanguage(language_key)
 %>
 <form id="create-profile-form" action="profiles/create" enctype="multipart/form-data" method="POST">
   <fieldset>