]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5007 refactor Q profile exporters
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 30 Jun 2014 22:10:10 +0000 (00:10 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 30 Jun 2014 22:20:57 +0000 (00:20 +0200)
20 files changed:
sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java
sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java
sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/profiles_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/profiles/permalinks.html.erb
sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperMediumTest.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java

index f392148114492984ad462faee489c2440b6774a8..79b4fa8d66a1d84cbfdae2aad5cbe6aa981d58fc 100644 (file)
@@ -178,7 +178,9 @@ import org.sonar.server.qualitygate.ws.QGatesWs;
 import org.sonar.server.qualityprofile.BuiltInProfiles;
 import org.sonar.server.qualityprofile.QProfileBackuper;
 import org.sonar.server.qualityprofile.QProfileCopier;
+import org.sonar.server.qualityprofile.QProfileExporters;
 import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLoader;
 import org.sonar.server.qualityprofile.QProfileLookup;
 import org.sonar.server.qualityprofile.QProfileOperations;
 import org.sonar.server.qualityprofile.QProfileProjectLookup;
@@ -432,6 +434,8 @@ class ServerComponents {
     pico.addSingleton(RuleActivationActions.class);
     pico.addSingleton(BulkRuleActivationActions.class);
     pico.addSingleton(RuleActivator.class);
+    pico.addSingleton(QProfileLoader.class);
+    pico.addSingleton(QProfileExporters.class);
     pico.addSingleton(QProfileService.class);
     pico.addSingleton(RuleActivatorContextFactory.class);
     pico.addSingleton(QProfileFactory.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java
new file mode 100644 (file)
index 0000000..d8a224f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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.commons.lang.ArrayUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.NotFoundException;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class QProfileExporters implements ServerComponent {
+
+  private final QProfileLoader loader;
+  private final RuleFinder ruleFinder;
+  private final ProfileExporter[] exporters;
+
+  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, ProfileExporter[] exporters) {
+    this.loader = loader;
+    this.ruleFinder = ruleFinder;
+    this.exporters = exporters;
+  }
+
+  public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder) {
+    this(loader, ruleFinder, new ProfileExporter[0]);
+  }
+
+  public List<ProfileExporter> exportersForLanguage(String language) {
+    List<ProfileExporter> result = new ArrayList<ProfileExporter>();
+    for (ProfileExporter exporter : exporters) {
+      if (exporter.getSupportedLanguages() == null || exporter.getSupportedLanguages().length == 0 || ArrayUtils.contains(exporter.getSupportedLanguages(), language)) {
+        result.add(exporter);
+      }
+    }
+    return result;
+  }
+
+  public String mimeType(String exporterKey) {
+    ProfileExporter exporter = findExporter(exporterKey);
+    return exporter.getMimeType();
+  }
+
+  public void export(String profileKey, String exporterKey, Writer writer) {
+    ProfileExporter exporter = findExporter(exporterKey);
+    QualityProfileDto profile = loader.getByKey(profileKey);
+    if (profile == null) {
+      throw new NotFoundException("Unknown Quality profile: " + profileKey);
+    }
+    exporter.exportProfile(wrap(profile), writer);
+  }
+
+  /**
+   * Only for ruby on rails
+   */
+  public String export(String profileKey, String tool) {
+    StringWriter writer = new StringWriter();
+    export(profileKey, tool, writer);
+    return writer.toString();
+  }
+
+  private RulesProfile wrap(QualityProfileDto profile) {
+    RulesProfile target = new RulesProfile(profile.getName(), profile.getLanguage());
+    for (ActiveRule activeRule : loader.findActiveRulesByProfile(profile.getKey())) {
+      Rule rule = ruleFinder.findByKey(activeRule.key().ruleKey());
+      org.sonar.api.rules.ActiveRule wrappedActiveRule = target.activateRule(rule, RulePriority.valueOf(activeRule.severity()));
+      for (Map.Entry<String, String> entry : activeRule.params().entrySet()) {
+        wrappedActiveRule.setParameter(entry.getKey(), entry.getValue());
+      }
+    }
+    return target;
+  }
+
+  private ProfileExporter findExporter(String exporterKey) {
+    for (ProfileExporter e : exporters) {
+      if (exporterKey.equals(e.getKey())) {
+        return e;
+      }
+    }
+    throw new NotFoundException("Unknown quality profile exporter: " + exporterKey);
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java
new file mode 100644 (file)
index 0000000..d55b8cd
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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.Lists;
+import com.google.common.collect.Multimap;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.rule.index.RuleIndex;
+import org.sonar.server.rule.index.RuleQuery;
+import org.sonar.server.search.FacetValue;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.QueryOptions;
+
+import javax.annotation.CheckForNull;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class QProfileLoader implements ServerComponent {
+
+  private final DbClient db;
+  private final IndexClient index;
+
+  public QProfileLoader(DbClient db, IndexClient index) {
+    this.db = db;
+    this.index = index;
+  }
+
+  /**
+   * Returns all Quality profiles as DTOs. This is a temporary solution as long as
+   * profiles are not indexed and declared as a business object
+   */
+  public List<QualityProfileDto> findAll() {
+    DbSession dbSession = db.openSession(false);
+    try {
+      return db.qualityProfileDao().findAll(dbSession);
+    } finally {
+      dbSession.close();
+    }
+  }
+
+  @CheckForNull
+  public QualityProfileDto getByKey(String key) {
+    DbSession dbSession = db.openSession(false);
+    try {
+      return db.qualityProfileDao().getByKey(dbSession, key);
+    } finally {
+      dbSession.close();
+    }
+  }
+
+  @CheckForNull
+  public QualityProfileDto getByLangAndName(String lang, String name) {
+    DbSession dbSession = db.openSession(false);
+    try {
+      return db.qualityProfileDao().getByNameAndLanguage(name, lang, dbSession);
+    } finally {
+      dbSession.close();
+    }
+  }
+
+  @CheckForNull
+  public ActiveRule getActiveRule(ActiveRuleKey key) {
+    return index.get(ActiveRuleIndex.class).getByKey(key);
+  }
+
+  public List<ActiveRule> findActiveRulesByRule(RuleKey key) {
+    return index.get(ActiveRuleIndex.class).findByRule(key);
+  }
+
+  public List<ActiveRule> findActiveRulesByProfile(String key) {
+    return index.get(ActiveRuleIndex.class).findByProfile(key);
+  }
+
+  public long countActiveRulesByProfile(String key) {
+    return index.get(ActiveRuleIndex.class).countByQualityProfileKey(key);
+  }
+
+  public Map<String, Long> countAllActiveRules() {
+    Map<String, Long> counts = new HashMap<String, Long>();
+    for (Map.Entry<String, Long> entry : index.get(ActiveRuleIndex.class).countAllByQualityProfileKey().entrySet()) {
+      counts.put(entry.getKey(), entry.getValue());
+    }
+    return counts;
+  }
+
+  public Multimap<String, FacetValue> getStatsByProfile(String key) {
+    return index.get(ActiveRuleIndex.class).getStatsByProfileKey(key);
+  }
+
+  public Map<String, Multimap<String, FacetValue>> getAllProfileStats() {
+    List<String> keys = Lists.newArrayList();
+    for (QualityProfileDto profile : this.findAll()) {
+      keys.add(profile.getKey());
+    }
+    return index.get(ActiveRuleIndex.class).getStatsByProfileKeys(keys);
+  }
+
+  public long countDeprecatedActiveRulesByProfile(String key) {
+    return index.get(RuleIndex.class).search(
+      new RuleQuery()
+        .setQProfileKey(key)
+        .setActivation(true)
+        .setStatuses(Lists.newArrayList(RuleStatus.DEPRECATED)),
+      new QueryOptions().setLimit(0)).getTotal();
+  }
+
+
+}
index d3bdcf5d466319f5f655f01eceffca605d5d7c27..ac29bc80f02b74fb0f8ad8003c40811d5b93e5d6 100644 (file)
@@ -27,8 +27,6 @@ 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.database.DatabaseSession;
-import org.sonar.api.profiles.ProfileExporter;
 import org.sonar.api.profiles.ProfileImporter;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.rules.ActiveRule;
@@ -38,13 +36,9 @@ 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.jpa.session.DatabaseSessionFactory;
 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;
 import java.util.List;
 
@@ -55,24 +49,19 @@ import static com.google.common.collect.Lists.newArrayList;
  */
 public class QProfileRepositoryExporter implements ServerComponent {
 
-  private final DatabaseSessionFactory sessionFactory;
   private final ActiveRuleDao activeRuleDao;
-  private final List<ProfileExporter> exporters;
   private final List<ProfileImporter> importers;
 
   /**
    * Used by pico when no plugin provide profile exporter / importer
    */
-  public QProfileRepositoryExporter(DatabaseSessionFactory sessionFactory, ActiveRuleDao activeRuleDao) {
-    this(sessionFactory, activeRuleDao, Lists.<ProfileImporter>newArrayList(), Lists.<ProfileExporter>newArrayList());
+  public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao) {
+    this(activeRuleDao, Lists.<ProfileImporter>newArrayList());
   }
 
-  public QProfileRepositoryExporter(DatabaseSessionFactory sessionFactory, ActiveRuleDao activeRuleDao,
-    List<ProfileImporter> importers, List<ProfileExporter> exporters) {
-    this.sessionFactory = sessionFactory;
+  public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao, List<ProfileImporter> importers) {
     this.activeRuleDao = activeRuleDao;
     this.importers = importers;
-    this.exporters = exporters;
   }
 
   public QProfileResult importXml(QProfile profile, String pluginKey, String xml, SqlSession session) {
@@ -85,22 +74,6 @@ public class QProfileRepositoryExporter implements ServerComponent {
     return result;
   }
 
-  public String exportToXml(QProfile profile, String pluginKey) {
-    DatabaseSession session = sessionFactory.getSession();
-    RulesProfile rulesProfile = session.getSingleResult(RulesProfile.class, "id", profile.id());
-    if (rulesProfile == null) {
-      throw new NotFoundException("This profile does not exist");
-    }
-    ProfileExporter exporter = getProfileExporter(pluginKey);
-    Writer writer = new StringWriter();
-    exporter.exportProfile(rulesProfile, writer);
-    return writer.toString();
-  }
-
-  public String getProfileExporterMimeType(String pluginKey) {
-    return getProfileExporter(pluginKey).getMimeType();
-  }
-
   private void importProfile(int profileId, RulesProfile rulesProfile, SqlSession sqlSession) {
     List<ActiveRuleDto> activeRuleDtos = newArrayList();
     Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
@@ -153,25 +126,6 @@ public class QProfileRepositoryExporter implements ServerComponent {
     throw new BadRequestException("No such importer : " + importerKey);
   }
 
-  private ProfileExporter getProfileExporter(String exporterKey) {
-    for (ProfileExporter exporter : exporters) {
-      if (StringUtils.equals(exporterKey, exporter.getKey())) {
-        return exporter;
-      }
-    }
-    throw new BadRequestException("No such exporter : " + exporterKey);
-  }
-
-  public List<ProfileExporter> getProfileExportersForLanguage(String language) {
-    List<ProfileExporter> result = new ArrayList<ProfileExporter>();
-    for (ProfileExporter exporter : exporters) {
-      if (exporter.getSupportedLanguages() == null || exporter.getSupportedLanguages().length == 0 || ArrayUtils.contains(exporter.getSupportedLanguages(), language)) {
-        result.add(exporter);
-      }
-    }
-    return result;
-  }
-
   public List<ProfileImporter> getProfileImportersForLanguage(String language) {
     List<ProfileImporter> result = new ArrayList<ProfileImporter>();
     for (ProfileImporter importer : importers) {
index 9ab2e196ba820f6e86aec8d622cd39d10945d4a8..45d196b3f1b0e8d408af4194acdd47fe14905298 100644 (file)
  */
 package org.sonar.server.qualityprofile;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.index.query.FilterBuilders;
 import org.elasticsearch.index.query.OrFilterBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
 import org.sonar.api.ServerComponent;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
@@ -37,10 +33,7 @@ import org.sonar.core.rule.RuleDto;
 import org.sonar.core.user.UserDto;
 import org.sonar.server.activity.index.ActivityIndex;
 import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
-import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.FacetValue;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.search.QueryOptions;
 import org.sonar.server.search.Result;
@@ -54,9 +47,7 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class QProfileService implements ServerComponent {
 
@@ -68,8 +59,8 @@ public class QProfileService implements ServerComponent {
   private final QProfileCopier copier;
   private final QProfileReset reset;
 
-  public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory, QProfileBackuper backuper,
-                         QProfileCopier copier, QProfileReset reset) {
+  public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory,
+    QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset) {
     this.db = db;
     this.index = index;
     this.ruleActivator = ruleActivator;
@@ -91,42 +82,6 @@ public class QProfileService implements ServerComponent {
     }
   }
 
-  /**
-   * Returns all Quality profiles as DTOs. This is a temporary solution as long as
-   * profiles are not indexed and declared as a business object
-   */
-  public List<QualityProfileDto> findAll() {
-    DbSession dbSession = db.openSession(false);
-    try {
-      return db.qualityProfileDao().findAll(dbSession);
-    } finally {
-      dbSession.close();
-    }
-  }
-
-  @CheckForNull
-  public QualityProfileDto getByKey(String key) {
-    DbSession dbSession = db.openSession(false);
-    try {
-      return db.qualityProfileDao().getByKey(dbSession, key);
-    } finally {
-      dbSession.close();
-    }
-  }
-
-  @CheckForNull
-  public ActiveRule getActiveRule(ActiveRuleKey key) {
-    return index.get(ActiveRuleIndex.class).getByKey(key);
-  }
-
-  public List<ActiveRule> findActiveRulesByRule(RuleKey key) {
-    return index.get(ActiveRuleIndex.class).findByRule(key);
-  }
-
-  public List<ActiveRule> findActiveRulesByProfile(String key) {
-    return index.get(ActiveRuleIndex.class).findByProfile(key);
-  }
-
   /**
    * Activate a rule on a Quality profile. Update configuration (severity/parameters) if the rule is already
    * activated.
@@ -247,39 +202,6 @@ public class QProfileService implements ServerComponent {
     UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
   }
 
-  public long countActiveRulesByProfile(String key) {
-    return index.get(ActiveRuleIndex.class).countByQualityProfileKey(key);
-  }
-
-  public Map<String, Long> countAllActiveRules() {
-    Map<String, Long> counts = new HashMap<String, Long>();
-    for (Map.Entry<String, Long> entry : index.get(ActiveRuleIndex.class).countAllByQualityProfileKey().entrySet()) {
-      counts.put(entry.getKey(), entry.getValue());
-    }
-    return counts;
-  }
-
-  public Multimap<String, FacetValue> getStatsByProfile(String key) {
-    return index.get(ActiveRuleIndex.class).getStatsByProfileKey(key);
-  }
-
-  public Map<String, Multimap<String, FacetValue>> getAllProfileStats() {
-    List<String> keys = Lists.newArrayList();
-    for (QualityProfileDto profile : this.findAll()) {
-      keys.add(profile.getKey());
-    }
-    return index.get(ActiveRuleIndex.class).getStatsByProfileKeys(keys);
-  }
-
-  public long countDeprecatedActiveRulesByProfile(String key) {
-    return index.get(RuleIndex.class).search(
-      new RuleQuery()
-        .setQProfileKey(key)
-        .setActivation(true)
-        .setStatuses(Lists.newArrayList(RuleStatus.DEPRECATED)),
-      new QueryOptions().setLimit(0)).getTotal();
-  }
-
   public Result<QProfileActivity> searchActivities(QProfileActivityQuery query, QueryOptions options) {
     DbSession session = db.openSession(false);
     try {
index 56ddaf26cacc8675d7ebb1be805b6f7939c57ec8..e36b55dae05f1ec54504302d3cad5dc099c8d4a7 100644 (file)
@@ -28,8 +28,8 @@ import org.sonar.server.user.UserSession;
 import org.sonar.server.util.Validation;
 
 import javax.annotation.CheckForNull;
+
 import java.util.List;
-import java.util.Map;
 
 public class QProfiles implements ServerComponent {
 
@@ -40,7 +40,7 @@ public class QProfiles implements ServerComponent {
   private final QProfileLookup profileLookup;
 
   public QProfiles(QProfileProjectOperations projectOperations, QProfileProjectLookup projectLookup,
-                   QProfileLookup profileLookup) {
+    QProfileLookup profileLookup) {
     this.projectOperations = projectOperations;
     this.projectLookup = projectLookup;
     this.profileLookup = profileLookup;
@@ -79,7 +79,6 @@ public class QProfiles implements ServerComponent {
     return profileLookup.ancestors(profile);
   }
 
-
   // PROJECTS
 
   public List<Component> projects(int profileId) {
@@ -114,7 +113,6 @@ public class QProfiles implements ServerComponent {
     projectOperations.removeAllProjects(profileId, UserSession.get());
   }
 
-
   private void checkProfileNameParam(String name) {
     if (Strings.isNullOrEmpty(name)) {
       throw new BadRequestException("quality_profiles.please_type_profile_name");
index b486a19c32c276c947820bc149fbcae25cab5fa6..e89c21d1e3257b3188c3ffdaf51d747991e2c7c6 100644 (file)
@@ -65,13 +65,6 @@ public class RuleActivation {
     return this;
   }
 
-  /**
-   * For internal use
-   */
-  boolean useDefaults() {
-    return severity == null && parameters.isEmpty();
-  }
-
   public RuleActivation setSeverity(@Nullable String s) {
     if (s != null && !Severity.ALL.contains(s)) {
       throw new IllegalArgumentException("Unknown severity: " + s);
index 4920d7501a92c3f06c5042acacfaf1ce375c8d75..5f90f91c96351e32b3d5d598b379611934fa3797 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.server.qualityprofile.ActiveRule;
-import org.sonar.server.qualityprofile.QProfileService;
+import org.sonar.server.qualityprofile.QProfileLoader;
 import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.index.RuleQuery;
 
@@ -37,10 +37,10 @@ import java.util.Map;
  * web services.
  */
 public class ActiveRuleCompleter implements ServerComponent {
-  private final QProfileService service;
+  private final QProfileLoader loader;
 
-  public ActiveRuleCompleter(QProfileService service) {
-    this.service = service;
+  public ActiveRuleCompleter(QProfileLoader loader) {
+    this.loader = loader;
   }
 
   void completeSearch(RuleQuery query, Collection<Rule> rules, JsonWriter json) {
@@ -49,7 +49,7 @@ public class ActiveRuleCompleter implements ServerComponent {
     if (query.getQProfileKey() != null) {
       // Load details of active rules on the selected profile
       for (Rule rule : rules) {
-        ActiveRule activeRule = service.getActiveRule(ActiveRuleKey.of(query.getQProfileKey(), rule.key()));
+        ActiveRule activeRule = loader.getActiveRule(ActiveRuleKey.of(query.getQProfileKey(), rule.key()));
         if (activeRule != null) {
           writeActiveRules(rule.key(), Arrays.asList(activeRule), json);
         }
@@ -57,7 +57,7 @@ public class ActiveRuleCompleter implements ServerComponent {
     } else {
       // Load details of all active rules
       for (Rule rule : rules) {
-        writeActiveRules(rule.key(), service.findActiveRulesByRule(rule.key()), json);
+        writeActiveRules(rule.key(), loader.findActiveRulesByRule(rule.key()), json);
       }
     }
     json.endObject();
@@ -65,7 +65,7 @@ public class ActiveRuleCompleter implements ServerComponent {
 
   void completeShow(Rule rule, JsonWriter json) {
     json.name("actives").beginArray();
-    for (ActiveRule activeRule : service.findActiveRulesByRule(rule.key())) {
+    for (ActiveRule activeRule : loader.findActiveRulesByRule(rule.key())) {
       writeActiveRule(activeRule, json);
     }
     json.endArray();
index 2169b669c31fab2548b87598204c197aee3286ce..5a85557efce4d3b800a733758fa4d653a41e4380 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.qualityprofile.QProfileService;
+import org.sonar.server.qualityprofile.QProfileLoader;
 import org.sonar.server.rule.RuleRepositories;
 import org.sonar.server.rule.RuleRepositories.Repository;
 import org.sonar.server.user.UserSession;
@@ -51,15 +51,15 @@ public class AppAction implements RequestHandler {
   private final RuleRepositories ruleRepositories;
   private final I18n i18n;
   private final DebtModel debtModel;
-  private final QProfileService qualityProfileService;
+  private final QProfileLoader profileLoader;
 
   public AppAction(Languages languages, RuleRepositories ruleRepositories, I18n i18n,
-    DebtModel debtModel, QProfileService qualityProfileService) {
+    DebtModel debtModel, QProfileLoader profileLoader) {
     this.languages = languages;
     this.ruleRepositories = ruleRepositories;
     this.i18n = i18n;
     this.debtModel = debtModel;
-    this.qualityProfileService = qualityProfileService;
+    this.profileLoader = profileLoader;
   }
 
   @Override
@@ -81,7 +81,7 @@ public class AppAction implements RequestHandler {
 
   private void addProfiles(JsonWriter json) {
     json.name("qualityprofiles").beginArray();
-    for (QualityProfileDto profile : qualityProfileService.findAll()) {
+    for (QualityProfileDto profile : profileLoader.findAll()) {
       if (languageIsSupported(profile)) {
         json
           .beginObject()
index 9c9d485beb8b5cfefa8d8a84eee2dc92bba5f0f4..008f76db170fb1cc9b37a2907738d065afe4c971 100644 (file)
@@ -30,7 +30,7 @@ class ProfilesController < ApplicationController
     add_breadcrumbs ProfilesController::root_breadcrumb
     call_backend do
       @profiles = Internal.quality_profiles.allProfiles().to_a
-      @active_rule_counts = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).countAllActiveRules()
+      @active_rule_counts = Internal.qprofile_loader.countAllActiveRules()
     end
     Api::Utils.insensitive_sort!(@profiles) { |profile| profile.name() }
   end
@@ -39,10 +39,10 @@ class ProfilesController < ApplicationController
   def show
     require_parameters 'key'
     call_backend do
-      @profile = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getByKey(params[:key])
+      @profile = Internal.qprofile_loader.getByKey(params[:key])
       not_found('Profile not found') unless @profile
-      @deprecated_active_rules = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).countDeprecatedActiveRulesByProfile(@profile.getKey())
-      @stats = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getStatsByProfile(@profile.getKey())
+      @deprecated_active_rules = Internal.qprofile_loader.countDeprecatedActiveRulesByProfile(@profile.getKey())
+      @stats = Internal.qprofile_loader.getStatsByProfile(@profile.getKey())
     end
     set_profile_breadcrumbs
   end
@@ -66,7 +66,7 @@ class ProfilesController < ApplicationController
         end
       end
       profile_name = Java::OrgSonarServerQualityprofile::QProfileName.new(params[:language], params[:name])
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).create(profile_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)
@@ -81,7 +81,7 @@ class ProfilesController < ApplicationController
     require_parameters 'language'
     @language = java_facade.getLanguages().find { |l| l.getKey()==params[:language].to_s }
     call_backend do
-      @builtin_profile_names = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).builtInProfileNamesForLanguage(params[:language].to_s)
+      @builtin_profile_names = Internal.qprofile_service.builtInProfileNamesForLanguage(params[:language].to_s)
     end
     render :partial => 'profiles/restore_built_in_form'
   end
@@ -91,7 +91,7 @@ class ProfilesController < ApplicationController
     verify_post_request
     require_parameters 'language'
     call_backend do
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restoreBuiltInProfilesForLanguage(params[:language].to_s)
+      Internal.qprofile_service.restoreBuiltInProfilesForLanguage(params[:language].to_s)
     end
     redirect_to :action => 'index'
   end
@@ -103,7 +103,7 @@ class ProfilesController < ApplicationController
 
     profile_key = profile_id_to_key(params[:id].to_i)
     call_backend do
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).delete(profile_key)
+      Internal.qprofile_service.delete(profile_key)
     end
 
     redirect_to(:controller => 'profiles', :action => 'index')
@@ -117,7 +117,7 @@ class ProfilesController < ApplicationController
 
     profile_key = profile_id_to_key(params[:id].to_i)
     call_backend do
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).setDefault(profile_key)
+      Internal.qprofile_service.setDefault(profile_key)
     end
     redirect_to :action => 'index'
   end
@@ -146,7 +146,7 @@ class ProfilesController < ApplicationController
     target_name = params['name']
 
     call_backend do
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).copyToName(source_key, target_name)
+      Internal.qprofile_service.copyToName(source_key, target_name)
       flash[:notice]= message('quality_profiles.profile_x_not_activated', :params => target_name)
       render :text => 'ok', :status => 200
     end
@@ -159,7 +159,7 @@ class ProfilesController < ApplicationController
 
     profile_key=params[:key]
     call_backend do
-      xml = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).backup(profile_key)
+      xml = Internal.qprofile_service.backup(profile_key)
       send_data(xml, :type => 'text/xml', :disposition => "attachment; filename=#{profile_key}.xml")
     end
   end
@@ -179,7 +179,7 @@ class ProfilesController < ApplicationController
     else
       call_backend do
         xml=Api::Utils.read_post_request_param(params[:backup])
-        Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restore(xml)
+        Internal.qprofile_service.restore(xml)
       end
     end
     redirect_to :action => 'index'
@@ -189,21 +189,21 @@ class ProfilesController < ApplicationController
   # GET /profiles/export?name=<profile name>&language=<language>&format<exporter key>
   def export
     language = params[:language]
-    if (params[:name].blank?)
-      profile = Internal.quality_profiles.defaultProfile(language)
+    if params[:name].blank?
+      profile = Internal.qprofile_service.getDefault(language)
     else
-      profile = Internal.quality_profiles.profile(CGI::unescape(params[:name]), language)
+      profile = Internal.qprofile_loader.getByLangAndName(language, CGI::unescape(params[:name]))
     end
     not_found('Profile not found') unless profile
 
-    if (params[:format].blank?)
+    if params[:format].blank?
       # standard sonar format
-      result = Internal.profile_backup.backupProfile(profile)
+      result = Internal.qprofile_service.backup(profile.getKee())
       send_data(result, :type => 'text/xml', :disposition => 'inline')
     else
       exporter_key = params[:format]
-      result = Internal.profile_exporter.exportToXml(profile, exporter_key)
-      send_data(result, :type => Internal.profile_exporter.getProfileExporterMimeType(exporter_key), :disposition => 'inline')
+      result = Internal.qprofile_exporters.export(profile.getKee(), exporter_key)
+      send_data(result, :type => Internal.qprofile_exporters.mimeType(exporter_key), :disposition => 'inline')
     end
   end
 
@@ -221,7 +221,7 @@ class ProfilesController < ApplicationController
       profiles = Api::Utils.insensitive_sort(profiles) { |p| p.name() }
       @select_parent = [[message('none'), nil]] + profiles.collect { |profile| [profile.name(), profile.id()] }
 
-      @all_profile_stats = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getAllProfileStats()
+      @all_profile_stats = Internal.qprofile_loader.getAllProfileStats()
     end
 
     set_profile_breadcrumbs
@@ -236,7 +236,7 @@ class ProfilesController < ApplicationController
     profile_key = profile_id_to_key(params[:id].to_i)
     parent_key = profile_id_to_key(params[:parent_id].to_i) unless params[:parent_id].empty?
     call_backend do
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).setParent(profile_key, parent_key)
+      Internal.qprofile_service.setParent(profile_key, parent_key)
     end
     redirect_to :action => 'inheritance', :id => params[:id]
   end
@@ -245,7 +245,7 @@ class ProfilesController < ApplicationController
   def changelog
     require_parameters 'key'
 
-    @profile = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getByKey(params[:key])
+    @profile = Internal.qprofile_loader.getByKey(params[:key])
     search = {'profileKeys' => @profile.key().to_s, 'since' => params[:since], 'to' => params[:to], 'p' => params[:p]}
     result = Internal.component(Java::OrgSonarServerActivity::RubyQProfileActivityService.java_class).search(search)
     @changes = result.activities
@@ -341,7 +341,7 @@ class ProfilesController < ApplicationController
 
     call_backend do
       profile_key = profile_id_to_key(params[:id].to_i)
-      Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).rename(profile_key, params[:new_name])
+      Internal.qprofile_service.rename(profile_key, params[:new_name])
     end
     render :text => 'ok', :status => 200
   end
index 6c0f82c432f22c07b52cbd1fe4513229207afd50..edc76af0fa95302e6ca67bfdd3920dcf84cdfe7b 100644 (file)
@@ -25,7 +25,7 @@ module ProfilesHelper
 
   def label_for_rules_count(qProfile, all_profile_stats)
     profile_stat = all_profile_stats[qProfile.key()] if all_profile_stats
-    profile_rules_count = profile_rules_count(qProfile, profile_stat)
+    profile_rules_count = profile_rules_count(profile_stat)
     label = "#{profile_rules_count} #{message('rules').downcase}"
 
     count_overriding = overriding_rules_count(profile_stat)
@@ -52,7 +52,7 @@ module ProfilesHelper
     Internal.quality_profiles.countProjects(qProfile).to_i
   end
 
-  def profile_rules_count(qProfile, profile_stat)
+  def profile_rules_count(profile_stat)
     count = 0
     count = profile_stat.get('countActiveRules').get(0).getValue() if profile_stat && profile_stat.get('countActiveRules')
     count
index bab4d8a47dc983af98dfbb96a46fcd626b59aa54..d2bd4ed0bf093b4f72091a5a5ad73f654b5638e5 100644 (file)
@@ -66,12 +66,20 @@ class Internal
     component(Java::OrgSonarServerQualityprofile::QProfiles.java_class)
   end
 
-  def self.quality_gates
-    component(Java::OrgSonarServerQualitygate::QualityGates.java_class)
+  def self.qprofile_service
+    component(Java::OrgSonarServerQualityprofile::QProfileService.java_class)
+  end
+
+  def self.qprofile_loader
+    component(Java::OrgSonarServerQualityprofile::QProfileLoader.java_class)
   end
 
-  def self.profile_exporter
-    component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class)
+  def self.qprofile_exporters
+    component(Java::OrgSonarServerQualityprofile::QProfileExporters.java_class)
+  end
+
+  def self.quality_gates
+    component(Java::OrgSonarServerQualitygate::QualityGates.java_class)
   end
 
   def self.rules
index 04101669b78c1066d971334bb890b64873f9a055..328e2af6add5fcdb1d932b0a31132db5efc8bd89 100644 (file)
@@ -1,6 +1,6 @@
 <%
    language = controller.java_facade.getLanguages().find { |l| l.getKey()==language_key }
-   importers = Internal.profile_exporter.getProfileImportersForLanguage(language_key)
+   importers = Internal.component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class).getProfileImportersForLanguage(language_key)
 %>
 <form id="create-profile-form" action="profiles/create" enctype="multipart/form-data" method="POST">
   <fieldset>
index 5770af503fedc863c22ec6c9e2e89a5ce6e879ac..ab14ed861ddca1a8d2dc04468f422eb3f6c66162 100644 (file)
@@ -50,7 +50,7 @@
     </tr>
     </thead>
     <tbody>
-    <% @profiles.select { |p| p.language == language.getKey() }.each do |profile| 
+    <% @profiles.select { |p| p.language == language.getKey() }.each do |profile|
        projects_count = projects_count(profile)
        is_default_profile = default_profile && default_profile==profile.key()
     %>
index 76e4a6e449d7bf69799149f1ef01693003f68a0a..71bb6fdfb07fbb2f2b25ca7c73d2ecf704533a03 100644 (file)
@@ -2,7 +2,7 @@
 <%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Permalinks'} %>
 
 <div class="tabs-panel marginbottom10 ">
-       <% exporters = Internal.profile_exporter.getProfileExportersForLanguage(@profile.language()) %>
+       <% exporters = Internal.qprofile_exporters.exportersForLanguage(@profile.language()) %>
        <br/>
        <table class="data without-header marginbottom10" id="permalinks-table">
       <tbody>
index 2b450686269bd9c470661a916831afa0326cf5e9..e27bc2cf9f68110e84f95b76a32d8aaa7744194d 100644 (file)
@@ -116,7 +116,7 @@ public class QProfileBackuperMediumTest {
     QualityProfileDto profile = db.qualityProfileDao().getByNameAndLanguage("P1", "xoo");
     assertThat(profile).isNotNull();
 
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(profile.getKey());
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(profile.getKey());
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
@@ -143,7 +143,7 @@ public class QProfileBackuperMediumTest {
     tester.get(QProfileBackuper.class).restore(new StringReader(
       Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)), null);
 
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
@@ -171,14 +171,14 @@ public class QProfileBackuperMediumTest {
       Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-child.xml"), Charsets.UTF_8)), null);
 
     // parent profile is unchanged
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("INFO");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
     assertThat(activeRules.get(0).params().get("max")).isEqualTo("10");
 
     // child profile overrides parent
-    activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
+    activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.OVERRIDES);
@@ -206,14 +206,14 @@ public class QProfileBackuperMediumTest {
       Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-parent.xml"), Charsets.UTF_8)), null);
 
     // parent profile is updated
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
     assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
 
     // child profile is inherited
-    activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
+    activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
     assertThat(activeRules).hasSize(1);
     assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
     assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.INHERITED);
@@ -241,7 +241,7 @@ public class QProfileBackuperMediumTest {
       Resources.toString(getClass().getResource("QProfileBackuperMediumTest/keep_other_inherited_rules.xml"), Charsets.UTF_8)), QProfileTesting.XOO_P2_NAME);
 
     // x1 and x2
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY);
     assertThat(activeRules).hasSize(2);
   }
 
@@ -274,12 +274,12 @@ public class QProfileBackuperMediumTest {
       Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)),
       QProfileTesting.XOO_P3_NAME);
 
-    List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
+    List<ActiveRule> activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY);
     assertThat(activeRules).hasSize(0);
 
     QualityProfileDto target = db.qualityProfileDao().getByNameAndLanguage("P3", "xoo");
     assertThat(target).isNotNull();
-    activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(target.getKey());
+    activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(target.getKey());
     assertThat(activeRules).hasSize(1);
   }
 
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java
new file mode 100644 (file)
index 0000000..72c4ea9
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.*;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.ServerTester;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class QProfileExportersTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester().addComponents(
+    XooRulesDefinition.class, XooProfileDefinition.class,
+    XooExporter.class, StandardExporter.class);
+
+  QProfileExporters exporters = tester.get(QProfileExporters.class);
+
+  @Test
+  public void exportersForLanguage() throws Exception {
+    assertThat(exporters.exportersForLanguage("xoo")).hasSize(2);
+    assertThat(exporters.exportersForLanguage("java")).hasSize(1);
+    assertThat(exporters.exportersForLanguage("java").get(0)).isInstanceOf(StandardExporter.class);
+  }
+
+  @Test
+  public void mimeType() throws Exception {
+    assertThat(exporters.mimeType("xootool")).isEqualTo("plain/custom");
+
+    // default mime type
+    assertThat(exporters.mimeType("standard")).isEqualTo("plain/text");
+  }
+
+  @Test
+  public void export() {
+    QualityProfileDto profile = tester.get(QProfileLoader.class).getByLangAndName("xoo", "P1");
+    assertThat(exporters.export(profile.getKey(), "xootool")).isEqualTo("xoo -> P1 -> 1");
+    assertThat(exporters.export(profile.getKey(), "standard")).isEqualTo("standard -> P1 -> 1");
+  }
+
+  @Test
+  public void fail_if_missing_exporter() {
+    QualityProfileDto profile = tester.get(QProfileLoader.class).getByLangAndName("xoo", "P1");
+    try {
+      exporters.export(profile.getKey(), "unknown");
+      fail();
+    } catch (NotFoundException e) {
+      assertThat(e).hasMessage("Unknown quality profile exporter: unknown");
+    }
+  }
+
+  @Test
+  public void fail_if_missing_profile() {
+    try {
+      exporters.export("unknown", "xootool");
+      fail();
+    } catch (NotFoundException e) {
+      assertThat(e).hasMessage("Unknown Quality profile: unknown");
+    }
+  }
+
+  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 StandardExporter extends ProfileExporter {
+    public StandardExporter() {
+      super("standard", "Standard");
+    }
+
+    @Override
+    public void exportProfile(RulesProfile profile, Writer writer) {
+      try {
+        writer.write("standard -> " + profile.getName() + " -> " + profile.getActiveRules().size());
+      } catch (IOException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+  public static class XooRulesDefinition implements RulesDefinition {
+    @Override
+    public void define(Context context) {
+      NewRepository repository = context.createRepository("xoo", "xoo").setName("Xoo Repo");
+      NewRule x1 = repository.createRule("R1")
+        .setName("R1 name")
+        .setHtmlDescription("R1 desc")
+        .setSeverity(Severity.MINOR);
+      x1.createParam("acceptWhitespace")
+        .setDefaultValue("false")
+        .setType(RuleParamType.BOOLEAN)
+        .setDescription("Accept whitespaces on the line");
+      repository.done();
+    }
+  }
+
+  public static class XooProfileDefinition extends ProfileDefinition {
+    @Override
+    public RulesProfile createProfile(ValidationMessages validation) {
+      RulesProfile profile = RulesProfile.create("P1", "xoo");
+      profile.activateRule(new Rule("xoo", "R1"), RulePriority.BLOCKER).setParameter("acceptWhitespace", "true");
+      return profile;
+    }
+  }
+
+}
index 50584694df2dbde2385a51d2e8f229c226352e16..d4bf7a3ecb839e8ee43341f2af0784805ff48182 100644 (file)
@@ -30,7 +30,6 @@ 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.ProfileExporter;
 import org.sonar.api.profiles.ProfileImporter;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.rule.Severity;
@@ -41,12 +40,9 @@ 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.jpa.session.DatabaseSessionFactory;
 import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.NotFoundException;
 
 import java.io.Reader;
-import java.io.Writer;
 import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -54,11 +50,7 @@ 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;
+import static org.mockito.Mockito.*;
 
 @RunWith(MockitoJUnitRunner.class)
 public class QProfileRepositoryExporterTest {
@@ -66,9 +58,6 @@ public class QProfileRepositoryExporterTest {
   @Mock
   SqlSession session;
 
-  @Mock
-  DatabaseSessionFactory sessionFactory;
-
   @Mock
   DatabaseSession hibernateSession;
 
@@ -76,7 +65,6 @@ public class QProfileRepositoryExporterTest {
   ActiveRuleDao activeRuleDao;
 
   List<ProfileImporter> importers = newArrayList();
-  List<ProfileExporter> exporters = newArrayList();
 
   Integer currentId = 1;
 
@@ -84,8 +72,6 @@ public class QProfileRepositoryExporterTest {
 
   @Before
   public void setUp() throws Exception {
-    when(sessionFactory.getSession()).thenReturn(hibernateSession);
-
     // Associate an id when inserting an object to simulate the db id generator
     doAnswer(new Answer() {
       public Object answer(InvocationOnMock invocation) {
@@ -96,7 +82,7 @@ public class QProfileRepositoryExporterTest {
       }
     }).when(activeRuleDao).insert(any(ActiveRuleDto.class), any(SqlSession.class));
 
-    operations = new QProfileRepositoryExporter(sessionFactory, activeRuleDao, importers, exporters);
+    operations = new QProfileRepositoryExporter(activeRuleDao, importers);
   }
 
   @Test
@@ -150,7 +136,8 @@ public class QProfileRepositoryExporterTest {
     }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class));
     importers.add(importer);
 
-    QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "<xml/>", session);;
+    QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "<xml/>", session);
+    ;
     assertThat(result.infos()).hasSize(1);
     assertThat(result.warnings()).hasSize(1);
   }
@@ -209,108 +196,22 @@ public class QProfileRepositoryExporterTest {
     verify(importer, never()).importProfile(any(Reader.class), any(ValidationMessages.class));
   }
 
-  @Test
-  public void export_to_plugin_xml() throws Exception {
-    RulesProfile profile = mock(RulesProfile.class);
-    when(profile.getId()).thenReturn(1);
-    when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(profile);
-
-    ProfileExporter exporter = mock(ProfileExporter.class);
-    when(exporter.getKey()).thenReturn("pmd");
-    exporters.add(exporter);
-
-    operations.exportToXml(new QProfile().setId(1), "pmd");
-
-    verify(exporter).exportProfile(eq(profile), any(Writer.class));
-  }
-
-  @Test
-  public void fail_to_export_profile_when_missing_exporter() throws Exception {
-    RulesProfile profile = mock(RulesProfile.class);
-    when(profile.getId()).thenReturn(1);
-    when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(profile);
-
-    ProfileExporter exporter = mock(ProfileExporter.class);
-    when(exporter.getKey()).thenReturn("pmd");
-    exporters.add(exporter);
-
-    try {
-      operations.exportToXml(new QProfile().setId(1), "unknown");
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such exporter : unknown");
-    }
-
-    verify(exporter, never()).exportProfile(any(RulesProfile.class), any(Writer.class));
-  }
-
-  @Test
-  public void fail_to_export_profile_when_profile_is_missing() throws Exception {
-    RulesProfile profile = mock(RulesProfile.class);
-    when(profile.getId()).thenReturn(1);
-    when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(null);
-
-    ProfileExporter exporter = mock(ProfileExporter.class);
-    when(exporter.getKey()).thenReturn("pmd");
-    exporters.add(exporter);
-
-    try {
-      operations.exportToXml(new QProfile().setId(1), "pmd");
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("This profile does not exist");
-    }
-
-    verify(exporter, never()).exportProfile(any(RulesProfile.class), any(Writer.class));
-  }
-
-  @Test
-  public void get_profile_exporter_mime_type() throws Exception {
-    ProfileExporter exporter = mock(ProfileExporter.class);
-    when(exporter.getKey()).thenReturn("pmd");
-    when(exporter.getMimeType()).thenReturn("mime");
-    exporters.add(exporter);
-
-    assertThat(operations.getProfileExporterMimeType("pmd")).isEqualTo("mime");
-  }
-
-  @Test
-  public void get_profile_exporters_for_language() throws Exception {
-    // 2 exporters not declaring supported languages -> match all languages -> to be include in result
-    ProfileExporter exporterWithEmptySupportedLanguagesList = mock(ProfileExporter.class);
-    when(exporterWithEmptySupportedLanguagesList.getSupportedLanguages()).thenReturn(new String[]{});
-    exporters.add(exporterWithEmptySupportedLanguagesList);
-    exporters.add(mock(ProfileExporter.class));
-
-    // 1 exporter supporting the java language -> to be include in result
-    ProfileExporter exporterSupportingJava = mock(ProfileExporter.class);
-    when(exporterSupportingJava.getSupportedLanguages()).thenReturn(new String[]{"java"});
-    exporters.add(exporterSupportingJava);
-
-    // 1 exporter supporting another language -> not to be include in result
-    ProfileExporter exporterSupportingAnotherLanguage = mock(ProfileExporter.class);
-    when(exporterSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[]{"js"});
-    exporters.add(exporterSupportingAnotherLanguage);
-
-    assertThat(operations.getProfileExportersForLanguage("java")).hasSize(3);
-  }
-
   @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[]{});
+    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"});
+    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"});
+    when(importerSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[] {"js"});
     importers.add(importerSupportingAnotherLanguage);
 
     assertThat(operations.getProfileImportersForLanguage("java")).hasSize(3);
index 184c4ca0232fd457db6e238b9cb2a394aa78ad5b..49b7d9470923e319ca61045f8cf6de02a5bfdb37 100644 (file)
@@ -60,6 +60,7 @@ public class QProfileServiceMediumTest {
   DbClient db;
   DbSession dbSession;
   QProfileService service;
+  QProfileLoader loader;
   RuleActivator activator;
 
   @Before
@@ -68,6 +69,7 @@ public class QProfileServiceMediumTest {
     db = tester.get(DbClient.class);
     dbSession = db.openSession(false);
     service = tester.get(QProfileService.class);
+    loader = tester.get(QProfileLoader.class);
     activator = tester.get(RuleActivator.class);
 
     // create pre-defined rules
@@ -94,7 +96,7 @@ public class QProfileServiceMediumTest {
 
     dbSession.clearCache();
 
-    Map<String, Long> counts = service.countAllActiveRules();
+    Map<String, Long> counts = loader.countAllActiveRules();
     assertThat(counts).hasSize(2);
     assertThat(counts.keySet()).containsOnly(XOO_P1_KEY, XOO_P2_KEY);
     assertThat(counts.values()).containsOnly(1L, 1L);
@@ -108,7 +110,7 @@ public class QProfileServiceMediumTest {
     service.activate(XOO_P2_KEY, new RuleActivation(RuleTesting.XOO_X1).setSeverity("BLOCKER"));
     dbSession.clearCache();
 
-    Map<String, Multimap<String, FacetValue>> stats = service.getAllProfileStats();
+    Map<String, Multimap<String, FacetValue>> stats = loader.getAllProfileStats();
 
     assertThat(stats.size()).isEqualTo(2);
     assertThat(stats.get(XOO_P1_KEY).size()).isEqualTo(3);
@@ -132,7 +134,7 @@ public class QProfileServiceMediumTest {
     service.activate(XOO_P1_KEY, new RuleActivation(RuleTesting.XOO_X1).setSeverity("BLOCKER"));
     dbSession.commit();
 
-    assertThat(service.countDeprecatedActiveRulesByProfile(XOO_P1_KEY)).isEqualTo(1);
+    assertThat(loader.countDeprecatedActiveRulesByProfile(XOO_P1_KEY)).isEqualTo(1);
   }
 
   @Test
index 8deaf65a854a68fd80e1573a61fd81d386bb3e6e..fa7103646a92b393589def1b75db9149a0ddbeed 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.api.server.debt.DebtModel;
 import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.qualityprofile.QProfileLoader;
 import org.sonar.server.qualityprofile.QProfileService;
 import org.sonar.server.qualityprofile.QProfileTesting;
 import org.sonar.server.rule.RuleRepositories;
@@ -63,11 +64,11 @@ public class AppActionTest {
   DebtModel debtModel;
 
   @Mock
-  QProfileService qualityProfileService;
+  QProfileLoader profileLoader;
 
   @Test
   public void should_generate_app_init_info() throws Exception {
-    AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, qualityProfileService);
+    AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, profileLoader);
     WsTester tester = new WsTester(new RulesWebService(
       mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class),
       app, mock(UpdateAction.class), mock(DeleteAction.class)));
@@ -76,7 +77,7 @@ public class AppActionTest {
 
     QualityProfileDto profile1 = QProfileTesting.newXooP1();
     QualityProfileDto profile2 = QProfileTesting.newXooP2().setParentKee(QProfileTesting.XOO_P1_KEY);
-    when(qualityProfileService.findAll()).thenReturn(ImmutableList.of(profile1, profile2));
+    when(profileLoader.findAll()).thenReturn(ImmutableList.of(profile1, profile2));
 
     Language xoo = mock(Language.class);
     when(xoo.getKey()).thenReturn("xoo");