]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5007 Complete new web services api/qualityprofiles and api/rules
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 12 May 2014 21:36:54 +0000 (23:36 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 12 May 2014 21:50:40 +0000 (23:50 +0200)
30 files changed:
sonar-core/src/main/java/org/sonar/core/db/Dao.java
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java
sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileKey.java
sonar-core/src/test/java/org/sonar/core/persistence/AbstractDaoTestCase.java
sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java
sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
sonar-server/src/main/java/org/sonar/server/db/DbClient.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleService.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivationContextFactory.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java [deleted file]
sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWs.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RuleActivationActions.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleNormalizer.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/rule2/ws/RulesWebService.java
sonar-server/src/main/java/org/sonar/server/rule2/ws/SetTagsAction.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/rule2/ws/TagsAction.java
sonar-server/src/main/java/org/sonar/server/search/BaseNormalizer.java
sonar-server/src/test/java/org/sonar/server/db/DbClientTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRecreateBuiltInActionTest.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java
sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/rule2/ws/RulesWebServiceTest.java

index 139fc06d0c2f6a0ec79a60b207fde583b56095bf..f19951d065f8589f24c9b4c5265913fab90b9ce7 100644 (file)
  */
 package org.sonar.core.db;
 
+import org.sonar.api.ServerComponent;
 import org.sonar.core.persistence.DbSession;
 
 import javax.annotation.CheckForNull;
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.List;
 
-public interface Dao<E extends Dto<K>, K extends Serializable> {
+public interface Dao<E extends Dto<K>, K extends Serializable> extends ServerComponent {
 
   @CheckForNull
   E getByKey(K key, DbSession session);
@@ -36,11 +38,11 @@ public interface Dao<E extends Dto<K>, K extends Serializable> {
 
   E insert(E item, DbSession session);
 
-   List<E> insert(List<E> items, DbSession session);
+  List<E> insert(List<E> items, DbSession session);
 
   void delete(E item, DbSession session);
 
-  void delete(List<E> items, DbSession session);
+  void delete(Collection<E> items, DbSession session);
 
   void deleteByKey(K key, DbSession session);
 
index c58d2eb57511cc9c298661b68a8068baf2381250..90bb4c29746659ac8ebb663e47c4adfcb4fc9aa6 100644 (file)
@@ -32,6 +32,7 @@ import java.sql.Statement;
  */
 public final class DatabaseUtils {
   private DatabaseUtils() {
+    // only static methods
   }
 
   public static void closeQuietly(@Nullable Connection connection) {
index cef4501b74b561f03b1d7185daae7e0eae1b65fd..f6677a43d5129fafe94eabccb6c1e32317897d8d 100644 (file)
@@ -32,7 +32,7 @@ import java.io.Serializable;
 public class QualityProfileKey implements Serializable{
   private final String name, lang;
 
-  protected QualityProfileKey(String name, String lang) {
+  private QualityProfileKey(String name, String lang) {
     this.lang = lang;
     this.name = name;
   }
index f4db47a783ee20a777040bf3d86fee0a88b81586..bd5113bccf528717ca1181acd8c751a922ad40c7 100644 (file)
@@ -19,9 +19,6 @@
  */
 package org.sonar.core.persistence;
 
-import org.sonar.core.cluster.NullQueue;
-
-import org.sonar.core.cluster.WorkQueue;
 import com.google.common.collect.Maps;
 import com.google.common.io.Closeables;
 import org.apache.commons.io.FileUtils;
@@ -33,7 +30,11 @@ import org.dbunit.DatabaseUnitException;
 import org.dbunit.IDatabaseTester;
 import org.dbunit.database.DatabaseConfig;
 import org.dbunit.database.IDatabaseConnection;
-import org.dbunit.dataset.*;
+import org.dbunit.dataset.CompositeDataSet;
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.ReplacementDataSet;
 import org.dbunit.dataset.filter.DefaultColumnFilter;
 import org.dbunit.dataset.xml.FlatXmlDataSet;
 import org.dbunit.ext.mssql.InsertIdentityOperation;
@@ -43,6 +44,8 @@ import org.junit.Before;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.config.Settings;
+import org.sonar.core.cluster.NullQueue;
+import org.sonar.core.cluster.WorkQueue;
 import org.sonar.core.config.Logback;
 
 import java.io.File;
@@ -56,10 +59,10 @@ import java.sql.SQLException;
 import java.util.Map;
 import java.util.Properties;
 
-import static org.mockito.Mockito.mock;
 import static org.junit.Assert.fail;
 
 public abstract class AbstractDaoTestCase {
+
   private static final Logger LOG = LoggerFactory.getLogger(AbstractDaoTestCase.class);
   private static Database database;
   private static DatabaseCommands databaseCommands;
@@ -90,7 +93,7 @@ public abstract class AbstractDaoTestCase {
       databaseCommands = DatabaseCommands.forDialect(database.getDialect());
       databaseTester = new DataSourceDatabaseTester(database.getDataSource());
 
-      myBatis = new MyBatis(database, new Logback(),queue);
+      myBatis = new MyBatis(database, new Logback(), queue);
       myBatis.start();
     }
 
index 6f9941d0966250ed060e4187d37ffcb8ff4ee492..5d0ad07a3b0daf8edaefc5d8b88028cafcf9f6b3 100644 (file)
@@ -19,9 +19,6 @@
  */
 package org.sonar.core.persistence;
 
-import org.sonar.core.cluster.NullQueue;
-
-import org.sonar.core.cluster.WorkQueue;
 import com.google.common.collect.Maps;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.dbutils.DbUtils;
@@ -48,6 +45,8 @@ import org.junit.rules.ExternalResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.config.Settings;
+import org.sonar.core.cluster.NullQueue;
+import org.sonar.core.cluster.WorkQueue;
 import org.sonar.core.config.Logback;
 import org.sonar.core.persistence.dialect.Dialect;
 
@@ -65,7 +64,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
-import static org.mockito.Mockito.mock;
 import static org.junit.Assert.fail;
 
 /**
index 5a94af5645569318c170657199187da64c49c77b..23fc54e0ea37e46f9b7f8743386feab86d00eaf9 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.server.search.KeyIndexAction;
 
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -170,10 +171,9 @@ public abstract class BaseDao<M, E extends Dto<K>, K extends Serializable> imple
   }
 
   @Override
-  public void delete(List<E> items, DbSession session) {
-    //TODO check for bulk inserts
+  public void delete(Collection<E> items, DbSession session) {
     for(E item:items) {
-      this.delete(item, session);
+      delete(item, session);
     }
   }
 
diff --git a/sonar-server/src/main/java/org/sonar/server/db/DbClient.java b/sonar-server/src/main/java/org/sonar/server/db/DbClient.java
new file mode 100644 (file)
index 0000000..b690d6c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.db;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.server.rule2.ActiveRuleDao;
+import org.sonar.server.rule2.RuleDao;
+
+/**
+ * Facade for all db components
+ */
+public class DbClient implements ServerComponent {
+
+  private final MyBatis myBatis;
+  private final RuleDao ruleDao;
+  private final ActiveRuleDao activeRuleDao;
+  private final QualityProfileDao qProfileDao;
+
+  public DbClient(MyBatis myBatis, RuleDao ruleDao, ActiveRuleDao activeRuleDao,
+                  QualityProfileDao qProfileDao) {
+    this.myBatis = myBatis;
+    this.ruleDao = ruleDao;
+    this.activeRuleDao = activeRuleDao;
+    this.qProfileDao = qProfileDao;
+  }
+
+  public DbSession openSession(boolean batch) {
+    return myBatis.openSession(batch);
+  }
+
+  public RuleDao ruleDao() {
+    return ruleDao;
+  }
+
+  public ActiveRuleDao activeRuleDao() {
+    return activeRuleDao;
+  }
+
+  public QualityProfileDao qualityProfileDao() {
+    return qProfileDao;
+  }
+}
index 55426551d76294c3c9a006b734a99067d51aea44..68371960e3f98ab4cc208ce71cc95d2221eac79d 100644 (file)
@@ -55,7 +55,13 @@ import org.sonar.core.measure.MeasureFilterFactory;
 import org.sonar.core.metric.DefaultMetricFinder;
 import org.sonar.core.notification.DefaultNotificationManager;
 import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.*;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DefaultDatabase;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.PreviewDatabaseFactory;
+import org.sonar.core.persistence.SemaphoreUpdater;
+import org.sonar.core.persistence.SemaphoresImpl;
 import org.sonar.core.preview.PreviewCache;
 import org.sonar.core.profiling.Profiling;
 import org.sonar.core.purge.PurgeProfiler;
@@ -84,13 +90,36 @@ import org.sonar.server.component.DefaultRubyComponentService;
 import org.sonar.server.component.ws.ComponentsWs;
 import org.sonar.server.component.ws.ProjectsWs;
 import org.sonar.server.component.ws.ResourcesWs;
+import org.sonar.server.db.DbClient;
 import org.sonar.server.db.EmbeddedDatabaseFactory;
 import org.sonar.server.db.migrations.DatabaseMigrations;
 import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.*;
+import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
+import org.sonar.server.debt.DebtModelBackup;
+import org.sonar.server.debt.DebtModelLookup;
+import org.sonar.server.debt.DebtModelOperations;
+import org.sonar.server.debt.DebtModelPluginRepository;
+import org.sonar.server.debt.DebtModelService;
+import org.sonar.server.debt.DebtModelXMLExporter;
+import org.sonar.server.debt.DebtRulesXMLImporter;
 import org.sonar.server.es.ESIndex;
 import org.sonar.server.es.ESNode;
-import org.sonar.server.issue.*;
+import org.sonar.server.issue.ActionService;
+import org.sonar.server.issue.AssignAction;
+import org.sonar.server.issue.CommentAction;
+import org.sonar.server.issue.DefaultIssueFinder;
+import org.sonar.server.issue.InternalRubyIssueService;
+import org.sonar.server.issue.IssueBulkChangeService;
+import org.sonar.server.issue.IssueChangelogFormatter;
+import org.sonar.server.issue.IssueChangelogService;
+import org.sonar.server.issue.IssueCommentService;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.issue.IssueStatsFinder;
+import org.sonar.server.issue.PlanAction;
+import org.sonar.server.issue.PublicRubyIssueService;
+import org.sonar.server.issue.ServerIssueStorage;
+import org.sonar.server.issue.SetSeverityAction;
+import org.sonar.server.issue.TransitionAction;
 import org.sonar.server.issue.actionplan.ActionPlanService;
 import org.sonar.server.issue.actionplan.ActionPlanWs;
 import org.sonar.server.issue.filter.IssueFilterService;
@@ -108,21 +137,74 @@ import org.sonar.server.permission.ws.PermissionsWs;
 import org.sonar.server.platform.ws.RestartHandler;
 import org.sonar.server.platform.ws.ServerWs;
 import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.plugins.*;
+import org.sonar.server.plugins.BatchWs;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerExtensionInstaller;
+import org.sonar.server.plugins.ServerPluginJarInstaller;
+import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.plugins.UpdateCenterClient;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
 import org.sonar.server.qualitygate.QgateProjectFinder;
 import org.sonar.server.qualitygate.QualityGates;
 import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.*;
-import org.sonar.server.qualityprofile.*;
-import org.sonar.server.qualityprofile.ws.ActivateRuleAction;
+import org.sonar.server.qualitygate.ws.QGatesAppAction;
+import org.sonar.server.qualitygate.ws.QGatesCopyAction;
+import org.sonar.server.qualitygate.ws.QGatesCreateAction;
+import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
+import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
+import org.sonar.server.qualitygate.ws.QGatesListAction;
+import org.sonar.server.qualitygate.ws.QGatesRenameAction;
+import org.sonar.server.qualitygate.ws.QGatesSearchAction;
+import org.sonar.server.qualitygate.ws.QGatesSelectAction;
+import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
+import org.sonar.server.qualitygate.ws.QGatesShowAction;
+import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
+import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesWs;
+import org.sonar.server.qualityprofile.ActiveRuleService;
+import org.sonar.server.qualityprofile.DefaultProfilesCache;
+import org.sonar.server.qualityprofile.ESActiveRule;
+import org.sonar.server.qualityprofile.ProfilesManager;
+import org.sonar.server.qualityprofile.QProfileActiveRuleOperations;
+import org.sonar.server.qualityprofile.QProfileBackup;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.qualityprofile.QProfileOperations;
+import org.sonar.server.qualityprofile.QProfileProjectLookup;
+import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.qualityprofile.QProfileRepositoryExporter;
+import org.sonar.server.qualityprofile.QProfileRuleLookup;
+import org.sonar.server.qualityprofile.QProfiles;
+import org.sonar.server.qualityprofile.RuleActivationContextFactory;
+import org.sonar.server.qualityprofile.ws.RuleActivationActions;
 import org.sonar.server.qualityprofile.ws.ProfilesWs;
 import org.sonar.server.qualityprofile.ws.QProfileRecreateBuiltInAction;
 import org.sonar.server.qualityprofile.ws.QProfilesWs;
-import org.sonar.server.rule.*;
-import org.sonar.server.rule.ws.*;
+import org.sonar.server.rule.DeprecatedRulesDefinition;
+import org.sonar.server.rule.ESRuleTags;
+import org.sonar.server.rule.RegisterRules;
+import org.sonar.server.rule.RubyRuleService;
+import org.sonar.server.rule.RuleDefinitionsLoader;
+import org.sonar.server.rule.RuleOperations;
+import org.sonar.server.rule.RuleRegistry;
+import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.rule.RuleTagLookup;
+import org.sonar.server.rule.RuleTagOperations;
+import org.sonar.server.rule.RuleTags;
+import org.sonar.server.rule.Rules;
+import org.sonar.server.rule.ws.AddTagsWsHandler;
+import org.sonar.server.rule.ws.RemoveTagsWsHandler;
+import org.sonar.server.rule.ws.RuleSearchWsHandler;
+import org.sonar.server.rule.ws.RuleShowWsHandler;
+import org.sonar.server.rule.ws.RuleTagsWs;
+import org.sonar.server.rule.ws.RulesWs;
 import org.sonar.server.rule2.RuleService;
 import org.sonar.server.rule2.ws.RulesWebService;
 import org.sonar.server.rule2.ws.SearchAction;
+import org.sonar.server.rule2.ws.SetTagsAction;
 import org.sonar.server.rule2.ws.TagsAction;
 import org.sonar.server.search.IndexUtils;
 import org.sonar.server.source.CodeColorizers;
@@ -133,7 +215,21 @@ import org.sonar.server.source.ws.ScmAction;
 import org.sonar.server.source.ws.ScmWriter;
 import org.sonar.server.source.ws.ShowAction;
 import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.*;
+import org.sonar.server.startup.CleanPreviewAnalysisCache;
+import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
+import org.sonar.server.startup.GeneratePluginIndex;
+import org.sonar.server.startup.GwtPublisher;
+import org.sonar.server.startup.JdbcDriverDeployer;
+import org.sonar.server.startup.LogServerId;
+import org.sonar.server.startup.RegisterDashboards;
+import org.sonar.server.startup.RegisterDebtModel;
+import org.sonar.server.startup.RegisterMetrics;
+import org.sonar.server.startup.RegisterNewMeasureFilters;
+import org.sonar.server.startup.RegisterPermissionTemplates;
+import org.sonar.server.startup.RegisterQualityProfiles;
+import org.sonar.server.startup.RegisterServletFilters;
+import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
+import org.sonar.server.startup.ServerMetadataPersister;
 import org.sonar.server.test.ws.TestsWs;
 import org.sonar.server.text.MacroInterpreter;
 import org.sonar.server.text.RubyTextService;
@@ -142,9 +238,20 @@ import org.sonar.server.ui.JRubyProfiling;
 import org.sonar.server.ui.PageDecorations;
 import org.sonar.server.ui.Views;
 import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.*;
+import org.sonar.server.user.DefaultUserService;
+import org.sonar.server.user.DoPrivileged;
+import org.sonar.server.user.GroupMembershipFinder;
+import org.sonar.server.user.GroupMembershipService;
+import org.sonar.server.user.NewUserNotifier;
+import org.sonar.server.user.SecurityRealmFactory;
 import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.*;
+import org.sonar.server.util.BooleanTypeValidation;
+import org.sonar.server.util.FloatTypeValidation;
+import org.sonar.server.util.IntegerTypeValidation;
+import org.sonar.server.util.StringListTypeValidation;
+import org.sonar.server.util.StringTypeValidation;
+import org.sonar.server.util.TextTypeValidation;
+import org.sonar.server.util.TypeValidations;
 import org.sonar.server.ws.ListingWs;
 import org.sonar.server.ws.WebServiceEngine;
 
@@ -188,7 +295,8 @@ class ServerComponents {
       new TempFolderProvider(),
       System2.INSTANCE,
       org.sonar.server.rule2.RuleDao.class,
-      org.sonar.server.rule2.ActiveRuleDao.class
+      org.sonar.server.rule2.ActiveRuleDao.class,
+      DbClient.class
     ));
     components.addAll(CorePropertyDefinitions.all());
     components.addAll(DatabaseMigrations.CLASSES);
@@ -288,7 +396,7 @@ class ServerComponents {
     pico.addSingleton(QProfileRecreateBuiltInAction.class);
     pico.addSingleton(QProfilesWs.class);
     pico.addSingleton(ProfilesWs.class);
-    pico.addSingleton(ActivateRuleAction.class);
+    pico.addSingleton(RuleActivationActions.class);
     pico.addSingleton(ActiveRuleService.class);
     pico.addSingleton(RuleActivationContextFactory.class);
 
@@ -317,6 +425,7 @@ class ServerComponents {
     pico.addSingleton(SearchAction.class);
     pico.addSingleton(org.sonar.server.rule2.ws.ShowAction.class);
     pico.addSingleton(TagsAction.class);
+    pico.addSingleton(SetTagsAction.class);
 
     // rule tags
     pico.addSingleton(ESRuleTags.class);
index d732e9edc1901636298ca89824b68d4f11af1386..431204c833815bdf67eb74c76c4e9230af3c3554 100644 (file)
@@ -26,11 +26,10 @@ import org.sonar.api.ServerComponent;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.core.rule.RuleParamDto;
-import org.sonar.server.rule2.ActiveRuleDao;
+import org.sonar.server.db.DbClient;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.util.TypeValidations;
 
@@ -41,15 +40,13 @@ import static com.google.common.collect.Lists.newArrayList;
 
 public class ActiveRuleService implements ServerComponent {
 
-  private final MyBatis myBatis;
-  private final ActiveRuleDao activeRuleDao;
+  private final DbClient db;
   private final TypeValidations typeValidations;
   private final RuleActivationContextFactory contextFactory;
 
-  public ActiveRuleService(MyBatis myBatis, ActiveRuleDao activeRuleDao,
+  public ActiveRuleService(DbClient db,
                            RuleActivationContextFactory contextFactory, TypeValidations typeValidations) {
-    this.myBatis = myBatis;
-    this.activeRuleDao = activeRuleDao;
+    this.db = db;
     this.contextFactory = contextFactory;
     this.typeValidations = typeValidations;
   }
@@ -58,10 +55,10 @@ public class ActiveRuleService implements ServerComponent {
    * Activate a rule on a Quality profile. Update configuration (severity/parameters) if the rule is already
    * activated.
    */
-  public List<ActiveRuleChange> activate(RuleActivation activation, UserSession userSession) {
-    verifyPermission(userSession);
+  public List<ActiveRuleChange> activate(RuleActivation activation) {
+    verifyPermission(UserSession.get());
 
-    DbSession dbSession = myBatis.openSession(false);
+    DbSession dbSession = db.openSession(false);
     List<ActiveRuleChange> changes = Lists.newArrayList();
     try {
       RuleActivationContext context = contextFactory.create(activation.getKey(), dbSession);
@@ -94,12 +91,12 @@ public class ActiveRuleService implements ServerComponent {
         ActiveRuleDto activeRule = ActiveRuleDto.createFor(null, null /* TODO */)
           .setKey(change.getKey())
           .setSeverity(change.getSeverity());
-        activeRuleDao.insert(activeRule, dbSession);
+        db.activeRuleDao().insert(activeRule, dbSession);
 
         // TODO insert activeruelparams
 
       } else if (change.getType() == ActiveRuleChange.Type.DEACTIVATED) {
-        activeRuleDao.deleteByKey(change.getKey(), dbSession);
+        db.activeRuleDao().deleteByKey(change.getKey(), dbSession);
 
       } else if (change.getType() == ActiveRuleChange.Type.UPDATED) {
 
@@ -110,13 +107,13 @@ public class ActiveRuleService implements ServerComponent {
   /**
    * Deactivate a rule on a Quality profile. Does nothing if the rule is not activated.
    */
-  public List<ActiveRuleChange> deactivate(ActiveRuleKey key, UserSession userSession) {
-    verifyPermission(userSession);
+  public List<ActiveRuleChange> deactivate(ActiveRuleKey key) {
+    verifyPermission(UserSession.get());
     throw new UnsupportedOperationException("TODO");
   }
 
-  public List<ActiveRuleChange> bulkActivate(BulkRuleActivation activation, UserSession userSession) {
-    verifyPermission(userSession);
+  public List<ActiveRuleChange> bulkActivate(BulkRuleActivation activation) {
+    verifyPermission(UserSession.get());
     throw new UnsupportedOperationException("TODO");
   }
 
index e83a71f62fd66d99d831c86b384072eeae5b8418..9cdc10b0033f4362190373625e34478f5ee4a0bb 100644 (file)
@@ -48,7 +48,7 @@ public class RuleActivation {
     return this;
   }
 
-  public RuleActivation setParam(String key, @Nullable String value) {
+  public RuleActivation setParameter(String key, @Nullable String value) {
     String sanitizedValue = Strings.emptyToNull(value);
     if (value == null) {
       parameters.remove(key);
@@ -58,6 +58,12 @@ public class RuleActivation {
     return this;
   }
 
+  public RuleActivation setParameters(Map<String, String> m) {
+    parameters.clear();
+    parameters.putAll(m);
+    return this;
+  }
+
   public ActiveRuleKey getKey() {
     return key;
   }
index 8d6240fd8dba27cb8d05e92f2ef357e824e57b33..8778f5871722175e998bc9e891564ef4c1964f41 100644 (file)
@@ -26,25 +26,19 @@ 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.QualityProfileDao;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
 import org.sonar.core.qualityprofile.db.QualityProfileKey;
 import org.sonar.core.rule.RuleDto;
-import org.sonar.server.rule2.ActiveRuleDao;
-import org.sonar.server.rule2.RuleDao;
+import org.sonar.server.db.DbClient;
 
 import java.util.Collection;
 
 public class RuleActivationContextFactory implements ServerComponent {
 
-  private final ActiveRuleDao activeRuleDao;
-  private final RuleDao ruleDao;
-  private final QualityProfileDao profileDao;
+  private final DbClient db;
 
-  public RuleActivationContextFactory(ActiveRuleDao activeRuleDao, RuleDao ruleDao, QualityProfileDao profileDao) {
-    this.activeRuleDao = activeRuleDao;
-    this.ruleDao = ruleDao;
-    this.profileDao = profileDao;
+  public RuleActivationContextFactory(DbClient db) {
+    this.db = db;
   }
 
   public RuleActivationContext create(ActiveRuleKey key, DbSession session) {
@@ -68,7 +62,7 @@ public class RuleActivationContextFactory implements ServerComponent {
   }
 
   private RuleDto initRule(RuleKey ruleKey, RuleActivationContext context, DbSession dbSession) {
-    RuleDto rule = ruleDao.getByKey(ruleKey, dbSession);
+    RuleDto rule = db.ruleDao().getByKey(ruleKey, dbSession);
     if (rule == null) {
       throw new IllegalArgumentException("Rule not found: " + ruleKey);
     }
@@ -76,12 +70,12 @@ public class RuleActivationContextFactory implements ServerComponent {
       throw new IllegalArgumentException("Rule was removed: " + ruleKey);
     }
     context.setRule(rule);
-    context.setRuleParams(ruleDao.findRuleParamsByRuleKey(rule.getKey(), dbSession));
+    context.setRuleParams(db.ruleDao().findRuleParamsByRuleKey(rule.getKey(), dbSession));
     return rule;
   }
 
   private QualityProfileDto initProfile(ActiveRuleKey key, RuleActivationContext context, DbSession session, boolean parent) {
-    QualityProfileDto profile = profileDao.selectByNameAndLanguage(
+    QualityProfileDto profile = db.qualityProfileDao().selectByNameAndLanguage(
       key.qProfile().name(), key.qProfile().lang());
     if (profile == null) {
       throw new IllegalArgumentException("Quality profile not found: " + key.qProfile());
@@ -95,10 +89,10 @@ public class RuleActivationContextFactory implements ServerComponent {
   }
 
   private void initActiveRules(ActiveRuleKey key, RuleActivationContext context, DbSession session, boolean parent) {
-    ActiveRuleDto activeRule = activeRuleDao.getByKey(key, session);
+    ActiveRuleDto activeRule = db.activeRuleDao().getByKey(key, session);
     Collection<ActiveRuleParamDto> activeRuleParams = null;
     if (activeRule != null) {
-      context.setActiveRuleParams(activeRuleDao.findParamsByActiveRule(activeRule, session));
+      context.setActiveRuleParams(db.activeRuleDao().findParamsByActiveRule(activeRule, session));
     }
     if (parent) {
       context.setParentActiveRule(activeRule);
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java
deleted file mode 100644 (file)
index 0b49d50..0000000
+++ /dev/null
@@ -1,77 +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.ws;
-
-import org.sonar.api.rule.Severity;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualityprofile.ActiveRuleService;
-
-public class ActivateRuleAction implements RequestHandler {
-
-  private final ActiveRuleService service;
-
-  public ActivateRuleAction(ActiveRuleService service) {
-    this.service = service;
-  }
-
-  void define(WebService.NewController controller) {
-    WebService.NewAction action = controller
-      .createAction("activate_rule")
-      .setDescription("Activate a rule on a Quality profile")
-      .setHandler(this)
-      .setPost(true)
-      .setSince("4.4");
-
-    action.createParam("profile_lang")
-      .setDescription("Profile language")
-      .setRequired(true)
-      .setExampleValue("java");
-
-    action.createParam("profile_name")
-      .setDescription("Profile name")
-      .setRequired(true)
-      .setExampleValue("My profile");
-
-    action.createParam("rule_repo")
-      .setDescription("Rule repository")
-      .setRequired(true)
-      .setExampleValue("squid");
-
-    action.createParam("rule_key")
-      .setDescription("Rule key")
-      .setRequired(true)
-      .setExampleValue("AvoidCycles");
-
-    action.createParam("severity")
-      .setDescription("Severity")
-      .setPossibleValues(Severity.ALL);
-
-    action.createParam("params")
-      .setDescription("Parameters");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-
-  }
-}
index d3dc74ae33482726e11474b2ec23f92b007a40bf..f15d3ef584facaa40349b4d00c92c4b96e3bb0fa 100644 (file)
@@ -24,11 +24,11 @@ import org.sonar.api.server.ws.WebService;
 public class QProfilesWs implements WebService {
 
   private final QProfileRecreateBuiltInAction recreateBuiltInAction;
-  private final ActivateRuleAction activateRuleAction;
+  private final RuleActivationActions ruleActivationActions;
 
-  public QProfilesWs(QProfileRecreateBuiltInAction recreateBuiltInAction, ActivateRuleAction activateRuleAction) {
+  public QProfilesWs(QProfileRecreateBuiltInAction recreateBuiltInAction, RuleActivationActions ruleActivationActions) {
     this.recreateBuiltInAction = recreateBuiltInAction;
-    this.activateRuleAction = activateRuleAction;
+    this.ruleActivationActions = ruleActivationActions;
   }
 
   @Override
@@ -38,7 +38,7 @@ public class QProfilesWs implements WebService {
       .setSince("4.4");
 
     recreateBuiltInAction.define(controller);
-    activateRuleAction.define(controller);
+    ruleActivationActions.define(controller);
 
     controller.done();
   }
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RuleActivationActions.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RuleActivationActions.java
new file mode 100644 (file)
index 0000000..9d80914
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.ws;
+
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileKey;
+import org.sonar.server.qualityprofile.ActiveRuleService;
+import org.sonar.server.qualityprofile.RuleActivation;
+
+public class RuleActivationActions {
+
+  private final ActiveRuleService service;
+
+  public RuleActivationActions(ActiveRuleService service) {
+    this.service = service;
+  }
+
+  void define(WebService.NewController controller) {
+    defineActivateAction(controller);
+    defineDeactivateAction(controller);
+  }
+
+  private void defineActivateAction(WebService.NewController controller) {
+    WebService.NewAction activate = controller
+      .createAction("activate_rule")
+      .setDescription("Activate a rule on a Quality profile")
+      .setHandler(new RequestHandler() {
+        @Override
+        public void handle(Request request, Response response) throws Exception {
+          activate(request, response);
+        }
+      })
+      .setPost(true)
+      .setSince("4.4");
+
+    defineActiveRuleKeyParameters(activate);
+
+    activate.createParam("severity")
+      .setDescription("Severity")
+      .setPossibleValues(Severity.ALL);
+
+    activate.createParam("params")
+      .setDescription("Parameters");
+  }
+
+  private void defineDeactivateAction(WebService.NewController controller) {
+    WebService.NewAction deactivate = controller
+      .createAction("deactivate_rule")
+      .setDescription("Deactivate a rule on a Quality profile")
+      .setHandler(new RequestHandler() {
+        @Override
+        public void handle(Request request, Response response) throws Exception {
+          deactivate(request, response);
+        }
+      })
+      .setPost(true)
+      .setSince("4.4");
+    defineActiveRuleKeyParameters(deactivate);
+  }
+
+  private void defineActiveRuleKeyParameters(WebService.NewAction action) {
+    action.createParam("profile_lang")
+      .setDescription("Profile language")
+      .setRequired(true)
+      .setExampleValue("java");
+
+    action.createParam("profile_name")
+      .setDescription("Profile name")
+      .setRequired(true)
+      .setExampleValue("My profile");
+
+    action.createParam("rule_repo")
+      .setDescription("Rule repository")
+      .setRequired(true)
+      .setExampleValue("squid");
+
+    action.createParam("rule_key")
+      .setDescription("Rule key")
+      .setRequired(true)
+      .setExampleValue("AvoidCycles");
+  }
+
+  private void activate(Request request, Response response) throws Exception {
+    ActiveRuleKey key = readKey(request);
+    RuleActivation activation = new RuleActivation(key);
+    activation.setSeverity(request.param("severity"));
+    String params = request.param("params");
+    if (params != null) {
+      activation.setParameters(KeyValueFormat.parse(params));
+    }
+    service.activate(activation);
+  }
+
+  private void deactivate(Request request, Response response) throws Exception {
+    service.deactivate(readKey(request));
+  }
+
+  private ActiveRuleKey readKey(Request request) {
+    return ActiveRuleKey.of(
+      QualityProfileKey.of(request.mandatoryParam("profile_name"), request.mandatoryParam("profile_lang")),
+      RuleKey.of(request.mandatoryParam("rule_repo"), request.mandatoryParam("rule_key")));
+  }
+}
index 93849fecd1083d6dc80f37e0edba905eaa570294..51a2ca8b53119e19f13ed3003bb631a14dcbf375 100644 (file)
@@ -22,18 +22,16 @@ package org.sonar.server.rule2;
 import org.elasticsearch.action.update.UpdateRequest;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
+import org.sonar.server.db.DbClient;
 import org.sonar.server.search.BaseNormalizer;
 
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 
 public class ActiveRuleNormalizer extends BaseNormalizer<ActiveRuleDto, ActiveRuleKey> {
 
-  private final ActiveRuleDao activeRuleDao;
-
   public static enum ActiveRuleField {
     OVERRIDE("override"),
     INHERITANCE("inheritance"),
@@ -78,16 +76,15 @@ public class ActiveRuleNormalizer extends BaseNormalizer<ActiveRuleDto, ActiveRu
     }
   }
 
-  public ActiveRuleNormalizer(MyBatis mybatis, ActiveRuleDao activeRuleDao) {
-    super(mybatis);
-    this.activeRuleDao = activeRuleDao;
+  public ActiveRuleNormalizer(DbClient db) {
+    super(db);
   }
 
   @Override
   public UpdateRequest normalize(ActiveRuleKey key) {
-    DbSession dbSession = getMyBatis().openSession(false);
+    DbSession dbSession = db().openSession(false);
     try {
-      return normalize(activeRuleDao.getByKey(key, dbSession));
+      return normalize(db().activeRuleDao().getByKey(key, dbSession));
     } finally {
       dbSession.close();
     }
@@ -124,7 +121,7 @@ public class ActiveRuleNormalizer extends BaseNormalizer<ActiveRuleDto, ActiveRu
       XContentBuilder document = jsonBuilder().startObject();
 
       ActiveRuleKey key = rule.getKey();
-      if(key == null){
+      if (key == null) {
         throw new IllegalStateException("Cannot normalize ActiveRuleDto with null key");
       }
 
index 96bea1ed13b72b7b4662ca21393c9e37f0f42bfa..f92e2d7aeac2bb22e4602323b2c5b6fbbc55c90e 100644 (file)
@@ -24,7 +24,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.ibatis.session.ResultContext;
 import org.apache.ibatis.session.ResultHandler;
-import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.persistence.DbSession;
@@ -42,7 +41,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
-public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements BatchComponent, ServerComponent {
+public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements ServerComponent {
 
   public RuleDao() {
     super(new RuleIndexDefinition(), RuleMapper.class);
@@ -78,7 +77,7 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
   }
 
   @CheckForNull
-  public RuleDto getParent(RuleDto rule, DbSession session){
+  public RuleDto getParent(RuleDto rule, DbSession session) {
     Preconditions.checkNotNull(rule.getParentId(), "Rule has no persisted parent!");
     return mapper(session).selectById(rule.getParentId());
   }
@@ -96,9 +95,11 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
     return keys;
   }
 
-  /** Finder methods for Rules */
+  /**
+   * Finder methods for Rules
+   */
 
-  public List<RuleDto> findByNonManual(DbSession session){
+  public List<RuleDto> findByNonManual(DbSession session) {
     return mapper(session).selectNonManual();
   }
 
@@ -115,7 +116,9 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
     return ImmutableList.of(mapper(session).selectByName(name));
   }
 
-  /** Nested DTO RuleParams */
+  /**
+   * Nested DTO RuleParams
+   */
 
   public void addRuleParam(RuleDto rule, RuleParamDto paramDto, DbSession session) {
     Preconditions.checkNotNull(rule.getId(), "Rule id must be set");
@@ -130,7 +133,7 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
     paramDto.setRuleId(rule.getId());
     System.out.println("paramDto = " + paramDto);
     session.enqueue(new EmbeddedIndexAction<RuleKey>(this.getIndexType(), IndexAction.Method.UPDATE, paramDto, rule.getKey()));
-     mapper(session).updateParameter(paramDto);
+    mapper(session).updateParameter(paramDto);
     return paramDto;
   }
 
@@ -140,7 +143,9 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
     session.enqueue(new EmbeddedIndexAction<RuleKey>(this.getIndexType(), IndexAction.Method.DELETE, param, rule.getKey()));
   }
 
-  /** Finder methods for RuleParams */
+  /**
+   * Finder methods for RuleParams
+   */
 
   public List<RuleParamDto> findAllRuleParams(DbSession session) {
     return mapper(session).selectAllParams();
@@ -152,7 +157,7 @@ public class RuleDao extends BaseDao<RuleMapper, RuleDto, RuleKey> implements Ba
 
   public List<RuleParamDto> findRuleParamsByRules(List<RuleDto> ruleDtos, DbSession session) {
     List<RuleParamDto> ruleParamDtos = new ArrayList<RuleParamDto>();
-    for(RuleDto rule:ruleDtos){
+    for (RuleDto rule : ruleDtos) {
       ruleParamDtos.addAll(findRuleParamsByRuleKey(rule.getKey(), session));
     }
     return ruleParamDtos;
index de064ba5ceb959be21d165bff96888a359753c25..319274d5fb5f7dda3b99d0c90cb4b17c44f66f39 100644 (file)
@@ -32,8 +32,6 @@ import org.elasticsearch.search.facet.terms.TermsFacet;
 import org.elasticsearch.search.sort.FieldSortBuilder;
 import org.elasticsearch.search.sort.SortBuilders;
 import org.elasticsearch.search.sort.SortOrder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.core.cluster.WorkQueue;
@@ -54,8 +52,6 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 
 public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
 
-  private static final Logger LOG = LoggerFactory.getLogger(RuleIndex.class);
-
   public static final Set<String> PUBLIC_FIELDS = ImmutableSet.of(
     RuleField.KEY.key(),
     RuleField.NAME.key(),
@@ -86,38 +82,38 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
   protected XContentBuilder getIndexSettings() throws IOException {
     return jsonBuilder().startObject()
       .startObject("index")
-        .field("number_of_replicas", 0)
-        .field("number_of_shards", 3)
-        .startObject("mapper")
-          .field("dynamic", true)
-        .endObject()
-        .startObject("analysis")
-          .startObject("analyzer")
-            .startObject("path_analyzer")
-              .field("type", "custom")
-              .field("tokenizer", "path_hierarchy")
-            .endObject()
-            .startObject("sortable")
-              .field("type", "custom")
-              .field("tokenizer", "keyword")
-              .field("filter", "lowercase")
-            .endObject()
-            .startObject("rule_name")
-              .field("type", "custom")
-              .field("tokenizer", "standard")
-              .array("filter", "lowercase", "rule_name_ngram")
-            .endObject()
-          .endObject()
-          .startObject("filter")
-            .startObject("rule_name_ngram")
-              .field("type", "nGram")
-              .field("min_gram", 3)
-              .field("max_gram", 5)
-              .array("token_chars", "letter", "digit")
-            .endObject()
-          .endObject()
-        .endObject()
-       .endObject()
+      .field("number_of_replicas", 0)
+      .field("number_of_shards", 3)
+      .startObject("mapper")
+      .field("dynamic", true)
+      .endObject()
+      .startObject("analysis")
+      .startObject("analyzer")
+      .startObject("path_analyzer")
+      .field("type", "custom")
+      .field("tokenizer", "path_hierarchy")
+      .endObject()
+      .startObject("sortable")
+      .field("type", "custom")
+      .field("tokenizer", "keyword")
+      .field("filter", "lowercase")
+      .endObject()
+      .startObject("rule_name")
+      .field("type", "custom")
+      .field("tokenizer", "standard")
+      .array("filter", "lowercase", "rule_name_ngram")
+      .endObject()
+      .endObject()
+      .startObject("filter")
+      .startObject("rule_name_ngram")
+      .field("type", "nGram")
+      .field("min_gram", 3)
+      .field("max_gram", 5)
+      .array("token_chars", "letter", "digit")
+      .endObject()
+      .endObject()
+      .endObject()
+      .endObject()
       .endObject();
   }
 
@@ -158,19 +154,19 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
       .endObject();
 
     mapping.startObject(RuleField.NAME.key())
-        .field("type", "multi_field")
-        .startObject("fields")
-          .startObject(RuleField.NAME.key())
-            .field("type", "string")
-            .field("index", "analyzed")
-          .endObject()
-          .startObject("search")
-            .field("type", "string")
-            .field("index", "analyzed")
-            .field("index_analyzer", "rule_name")
-            .field("search_analyzer", "standard")
-          .endObject()
-        .endObject()
+      .field("type", "multi_field")
+      .startObject("fields")
+      .startObject(RuleField.NAME.key())
+      .field("type", "string")
+      .field("index", "analyzed")
+      .endObject()
+      .startObject("search")
+      .field("type", "string")
+      .field("index", "analyzed")
+      .field("index_analyzer", "rule_name")
+      .field("search_analyzer", "standard")
+      .endObject()
+      .endObject()
       .endObject();
 
     mapping.startObject(RuleField.ACTIVE.key())
@@ -194,20 +190,20 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
       .setIndices(this.getIndexName());
 
     /* Integrate Facets */
-    if(options.isFacet()) {
+    if (options.isFacet()) {
       this.setFacets(esSearch);
     }
 
     /* integrate Query Sort */
-    if(query.getSortField() != null){
+    if (query.getSortField() != null) {
       FieldSortBuilder sort = SortBuilders.fieldSort(query.getSortField().field().key());
-      if(query.isAscendingSort()){
+      if (query.isAscendingSort()) {
         sort.order(SortOrder.ASC);
       } else {
         sort.order(SortOrder.DESC);
       }
       esSearch.addSort(sort);
-    } else if(query.getQueryText() != null && !query.getQueryText().isEmpty()){
+    } else if (query.getQueryText() != null && !query.getQueryText().isEmpty()) {
       esSearch.addSort(SortBuilders.scoreSort());
     } else {
       esSearch.addSort(RuleField.UPDATED_AT.key(), SortOrder.DESC);
@@ -220,7 +216,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
     /* integrate Option's Fields */
     if (options.getFieldsToReturn() != null &&
       !options.getFieldsToReturn().isEmpty()) {
-      for(String field:options.getFieldsToReturn()) {
+      for (String field : options.getFieldsToReturn()) {
         esSearch.addField(field);
       }
     } else {
@@ -243,7 +239,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
       qb = QueryBuilders.multiMatchQuery(query.getQueryText(),
         "_id",
         RuleField.NAME.key(),
-        RuleField.NAME.key()+".search",
+        RuleField.NAME.key() + ".search",
         RuleField.HTML_DESCRIPTION.key(),
         RuleField.KEY.key(),
         RuleField.LANGUAGE.key(),
@@ -265,7 +261,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
 
     this.addMultiFieldTermFilter(query.getTags(), fb, RuleField.TAGS.key(), RuleField.SYSTEM_TAGS.key());
 
-    if(query.getStatuses() != null && !query.getStatuses().isEmpty()) {
+    if (query.getStatuses() != null && !query.getStatuses().isEmpty()) {
       Collection<String> stringStatus = new ArrayList<String>();
       for (RuleStatus status : query.getStatuses()) {
         stringStatus.add(status.name());
@@ -273,7 +269,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
       this.addTermFilter(RuleField.STATUS.key(), stringStatus, fb);
     }
 
-    if((query.getLanguages() != null && !query.getLanguages().isEmpty()) ||
+    if ((query.getLanguages() != null && !query.getLanguages().isEmpty()) ||
       (query.getRepositories() != null && !query.getRepositories().isEmpty()) ||
       (query.getSeverities() != null && !query.getSeverities().isEmpty()) ||
       (query.getTags() != null && !query.getTags().isEmpty()) ||
@@ -285,7 +281,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
     }
   }
 
-  private void setFacets(SearchRequestBuilder query){
+  private void setFacets(SearchRequestBuilder query) {
     //TODO there are no aggregation in 0.9!!! Must use facet...
 
      /* the Lang facet */
@@ -313,7 +309,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleQuery, RuleDto, RuleKey> {
 
   @Override
   protected Rule getSearchResult(Map<String, Object> response) {
-    if(response == null){
+    if (response == null) {
       throw new IllegalStateException("Cannot construct Rule with null map!!!");
     }
     return new RuleDoc(response);
index 3ad19f00720453aa2d5667ecb3a864d6a604047a..c510894b5617f4314be41a48f8e50f41b9a34225 100644 (file)
@@ -27,14 +27,13 @@ import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.rule.RuleParamDto;
+import org.sonar.server.db.DbClient;
 import org.sonar.server.search.BaseNormalizer;
 
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 
 public class RuleNormalizer extends BaseNormalizer<RuleDto, RuleKey> {
 
-  private final RuleDao ruleDao;
-
   public static enum RuleField {
     KEY("key"),
     REPOSITORY("repo"),
@@ -90,16 +89,15 @@ public class RuleNormalizer extends BaseNormalizer<RuleDto, RuleKey> {
     }
   }
 
-  public RuleNormalizer(MyBatis myBatis, RuleDao ruleDao) {
-    super(myBatis);
-    this.ruleDao = ruleDao;
+  public RuleNormalizer(DbClient db) {
+    super(db);
   }
 
   @Override
   public UpdateRequest normalize(RuleKey key) {
-    DbSession dbSession = getMyBatis().openSession(false);
+    DbSession dbSession = db().openSession(false);
     try {
-      return normalize(ruleDao.getByKey(key, dbSession));
+      return normalize(db().ruleDao().getByKey(key, dbSession));
     } finally {
       dbSession.close();
     }
index 84d4c1de835a498a5f39542ec156fff17b58c935..24bc177080f81516c8a0b9ce9374e4c05ce8d7aa 100644 (file)
@@ -21,32 +21,34 @@ package org.sonar.server.rule2;
 
 import org.sonar.api.ServerComponent;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.core.rule.RuleDao;
-import org.sonar.server.search.Hit;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.search.QueryOptions;
 import org.sonar.server.search.Result;
+import org.sonar.server.user.UserSession;
 
 import javax.annotation.CheckForNull;
-import java.util.List;
+import java.util.Set;
 
 /**
  * @since 4.4
  */
 public class RuleService implements ServerComponent {
 
-  private RuleIndex index;
+  private final RuleIndex index;
+  private final DbClient db;
 
-  public RuleService(RuleIndex index) {
+  public RuleService(RuleIndex index, DbClient db) {
     this.index = index;
+    this.db = db;
   }
 
   @CheckForNull
   public Rule getByKey(RuleKey key) {
-    Rule hit = index.getByKey(key);
-    if (hit != null) {
-      return hit;
-    }
-    return null;
+    return index.getByKey(key);
   }
 
   public RuleQuery newRuleQuery() {
@@ -63,10 +65,33 @@ public class RuleService implements ServerComponent {
   /**
    * List all tags
    */
-  public List<String> listTags() {
+  public Set<String> listTags() {
     throw new UnsupportedOperationException("TODO");
   }
 
+  public void setTags(RuleKey ruleKey, Set<String> tags) {
+    checkAdminPermission(UserSession.get());
+
+    DbSession dbSession = db.openSession(false);
+    try {
+      RuleDto rule = db.ruleDao().getByKey(ruleKey, dbSession);
+      if (rule == null) {
+        throw new NotFoundException(String.format("Rule %s not found", ruleKey));
+      }
+      boolean changed = RuleTagHelper.applyTags(rule, tags);
+      if (changed) {
+        db.ruleDao().update(rule, dbSession);
+        dbSession.commit();
+      }
+    } finally {
+      dbSession.close();
+    }
+  }
+
+  private void checkAdminPermission(UserSession userSession) {
+    userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+  }
+
   public RuleService refresh() {
     this.index.refresh();
     return this;
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java
new file mode 100644 (file)
index 0000000..99c9535
--- /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.server.rule2;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Sets;
+import org.sonar.api.server.rule.RuleTagFormat;
+import org.sonar.core.rule.RuleDto;
+
+import javax.annotation.Nullable;
+import java.util.Set;
+
+class RuleTagHelper {
+
+  private RuleTagHelper() {
+    // only static stuff
+  }
+
+  /**
+   * Validates tags and resolves conflicts between user and system tags.
+   */
+  static boolean applyTags(RuleDto rule, Set<String> tags) {
+    for (String tag : tags) {
+      RuleTagFormat.validate(tag);
+    }
+
+    Set<String> initialTags = rule.getTags();
+    final Set<String> systemTags = rule.getSystemTags();
+    Set<String> withoutSystemTags = Sets.filter(tags, new Predicate<String>() {
+      @Override
+      public boolean apply(@Nullable String input) {
+        return input != null && !systemTags.contains(input);
+      }
+    });
+    rule.setTags(withoutSystemTags);
+    return Sets.difference(initialTags, withoutSystemTags).size() > 0;
+  }
+}
index 11756b8fb96ed243413bc4634370588434bc707e..b665e0c2749f08edd8383772bb1c931ebca4c7e4 100644 (file)
@@ -26,11 +26,13 @@ public class RulesWebService implements WebService {
   private final SearchAction search;
   private final ShowAction show;
   private final TagsAction tags;
+  private final SetTagsAction setTags;
 
-  public RulesWebService(SearchAction search, ShowAction show, TagsAction tags) {
+  public RulesWebService(SearchAction search, ShowAction show, TagsAction tags, SetTagsAction setTags) {
     this.search = search;
     this.show = show;
     this.tags = tags;
+    this.setTags = setTags;
   }
 
   @Override
@@ -42,6 +44,7 @@ public class RulesWebService implements WebService {
     search.define(controller);
     show.define(controller);
     tags.define(controller);
+    setTags.define(controller);
 
     controller.done();
   }
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SetTagsAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SetTagsAction.java
new file mode 100644 (file)
index 0000000..170f1b1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.rule2.ws;
+
+import com.google.common.collect.Sets;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.rule2.RuleService;
+
+import java.util.Set;
+
+public class SetTagsAction implements RequestHandler {
+
+  private final RuleService service;
+
+  public SetTagsAction(RuleService service) {
+    this.service = service;
+  }
+
+  void define(WebService.NewController controller) {
+    WebService.NewAction setTags = controller
+      .createAction("set_tags")
+      .setDescription("Set the tags of a coding rule")
+      .setSince("4.4")
+      .setPost(true)
+      .setHandler(this);
+    setTags
+      .createParam("repo")
+      .setRequired(true)
+      .setDescription("Repository key")
+      .setExampleValue("javascript");
+    setTags
+      .createParam("key")
+      .setRequired(true)
+      .setDescription("Rule key")
+      .setExampleValue("EmptyBlock");
+    setTags
+      .createParam("tags")
+      .setDescription("Comma-separated list of tags. Blank value is used to remove all tags.")
+      .setRequired(true)
+      .setExampleValue("java8,security");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    RuleKey key = RuleKey.of(request.mandatoryParam("repo"), request.mandatoryParam("key"));
+    Set<String> tags = Sets.newHashSet(request.paramAsStrings("tags"));
+    service.setTags(key, tags);
+  }
+}
index 38f028afa231e5cedb75770323169dac277023b3..e16fb8b51b56790f4a269f5267d85fd7d8ed0eb0 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.rule2.RuleService;
 
-import java.util.List;
+import java.util.Set;
 
 public class TagsAction implements RequestHandler {
 
@@ -39,14 +39,14 @@ public class TagsAction implements RequestHandler {
   void define(WebService.NewController controller) {
     controller
       .createAction("tags")
-      .setDescription("Search for a collection of relevant rules matching a specified query")
+      .setDescription("List all rule tags")
       .setSince("4.4")
       .setHandler(this);
   }
 
   @Override
   public void handle(Request request, Response response) {
-    List<String> tags = service.listTags();
+    Set<String> tags = service.listTags();
     JsonWriter json = response.newJsonWriter().beginObject();
     json.name("tags").beginArray();
     for (String tag : tags) {
index 8cea549b397d738cf576a52e76b8c4c38ca028b4..d1bb3e914baede1f9af8196afa2e7d40a17076ad 100644 (file)
@@ -24,21 +24,23 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.core.db.Dto;
-import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
 
 import java.io.IOException;
 import java.io.Serializable;
 
 public abstract class BaseNormalizer<E extends Dto<K>, K extends Serializable> {
 
-  private MyBatis myBatis;
+  private static final Logger LOG = LoggerFactory.getLogger(BaseNormalizer.class);
+
+  private final DbClient db;
 
-  protected BaseNormalizer(MyBatis mybatis) {
-    this.myBatis = mybatis;
+  protected BaseNormalizer(DbClient db) {
+    this.db = db;
   }
 
-  protected MyBatis getMyBatis() {
-    return myBatis;
+  protected DbClient db() {
+    return db;
   }
 
   public boolean canNormalize(Class<?> objectClass, Class<?> keyClass) {
@@ -63,8 +65,6 @@ public abstract class BaseNormalizer<E extends Dto<K>, K extends Serializable> {
 
   public abstract UpdateRequest normalize(E dto);
 
-  private static final Logger LOG = LoggerFactory.getLogger(BaseNormalizer.class);
-
   protected void indexField(String field, Object value, XContentBuilder document) {
     try {
       document.field(field, value);
diff --git a/sonar-server/src/test/java/org/sonar/server/db/DbClientTest.java b/sonar-server/src/test/java/org/sonar/server/db/DbClientTest.java
new file mode 100644 (file)
index 0000000..ef296d2
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.db;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.TestDatabase;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.server.rule2.ActiveRuleDao;
+import org.sonar.server.rule2.RuleDao;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class DbClientTest {
+
+  @Rule
+  public TestDatabase db = new TestDatabase();
+
+  @Test
+  public void facade() throws Exception {
+    MyBatis myBatis = db.myBatis();
+    RuleDao ruleDao = mock(RuleDao.class);
+    ActiveRuleDao activeRuleDao = mock(ActiveRuleDao.class);
+    QualityProfileDao qualityProfileDao = mock(QualityProfileDao.class);
+
+    DbClient client = new DbClient(myBatis, ruleDao, activeRuleDao, qualityProfileDao);
+
+    DbSession dbSession = client.openSession(true);
+    assertThat(dbSession).isNotNull();
+    assertThat(dbSession.getConnection().isClosed()).isFalse();
+    dbSession.close();
+
+    // DAO
+    assertThat(client.ruleDao()).isSameAs(ruleDao);
+    assertThat(client.activeRuleDao()).isSameAs(activeRuleDao);
+    assertThat(client.qualityProfileDao()).isSameAs(qualityProfileDao);
+  }
+}
index 5426970eef9cc5aff07d6cf6fc4840aede6b36b9..e6de1bc70ddc46d8c79a10e18c2ffe0ea4d8e5d9 100644 (file)
@@ -46,7 +46,7 @@ public class QProfileRecreateBuiltInActionTest {
   public void setUp() throws Exception {
     tester = new WsTester(new QProfilesWs(
       new QProfileRecreateBuiltInAction(qProfileBackup),
-      new ActivateRuleAction(mock(ActiveRuleService.class))));
+      new RuleActivationActions(mock(ActiveRuleService.class))));
   }
 
   @Test
index 8bb83cb94513987c658f0d16a44ff7b6cef9151b..0e982e50a1f9cafba9dbbd73038a91fe79136c85 100644 (file)
@@ -36,7 +36,7 @@ public class QProfilesWsTest {
 
   @Before
   public void setUp() {
-    controller = new WsTester(new QProfilesWs(new QProfileRecreateBuiltInAction(mock(QProfileBackup.class)), new ActivateRuleAction(mock(ActiveRuleService.class))))
+    controller = new WsTester(new QProfilesWs(new QProfileRecreateBuiltInAction(mock(QProfileBackup.class)), new RuleActivationActions(mock(ActiveRuleService.class))))
       .controller("api/qualityprofiles");
   }
 
@@ -45,11 +45,11 @@ public class QProfilesWsTest {
     assertThat(controller).isNotNull();
     assertThat(controller.path()).isEqualTo("api/qualityprofiles");
     assertThat(controller.description()).isNotEmpty();
-    assertThat(controller.actions()).hasSize(2);
+    assertThat(controller.actions()).hasSize(3);
   }
 
   @Test
-  public void define_recreate_built_in_action() throws Exception {
+  public void define_recreate_built_action() throws Exception {
     WebService.Action restoreProfiles = controller.action("recreate_built_in");
     assertThat(restoreProfiles).isNotNull();
     assertThat(restoreProfiles.isPost()).isTrue();
@@ -57,11 +57,19 @@ public class QProfilesWsTest {
   }
 
   @Test
-  public void define_activate_rule_in_action() throws Exception {
+  public void define_activate_rule_action() throws Exception {
     WebService.Action restoreProfiles = controller.action("activate_rule");
     assertThat(restoreProfiles).isNotNull();
     assertThat(restoreProfiles.isPost()).isTrue();
     assertThat(restoreProfiles.params()).hasSize(6);
   }
 
+  @Test
+  public void define_deactivate_rule_action() throws Exception {
+    WebService.Action restoreProfiles = controller.action("deactivate_rule");
+    assertThat(restoreProfiles).isNotNull();
+    assertThat(restoreProfiles.isPost()).isTrue();
+    assertThat(restoreProfiles.params()).hasSize(4);
+  }
+
 }
index 60a607955ba4e74323fcb092f0e5194fb34f2ed7..4762d18919a10898cf95d2be15f15e6fc98e61de 100644 (file)
@@ -21,9 +21,11 @@ package org.sonar.server.rule2;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
@@ -31,25 +33,32 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.check.Cardinality;
+import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.rule.RuleParamDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
 
 public class RuleServiceMediumTest {
 
   @ClassRule
-  public static ServerTester tester = new ServerTester()
-    .setProperty("sonar.es.http.port","9200");
+  public static ServerTester tester = new ServerTester();
 
   MyBatis myBatis = tester.get(MyBatis.class);
   RuleDao dao = tester.get(RuleDao.class);
   RuleIndex index = tester.get(RuleIndex.class);
+  RuleService service = tester.get(RuleService.class);
   DbSession dbSession;
 
   @Before
@@ -81,10 +90,6 @@ public class RuleServiceMediumTest {
 
     // verify that rule is indexed in es
     index.refresh();
-
-//    Thread.sleep(10000000);
-
-
     Rule hit = index.getByKey(ruleKey);
     assertThat(hit).isNotNull();
     assertThat(hit.key().repository()).isEqualTo(ruleKey.repository());
@@ -100,7 +105,6 @@ public class RuleServiceMediumTest {
     assertThat(hit.template()).isFalse();
     assertThat(hit.tags()).containsOnly("tag1", "tag2");
     assertThat(hit.systemTags()).containsOnly("systag1", "systag2");
-
   }
 
   @Test
@@ -135,7 +139,6 @@ public class RuleServiceMediumTest {
     assertThat(hit).isNotNull();
     assertThat(hit.key()).isNotNull();
 
-
     RuleService service = tester.get(RuleService.class);
     Rule rule = service.getByKey(ruleKey);
 
@@ -143,6 +146,55 @@ public class RuleServiceMediumTest {
     assertThat(Iterables.getLast(rule.params(), null).key()).isEqualTo("max");
   }
 
+  @Test
+  @Ignore
+  public void setTags() {
+    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    // insert db
+    RuleKey rule1 = RuleKey.of("javascript", "S001");
+    dao.insert(newRuleDto(rule1)
+        .setTags(Sets.newHashSet("security"))
+        .setSystemTags(Collections.<String>emptySet()),
+      dbSession
+    );
+
+    RuleKey rule2 = RuleKey.of("java", "S001");
+    dao.insert(newRuleDto(rule2)
+      .setTags(Sets.newHashSet("toberemoved"))
+      .setSystemTags(Sets.newHashSet("bug")), dbSession);
+    dbSession.commit();
+
+    service.setTags(rule2, Sets.newHashSet("bug", "security"));
+
+    // verify that tags are indexed in es
+    service.refresh();
+    Set<String> tags = service.listTags();
+    assertThat(tags).containsOnly("security", "java8", "bug");
+  }
+
+  @Test
+  public void setTags_fail_if_rule_does_not_exist() {
+    try {
+      MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+      service.setTags(RuleKey.of("java", "S001"), Sets.newHashSet("bug", "security"));
+      fail();
+    } catch (NotFoundException e) {
+      assertThat(e).hasMessage("Rule java:S001 not found");
+    }
+  }
+
+  @Test
+  public void setTags_fail_if_not_permitted() {
+    try {
+      MockUserSession.set();
+      service.setTags(RuleKey.of("java", "S001"), Sets.newHashSet("bug", "security"));
+      fail();
+    } catch (ForbiddenException e) {
+      assertThat(e).hasMessage("Insufficient privileges");
+    }
+  }
+
   private RuleDto newRuleDto(RuleKey ruleKey) {
     return new RuleDto()
       .setRuleKey(ruleKey.rule())
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java
new file mode 100644 (file)
index 0000000..fe51a8c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.rule2;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+import org.sonar.core.rule.RuleDto;
+
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class RuleTagHelperTest {
+
+  @Test
+  public void applyTags() throws Exception {
+    RuleDto rule = new RuleDto().setTags(Sets.newHashSet("performance"));
+    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+    assertThat(rule.getTags()).containsOnly("java8", "security");
+  }
+
+  @Test
+  public void applyTags_remove_all_existing_tags() throws Exception {
+    RuleDto rule = new RuleDto().setTags(Sets.newHashSet("performance"));
+    RuleTagHelper.applyTags(rule, Collections.<String>emptySet());
+    assertThat(rule.getTags()).isEmpty();
+  }
+
+  @Test
+  public void applyTags_validate_format() throws Exception {
+    RuleDto rule = new RuleDto();
+    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+    assertThat(rule.getTags()).containsOnly("java8", "security");
+
+    try {
+      RuleTagHelper.applyTags(rule, Sets.newHashSet("Java Eight"));
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e.getMessage()).startsWith("Tag 'Java Eight' is invalid");
+    }
+  }
+
+  @Test
+  public void applyTags_do_not_duplicate_system_tags() throws Exception {
+    RuleDto rule = new RuleDto()
+      .setTags(Sets.newHashSet("performance"))
+      .setSystemTags(Sets.newHashSet("security"));
+
+    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+
+    assertThat(rule.getTags()).containsOnly("java8");
+    assertThat(rule.getSystemTags()).containsOnly("security");
+  }
+}
index 82e499672588b3d2e3b5b799d78d55bd6b227720..3ab3e0751c241cf1a15a96369097b079e34e7440 100644 (file)
@@ -67,10 +67,11 @@ public class RulesWebServiceTest {
     WebService.Controller controller = context.controller("api/rules2");
 
     assertThat(controller).isNotNull();
-    assertThat(controller.actions()).hasSize(3);
+    assertThat(controller.actions()).hasSize(4);
     assertThat(controller.action("search")).isNotNull();
     assertThat(controller.action("show")).isNotNull();
     assertThat(controller.action("tags")).isNotNull();
+    assertThat(controller.action("set_tags")).isNotNull();
   }
 
   @Test
@@ -86,7 +87,6 @@ public class RulesWebServiceTest {
 
   @Test
   public void search_2_rules() throws Exception {
-
     DbSession session = tester.get(MyBatis.class).openSession(false);
     ruleDao.insert(newRuleDto(RuleKey.of("javascript", "S001")), session);
     ruleDao.insert(newRuleDto(RuleKey.of("javascript", "S002")), session);
@@ -96,10 +96,8 @@ public class RulesWebServiceTest {
 
     MockUserSession.set();
     WsTester.TestRequest request = wsTester.newGetRequest("api/rules2", "search");
-    System.out.println("request.toString() = " + request.toString());
-
     WsTester.Result result = request.execute();
-    System.out.println("result.outputAsString() = " + result.outputAsString());
+    //TODO
   }