summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Gamard <stephane.gamard@searchbox.com>2014-04-28 11:39:30 +0200
committerStephane Gamard <stephane.gamard@searchbox.com>2014-04-28 11:39:30 +0200
commite197f0547682ce01ce724229de6f79daa0860cb6 (patch)
tree52d8d8aefbc3cc857838d221669ae05202b3f6a2
parent13ab972c11fabc8a4979f85ba1cf1f6da4a17ea2 (diff)
downloadsonarqube-e197f0547682ce01ce724229de6f79daa0860cb6.tar.gz
sonarqube-e197f0547682ce01ce724229de6f79daa0860cb6.zip
SONAR-5237 - complete skeleton stack in rule2 package
-rw-r--r--sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java73
-rw-r--r--sonar-server/src/main/java/org/sonar/server/cluster/WorkQueue.java8
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/BaseDao.java110
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/Dao.java3
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleConstants.java7
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java26
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleDto.java344
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java97
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java123
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java5
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java29
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java182
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/Index.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java28
-rw-r--r--sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java136
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexTest.java (renamed from sonar-server/src/test/java/org/sonar/server/es/BaseIndexTest.java)61
-rw-r--r--sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java132
17 files changed, 1243 insertions, 123 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
new file mode 100644
index 00000000000..c3c53600c41
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/cluster/LocalNonBlockingWorkQueue.java
@@ -0,0 +1,73 @@
+package org.sonar.server.cluster;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class LocalNonBlockingWorkQueue implements WorkQueue{
+
+ private final static int WORKQUEUE_INITIAL_CAPACITY = 20;
+
+ private ConcurrentHashMap<String, Queue<Serializable>> index;
+ private ConcurrentHashMap<String, Queue<Serializable>> update;
+ private ConcurrentHashMap<String, Queue<Serializable>> delete;
+
+ public LocalNonBlockingWorkQueue(){
+ this.index = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY);
+ this.update = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY);
+ this.delete = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY);
+ }
+
+ private Integer enqueue(Map<String, Queue<Serializable>> map, String indexName, Serializable key){
+ if(!map.containsKey(indexName)){
+ map.put(indexName, new ConcurrentLinkedQueue<Serializable>());
+ }
+ map.get(indexName).offer(key);
+ return 0;
+ }
+
+ private Object dequeue(Map<String, Queue<Serializable>> map, String indexName){
+ return (map.containsKey(indexName))?
+ map.get(indexName).poll():
+ null;
+ }
+
+ @Override
+ public Integer enqueInsert(String indexName, Serializable key) {
+ return this.enqueue(index, indexName, key);
+ }
+
+ @Override
+ public Integer enqueUpdate(String indexName, Serializable key) {
+ return this.enqueue(update, indexName, key);
+ }
+
+ @Override
+ public Integer enqueDelete(String indexName, Serializable key) {
+ return this.enqueue(delete, indexName, key);
+ }
+
+ @Override
+ public Object dequeInsert(String indexName) {
+ return this.dequeue(index, indexName);
+ }
+
+ @Override
+ public Object dequeUpdate(String indexName) {
+ return this.dequeue(update, indexName);
+ }
+
+ @Override
+ public Object dequeDelete(String indexName) {
+ return this.dequeue(delete, indexName);
+ }
+
+ @Override
+ public Status getStatus(Integer workId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/cluster/WorkQueue.java b/sonar-server/src/main/java/org/sonar/server/cluster/WorkQueue.java
index 1b6a89117c9..79c3b520dc9 100644
--- a/sonar-server/src/main/java/org/sonar/server/cluster/WorkQueue.java
+++ b/sonar-server/src/main/java/org/sonar/server/cluster/WorkQueue.java
@@ -19,13 +19,15 @@
*/
package org.sonar.server.cluster;
+import java.io.Serializable;
+
public interface WorkQueue {
- Integer enqueInsert(String indexName, Object key);
+ Integer enqueInsert(String indexName, Serializable key);
- Integer enqueUpdate(String indexName, Object key);
+ Integer enqueUpdate(String indexName, Serializable key);
- Integer enqueDelete(String indexName, Object key);
+ Integer enqueDelete(String indexName, Serializable key);
Object dequeInsert(String indexName);
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..21a2270ef63
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
@@ -0,0 +1,110 @@
+/*
+ * 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.persistence.MyBatis;
+import org.sonar.server.cluster.WorkQueue;
+
+import java.io.Serializable;
+
+public abstract class BaseDao<E extends Dto<K>, K extends Serializable> implements Dao<E, K> {
+
+ private MyBatis myBatis;
+ private WorkQueue workQueue;
+
+ protected BaseDao(WorkQueue workQueue, MyBatis myBatis) {
+ this.myBatis = myBatis;
+ this.workQueue = workQueue;
+ }
+
+ protected abstract String getIndexName();
+
+ protected void enqueInsert(K key) {
+ this.workQueue.enqueInsert(this.getIndexName(), key);
+ }
+
+ protected void enqueUpdate(K key) {
+ this.workQueue.enqueUpdate(this.getIndexName(), key);
+ }
+
+ protected void enqueDelete(K key) {
+ this.workQueue.enqueDelete(this.getIndexName(), key);
+ }
+
+ protected MyBatis getMyBatis(){
+ return this.myBatis;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public E getByKey(K key) {
+ E item = null;
+ SqlSession session = getMyBatis().openSession();
+ item = (E) session.getMapper(this.getClass()).getByKey(key);
+ MyBatis.closeQuietly(session);
+ return item;
+ }
+
+ @Override
+ public E update(E item) {
+ SqlSession session = getMyBatis().openSession();
+ E result = null;
+ try {
+ result = (E) session.getMapper(this.getClass()).update(item);
+ session.commit();
+ } finally {
+ this.enqueUpdate(item.getKey());
+ MyBatis.closeQuietly(session);
+ return result;
+ }
+ }
+
+ @Override
+ public E insert(E item) {
+ SqlSession session = getMyBatis().openSession();
+ E result = null;
+ try {
+ result = (E) session.getMapper(this.getClass()).insert(item);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ this.enqueInsert(item.getKey());
+ return result;
+ }
+ }
+
+ @Override
+ public void delete(E item) {
+ this.deleteByKey(item.getKey());
+ }
+
+ @Override
+ public void deleteByKey(K key) {
+ SqlSession session = getMyBatis().openSession();
+ try {
+ session.getMapper(this.getClass()).deleteByKey(key);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ this.enqueDelete(key);
+ }
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/Dao.java b/sonar-server/src/main/java/org/sonar/server/db/Dao.java
index 44fd54dd41a..e3fad2e59f5 100644
--- a/sonar-server/src/main/java/org/sonar/server/db/Dao.java
+++ b/sonar-server/src/main/java/org/sonar/server/db/Dao.java
@@ -20,6 +20,7 @@
package org.sonar.server.db;
import java.io.Serializable;
+import java.util.Collection;
public interface Dao<E extends Dto<K>, K extends Serializable> {
@@ -33,4 +34,6 @@ public interface Dao<E extends Dto<K>, K extends Serializable> {
public void deleteByKey(K key);
+ public Collection<K> insertsSince(Long timestamp);
+
}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleConstants.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleConstants.java
new file mode 100644
index 00000000000..98abd6f7979
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleConstants.java
@@ -0,0 +1,7 @@
+package org.sonar.server.rule2;
+
+public interface RuleConstants {
+
+ public static final String INDEX_NAME = "rules";
+ public static final String ES_TYPE = "rule";
+}
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..3bc9875c398
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
@@ -0,0 +1,26 @@
+package org.sonar.server.rule2;
+
+import java.util.Collection;
+
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.cluster.WorkQueue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.server.db.BaseDao;
+
+public class RuleDao extends BaseDao<RuleDto, RuleKey> {
+
+ protected RuleDao(WorkQueue workQueue, MyBatis myBatis) {
+ super(workQueue, myBatis);
+ }
+
+ @Override
+ protected String getIndexName() {
+ return RuleConstants.INDEX_NAME;
+ }
+
+ @Override
+ public Collection<RuleKey> insertsSince(Long timestamp) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDto.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDto.java
new file mode 100644
index 00000000000..621de3ae268
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDto.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 org.sonar.api.rule.RuleKey;
+
+import org.sonar.core.rule.SeverityUtil;
+import org.sonar.server.db.Dto;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.check.Cardinality;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.Date;
+
+public final class RuleDto implements Dto<RuleKey> {
+
+ public static final Integer DISABLED_CHARACTERISTIC_ID = -1;
+
+ private String repositoryKey;
+ private String ruleKey;
+ private String description;
+ private String status;
+ private String name;
+ private String configKey;
+ private Integer severity;
+ private Cardinality cardinality;
+ private String language;
+ private Integer parentId;
+ private String noteData;
+ private String noteUserLogin;
+ private Date noteCreatedAt;
+ private Date noteUpdatedAt;
+ private Integer subCharacteristicId;
+ private Integer defaultSubCharacteristicId;
+ private String remediationFunction;
+ private String defaultRemediationFunction;
+ private String remediationCoefficient;
+ private String defaultRemediationCoefficient;
+ private String remediationOffset;
+ private String defaultRemediationOffset;
+ private String effortToFixDescription;
+ private Date createdAt;
+ private Date updatedAt;
+
+ @Override
+ public RuleKey getKey() {
+ return RuleKey.of(this.getRepositoryKey(), this.getRuleKey());
+ }
+
+ public String getRepositoryKey() {
+ return repositoryKey;
+ }
+
+ public RuleDto setRepositoryKey(String repositoryKey) {
+ this.repositoryKey = repositoryKey;
+ return this;
+ }
+
+ public String getRuleKey() {
+ return ruleKey;
+ }
+
+ public RuleDto setRuleKey(String ruleKey) {
+ this.ruleKey = ruleKey;
+ return this;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public RuleDto setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public RuleDto setStatus(String status) {
+ this.status = status;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public RuleDto setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getConfigKey() {
+ return configKey;
+ }
+
+ public RuleDto setConfigKey(String configKey) {
+ this.configKey = configKey;
+ return this;
+ }
+
+ public Integer getSeverity() {
+ return severity;
+ }
+
+ public String getSeverityString() {
+ return SeverityUtil.getSeverityFromOrdinal(severity);
+ }
+
+ public RuleDto setSeverity(String severity) {
+ this.severity = SeverityUtil.getOrdinalFromSeverity(severity);
+ return this;
+ }
+
+ public RuleDto setSeverity(Integer severity) {
+ this.severity = severity;
+ return this;
+ }
+
+
+ public Cardinality getCardinality() {
+ return cardinality;
+ }
+
+ public RuleDto setCardinality(Cardinality cardinality) {
+ this.cardinality = cardinality;
+ return this;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public RuleDto setLanguage(String language) {
+ this.language = language;
+ return this;
+ }
+
+ @CheckForNull
+ public Integer getParentId() {
+ return parentId;
+ }
+
+ public RuleDto setParentId(@Nullable Integer parentId) {
+ this.parentId = parentId;
+ return this;
+ }
+
+ public String getNoteData() {
+ return noteData;
+ }
+
+ public RuleDto setNoteData(String noteData) {
+ this.noteData = noteData;
+ return this;
+ }
+
+ public String getNoteUserLogin() {
+ return noteUserLogin;
+ }
+
+ public RuleDto setNoteUserLogin(String noteUserLogin) {
+ this.noteUserLogin = noteUserLogin;
+ return this;
+ }
+
+ public Date getNoteCreatedAt() {
+ return noteCreatedAt;
+ }
+
+ public RuleDto setNoteCreatedAt(Date noteCreatedAt) {
+ this.noteCreatedAt = noteCreatedAt;
+ return this;
+ }
+
+ public Date getNoteUpdatedAt() {
+ return noteUpdatedAt;
+ }
+
+ public RuleDto setNoteUpdatedAt(Date noteUpdatedAt) {
+ this.noteUpdatedAt = noteUpdatedAt;
+ return this;
+ }
+
+ @CheckForNull
+ public Integer getSubCharacteristicId() {
+ return subCharacteristicId;
+ }
+
+ public RuleDto setSubCharacteristicId(@Nullable Integer subCharacteristicId) {
+ this.subCharacteristicId = subCharacteristicId;
+ return this;
+ }
+
+ @CheckForNull
+ public Integer getDefaultSubCharacteristicId() {
+ return defaultSubCharacteristicId;
+ }
+
+ public RuleDto setDefaultSubCharacteristicId(@Nullable Integer defaultSubCharacteristicId) {
+ this.defaultSubCharacteristicId = defaultSubCharacteristicId;
+ return this;
+ }
+
+ @CheckForNull
+ public String getRemediationFunction() {
+ return remediationFunction;
+ }
+
+ public RuleDto setRemediationFunction(@Nullable String remediationFunction) {
+ this.remediationFunction = remediationFunction;
+ return this;
+ }
+
+ @CheckForNull
+ public String getDefaultRemediationFunction() {
+ return defaultRemediationFunction;
+ }
+
+ public RuleDto setDefaultRemediationFunction(@Nullable String defaultRemediationFunction) {
+ this.defaultRemediationFunction = defaultRemediationFunction;
+ return this;
+ }
+
+ @CheckForNull
+ public String getRemediationCoefficient() {
+ return remediationCoefficient;
+ }
+
+ public RuleDto setRemediationCoefficient(@Nullable String remediationCoefficient) {
+ this.remediationCoefficient = remediationCoefficient;
+ return this;
+ }
+
+ @CheckForNull
+ public String getDefaultRemediationCoefficient() {
+ return defaultRemediationCoefficient;
+ }
+
+ public RuleDto setDefaultRemediationCoefficient(@Nullable String defaultRemediationCoefficient) {
+ this.defaultRemediationCoefficient = defaultRemediationCoefficient;
+ return this;
+ }
+
+ @CheckForNull
+ public String getRemediationOffset() {
+ return remediationOffset;
+ }
+
+ public RuleDto setRemediationOffset(@Nullable String remediationOffset) {
+ this.remediationOffset = remediationOffset;
+ return this;
+ }
+
+ @CheckForNull
+ public String getDefaultRemediationOffset() {
+ return defaultRemediationOffset;
+ }
+
+ public RuleDto setDefaultRemediationOffset(@Nullable String defaultRemediationOffset) {
+ this.defaultRemediationOffset = defaultRemediationOffset;
+ return this;
+ }
+
+ @CheckForNull
+ public String getEffortToFixDescription() {
+ return effortToFixDescription;
+ }
+
+ public RuleDto setEffortToFixDescription(@Nullable String effortToFixDescription) {
+ this.effortToFixDescription = effortToFixDescription;
+ return this;
+ }
+
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ public RuleDto setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+
+ public Date getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public RuleDto setUpdatedAt(Date updatedAt) {
+ this.updatedAt = updatedAt;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RuleDto)) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ RuleDto other = (RuleDto) obj;
+ return new EqualsBuilder()
+ .append(repositoryKey, other.getRepositoryKey())
+ .append(ruleKey, other.getRuleKey())
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder(17, 37)
+ .append(repositoryKey)
+ .append(ruleKey)
+ .toHashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+ }
+}
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..89ccff40a50
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java
@@ -0,0 +1,97 @@
+package org.sonar.server.rule2;
+
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+
+import java.util.Date;
+import java.util.List;
+
+import org.sonar.api.rule.RuleKey;
+
+public class RuleImpl implements Rule {
+
+ @Override
+ public RuleKey key() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String language() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String name() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String description() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Severity severity() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String status() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean template() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public List<String> tags() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List<RuleParam> params() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String debtCharacteristicKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String debtSubCharacteristicKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public DebtRemediationFunction debtRemediationFunction() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date createdAt() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date updatedAt() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
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
new file mode 100644
index 00000000000..d7bda890e89
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
@@ -0,0 +1,123 @@
+package org.sonar.server.rule2;
+
+import org.elasticsearch.common.settings.ImmutableSettings;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.server.cluster.WorkQueue;
+import org.sonar.server.search.BaseIndex;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+
+
+public class RuleIndex extends BaseIndex<RuleKey> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RuleIndex.class);
+
+ public RuleIndex(WorkQueue workQueue, RuleDao dao, Profiling profiling) {
+ super(workQueue, dao, profiling);
+ }
+
+ @Override
+ public String getIndexName() {
+ return RuleConstants.INDEX_NAME;
+ }
+
+ @Override
+ protected String getType() {
+ return RuleConstants.ES_TYPE;
+ }
+
+ protected QueryBuilder getKeyQuery(RuleKey key){
+ return QueryBuilders.boolQuery()
+ .must(QueryBuilders.termQuery("repositoryKey", key.repository()))
+ .must(QueryBuilders.termQuery("ruleKey", key.rule()));
+ }
+
+ @Override
+ protected Settings getIndexSettings() {
+ try {
+ return ImmutableSettings.builder()
+ .loadFromSource(
+ jsonBuilder().startObject()
+ .startObject("index")
+ .field("number_of_replicas", 0)
+ .field("number_of_shards",4)
+ .startObject("mapper")
+ .field("dynamic", true)
+ .endObject()
+ .startObject("analysis")
+ .startObject("analyzer")
+ .startObject("path_analyzer")
+ .field("type", "custom")
+ .field("tokenizer", "path_hierarchy")
+ .endObject()
+ .endObject()
+ .endObject()
+ .endObject().toString())
+ .build();
+ } catch (IOException e) {
+ LOG.error("Could not create index settings for {}",this.getIndexName());
+ return ImmutableSettings.builder().build();
+ }
+ }
+
+ @Override
+ protected XContentBuilder getMapping() {
+ try {
+ return jsonBuilder().startObject()
+ .startObject("issue")
+ .startObject("properties")
+ .startObject("component.path")
+ .field("type", "string")
+ .field("index_analyzer", "path_analyzer")
+ .field("search_analyzer", "keyword")
+ .endObject()
+ .startObject("rule.name")
+ .field("type", "string")
+ .field("analyzer", "keyword")
+ .endObject()
+ .startObject("root.id")
+ .field("type", "multi_field")
+ .startObject("fields")
+ .startObject("str")
+ .field("type", "string")
+ .field("index","analyzed")
+ .field("analyzer", "default")
+ .endObject()
+ .startObject("num")
+ .field("type", "long")
+ .field("index","analyzed")
+ .endObject()
+ .endObject()
+ .endObject()
+ .endObject().endObject();
+ } catch (IOException e) {
+ LOG.error("Could not create mapping for {}",this.getIndexName());
+ return null;
+ }
+ }
+
+ @Override
+ public Map<String, Object> normalize(RuleKey key) {
+ //Use a MyBatis to normalize the Rule form multiple Table
+ return null;
+ }
+
+ @Override
+ public Collection<RuleKey> synchronizeSince(Long date) {
+ //Use MyBatis to get the RuleKey created since date X
+ return null;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java
new file mode 100644
index 00000000000..2a7cc349988
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java
@@ -0,0 +1,5 @@
+package org.sonar.server.rule2;
+
+public class RuleQuery {
+
+}
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
new file mode 100644
index 00000000000..1260fe98638
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
@@ -0,0 +1,29 @@
+package org.sonar.server.rule2;
+
+import org.sonar.server.search.Hit;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class RuleService {
+
+ private RuleDao dao;
+ private RuleIndex index;
+
+ public RuleService(RuleDao dao, RuleIndex index){
+ this.dao = dao;
+ this.index = index;
+ }
+
+ 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 new RuleImpl();
+ }
+}
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 e3716781f89..9eaf598196e 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
@@ -20,29 +20,30 @@
package org.sonar.server.search;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsNodes;
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
+import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.query.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.core.persistence.MyBatis;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.profiling.Profiling.Level;
import org.sonar.core.profiling.StopWatch;
import org.sonar.server.cluster.WorkQueue;
+import org.sonar.server.db.Dao;
import java.io.Serializable;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-public abstract class BaseIndex<K extends Serializable> implements Index<K>{
-
- private static final String ES_EXECUTE_FAILED = "Failed execution of {}. Root is {}";
-
- private static final String BULK_EXECUTE_FAILED = "Execution of bulk operation failed";
- private static final String BULK_INTERRUPTED = "Interrupted during bulk operation";
+public abstract class BaseIndex<K extends Serializable> implements Index<K> {
private static final String PROFILE_DOMAIN = "es";
private static final Logger LOG = LoggerFactory.getLogger(BaseIndex.class);
@@ -55,17 +56,51 @@ public abstract class BaseIndex<K extends Serializable> implements Index<K>{
private final Profiling profiling;
private Client client;
private WorkQueue workQueue;
- private IndexSynchronizer synchronizer;
+ private IndexSynchronizer<K> synchronizer;
+ protected Dao<?,K> dao;
- public BaseIndex(WorkQueue workQueue, Profiling profiling) {
+ public BaseIndex(WorkQueue workQueue, Dao<?,K> dao, Profiling profiling) {
this.profiling = profiling;
this.workQueue = workQueue;
this.synchronizer = IndexSynchronizer.getOnetimeSynchronizer(this, this.workQueue);
+ this.dao = dao;
+ }
+
+ protected Dao<?,K> getDao(){
+ return this.dao;
+ }
+
+ protected Client getClient(){
+ return this.client;
}
+ /* Component Methods */
+
@Override
public void start() {
+ /* Connect to the local ES Cluster */
+ this.connect();
+
+ /* Setup the index if necessary */
+ this.intializeIndex();
+
+ /* Launch synchronization */
+ synchronizer.start();
+ }
+
+ @Override
+ public void stop() {
+ if (client != null) {
+ client.close();
+ }
+ }
+
+ private StopWatch createWatch() {
+ return profiling.start(PROFILE_DOMAIN, Level.FULL);
+ }
+
+ public void connect(){
/* Settings to access our local ES node */
Settings settings = ImmutableSettings.settingsBuilder()
.put("client.transport.sniff", true)
@@ -76,30 +111,35 @@ public abstract class BaseIndex<K extends Serializable> implements Index<K>{
this.client = new TransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(LOCAL_ES_NODE_HOST, LOCAL_ES_NODE_PORT));
- /* Cannot do that yet, need version >= 1.0
- ImmutableList<DiscoveryNode> nodes = client.connectedNodes();
- if (nodes.isEmpty()) {
- throw new ElasticSearchUnavailableException("No nodes available. Verify ES is running!");
- } else {
- log.info("connected to nodes: " + nodes.toString());
- }
- */
-
- /* Launch synchronization */
- synchronizer.start();
+ /*
+ * Cannot do that yet, need version >= 1.0
+ * ImmutableList<DiscoveryNode> nodes = client.connectedNodes();
+ * if (nodes.isEmpty()) {
+ * throw new ElasticSearchUnavailableException("No nodes available. Verify ES is running!");
+ * } else {
+ * log.info("connected to nodes: " + nodes.toString());
+ * }
+ */
}
- @Override
- public void stop() {
- if (client != null) {
- client.close();
+ /* Cluster And ES Stats/Client methods */
+
+ private void intializeIndex() {
+
+ String index = this.getIndexName();
+
+ IndicesExistsResponse indexExistsResponse = client.admin().indices()
+ .prepareExists(index).execute().actionGet();
+
+ if (!indexExistsResponse.isExists()) {
+
+ client.admin().indices().prepareCreate(index)
+ .setSettings(getIndexSettings())
+ .addMapping(getType(), getMapping())
+ .execute().actionGet();
}
}
- public Collection<K> synchronizeSince(Long date) {
- // TODO Auto-generated method stub
- return Collections.EMPTY_LIST;
- }
public ClusterStatsNodes getNodesStats() {
StopWatch watch = createWatch();
@@ -110,71 +150,87 @@ public abstract class BaseIndex<K extends Serializable> implements Index<K>{
}
}
- private StopWatch createWatch() {
- return profiling.start(PROFILE_DOMAIN, Level.FULL);
- }
+
+ /* Index management and Tx methods */
+
+ protected abstract Settings getIndexSettings();
+
+ protected abstract String getType();
+
+ protected abstract XContentBuilder getMapping();
+
+ public abstract Collection<K> synchronizeSince(Long date);
+
+
+ /* Base CRUD methods */
+
+ protected abstract QueryBuilder getKeyQuery(K key);
@Override
public Hit getByKey(K key) {
- // TODO Auto-generated method stub
+ getClient().prepareSearch(this.getIndexName())
+ .setQuery(getKeyQuery(key))
+ .get();
return null;
}
@Override
public void insert(K key) {
- // TODO Auto-generated method stub
-
+ this.update(key);
}
@Override
- public void udpate(K key) {
- // TODO Auto-generated method stub
+ public void update(K key) {
+ IndexResponse result = getClient().index(new IndexRequest()
+ .type(this.getType())
+ .index(this.getIndexName())
+ .source(this.normalize(key))).actionGet();
}
@Override
public void delete(K key) {
- // TODO Auto-generated method stub
-
+ DeleteByQueryResponse result = getClient().prepareDeleteByQuery(this.getIndexName())
+ .setQuery(getKeyQuery(key)).get();
}
- @Override
- public K dequeueInsert() {
- // TODO Auto-generated method stub
- return null;
- }
+ /* Synchronization methods */
- @Override
- public K dequeueUpdate() {
- // TODO Auto-generated method stub
- return null;
- }
+ Long lastSynch = 0l;
+ long cooldown = 30000;
@Override
- public K dequeueDelete() {
- // TODO Auto-generated method stub
- return null;
+ public void setLastSynchronization(Long time) {
+ if(time > (getLastSynchronization() + cooldown)){
+ LOG.trace("Updating synchTime updating");
+ lastSynch = time;
+ } else {
+ LOG.trace("Not updating synchTime, still cooling down");
+ }
+
}
@Override
- public abstract Map<String, Object> normalize(K key);
-
+ public Long getLastSynchronization() {
+ // need to read that in the admin index;
+ return 0l;
+ }
@Override
- public String getIndexName() {
- // TODO Auto-generated method stub
- return null;
+ @SuppressWarnings("unchecked")
+ public K dequeueInsert() {
+ return (K) this.workQueue.dequeUpdate(this.getIndexName());
}
@Override
- public void setLastSynchronization(Long time) {
- // TODO Auto-generated method stub
-
+ @SuppressWarnings("unchecked")
+ public K dequeueUpdate() {
+ return (K) this.workQueue.dequeUpdate(this.getIndexName());
}
@Override
- public Long getLastSynchronization() {
- // TODO Auto-generated method stub
- return null;
+ @SuppressWarnings("unchecked")
+ public K dequeueDelete() {
+ return (K) this.workQueue.dequeDelete(this.getIndexName());
}
}
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 4505806039c..25c91080bc1 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
@@ -34,7 +34,7 @@ public interface Index<K extends Serializable> extends Startable {
void insert(K key);
- void udpate(K key);
+ void update(K key);
void delete(K key);
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 a7a19d08577..0547675b535 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
@@ -23,9 +23,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.server.cluster.WorkQueue;
-import java.util.Date;
+import java.io.Serializable;
-public class IndexSynchronizer {
+public class IndexSynchronizer<K extends Serializable> {
private static final Logger LOG = LoggerFactory.getLogger(IndexSynchronizer.class);
@@ -34,49 +34,49 @@ public class IndexSynchronizer {
private long wait = 0;
private boolean continuous;
- private final Index<?> index;
+ private final Index<K> index;
private final WorkQueue workQueue;
- public static IndexSynchronizer getContinuousSynchronizer(Index<?> index, WorkQueue workQueue) {
- return new IndexSynchronizer(index, workQueue)
+ public static <K extends Serializable> IndexSynchronizer<K> getContinuousSynchronizer(Index<K> index, WorkQueue workQueue) {
+ return new IndexSynchronizer<K>(index, workQueue)
.setContinuous(true)
.setWait(DEFAULT_WAIT_TIME);
}
- public static IndexSynchronizer getContinuousSynchronizer(Index<?> index, WorkQueue workQueue, Long wait) {
- return new IndexSynchronizer(index, workQueue)
+ public static <K extends Serializable> IndexSynchronizer<K> getContinuousSynchronizer(Index<K> index, WorkQueue workQueue, Long wait) {
+ return new IndexSynchronizer<K>(index, workQueue)
.setContinuous(true)
.setWait(wait);
}
- public static IndexSynchronizer getOnetimeSynchronizer(Index<?> index, WorkQueue workQueue) {
- return new IndexSynchronizer(index, workQueue)
+ public static <K extends Serializable> IndexSynchronizer<K> getOnetimeSynchronizer(Index<K> index, WorkQueue workQueue) {
+ return new IndexSynchronizer<K>(index, workQueue)
.setContinuous(false);
}
- private IndexSynchronizer(Index<?> index, WorkQueue workQueue) {
+ private IndexSynchronizer(Index<K> index, WorkQueue workQueue) {
this.index = index;
this.workQueue = workQueue;
}
- private IndexSynchronizer setWait(Long wait) {
+ private IndexSynchronizer<K> setWait(Long wait) {
this.wait = wait;
return this;
}
- private IndexSynchronizer setContinuous(Boolean continuous) {
+ private IndexSynchronizer<K> setContinuous(Boolean continuous) {
this.continuous = continuous;
return this;
}
- public IndexSynchronizer start() {
+ public IndexSynchronizer<K> start() {
LOG.info("Starting synchronization thread for ", index.getClass().getSimpleName());
Long since = index.getLastSynchronization();
index.setLastSynchronization(System.currentTimeMillis());
- for (Object key : index.synchronizeSince(since)) {
+ for (K key : index.synchronizeSince(since)) {
if (LOG.isTraceEnabled()) {
LOG.trace("Adding {} to workQueue for {}", key, index.getClass().getSimpleName());
}
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
new file mode 100644
index 00000000000..117db387a9a
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/cluster/LocalNonBlockingWorkQueueTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.junit.Test;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+
+public class LocalNonBlockingWorkQueueTest {
+
+ private static final String WORKING_INDEX = "working_index";
+ private static final String NON_WORKING_INDEX = "non_working_index";
+
+ @Test
+ public void test_insert_queue(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ assertThat(queue.dequeInsert(WORKING_INDEX)).isNull();
+ assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull();
+
+ queue.enqueInsert(WORKING_INDEX, new Integer(0));
+ assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull();
+
+ Object dequeued = queue.dequeInsert(WORKING_INDEX);
+ assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull();
+ assertThat(queue.dequeInsert(WORKING_INDEX)).isNull();
+
+ assertThat(dequeued).isEqualTo(new Integer(0));
+ }
+
+ @Test
+ public void test_update_queue(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ assertThat(queue.dequeUpdate(WORKING_INDEX)).isNull();
+ assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull();
+
+ queue.enqueUpdate(WORKING_INDEX, new Integer(0));
+ assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull();
+
+ Object dequeued = queue.dequeUpdate(WORKING_INDEX);
+ assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull();
+ assertThat(queue.dequeUpdate(WORKING_INDEX)).isNull();
+
+ assertThat(dequeued).isEqualTo(new Integer(0));
+ }
+
+ @Test
+ public void test_delete_queue(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNull();
+ assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull();
+
+ queue.enqueDelete(WORKING_INDEX, new Integer(0));
+ assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull();
+
+ Object dequeued = queue.dequeDelete(WORKING_INDEX);
+ assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull();
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNull();
+
+ assertThat(dequeued).isEqualTo(new Integer(0));
+ }
+
+ @Test
+ public void test_enque_seralizable_object(){
+
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ class NonSerializable implements Serializable{
+ private Object var1;
+ private Map<String, Object> objs;
+ }
+
+ NonSerializable nonSer = new NonSerializable();
+ assertThat(queue.enqueInsert(WORKING_INDEX, nonSer)).isNotNull();
+
+ Object dequeued = queue.dequeInsert(WORKING_INDEX);
+ assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull();
+
+ assertThat(dequeued).isNotNull();
+ assertThat(dequeued.getClass()).isEqualTo(NonSerializable.class);
+ }
+
+ @Test
+ public void test_under_queue_capacity(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ for(int i = 0; i < 10; i++){
+ assertThat(queue.enqueDelete(WORKING_INDEX, i)).isNotNull();
+ }
+
+ for(int i = 0; i < 10; i++){
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNotNull();
+ }
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNull();
+
+ }
+
+ @Test
+ public void test_over_queue_capacity(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+
+ for(int i = 0; i < 100; i++){
+ assertThat(queue.enqueDelete(WORKING_INDEX, i)).isNotNull();
+ }
+
+ for(int i = 0; i < 100; i++){
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNotNull();
+ }
+ assertThat(queue.dequeDelete(WORKING_INDEX)).isNull();
+
+ }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/es/BaseIndexTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexTest.java
index 900efa8d6d3..a1e21f995b8 100644
--- a/sonar-server/src/test/java/org/sonar/server/es/BaseIndexTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexTest.java
@@ -17,51 +17,43 @@
* 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.es;
+package org.sonar.server.rule2;
-import java.io.Serializable;
-import java.util.Map;
+import org.sonar.server.cluster.LocalNonBlockingWorkQueue;
-import org.elasticsearch.client.transport.NoNodeAvailableException;
-import org.elasticsearch.common.settings.ImmutableSettings;
+import com.github.tlrx.elasticsearch.test.annotations.ElasticsearchNode;
+import com.github.tlrx.elasticsearch.test.support.junit.runners.ElasticsearchRunner;
import org.elasticsearch.node.Node;
-import org.elasticsearch.node.NodeBuilder;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.sonar.api.config.Settings;
import org.sonar.core.profiling.Profiling;
import org.sonar.server.search.BaseIndex;
import static org.fest.assertions.Assertions.assertThat;
-@Ignore
-public class BaseIndexTest {
+@RunWith(ElasticsearchRunner.class)
+public class RuleIndexTest {
private static final String TEST_NODE_NAME = "es_node_for_tests";
- private BaseIndex<?> searchIndex;
+ @ElasticsearchNode(name = TEST_NODE_NAME,
+ clusterName = BaseIndex.ES_CLUSTER_NAME,
+ local = false, data = true)
private Node node;
@Before
public void setUp() throws Exception {
- this.node = NodeBuilder.nodeBuilder()
- .settings(ImmutableSettings.settingsBuilder()
- .put("node.name", TEST_NODE_NAME).build())
- .clusterName(BaseIndex.ES_CLUSTER_NAME).node();
}
- private BaseIndex<?> getBaseIndex(){
+ private RuleIndex getRuleIndex(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
Settings settings = new Settings();
settings.setProperty("sonar.log.profilingLevel", "BASIC");
- return new BaseIndex<Serializable>(null, new Profiling(settings)) {
- @Override
- public Map<String, Object> normalize(Serializable key) {
- // TODO Auto-generated method stub
- return null;
- }
- };
+ RuleIndex rindex = new RuleIndex(queue, null, new Profiling(settings));
+ return rindex;
}
@After
@@ -72,30 +64,15 @@ public class BaseIndexTest {
}
@Test
- public void should_start_and_stop_properly() {
+ public void test_ruleIndex_conencts_to_es() {
- searchIndex = getBaseIndex();
- searchIndex.start();
+ RuleIndex ruleIndex = getRuleIndex();
+ ruleIndex.connect();
assertThat(node.client().admin().cluster().prepareClusterStats().get().getNodesStats().getCounts().getTotal())
- .isEqualTo(searchIndex.getNodesStats().getCounts().getTotal());
-
- searchIndex.stop();
-
- }
-
- @Test(expected = NoNodeAvailableException.class)
- public void fails_when_es_gone(){
- searchIndex = getBaseIndex();
- searchIndex.start();
-
- node.stop();
-
-
- assertThat(searchIndex.getNodesStats().getCounts().getTotal());
-
- node.start();
+ .isEqualTo(ruleIndex.getNodesStats().getCounts().getTotal());
+ ruleIndex.stop();
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java b/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java
new file mode 100644
index 00000000000..0f75176d5e1
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.server.cluster.LocalNonBlockingWorkQueue;
+
+import com.github.tlrx.elasticsearch.test.annotations.ElasticsearchNode;
+import com.github.tlrx.elasticsearch.test.support.junit.runners.ElasticsearchRunner;
+import org.elasticsearch.client.transport.NoNodeAvailableException;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.node.Node;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.sonar.api.config.Settings;
+import org.sonar.core.profiling.Profiling;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+@RunWith(ElasticsearchRunner.class)
+public class BaseIndexTest {
+
+ private static final String TEST_NODE_NAME = "es_node_for_tests";
+
+ @ElasticsearchNode(name = TEST_NODE_NAME,
+ clusterName = BaseIndex.ES_CLUSTER_NAME,
+ local = false, data = true)
+ private Node node;
+
+ @Before
+ public void setUp() throws Exception {
+
+ }
+
+ private BaseIndex<?> getBaseIndex(){
+ LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue();
+ Settings settings = new Settings();
+ settings.setProperty("sonar.log.profilingLevel", "BASIC");
+ return new BaseIndex<Serializable>(queue, null, new Profiling(settings)) {
+
+ @Override
+ public String getIndexName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected org.elasticsearch.common.settings.Settings getIndexSettings() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected String getType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected XContentBuilder getMapping() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Collection<Serializable> synchronizeSince(Long date) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected QueryBuilder getKeyQuery(Serializable key) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Map<String, Object> normalize(Serializable key) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+ }
+
+ @After
+ public void tearDown() {
+ if (node != null && !node.isClosed()) {
+ node.close();
+ }
+ }
+
+ @Test
+ public void baseIndex_connects_to_es() {
+ BaseIndex<?> searchIndex = getBaseIndex();
+ searchIndex.connect();
+ assertThat(node.client().admin().cluster().prepareClusterStats().get().getNodesStats().getCounts().getTotal())
+ .isEqualTo(searchIndex.getNodesStats().getCounts().getTotal());
+
+ searchIndex.stop();
+ }
+
+ @Test(expected = NoNodeAvailableException.class)
+ public void baseIndex_fails_when_es_gone(){
+ BaseIndex<?> searchIndex = getBaseIndex();
+ searchIndex.connect();
+ node.close();
+ assertThat(searchIndex.getNodesStats().getCounts().getTotal()).isNotNull();
+ }
+}