aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server/src
diff options
context:
space:
mode:
authorStephane Gamard <stephane.gamard@searchbox.com>2014-04-30 07:45:12 +0200
committerStephane Gamard <stephane.gamard@searchbox.com>2014-04-30 10:31:17 +0200
commit26cad71c1190b262971a42565ed97e677fe895f9 (patch)
tree0654b45ebb178c2d4371e37158b872e644ee5326 /sonar-server/src
parent5971e4bde6ffde66db4ba42ce0c447aafe4a7f8c (diff)
downloadsonarqube-26cad71c1190b262971a42565ed97e677fe895f9.tar.gz
sonarqube-26cad71c1190b262971a42565ed97e677fe895f9.zip
SONAR-5237 - Moved Dao Back to server and Using ThreadPool for QueueWorker
Diffstat (limited to 'sonar-server/src')
-rw-r--r--sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java33
-rw-r--r--sonar-server/src/main/java/org/sonar/server/cluster/LocalQueueWorker.java62
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/BaseDao.java139
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java11
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java344
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java125
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java18
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java16
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java17
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/Index.java3
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/IndexAction.java83
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java3
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/IndexUtils.java5
-rw-r--r--sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java48
-rw-r--r--sonar-server/src/test/java/org/sonar/server/cluster/LocalQueueWorkerTest.java46
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleDaoTest.java412
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java35
17 files changed, 1201 insertions, 199 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java b/sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java
index 0a6b282f7ec..dc2e29f2247 100644
--- a/sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java
+++ b/sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java
@@ -19,32 +19,33 @@
*/
package org.sonar.server.cluster;
-import org.sonar.core.cluster.IndexAction;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.cluster.ClusterAction;
import org.sonar.core.cluster.WorkQueue;
-import javax.annotation.CheckForNull;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
-public class LocalNonBlockingWorkQueue implements WorkQueue {
+public class LocalNonBlockingWorkQueue extends LinkedBlockingQueue<Runnable>
+ implements ServerComponent, WorkQueue{
- private final ConcurrentLinkedQueue<IndexAction<?>> actions = new ConcurrentLinkedQueue<IndexAction<?>>();
-
- @Override
- public void enqueue(IndexAction<?> indexAction) {
- actions.offer(indexAction);
+ public LocalNonBlockingWorkQueue(){
+ super();
}
@Override
- public void enqueue(Iterable<IndexAction<?>> indexActions) {
- for (IndexAction<?> action : indexActions) {
- enqueue(action);
+ public void enqueue(ClusterAction action) {
+ try {
+ this.offer(action, 1000,TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ //TODO throw a runtime error here.
}
}
- @CheckForNull
@Override
- public IndexAction<?> dequeue() {
- IndexAction<?> out = actions.poll();
- return out;
+ public void enqueue(Iterable<ClusterAction> actions) {
+ for (ClusterAction action : actions) {
+ enqueue(action);
+ }
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/cluster/LocalQueueWorker.java b/sonar-server/src/main/java/org/sonar/server/cluster/LocalQueueWorker.java
index 57884afc6ce..1cbc2a9b440 100644
--- a/sonar-server/src/main/java/org/sonar/server/cluster/LocalQueueWorker.java
+++ b/sonar-server/src/main/java/org/sonar/server/cluster/LocalQueueWorker.java
@@ -19,70 +19,56 @@
*/
package org.sonar.server.cluster;
-import org.jfree.util.Log;
import org.picocontainer.Startable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
-import org.sonar.core.cluster.IndexAction;
-import org.sonar.core.cluster.WorkQueue;
import org.sonar.server.search.Index;
+import org.sonar.server.search.IndexAction;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
-public class LocalQueueWorker implements ServerComponent, Startable {
+public class LocalQueueWorker extends ThreadPoolExecutor
+ implements ServerComponent, Startable {
- private static final Logger LOG = LoggerFactory.getLogger(LocalNonBlockingWorkQueue.class);
+ private static final Logger LOG = LoggerFactory.getLogger(LocalQueueWorker.class);
- private WorkQueue queue;
-
- private volatile Thread worker;
private Map<String, Index<?>> indexes;
- class Worker implements Runnable {
-
- @Override
- @SuppressWarnings("unchecked")
- public void run() {
- LOG.info("Starting Worker Thread");
- Thread thisThread = Thread.currentThread();
- while (worker == thisThread) {
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- Log.error("Oops");
- }
+ public LocalQueueWorker(LocalNonBlockingWorkQueue queue, Index<?>... allIndexes) {
+ super(10, 10, 500l, TimeUnit.MILLISECONDS, queue);
- @SuppressWarnings("rawtypes")
- IndexAction action = queue.dequeue();
-
- if (action != null && indexes.containsKey(action.getIndexName())) {
- LOG.info("Dequeued action {}",action);
- indexes.get(action.getIndexName()).executeAction(action);
- }
- }
- LOG.info("Stoping Worker Thread");
+ // Save all instances of Index<?>
+ this.indexes = new HashMap<String, Index<?>>();
+ for (Index<?> index : allIndexes) {
+ this.indexes.put(index.getIndexName(), index);
}
}
- public LocalQueueWorker(WorkQueue queue, Index<?>... indexes) {
- this.queue = queue;
- this.worker = new Thread(new Worker());
- this.indexes = new HashMap<String, Index<?>>();
- for(Index<?> index:indexes){
- this.indexes.put(index.getIndexName(), index);
+ protected void beforeExecute(Thread t, Runnable r) {
+ LOG.debug("Starting task: {}",r);
+ super.beforeExecute(t, r);
+ if(r.getClass().isAssignableFrom(IndexAction.class)){
+ IndexAction<?> ia = (IndexAction<?>)r;
+ LOG.trace("Task is an IndexAction for {}",ia.getIndexName());
+ ia.setIndex(indexes.get(ia.getIndexName()));
}
}
+ protected void afterExecute(Runnable r, Throwable t) {
+ super.afterExecute(r, t);
+ }
@Override
public void start() {
- this.worker.start();
+ this.prestartCoreThread();
}
@Override
public void stop() {
- this.worker = null;
+ this.shutdown();
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java b/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
new file mode 100644
index 00000000000..fd588c97f2e
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
@@ -0,0 +1,139 @@
+/*
+ * 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.apache.ibatis.session.SqlSession;
+import org.sonar.core.db.Dao;
+import org.sonar.core.db.Dto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.search.IndexAction;
+
+import java.io.Serializable;
+
+public abstract class BaseDao<E extends Dto<K>, K extends Serializable>
+ implements Dao<E, K> {
+
+ protected MyBatis mybatis;
+
+ protected BaseDao(MyBatis myBatis) {
+ this.mybatis = myBatis;
+ }
+
+ protected abstract String getIndexName();
+
+ protected abstract E doGetByKey(K key, SqlSession session);
+
+ protected abstract E doInsert(E item, SqlSession session);
+
+ protected abstract E doUpdate(E item, SqlSession session);
+
+ protected abstract void doDelete(E item, SqlSession session);
+
+ protected abstract void doDeleteByKey(K key, SqlSession session);
+
+ protected MyBatis getMyBatis() {
+ return this.mybatis;
+ }
+
+ @Override
+ public E getByKey(K key) {
+ DbSession session = getMyBatis().openSession(false);
+ E item = this.doGetByKey(key, session);
+ MyBatis.closeQuietly(session);
+ return item;
+ }
+
+ @Override
+ public E update(E item, DbSession session) {
+ session.enqueue(new IndexAction(this.getIndexName(),
+ IndexAction.Method.UPDATE, item.getKey()));
+ return this.doUpdate(item, session);
+ }
+
+ @Override
+ public E update(E item) {
+ DbSession session = getMyBatis().openSession(false);
+ try {
+ this.update(item, session);
+ session.commit();
+ return item;
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @Override
+ public E insert(E item, DbSession session) {
+ IndexAction action = new IndexAction(this.getIndexName(),
+ IndexAction.Method.INSERT, item.getKey());
+ session.enqueue(action);
+ this.doInsert(item, session);
+ return item;
+ }
+
+ @Override
+ public E insert(E item) {
+ DbSession session = getMyBatis().openSession(false);
+ try {
+ this.insert(item, session);
+ session.commit();
+ return item;
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @Override
+ public void delete(E item, DbSession session) {
+ session.enqueue(new IndexAction(this.getIndexName(),
+ IndexAction.Method.DELETE, item.getKey()));
+ this.doDelete(item, session);
+ }
+
+ @Override
+ public void delete(E item) {
+ DbSession session = getMyBatis().openSession(false);
+ try {
+ this.delete(item, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @Override
+ public void deleteByKey(K key, DbSession session) {
+ session.enqueue(new IndexAction(this.getIndexName(),
+ IndexAction.Method.DELETE, key));
+ this.doDeleteByKey(key, session);
+ }
+
+ @Override
+ public void deleteByKey(K key) {
+ DbSession session = getMyBatis().openSession(false);
+ try {
+ this.doDeleteByKey(key, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index b2fcfe87dcd..4b3521cac18 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -19,6 +19,10 @@
*/
package org.sonar.server.platform;
+import org.sonar.server.cluster.LocalNonBlockingWorkQueue;
+
+import org.sonar.server.rule2.RuleDao;
+import org.sonar.server.rule2.RuleService;
import com.google.common.collect.Lists;
import org.apache.commons.configuration.BaseConfiguration;
import org.sonar.api.config.EmailSettings;
@@ -78,7 +82,6 @@ import org.sonar.jpa.session.DefaultDatabaseConnector;
import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
import org.sonar.server.authentication.ws.AuthenticationWs;
import org.sonar.server.charts.ChartFactory;
-import org.sonar.server.cluster.LocalNonBlockingWorkQueue;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.db.EmbeddedDatabaseFactory;
@@ -170,7 +173,10 @@ class ServerComponents {
SemaphoresImpl.class,
TempFolderCleaner.class,
new TempFolderProvider(),
- System2.INSTANCE
+ System2.INSTANCE,
+
+ /* new RuleDao working with ES */
+ RuleDao.class
));
components.addAll(CorePropertyDefinitions.all());
components.addAll(DatabaseMigrations.CLASSES);
@@ -284,6 +290,7 @@ class ServerComponents {
pico.addSingleton(AddTagsWsHandler.class);
pico.addSingleton(RemoveTagsWsHandler.class);
pico.addSingleton(RulesDefinitionXmlLoader.class);
+ pico.addSingleton(RuleService.class);
// rule tags
pico.addSingleton(ESRuleTags.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
new file mode 100644
index 00000000000..87be472f55a
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
@@ -0,0 +1,344 @@
+/*
+ * 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.Lists;
+import org.apache.ibatis.session.ResultContext;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.core.db.UnsuportedException;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.rule.RuleConstants;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.rule.RuleMapper;
+import org.sonar.core.rule.RuleParamDto;
+import org.sonar.core.rule.RuleRuleTagDto;
+import org.sonar.server.db.BaseDao;
+
+import javax.annotation.CheckForNull;
+
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+public class RuleDao extends BaseDao<RuleDto, RuleKey>
+ implements BatchComponent, ServerComponent {
+
+ public RuleDao(MyBatis mybatis) {
+ super(mybatis);
+ }
+
+ @Override
+ protected String getIndexName() {
+ return RuleConstants.INDEX_NAME;
+ }
+
+ @Override
+ @CheckForNull
+ protected RuleDto doGetByKey(RuleKey key, SqlSession session) {
+ return getMapper(session).selectByKey(key);
+ }
+
+ @Override
+ protected RuleDto doInsert(RuleDto item, SqlSession session) {
+ session.getMapper(RuleMapper.class).insert(item);
+ return item;
+ }
+
+ @Override
+ protected RuleDto doUpdate(RuleDto item, SqlSession session) {
+ session.getMapper(RuleMapper.class).update(item);
+ return item;
+ }
+
+ @Override
+ protected void doDelete(RuleDto item, SqlSession session) {
+ throw new UnsuportedException("Rules cannot be deleted");
+ }
+
+ @Override
+ protected void doDeleteByKey(RuleKey key, SqlSession session) {
+ throw new UnsuportedException("Rules cannot be deleted");
+ }
+
+ public List<RuleDto> selectAll() {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectAll(session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleDto> selectAll(SqlSession session) {
+ return getMapper(session).selectAll();
+ }
+
+ public List<RuleDto> selectEnablesAndNonManual() {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectEnablesAndNonManual(session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleDto> selectEnablesAndNonManual(SqlSession session) {
+ return getMapper(session).selectEnablesAndNonManual();
+ }
+
+ public List<RuleDto> selectNonManual(SqlSession session) {
+ return getMapper(session).selectNonManual();
+ }
+
+ public List<RuleDto> selectBySubCharacteristicId(Integer characteristicOrSubCharacteristicId) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectBySubCharacteristicId(characteristicOrSubCharacteristicId, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ /**
+ * Return all rules (even the REMOVED ones) linked on to a sub characteristic
+ */
+ public List<RuleDto> selectBySubCharacteristicId(Integer subCharacteristicId, SqlSession session) {
+ return getMapper(session).selectBySubCharacteristicId(subCharacteristicId);
+ }
+
+ @CheckForNull
+ public RuleDto selectById(Integer id, SqlSession session) {
+ return getMapper(session).selectById(id);
+ }
+
+ @CheckForNull
+ public RuleDto selectById(Integer id) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectById(id, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public RuleDto selectByKey(RuleKey ruleKey, SqlSession session) {
+ return getMapper(session).selectByKey(ruleKey);
+ }
+
+
+ @CheckForNull
+ public RuleDto selectByKey(RuleKey ruleKey) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectByKey(ruleKey, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public RuleDto selectByName(String name) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return getMapper(session).selectByName(name);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void insert(Collection<RuleDto> rules) {
+ DbSession session = mybatis.openSession(true);
+ try {
+ for (RuleDto rule : rules) {
+ getMapper(session).batchInsert(rule);
+ }
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ // ******************************
+ // Methods for Rule Parameters
+ // ******************************
+
+ public List<RuleParamDto> selectParameters() {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectParameters(session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleParamDto> selectParameters(SqlSession session) {
+ return getMapper(session).selectAllParams();
+ }
+
+ public List<RuleParamDto> selectParametersByRuleId(Integer ruleId) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectParametersByRuleId(ruleId, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleParamDto> selectParametersByRuleId(Integer ruleId, SqlSession session) {
+ return selectParametersByRuleIds(newArrayList(ruleId));
+ }
+
+ public List<RuleParamDto> selectParametersByRuleIds(List<Integer> ruleIds) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectParametersByRuleIds(ruleIds, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleParamDto> selectParametersByRuleIds(List<Integer> ruleIds, SqlSession session) {
+ List<RuleParamDto> dtos = newArrayList();
+ List<List<Integer>> partitionList = Lists.partition(newArrayList(ruleIds), 1000);
+ for (List<Integer> partition : partitionList) {
+ dtos.addAll(getMapper(session).selectParamsByRuleIds(partition));
+ }
+ return dtos;
+ }
+
+ public void insert(RuleParamDto param, SqlSession session) {
+ getMapper(session).insertParameter(param);
+ }
+
+ public void insert(RuleParamDto param) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ insert(param, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void update(RuleParamDto param, SqlSession session) {
+ getMapper(session).updateParameter(param);
+ }
+
+ public void update(RuleParamDto param) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ update(param, session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public RuleParamDto selectParamByRuleAndKey(Integer ruleId, String key, SqlSession session) {
+ return getMapper(session).selectParamByRuleAndKey(ruleId, key);
+ }
+
+ private RuleMapper getMapper(SqlSession session) {
+ return session.getMapper(RuleMapper.class);
+ }
+
+ // ***************************
+ // Methods for Rule Tags
+ // ***************************
+
+ public void insert(RuleRuleTagDto newTag, SqlSession session) {
+ getMapper(session).insertTag(newTag);
+ }
+
+ public void deleteParam(RuleParamDto persistedParam, SqlSession sqlSession) {
+ getMapper(sqlSession).deleteParameter(persistedParam.getId());
+ }
+
+ public void deleteTag(RuleRuleTagDto tagToDelete, SqlSession session) {
+ getMapper(session).deleteTag(tagToDelete.getId().intValue());
+ }
+
+ public void update(RuleRuleTagDto existingTag, SqlSession session) {
+ getMapper(session).updateTag(existingTag);
+ }
+
+ public List<RuleRuleTagDto> selectTags(SqlSession session) {
+ return getMapper(session).selectAllTags();
+ }
+
+ public List<RuleRuleTagDto> selectTagsByRuleId(Integer ruleId) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectTagsByRuleIds(ruleId, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleRuleTagDto> selectTagsByRuleIds(Integer ruleId, SqlSession session) {
+ return selectTagsByRuleIds(newArrayList(ruleId), session);
+ }
+
+ public List<RuleRuleTagDto> selectTagsByRuleIds(List<Integer> ruleIds) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return selectTagsByRuleIds(ruleIds, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<RuleRuleTagDto> selectTagsByRuleIds(List<Integer> ruleIds, SqlSession session) {
+ List<RuleRuleTagDto> dtos = newArrayList();
+ List<List<Integer>> partitionList = Lists.partition(newArrayList(ruleIds), 1000);
+ for (List<Integer> partition : partitionList) {
+ dtos.addAll(getMapper(session).selectTagsByRuleIds(partition));
+ }
+ return dtos;
+ }
+
+ @Override
+ public Collection<RuleKey> keysOfRowsUpdatedAfter(long timestamp) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ final List<RuleKey> keys = Lists.newArrayList();
+ session.select("selectKeysOfRulesUpdatedSince", new Timestamp(timestamp), new ResultHandler() {
+ @Override
+ public void handleResult(ResultContext context) {
+ Map<String, String> map = (Map) context.getResultObject();
+ keys.add(RuleKey.of(map.get("repo"), map.get("rule")));
+ }
+ });
+ return keys;
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java
new file mode 100644
index 00000000000..c3633d38c55
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java
@@ -0,0 +1,125 @@
+/*
+ * 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 org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.server.search.Hit;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RuleImpl implements Rule {
+
+ private Map<String, Object> fields;
+
+ public RuleImpl(){
+ this.fields = new HashMap<String, Object>();
+ }
+
+ private RuleImpl(Map<String, Object> fields){
+ this.fields = fields;
+ }
+
+ @Override
+ public RuleKey key() {
+ return RuleKey.of((String)this.fields.get("repositoryKey"),
+ (String)this.fields.get("ruleKey"));
+ }
+
+ @Override
+ public String language() {
+ return (String) this.fields.get("language");
+ }
+
+ @Override
+ public String name() {
+ return (String) this.fields.get("name");
+ }
+
+ @Override
+ public String description() {
+ return (String) this.fields.get("description");
+ }
+
+ @Override
+ public Severity severity() {
+ //FIXME missign Severity.of(String) or Severity.of(int);
+ return null;
+ }
+
+ @Override
+ public String status() {
+ return (String) this.fields.get("status");
+ }
+
+ @Override
+ public boolean template() {
+ //FIXME missign information in map.
+ return false;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<String> tags() {
+ return (List<String>) this.fields.get("tags");
+ }
+
+ @Override
+ public List<RuleParam> params() {
+ //FIXME not yet Implemented in ES
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String debtCharacteristicKey() {
+ return (String) this.fields.get("debtCharacteristicKey");
+ }
+
+ @Override
+ public String debtSubCharacteristicKey() {
+ return (String) this.fields.get("debtSubCharacteristicKey");
+ }
+
+ @Override
+ public DebtRemediationFunction debtRemediationFunction() {
+ //FIXME how to construct from string "defaultRemediationFunction"
+ return null;
+ }
+
+ @Override
+ public Date createdAt() {
+ return (Date) this.fields.get("createdAt");
+ }
+
+ @Override
+ public Date updatedAt() {
+ return (Date) this.fields.get("updatedAt");
+ }
+
+ public static Rule fromHit(Hit hit) {
+ return new RuleImpl(hit.getFields());
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
index 6d6fd7e0036..229d65bc2b0 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
@@ -19,8 +19,6 @@
*/
package org.sonar.server.rule2;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.ActiveRuleDao;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.slf4j.Logger;
@@ -28,8 +26,10 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.cluster.WorkQueue;
import org.sonar.core.profiling.Profiling;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.rule.RuleConstants;
-import org.sonar.core.rule.RuleDao;
+import org.sonar.server.rule2.RuleDao;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.es.ESNode;
import org.sonar.server.search.BaseIndex;
@@ -47,8 +47,8 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
private ActiveRuleDao activeRuleDao;
- public RuleIndex(WorkQueue queue, RuleDao dao, ActiveRuleDao ActiveRuleDao, Profiling profiling, ESNode node) {
- super(queue, dao, profiling, node);
+ public RuleIndex(WorkQueue workQueue, RuleDao dao, ActiveRuleDao ActiveRuleDao, Profiling profiling, ESNode node) {
+ super(workQueue, dao, profiling, node);
this.activeRuleDao = ActiveRuleDao;
}
@@ -157,10 +157,7 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
try {
- long start = System.currentTimeMillis();
RuleDto rule = dao.getByKey(key);
- LOG.info("Action dao.getByKey(key) in {} took {}ms",
- this.getIndexName(), (System.currentTimeMillis() - start));
XContentBuilder document = jsonBuilder().startObject();
@@ -171,8 +168,6 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
document.field(property.getKey(), property.getValue());
}
- start = System.currentTimeMillis();
-
document.startArray("active");
for (ActiveRuleDto activeRule : activeRuleDao.selectByRuleId(rule.getId())) {
document.startObject();
@@ -185,9 +180,6 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
}
document.endArray();
- LOG.info("Action activeRuleDao.selectByRuleId(rule.getId()) in {} took {}ms",
- this.getIndexName(), (System.currentTimeMillis() - start));
-
return document.endObject();
} catch (IOException e) {
LOG.error("Could not normalize {} in {} because {}",
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
index c712d96d2a5..ad8853d6599 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
@@ -22,12 +22,16 @@ 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.core.rule.RuleDto;
import org.sonar.server.search.Hit;
import org.sonar.server.search.QueryOptions;
import org.sonar.server.search.Results;
import javax.annotation.CheckForNull;
+import java.util.Collection;
+import java.util.Collections;
+
/**
* @since 4.4
*/
@@ -53,4 +57,16 @@ public class RuleService implements ServerComponent {
public Results search(RuleQuery query, QueryOptions options) {
throw new UnsupportedOperationException("TODO");
}
+
+ public Collection<Hit> search(RuleQuery query) {
+ return Collections.emptyList();
+ }
+
+ public static Rule toRule(RuleDto ruleDto) {
+ return new RuleImpl();
+ }
+
+ public static Rule toRule(Hit hit) {
+ return RuleImpl.fromHit(hit);
+ }
}
diff --git a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
index 727246c4689..e7916ca6402 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
@@ -31,8 +31,8 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.sonar.core.cluster.IndexAction;
-import org.sonar.core.cluster.IndexAction.Method;
+import org.sonar.server.search.IndexAction;
+import org.sonar.server.search.IndexAction.Method;
import org.sonar.core.cluster.WorkQueue;
import org.sonar.core.db.Dao;
import org.sonar.core.db.Dto;
@@ -58,14 +58,12 @@ public abstract class BaseIndex<K extends Serializable, E extends Dto<K>> implem
private final Profiling profiling;
private Client client;
private final ESNode node;
- private WorkQueue workQueue;
private IndexSynchronizer<K> synchronizer;
protected Dao<E, K> dao;
public BaseIndex(WorkQueue workQueue, Dao<E, K> dao, Profiling profiling, ESNode node) {
this.profiling = profiling;
- this.workQueue = workQueue;
- this.synchronizer = new IndexSynchronizer<K>(this, dao, this.workQueue);
+ this.synchronizer = new IndexSynchronizer<K>(this, dao, workQueue);
this.dao = dao;
this.node = node;
}
@@ -167,8 +165,7 @@ public abstract class BaseIndex<K extends Serializable, E extends Dto<K>> implem
/* Index Action Methods */
@Override
- public void executeAction(IndexAction<K> action) {
- StopWatch watch = this.createWatch();
+ public boolean executeAction(IndexAction<K> action) {
long start = System.currentTimeMillis();
if (action.getMethod().equals(Method.DELETE)) {
this.delete(action.getKey());
@@ -177,9 +174,9 @@ public abstract class BaseIndex<K extends Serializable, E extends Dto<K>> implem
} else if (action.getMethod().equals(Method.UPDATE)) {
this.update(action.getKey());
}
- LOG.info("Action {} in {} took {}ms", action.getMethod(),
+ LOG.debug("Action {} in {} took {}ms", action.getMethod(),
this.getIndexName(), (System.currentTimeMillis() - start));
- watch.stop("Action {} in {}", action.getMethod(), this.getIndexName());
+ return true;
}
/* Index management methods */
@@ -207,7 +204,7 @@ public abstract class BaseIndex<K extends Serializable, E extends Dto<K>> implem
XContentBuilder doc = this.normalize(key);
String keyvalue = this.getKeyValue(key);
if (doc != null && keyvalue != null && !keyvalue.isEmpty()) {
- LOG.info("Update document with key {}", key);
+ LOG.debug("Update document with key {}", key);
IndexResponse result = getClient().index(
new IndexRequest(this.getIndexName(),
this.getType(), keyvalue)
diff --git a/sonar-server/src/main/java/org/sonar/server/search/Index.java b/sonar-server/src/main/java/org/sonar/server/search/Index.java
index 6a45b550dde..d0046510e79 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/Index.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/Index.java
@@ -21,7 +21,6 @@ package org.sonar.server.search;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.picocontainer.Startable;
-import org.sonar.core.cluster.IndexAction;
import javax.annotation.CheckForNull;
import java.io.Serializable;
@@ -30,7 +29,7 @@ public interface Index<K extends Serializable> extends Startable {
String getIndexName();
- void executeAction(IndexAction<K> action);
+ boolean executeAction(IndexAction<K> action);
@CheckForNull
Hit getByKey(K key);
diff --git a/sonar-server/src/main/java/org/sonar/server/search/IndexAction.java b/sonar-server/src/main/java/org/sonar/server/search/IndexAction.java
new file mode 100644
index 00000000000..c882941fe65
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/search/IndexAction.java
@@ -0,0 +1,83 @@
+/*
+ * 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.search;
+
+import org.sonar.core.cluster.ClusterAction;
+
+import java.io.Serializable;
+
+public class IndexAction<K extends Serializable> extends ClusterAction {
+
+ public enum Method {
+ INSERT, UPDATE, DELETE
+ }
+
+ private String indexName;
+ private K key;
+ private Method method;
+ private Index<K> index;
+
+
+ public IndexAction(String indexName, Method method, K key){
+ super();
+ this.indexName = indexName;
+ this.method = method;
+ this.key = key;
+ }
+
+ public Method getMethod(){
+ return this.method;
+ }
+
+ public String getIndexName() {
+ return indexName;
+ }
+
+ public void setIndexName(String indexName) {
+ this.indexName = indexName;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public void setKey(K key) {
+ this.key = key;
+ }
+
+ public void setMethod(Method method) {
+ this.method = method;
+ }
+
+ @Override
+ public void doExecute() {
+ index.executeAction(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setIndex(Index<?> index) {
+ this.index = (Index<K>) index;
+ }
+
+ @Override
+ public String toString(){
+ return "{IndexAction {key: " + getKey()+"}";
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java b/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
index 0371e5309ad..56ae2f4b8e9 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
@@ -21,7 +21,6 @@ package org.sonar.server.search;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.sonar.core.cluster.IndexAction;
import org.sonar.core.cluster.WorkQueue;
import org.sonar.core.db.Dao;
@@ -52,7 +51,7 @@ public class IndexSynchronizer<K extends Serializable> {
if (LOG.isTraceEnabled()) {
LOG.trace("Adding {} to workQueue for {}", key, index.getClass().getSimpleName());
}
- workQueue.enqueue(new IndexAction(index.getIndexName(), IndexAction.Method.INSERT, key));
+ workQueue.enqueue(new IndexAction<K>(index.getIndexName(), IndexAction.Method.INSERT, key));
}
return this;
diff --git a/sonar-server/src/main/java/org/sonar/server/search/IndexUtils.java b/sonar-server/src/main/java/org/sonar/server/search/IndexUtils.java
index 39a65b0c0a4..6680efacd84 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/IndexUtils.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/IndexUtils.java
@@ -20,16 +20,13 @@
package org.sonar.server.search;
import com.google.common.collect.ImmutableList;
-
-import org.sonar.server.rule2.RuleIndex;
import org.sonar.server.cluster.LocalQueueWorker;
+import org.sonar.server.rule2.RuleIndex;
import java.util.List;
public final class IndexUtils {
- private IndexUtils() {
- }
@SuppressWarnings("unchecked")
public static List<Class> getIndexClasses() {
diff --git a/sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java b/sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java
deleted file mode 100644
index 74b2b9fddf2..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java
+++ /dev/null
@@ -1,48 +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.cluster;
-
-import org.sonar.core.cluster.IndexAction;
-import org.junit.Test;
-import static org.fest.assertions.Assertions.assertThat;
-
-public class LocalNonBlockingWorkQueueTest {
-
- private static final String WORKING_IDNEX = "working_index";
-
- @Test
- public void test_enqueue_dequeue_indexAction(){
- LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
- queue.enqueue(new IndexAction(WORKING_IDNEX, IndexAction.Method.INSERT,new Integer(33)));
- IndexAction action = queue.dequeue();
- assertThat(action.getIndexName()).isEqualTo(WORKING_IDNEX);
- assertThat(action.getKey()).isEqualTo(new Integer(33));
- }
-
- @Test
- public void test_enqueue_dequeue_to_null(){
- LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
- queue.enqueue(new IndexAction<Integer>(WORKING_IDNEX, IndexAction.Method.INSERT,new Integer(33)));
- queue.enqueue(new IndexAction(WORKING_IDNEX, IndexAction.Method.INSERT,new Integer(33)));
- assertThat(queue.dequeue()).isNotNull();
- assertThat(queue.dequeue()).isNotNull();
- assertThat(queue.dequeue()).isNull();
- }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/cluster/LocalQueueWorkerTest.java b/sonar-server/src/test/java/org/sonar/server/cluster/LocalQueueWorkerTest.java
deleted file mode 100644
index abe89bbd1bd..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/cluster/LocalQueueWorkerTest.java
+++ /dev/null
@@ -1,46 +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.cluster;
-
-import org.sonar.core.cluster.IndexAction;
-import org.junit.Test;
-import static org.fest.assertions.Assertions.assertThat;
-
-public class LocalQueueWorkerTest {
-
- private static final String WORKING_IDNEX = "working_index";
-
- @Test
- public void test_worker_dequeue(){
- LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
- LocalQueueWorker worker = new LocalQueueWorker(queue);
- worker.start();
- queue.enqueue(new IndexAction(WORKING_IDNEX, IndexAction.Method.INSERT,new Integer(33)));
- queue.enqueue(new IndexAction(WORKING_IDNEX, IndexAction.Method.INSERT,new Integer(33)));
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- assertThat(queue.dequeue()).isNull();
- queue = null;
- }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleDaoTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleDaoTest.java
new file mode 100644
index 00000000000..704b3c6d082
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleDaoTest.java
@@ -0,0 +1,412 @@
+/*
+ * 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.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.apache.ibatis.session.SqlSession;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.check.Cardinality;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.rule.RuleParamDto;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RuleDaoTest extends AbstractDaoTestCase {
+
+ private static RuleDao dao;
+
+ @Before
+ public void createDao() throws Exception {
+ dao = new RuleDao(getMyBatis());
+ }
+
+ @Test
+ public void select_all() throws Exception {
+ setupData("selectAll");
+ List<RuleDto> ruleDtos = dao.selectAll();
+
+ assertThat(ruleDtos).hasSize(1);
+
+ RuleDto ruleDto = ruleDtos.get(0);
+ assertThat(ruleDto.getId()).isEqualTo(1);
+ assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
+ assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
+ assertThat(ruleDto.getStatus()).isEqualTo(Rule.STATUS_READY);
+ assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
+ assertThat(ruleDto.getNoteData()).isEqualTo("Rule note with accents \u00e9\u00e8\u00e0");
+ assertThat(ruleDto.getSubCharacteristicId()).isEqualTo(100);
+ assertThat(ruleDto.getDefaultSubCharacteristicId()).isEqualTo(101);
+ assertThat(ruleDto.getRemediationFunction()).isEqualTo("linear");
+ assertThat(ruleDto.getDefaultRemediationFunction()).isEqualTo("linear_offset");
+ assertThat(ruleDto.getRemediationCoefficient()).isEqualTo("1h");
+ assertThat(ruleDto.getDefaultRemediationCoefficient()).isEqualTo("5d");
+ assertThat(ruleDto.getRemediationOffset()).isEqualTo("5min");
+ assertThat(ruleDto.getDefaultRemediationOffset()).isEqualTo("10h");
+ assertThat(ruleDto.getEffortToFixDescription()).isEqualTo("squid.S115.effortToFix");
+ }
+
+ @Test
+ public void select_enables_and_non_manual() throws Exception {
+ setupData("select_enables_and_non_manual");
+ List<RuleDto> ruleDtos = dao.selectEnablesAndNonManual();
+
+ assertThat(ruleDtos.size()).isEqualTo(1);
+ RuleDto ruleDto = ruleDtos.get(0);
+ assertThat(ruleDto.getId()).isEqualTo(1);
+ assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
+ assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
+ assertThat(ruleDto.getStatus()).isEqualTo(Rule.STATUS_READY);
+ assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
+ assertThat(ruleDto.getNoteData()).isEqualTo("Rule note with accents \u00e9\u00e8\u00e0");
+ assertThat(ruleDto.getSubCharacteristicId()).isEqualTo(100);
+ assertThat(ruleDto.getDefaultSubCharacteristicId()).isEqualTo(101);
+ assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR");
+ assertThat(ruleDto.getDefaultRemediationFunction()).isEqualTo("LINEAR_OFFSET");
+ assertThat(ruleDto.getRemediationCoefficient()).isEqualTo("1h");
+ assertThat(ruleDto.getDefaultRemediationCoefficient()).isEqualTo("5d");
+ assertThat(ruleDto.getRemediationOffset()).isEqualTo("5min");
+ assertThat(ruleDto.getDefaultRemediationOffset()).isEqualTo("10h");
+ assertThat(ruleDto.getEffortToFixDescription()).isEqualTo("squid.S115.effortToFix");
+ }
+
+ @Test
+ public void select_by_id() throws Exception {
+ setupData("selectById");
+ RuleDto ruleDto = dao.selectById(2);
+
+ assertThat(ruleDto.getId()).isEqualTo(2);
+ assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
+ assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
+ assertThat(ruleDto.getStatus()).isEqualTo(Rule.STATUS_READY);
+ assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
+ }
+
+ @Test
+ public void select_by_rule_key() throws Exception {
+ setupData("select_by_rule_key");
+ assertThat(dao.selectByKey(RuleKey.of("checkstyle", "AvoidComparison"))).isNotNull();
+ assertThat(dao.selectByKey(RuleKey.of("checkstyle", "Unknown"))).isNull();
+ assertThat(dao.selectByKey(RuleKey.of("Unknown", "AvoidComparison"))).isNull();
+ }
+
+ @Test
+ public void select_by_name() throws Exception {
+ setupData("select_by_name");
+ RuleDto ruleDto = dao.selectByName("Avoid Null");
+
+ assertThat(ruleDto.getId()).isEqualTo(2);
+ assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
+ assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
+ assertThat(ruleDto.getStatus()).isEqualTo(Rule.STATUS_READY);
+ assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
+ }
+
+ @Test
+ public void select_non_manual() throws Exception {
+ setupData("selectNonManual");
+ SqlSession session = getMyBatis().openSession();
+ List<RuleDto> ruleDtos = dao.selectNonManual(session);
+ session.commit();
+ session.close();
+
+ assertThat(ruleDtos.size()).isEqualTo(1);
+ RuleDto ruleDto = ruleDtos.get(0);
+ assertThat(ruleDto.getId()).isEqualTo(1);
+ assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
+ assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
+ assertThat(ruleDto.getStatus()).isEqualTo(Rule.STATUS_READY);
+ assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
+ }
+
+ @Test
+ public void select_by_sub_characteristic_id(){
+ setupData("select_by_sub_characteristic_id");
+
+ // Rules from sub characteristic (even REMOVED ones are returned)
+ List<RuleDto> ruleDtos = dao.selectBySubCharacteristicId(3);
+ assertThat(ruleDtos).hasSize(3);
+ assertThat(idsFromRuleDtos(ruleDtos)).containsExactly(2, 4, 5);
+
+ // Nothing on root characteristic
+ ruleDtos = dao.selectBySubCharacteristicId(1);
+ assertThat(ruleDtos).isEmpty();
+
+ // Rules from disabled characteristic
+ ruleDtos = dao.selectBySubCharacteristicId(11);
+ assertThat(idsFromRuleDtos(ruleDtos)).containsExactly(3);
+ }
+
+ @Test
+ public void update() {
+ setupData("update");
+
+ RuleDto ruleToUpdate = new RuleDto()
+ .setId(1)
+ .setRuleKey("NewRuleKey")
+ .setRepositoryKey("plugin")
+ .setName("new name")
+ .setDescription("new description")
+ .setStatus(Rule.STATUS_DEPRECATED)
+ .setConfigKey("NewConfigKey")
+ .setSeverity(Severity.INFO)
+ .setCardinality(Cardinality.MULTIPLE)
+ .setLanguage("dart")
+ .setParentId(3)
+ .setNoteData("My note")
+ .setNoteUserLogin("admin")
+ .setNoteCreatedAt(DateUtils.parseDate("2013-12-19"))
+ .setNoteUpdatedAt(DateUtils.parseDate("2013-12-20"))
+ .setSubCharacteristicId(100)
+ .setDefaultSubCharacteristicId(101)
+ .setRemediationFunction("linear")
+ .setDefaultRemediationFunction("linear_offset")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription("squid.S115.effortToFix")
+ .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
+
+ dao.update(ruleToUpdate);
+
+ checkTables("update", "rules");
+ }
+
+ @Test
+ public void insert() {
+ setupData("empty");
+
+ RuleDto ruleToInsert = new RuleDto()
+ .setId(1)
+ .setRuleKey("NewRuleKey")
+ .setRepositoryKey("plugin")
+ .setName("new name")
+ .setDescription("new description")
+ .setStatus(Rule.STATUS_DEPRECATED)
+ .setConfigKey("NewConfigKey")
+ .setSeverity(Severity.INFO)
+ .setCardinality(Cardinality.MULTIPLE)
+ .setLanguage("dart")
+ .setParentId(3)
+ .setSubCharacteristicId(100)
+ .setDefaultSubCharacteristicId(101)
+ .setRemediationFunction("linear")
+ .setDefaultRemediationFunction("linear_offset")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription("squid.S115.effortToFix")
+ .setCreatedAt(DateUtils.parseDate("2013-12-16"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
+
+ dao.insert(ruleToInsert);
+
+ checkTables("insert", "rules");
+ }
+
+ @Test
+ public void insert_all() {
+ setupData("empty");
+
+ RuleDto ruleToInsert1 = new RuleDto()
+ .setId(1)
+ .setRuleKey("NewRuleKey")
+ .setRepositoryKey("plugin")
+ .setName("new name")
+ .setDescription("new description")
+ .setStatus(Rule.STATUS_DEPRECATED)
+ .setConfigKey("NewConfigKey")
+ .setSeverity(Severity.INFO)
+ .setCardinality(Cardinality.MULTIPLE)
+ .setLanguage("dart")
+ .setParentId(3)
+ .setSubCharacteristicId(100)
+ .setDefaultSubCharacteristicId(101)
+ .setRemediationFunction("linear")
+ .setDefaultRemediationFunction("linear_offset")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription("squid.S115.effortToFix")
+ .setCreatedAt(DateUtils.parseDate("2013-12-16"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
+
+ RuleDto ruleToInsert2 = new RuleDto()
+ .setId(2)
+ .setRuleKey("NewRuleKey2")
+ .setRepositoryKey("plugin2")
+ .setName("new name2")
+ .setDescription("new description2")
+ .setStatus(Rule.STATUS_BETA)
+ .setConfigKey("NewConfigKey2")
+ .setSeverity(Severity.MAJOR)
+ .setCardinality(Cardinality.SINGLE)
+ .setLanguage("js")
+ .setParentId(null)
+ .setSubCharacteristicId(102)
+ .setDefaultSubCharacteristicId(103)
+ .setRemediationFunction("linear_offset")
+ .setDefaultRemediationFunction("linear")
+ .setRemediationCoefficient("5d")
+ .setDefaultRemediationCoefficient("1h")
+ .setRemediationOffset("10h")
+ .setDefaultRemediationOffset("5min")
+ .setEffortToFixDescription("squid.S115.effortToFix2")
+ .setCreatedAt(DateUtils.parseDate("2013-12-14"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-15"));
+
+ dao.insert(ImmutableList.of(ruleToInsert1, ruleToInsert2));
+
+ checkTables("insert_all", "rules");
+ }
+
+ @Test
+ public void select_parameters() throws Exception {
+ setupData("selectParameters");
+ List<RuleParamDto> ruleDtos = dao.selectParameters();
+
+ assertThat(ruleDtos.size()).isEqualTo(1);
+ RuleParamDto ruleDto = ruleDtos.get(0);
+ assertThat(ruleDto.getId()).isEqualTo(1);
+ assertThat(ruleDto.getName()).isEqualTo("myParameter");
+ assertThat(ruleDto.getDescription()).isEqualTo("My Parameter");
+ assertThat(ruleDto.getType()).isEqualTo("plop");
+ assertThat(ruleDto.getDefaultValue()).isEqualTo("plouf");
+ }
+
+ @Test
+ public void select_parameters_by_rule_id() throws Exception {
+ setupData("select_parameters_by_rule_id");
+ int ruleId = 1;
+ List<RuleParamDto> ruleDtos = dao.selectParametersByRuleId(ruleId);
+
+ assertThat(ruleDtos.size()).isEqualTo(1);
+ RuleParamDto ruleDto = ruleDtos.get(0);
+ assertThat(ruleDto.getId()).isEqualTo(1);
+ assertThat(ruleDto.getName()).isEqualTo("myParameter");
+ assertThat(ruleDto.getDescription()).isEqualTo("My Parameter");
+ assertThat(ruleDto.getType()).isEqualTo("plop");
+ assertThat(ruleDto.getRuleId()).isEqualTo(ruleId);
+ }
+
+ @Test
+ public void select_parameters_by_rule_ids() throws Exception {
+ setupData("select_parameters_by_rule_ids");
+
+ assertThat(dao.selectParametersByRuleIds(newArrayList(1, 2))).hasSize(2);
+ assertThat(dao.selectParametersByRuleIds(newArrayList(1))).hasSize(1);
+ }
+
+ @Test
+ public void insert_parameter() {
+ setupData("insert_parameter");
+
+ RuleParamDto param = new RuleParamDto()
+ .setRuleId(1)
+ .setName("max")
+ .setType("INTEGER")
+ .setDefaultValue("30")
+ .setDescription("My Parameter");
+
+ dao.insert(param);
+
+ checkTables("insert_parameter", "rules_parameters");
+ }
+
+ @Test
+ public void update_parameter() {
+ setupData("update_parameter");
+
+ RuleParamDto param = new RuleParamDto()
+ .setId(1)
+ .setName("format")
+ .setType("STRING")
+ .setDefaultValue("^[a-z]+(\\.[a-z][a-z0-9]*)*$")
+ .setDescription("Regular expression used to check the package names against.");
+
+ dao.update(param);
+
+ checkTables("update_parameter", "rules_parameters");
+ }
+
+ @Test
+ public void select_tags_by_rule_id() throws Exception {
+ setupData("select_tags_by_rule_id");
+
+ assertThat(dao.selectTagsByRuleId(3)).hasSize(2);
+ }
+
+ @Test
+ public void select_tags_by_rule_ids() throws Exception {
+ setupData("select_tags_by_rule_ids");
+
+ assertThat(dao.selectTagsByRuleIds(newArrayList(3, 4))).hasSize(3);
+ }
+
+ @Test
+ public void keysOfRowsUpdatedAfter() throws Exception {
+ setupData("empty");
+
+ RuleDto rule1 = new RuleDto()
+ .setId(1)
+ .setRepositoryKey("foo")
+ .setRuleKey("R1")
+ .setName("ROne")
+ .setCreatedAt(DateUtils.parseDate("2013-12-16"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-16"));
+ RuleDto rule2 = new RuleDto()
+ .setId(2)
+ .setRepositoryKey("foo")
+ .setRuleKey("R2")
+ .setName("RTwo")
+ .setCreatedAt(DateUtils.parseDate("2014-01-28"))
+ .setUpdatedAt(DateUtils.parseDate("2014-05-19"));
+ dao.insert(Arrays.asList(rule1, rule2));
+
+ assertThat(dao.keysOfRowsUpdatedAfter(DateUtils.parseDate("2014-06-01").getTime())).isEmpty();
+ assertThat(dao.keysOfRowsUpdatedAfter(DateUtils.parseDate("2012-01-01").getTime())).hasSize(2);
+ Iterable<RuleKey> keys = dao.keysOfRowsUpdatedAfter(DateUtils.parseDate("2014-05-17").getTime());
+ assertThat(keys).hasSize(1);
+ assertThat(Iterables.getFirst(keys, null).rule()).isEqualTo("R2");
+ }
+
+ private List<Integer> idsFromRuleDtos(List<RuleDto> ruleDtos){
+ return newArrayList(Iterables.transform(ruleDtos, new Function<RuleDto, Integer>() {
+ @Override
+ public Integer apply(RuleDto input) {
+ return input.getId();
+ }
+ }));
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java
index de48aaa6022..819bbb68177 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java
@@ -19,15 +19,17 @@
*/
package org.sonar.server.rule2;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.rule.Severity;
import org.sonar.api.utils.DateUtils;
import org.sonar.check.Cardinality;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
import org.sonar.core.qualityprofile.db.ActiveRuleDao;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.rule.RuleDao;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.search.Hit;
import org.sonar.server.tester.ServerTester;
@@ -40,19 +42,24 @@ public class RuleMediumTest {
@Rule
public ServerTester tester = new ServerTester()
- //.setProperty("sonar.log.profilingLevel", "FULL")
- .setProperty("sonar.es.http.port", "8888");
+ // .setProperty("sonar.log.profilingLevel", "FULL")
+ .setProperty("sonar.es.http.port", "8888");
private RuleDto dto;
private ActiveRuleDto adto;
@Before
- public void setup(){
+ public void setup() {
dto = getRuleDto(1);
adto = getActiveRuleDto(dto);
}
- private ActiveRuleDto getActiveRuleDto(RuleDto dto){
+ @After
+ public void teardown() {
+ tester.stop();
+ }
+
+ private ActiveRuleDto getActiveRuleDto(RuleDto dto) {
return new ActiveRuleDto()
.setId(1)
.setNoteCreatedAt(new Date())
@@ -61,12 +68,12 @@ public class RuleMediumTest {
.setProfileId(1)
.setParentId(0)
.setSeverity(3);
- }
+ }
private RuleDto getRuleDto(int id) {
return new RuleDto()
- .setId(id)
- .setRuleKey("NewRuleKey="+id)
+ // .setId(id)
+ .setRuleKey("NewRuleKey=" + id)
.setRepositoryKey("plugin")
.setName("new name")
.setDescription("new description")
@@ -97,13 +104,6 @@ public class RuleMediumTest {
RuleIndex index = tester.get(RuleIndex.class);
dao.insert(dto);
- adao.insert(adto);
-
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- ;
- }
Hit hit = index.getByKey(dto.getKey());
assertThat(hit.getFields().get("ruleKey")).isEqualTo(dto.getRuleKey());
@@ -116,10 +116,9 @@ public class RuleMediumTest {
dao.insert(dto);
- //org.sonar.server.rule2.Rule rule = service.getByKey(dto.getKey());
-
- //assertThat(rule.key()).isEqualTo(dto.getKey());
+ org.sonar.server.rule2.Rule rule = service.getByKey(dto.getKey());
+ assertThat(rule.key()).isEqualTo(dto.getKey());
}
}