]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5666 SONAR-5697
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 4 Nov 2014 12:37:52 +0000 (13:37 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 4 Nov 2014 12:37:52 +0000 (13:37 +0100)
When setting 'sonar.log.profilingLevel' to FULL, only ES requests and not ES answers should be logged
Improve exception handling in E/S

44 files changed:
server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationNormalizer.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java
server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java
server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java
server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyBulkRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCountRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyFlushRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyGetRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyRefreshRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilder.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/SearchClientMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyBulkRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilderText.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilderText.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCountRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilderText.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyFlushRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyGetRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyRefreshRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchRequestBuilderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilderTest.java [new file with mode: 0644]

index 45950738e4c7d7fb7cdd0fe37ff01a226388792e..0e1ced87c50356b4188dc8044c07a6c73408905d 100644 (file)
@@ -24,22 +24,14 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.index.query.AndFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.OrFilterBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.sort.SortOrder;
 import org.sonar.core.activity.Activity;
 import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-import org.sonar.server.search.SearchClient;
+import org.sonar.server.search.*;
 
 import javax.annotation.Nullable;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -89,7 +81,7 @@ public class ActivityIndex extends BaseIndex<Activity, ActivityDto, String> {
       .setQuery(QueryBuilders.matchAllQuery())
       .setTypes(this.getIndexType())
       .setSize(Integer.MAX_VALUE);
-    SearchResponse response = getClient().execute(request);
+    SearchResponse response = request.get();
     return new Result<Activity>(this, response);
   }
 
@@ -140,8 +132,6 @@ public class ActivityIndex extends BaseIndex<Activity, ActivityDto, String> {
       esSearch.setScroll(TimeValue.timeValueMinutes(3));
     }
 
-    SearchResponse response = getClient().execute(esSearch);
-
-    return response;
+    return esSearch.get();
   }
 }
index a2bd856d303885abccd60dc860f6c1d208172445..1880e3e098e769669ae7e8127f37f9bb6efb5d4d 100644 (file)
@@ -20,7 +20,6 @@
 
 package org.sonar.server.issue.index;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import org.elasticsearch.action.update.UpdateRequest;
@@ -55,7 +54,7 @@ public class IssueAuthorizationNormalizer extends BaseNormalizer<IssueAuthorizat
   public List<UpdateRequest> normalize(IssueAuthorizationDto dto) {
     Map<String, Object> update = new HashMap<String, Object>();
 
-    Preconditions.checkNotNull(dto.getProjectUuid(), "Project uuid is null");
+//    Preconditions.checkNotNull(dto.getProjectUuid(), "Project uuid is null");
 
     update.put(IssueAuthorizationField.PROJECT.field(), dto.getProjectUuid());
     update.put(IssueAuthorizationField.USERS.field(), dto.getUsers());
index 3bc3b6093a5d18a73630d44f09ac75e6e70c1983..a9f0b3903e237d3ef184c85f59c77d1a0c14e8a1 100644 (file)
@@ -172,7 +172,7 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> {
     esSearch.addAggregation(AggregationBuilders.missing("notAssigned")
       .field(IssueNormalizer.IssueField.ASSIGNEE.field()));
 
-    SearchResponse response = getClient().execute(esSearch);
+    SearchResponse response = esSearch.get();
     Terms aggregation = (Terms) response.getAggregations().getAsMap().get(IssueNormalizer.IssueField.ASSIGNEE.field());
     List<FacetValue> facetValues = newArrayList();
     for (Terms.Bucket value : aggregation.getBuckets()) {
@@ -214,7 +214,7 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> {
 
     setFacets(query, options, filters, esQuery, esSearch);
 
-    SearchResponse response = getClient().execute(esSearch);
+    SearchResponse response = esSearch.get();
     return new Result<Issue>(this, response);
   }
 
index 5f578de95344037ec09a240c0a05f7a7fcb67153..0e3b8c66aa107dbdfe6fd744f591b7dcd8dd7d68 100644 (file)
@@ -77,15 +77,15 @@ public class BackendCleanup implements ServerComponent {
   }
 
   public void clearIndexes() {
-    searchClient.prepareDeleteByQuery(searchClient.admin().cluster().prepareState().get()
+    searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
       .getState().getMetaData().concreteAllIndices())
       .setQuery(QueryBuilders.matchAllQuery())
       .get();
-    searchClient.admin().indices().prepareRefresh(searchClient.admin().cluster().prepareState().get()
+    searchClient.prepareRefresh(searchClient.prepareState().get()
       .getState().getMetaData().concreteAllIndices())
       .setForce(true)
       .get();
-    searchClient.admin().indices().prepareFlush(searchClient.admin().cluster().prepareState().get()
+    searchClient.prepareFlush(searchClient.prepareState().get()
       .getState().getMetaData().concreteAllIndices())
       .get();
   }
@@ -150,7 +150,7 @@ public class BackendCleanup implements ServerComponent {
    * Completely remove a index with all types
    */
   public void clearIndex(IndexDefinition indexDefinition){
-    searchClient.prepareDeleteByQuery(searchClient.admin().cluster().prepareState().get()
+    searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
       .getState().getMetaData().concreteIndices(new String[]{indexDefinition.getIndexName()}))
       .setQuery(QueryBuilders.matchAllQuery())
       .get();
@@ -160,7 +160,7 @@ public class BackendCleanup implements ServerComponent {
    * Remove only the type of an index
    */
   public void clearIndexType(IndexDefinition indexDefinition){
-    searchClient.prepareDeleteByQuery(searchClient.admin().cluster().prepareState().get()
+    searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
       .getState().getMetaData().concreteIndices(new String[]{indexDefinition.getIndexName()})).setTypes(indexDefinition.getIndexType())
       .setQuery(QueryBuilders.matchAllQuery())
       .get();
index 80576ddfb7828aef0c86ea5babec70e250f9e044..595b6e72bc03e328bc94116b77e0f801b26e2383 100644 (file)
@@ -35,11 +35,7 @@ import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.server.qualityprofile.ActiveRule;
 import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.SearchClient;
+import org.sonar.server.search.*;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -116,7 +112,7 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
       // TODO replace by scrolling
       .setSize(Integer.MAX_VALUE);
 
-    SearchResponse response = getClient().execute(request);
+    SearchResponse response = request.get();
 
     List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
     for (SearchHit hit : response.getHits()) {
@@ -135,7 +131,7 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
       .setRouting(key)
       // TODO replace by scrolling
       .setSize(Integer.MAX_VALUE);
-    SearchResponse response = getClient().execute(request);
+    SearchResponse response = request.get();
     List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
     for (SearchHit hit : response.getHits()) {
       activeRules.add(toDoc(hit.getSource()));
@@ -181,7 +177,7 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
         .subAggregation(AggregationBuilders.count("countActiveRules")))
       .setSize(0)
       .setTypes(this.getIndexType());
-    SearchResponse response = getClient().execute(request);
+    SearchResponse response = request.get();
     Map<String, Multimap<String, FacetValue>> stats = new HashMap<String, Multimap<String, FacetValue>>();
     Aggregation aggregation = response.getAggregations().get(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field());
     for (Terms.Bucket value : ((Terms) aggregation).getBuckets()) {
index f87aa8ba4a068529ce891a7d84cfee16cd15e3e8..e8c188ca5b165da60cf81121f1b780fccaa089ce 100644 (file)
@@ -357,7 +357,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
     }
 
     esSearch.setQuery(QueryBuilders.filteredQuery(qb, fb));
-    SearchResponse esResult = getClient().execute(esSearch);
+    SearchResponse esResult = esSearch.get();
     return new Result<Rule>(this, esResult);
   }
 
@@ -379,7 +379,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
         .size(Integer.MAX_VALUE)
         .minDocCount(1));
 
-    SearchResponse esResponse = getClient().execute(request);
+    SearchResponse esResponse = request.get();
 
     Terms aggregation = esResponse.getAggregations().get(key);
 
@@ -401,7 +401,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
       .setTypes(this.getIndexType())
       .setQuery(QueryBuilders.termQuery(RuleNormalizer.RuleField.ID.field(), id))
       .setSize(1);
-    SearchResponse response = getClient().execute(request);
+    SearchResponse response = request.get();
 
     SearchHit hit = response.getHits().getAt(0);
     if (hit == null) {
@@ -422,7 +422,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
       .setScroll(TimeValue.timeValueSeconds(3L))
       .setSize(100)
       .setQuery(QueryBuilders.termsQuery(RuleNormalizer.RuleField.ID.field(), ids));
-    SearchResponse scrollResp = getClient().execute(request);
+    SearchResponse scrollResp = request.get();
 
     List<Rule> rules = newArrayList();
     while (true) {
@@ -430,7 +430,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
         .prepareSearchScroll(scrollResp.getScrollId())
         .setScroll(TimeValue.timeValueSeconds(3L));
 
-      scrollResp = getClient().execute(scrollRequest);
+      scrollResp = scrollRequest.get();
 
       for (SearchHit hit : scrollResp.getHits()) {
         rules.add(toDoc(hit.getSource()));
index e511f162f20db03b45a2812535c8678be5561b83..9294371e22d9d80f5671ac797b974d6b45001172 100644 (file)
@@ -113,7 +113,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
         try {
           SearchScrollRequestBuilder esRequest = client.prepareSearchScroll(scrollId)
             .setScroll(TimeValue.timeValueMinutes(3));
-          Collections.addAll(hits, ((SearchResponse) client.execute(esRequest)).getHits().getHits());
+          Collections.addAll(hits, esRequest.get().getHits().getHits());
         } catch (Exception e) {
           throw new IllegalStateException("Error while filling in the scroll buffer", e);
         }
@@ -148,19 +148,18 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
   protected void initializeIndex() {
     String index = this.getIndexName();
 
-    IndicesExistsResponse indexExistsResponse = client.admin().indices()
-      .prepareExists(index).execute().actionGet();
+    IndicesExistsResponse indexExistsResponse = client.prepareExists(index).get();
     try {
 
       if (!indexExistsResponse.isExists()) {
         LOG.debug("Setup of {} for type {}", this.getIndexName(), this.getIndexType());
-        client.admin().indices().prepareCreate(index)
+        client.prepareCreate(index)
           .setSettings(getIndexSettings())
-          .execute().actionGet();
+          .get();
       }
 
       LOG.debug("Update of index {} for type {}", this.getIndexName(), this.getIndexType());
-      client.admin().indices().preparePutMapping(index)
+      client.preparePutMapping(index)
         .setType(getIndexType())
         .setIgnoreConflicts(true)
         .setSource(mapDomain())
@@ -176,7 +175,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
     CountRequestBuilder countRequest = client.prepareCount(this.getIndexName())
       .setTypes(this.getIndexType())
       .setQuery(QueryBuilders.matchAllQuery());
-    CountResponse response = client.execute(countRequest);
+    CountResponse response = countRequest.get();
     return new IndexStat(getLastSynchronization(), response.getCount());
   }
 
@@ -201,7 +200,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
       .addAggregation(AggregationBuilders.max("latest")
         .field(BaseNormalizer.UPDATED_AT_FIELD));
 
-    SearchResponse response = client.execute(request);
+    SearchResponse response = request.get();
 
     Max max = response.getAggregations().get("latest");
     if (max.getValue() > 0) {
@@ -416,7 +415,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
       .setFetchSource(true)
       .setRouting(this.getKeyValue(key));
 
-    GetResponse response = client.execute(request);
+    GetResponse response = request.get();
 
     if (response.isExists()) {
       return toDoc(response.getSource());
@@ -438,7 +437,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
           .fetchSourceContext(FetchSourceContext.FETCH_SOURCE));
     }
 
-    MultiGetResponse response = client.execute(request);
+    MultiGetResponse response = request.get();
     if (response.getResponses() != null) {
       for (MultiGetItemResponse item : response.getResponses()) {
         Map<String, Object> source = item.getResponse().getSource();
@@ -497,7 +496,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
         .size(Integer.MAX_VALUE)
         .minDocCount(0));
 
-    SearchResponse response = client.execute(request);
+    SearchResponse response = request.get();
 
     Terms values =
       response.getAggregations().get(indexField.field());
index 6fe769ca0204c4d401a8e3b498b5c1ea18fe6da1..821ed4526ad3d72a20051735def879f157a4e604 100644 (file)
@@ -19,8 +19,6 @@
  */
 package org.sonar.server.search;
 
-import com.google.common.annotations.VisibleForTesting;
-
 public class IndexDefinition {
 
   private final String indexName;
@@ -45,8 +43,8 @@ public class IndexDefinition {
   public static final IndexDefinition ISSUES = new IndexDefinition("issues", "issue");
   public static final IndexDefinition LOG = new IndexDefinition("logs", "sonarLog");
 
-  @VisibleForTesting
-  protected static IndexDefinition TEST = new IndexDefinition("test", "test");
+  // Only used for test
+  public static IndexDefinition TEST = new IndexDefinition("test", "test");
 
   public static IndexDefinition createFor(String indexName, String indexType) {
     return new IndexDefinition(indexName, indexType);
index a7fb911ad3f9b678086afcb61d8f58dc8dcba45b..2944ac897015eff05cb706334b3df9fa6a0c7375 100644 (file)
@@ -73,14 +73,14 @@ public class IndexQueue implements ServerComponent, WorkQueue<IndexAction<?>> {
       }
     }
 
-    BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient);
+    BulkRequestBuilder bulkRequestBuilder = searchClient.prepareBulk();
 
     long normTime = processActionsIntoQueries(bulkRequestBuilder, actions);
 
     if (bulkRequestBuilder.numberOfActions() > 0) {
       // execute the request
       long indexTime = System.currentTimeMillis();
-      BulkResponse response = searchClient.execute(bulkRequestBuilder.setRefresh(false));
+      BulkResponse response = bulkRequestBuilder.setRefresh(false).get();
 
       indexTime = System.currentTimeMillis() - indexTime;
 
@@ -99,14 +99,12 @@ public class IndexQueue implements ServerComponent, WorkQueue<IndexAction<?>> {
   }
 
   private long refreshRequiredIndex(Set<String> indices) {
-
     long refreshTime = System.currentTimeMillis();
     if (!indices.isEmpty()) {
-      RefreshRequestBuilder refreshRequest = searchClient.admin().indices()
-        .prepareRefresh(indices.toArray(new String[indices.size()]))
+      RefreshRequestBuilder refreshRequest = searchClient.prepareRefresh(indices.toArray(new String[indices.size()]))
         .setForce(false);
 
-      RefreshResponse refreshResponse = searchClient.execute(refreshRequest);
+      RefreshResponse refreshResponse = refreshRequest.get();
 
       if (refreshResponse.getFailedShards() > 0) {
         LOGGER.warn("{} Shard(s) did not refresh", refreshResponse.getFailedShards());
index 2afafd06752f2e441c5c53fe850257b7b9590d3d..8383658bb548ccbad676f0a5c876fdc9c33f4557 100644 (file)
 package org.sonar.server.search;
 
 import org.apache.commons.lang.StringUtils;
-import org.elasticsearch.action.ActionRequestBuilder;
-import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequestBuilder;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
+import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestBuilder;
+import org.elasticsearch.action.admin.cluster.state.ClusterStateRequestBuilder;
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequestBuilder;
 import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
+import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequestBuilder;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.count.CountRequestBuilder;
+import org.elasticsearch.action.delete.DeleteRequestBuilder;
+import org.elasticsearch.action.deletebyquery.DeleteByQueryRequestBuilder;
+import org.elasticsearch.action.explain.ExplainRequestBuilder;
+import org.elasticsearch.action.get.GetRequestBuilder;
+import org.elasticsearch.action.get.MultiGetRequestBuilder;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.action.mlt.MoreLikeThisRequestBuilder;
+import org.elasticsearch.action.percolate.MultiPercolateRequestBuilder;
+import org.elasticsearch.action.percolate.PercolateRequestBuilder;
+import org.elasticsearch.action.search.ClearScrollRequestBuilder;
+import org.elasticsearch.action.search.MultiSearchRequestBuilder;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.action.search.SearchScrollRequestBuilder;
+import org.elasticsearch.action.suggest.SuggestRequestBuilder;
+import org.elasticsearch.action.termvector.MultiTermVectorsRequestBuilder;
+import org.elasticsearch.action.termvector.TermVectorRequestBuilder;
+import org.elasticsearch.action.update.UpdateRequestBuilder;
 import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.common.Nullable;
 import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.logging.slf4j.Slf4jESLoggerFactory;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.elasticsearch.common.xcontent.ToXContent;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
 import org.picocontainer.Startable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.sonar.api.config.Settings;
 import org.sonar.core.profiling.Profiling;
-import org.sonar.core.profiling.StopWatch;
 import org.sonar.process.LoopbackAddress;
 import org.sonar.process.ProcessConstants;
+import org.sonar.server.search.request.*;
 
 /**
  * ElasticSearch Node used to connect to index.
  */
 public class SearchClient extends TransportClient implements Startable {
 
-  private static final Logger LOGGER = LoggerFactory.getLogger(SearchClient.class);
-
   private final Profiling profiling;
 
   public SearchClient(Settings settings) {
@@ -66,7 +87,7 @@ public class SearchClient extends TransportClient implements Startable {
 
   public ClusterHealth getClusterHealth() {
     ClusterHealth health = new ClusterHealth();
-    ClusterStatsResponse clusterStatsResponse = this.admin().cluster().prepareClusterStats().get();
+    ClusterStatsResponse clusterStatsResponse = this.prepareClusterStats().get();
 
     // Cluster health
     health.setClusterAvailable(clusterStatsResponse.getStatus() != ClusterHealthStatus.RED);
@@ -81,28 +102,173 @@ public class SearchClient extends TransportClient implements Startable {
     ESLoggerFactory.setDefaultFactory(new Slf4jESLoggerFactory());
   }
 
-  public <K extends ActionResponse> K execute(ActionRequestBuilder request) {
-    StopWatch fullProfile = profiling.start("search", Profiling.Level.FULL);
-    K response = null;
-    try {
-      response = (K) request.get();
-
-      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
-        if (ToXContent.class.isAssignableFrom(request.getClass())) {
-          XContentBuilder debugResponse = XContentFactory.jsonBuilder();
-          debugResponse.startObject();
-          ((ToXContent) request).toXContent(debugResponse, ToXContent.EMPTY_PARAMS);
-          debugResponse.endObject();
-          fullProfile.stop("ES Request: %s", debugResponse.string());
-        } else {
-          fullProfile.stop("ES Request: %s", request.toString().replaceAll("\n", ""));
-        }
-      }
-      return response;
-    } catch (Exception e) {
-      LOGGER.error(String.format("could not execute request: %s", request), e);
-      throw new IllegalStateException("ES error: ", e);
-    }
+  public RefreshRequestBuilder prepareRefresh(String... indices) {
+    return new ProxyRefreshRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  public FlushRequestBuilder prepareFlush(String... indices) {
+    return new ProxyFlushRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  public IndicesStatsRequestBuilder prepareStats(String... indices) {
+    return new ProxyIndicesStatsRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  public NodesStatsRequestBuilder prepareNodesStats(String... nodesIds) {
+    return new ProxyNodesStatsRequestBuilder(this, profiling).setNodesIds(nodesIds);
+  }
+
+  public ClusterStatsRequestBuilder prepareClusterStats() {
+    return new ProxyClusterStatsRequestBuilder(this, profiling);
+  }
+
+  public ClusterStateRequestBuilder prepareState() {
+    return new ProxyClusterStateRequestBuilder(this, profiling);
+  }
+
+  public ClusterHealthRequestBuilder prepareHealth(String... indices) {
+    return new ProxyClusterHealthRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  public IndicesExistsRequestBuilder prepareExists(String... indices) {
+    return new ProxyIndicesExistsRequestBuilder(this, profiling, indices);
+  }
+
+  public CreateIndexRequestBuilder prepareCreate(String index) {
+    return new ProxyCreateIndexRequestBuilder(this, profiling, index);
+  }
+
+  public PutMappingRequestBuilder preparePutMapping(String... indices) {
+    return new ProxyPutMappingRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  @Override
+  public SearchRequestBuilder prepareSearch(String... indices) {
+    return new ProxySearchRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  @Override
+  public SearchScrollRequestBuilder prepareSearchScroll(String scrollId) {
+    return new ProxySearchScrollRequestBuilder(scrollId, this, profiling);
+  }
+
+  @Override
+  public GetRequestBuilder prepareGet() {
+    return new ProxyGetRequestBuilder(this, profiling);
+  }
+
+  @Override
+  public GetRequestBuilder prepareGet(String index, String type, String id) {
+    return new ProxyGetRequestBuilder(this, profiling).setIndex(index).setType(type).setId(id);
+  }
+
+  @Override
+  public MultiGetRequestBuilder prepareMultiGet() {
+    return new ProxyMultiGetRequestBuilder(this, profiling);
+  }
+
+  @Override
+  public CountRequestBuilder prepareCount(String... indices) {
+    return new ProxyCountRequestBuilder(this, profiling).setIndices(indices);
+  }
+
+  @Override
+  public BulkRequestBuilder prepareBulk() {
+    return new ProxyBulkRequestBuilder(this, profiling);
+  }
+
+  @Override
+  public DeleteByQueryRequestBuilder prepareDeleteByQuery(String... indices) {
+    // TODO
+    return new DeleteByQueryRequestBuilder(this).setIndices(indices);
+  }
+
+  // ****************************************************************************************************************
+  // Not yet implemented methods
+  // ****************************************************************************************************************
+
+  @Override
+  public MultiSearchRequestBuilder prepareMultiSearch() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public IndexRequestBuilder prepareIndex() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public IndexRequestBuilder prepareIndex(String index, String type) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public IndexRequestBuilder prepareIndex(String index, String type, @Nullable String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public UpdateRequestBuilder prepareUpdate() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public UpdateRequestBuilder prepareUpdate(String index, String type, String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public DeleteRequestBuilder prepareDelete() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public DeleteRequestBuilder prepareDelete(String index, String type, String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public PercolateRequestBuilder preparePercolate() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public MultiPercolateRequestBuilder prepareMultiPercolate() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public SuggestRequestBuilder prepareSuggest(String... indices) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public MoreLikeThisRequestBuilder prepareMoreLikeThis(String index, String type, String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public TermVectorRequestBuilder prepareTermVector(String index, String type, String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public MultiTermVectorsRequestBuilder prepareMultiTermVectors() {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public ExplainRequestBuilder prepareExplain(String index, String type, String id) {
+    throw throwNotYetImplemented();
+  }
+
+  @Override
+  public ClearScrollRequestBuilder prepareClearScroll() {
+    throw throwNotYetImplemented();
+  }
+
+  private static IllegalStateException throwNotYetImplemented(){
+    return new IllegalStateException("Not yet implemented");
   }
 
   @Override
index cfc274c1780d6b81953c6106923654999f64b560..fd03d6fc3e5fa00e72f33efe588dd13e7958c832 100644 (file)
@@ -54,9 +54,9 @@ public class SearchHealth {
       newIndexHealth.documentCount = indexStat.getDocumentCount();
       newIndexHealth.lastSync = indexStat.getLastUpdate();
 
-      IndicesStatsRequestBuilder statRequest = searchClient.admin().indices().prepareStats(index.getIndexName())
+      IndicesStatsRequestBuilder statRequest = searchClient.prepareStats(index.getIndexName())
         .setTypes(index.getIndexType());
-      IndicesStatsResponse indicesStatsResponse = searchClient.execute(statRequest);
+      IndicesStatsResponse indicesStatsResponse = statRequest.get();
       newIndexHealth.segmentCount = indicesStatsResponse.getTotal().getSegments().getCount();
       newIndexHealth.pendingDeletion = indicesStatsResponse.getTotal().getDocs().getDeleted();
 
@@ -66,8 +66,8 @@ public class SearchHealth {
   }
 
   public Map<String, NodeHealth > getNodesHealth() {
-    NodesStatsRequestBuilder nodesStatsRequest = searchClient.admin().cluster().prepareNodesStats().all();
-    NodesStatsResponse nodesStats = searchClient.execute(nodesStatsRequest);
+    NodesStatsRequestBuilder nodesStatsRequest = searchClient.prepareNodesStats().all();
+    NodesStatsResponse nodesStats = nodesStatsRequest.get();
 
     Map<String, NodeHealth> health = Maps.newHashMap();
     for (Entry<String, NodeStats> nodeEntry: nodesStats.getNodesMap().entrySet()) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyBulkRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyBulkRequestBuilder.java
new file mode 100644 (file)
index 0000000..b0e2d19
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.delete.DeleteRequest;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyBulkRequestBuilder extends BulkRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyBulkRequestBuilder(Client client, Profiling profiling) {
+    super(client);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public BulkResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("bulk", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public BulkResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public BulkResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<BulkResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES bulk request for ");
+    for (ActionRequest item : request.requests()) {
+      message.append(String.format("[Action '%s' ", item.getClass().getSimpleName()));
+      if (item instanceof IndexRequest) {
+        IndexRequest request = (IndexRequest) item;
+        message.append(String.format("for key '%s'", request.id()));
+        message.append(String.format(" on index '%s'", request.index()));
+        message.append(String.format(" on type '%s'", request.type()));
+      } else if (item instanceof UpdateRequest) {
+        UpdateRequest request = (UpdateRequest) item;
+        message.append(String.format("for key '%s'", request.id()));
+        message.append(String.format(" on index '%s'", request.index()));
+        message.append(String.format(" on type '%s'", request.type()));
+      } else if (item instanceof DeleteRequest) {
+        DeleteRequest request = (DeleteRequest) item;
+        message.append(String.format("for key '%s'", request.id()));
+        message.append(String.format(" on index '%s'", request.index()));
+        message.append(String.format(" on type '%s'", request.type()));
+      }
+      message.append("],");
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilder.java
new file mode 100644 (file)
index 0000000..ffb4115
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequestBuilder;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyClusterHealthRequestBuilder extends ClusterHealthRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyClusterHealthRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().cluster());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public ClusterHealthResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("cluster health", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public ClusterHealthResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ClusterHealthResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<ClusterHealthResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES cluster health request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilder.java
new file mode 100644 (file)
index 0000000..dee6889
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.cluster.state.ClusterStateRequestBuilder;
+import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyClusterStateRequestBuilder extends ClusterStateRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyClusterStateRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().cluster());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public ClusterStateResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("cluster state", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public ClusterStateResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ClusterStateResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<ClusterStateResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES cluster state request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilder.java
new file mode 100644 (file)
index 0000000..ec47c0a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequestBuilder;
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyClusterStatsRequestBuilder extends ClusterStatsRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyClusterStatsRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().cluster());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public ClusterStatsResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("cluster stats", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public ClusterStatsResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ClusterStatsResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<ClusterStatsResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES cluster stats request");
+    if (request.nodesIds().length > 0) {
+      message.append(String.format(" on nodes '%s'", StringUtils.join(request.nodesIds(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCountRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCountRequestBuilder.java
new file mode 100644 (file)
index 0000000..ad55ef1
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.count.CountRequestBuilder;
+import org.elasticsearch.action.count.CountResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyCountRequestBuilder extends CountRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyCountRequestBuilder(Client client, Profiling profiling) {
+    super(client);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public CountResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("count", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public CountResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public CountResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<CountResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES count request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    if (request.types().length > 0) {
+      message.append(String.format(" on types '%s'", StringUtils.join(request.types(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilder.java
new file mode 100644 (file)
index 0000000..886088a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
+import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyCreateIndexRequestBuilder extends CreateIndexRequestBuilder {
+
+  private final Profiling profiling;
+  private final String index;
+
+  public ProxyCreateIndexRequestBuilder(Client client, Profiling profiling, String index) {
+    super(client.admin().indices(), index);
+    this.profiling = profiling;
+    this.index = index;
+  }
+
+  @Override
+  public CreateIndexResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("create index", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public CreateIndexResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public CreateIndexResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<CreateIndexResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    return String.format("ES create index '%s'", index);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyFlushRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyFlushRequestBuilder.java
new file mode 100644 (file)
index 0000000..3a846ba
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder;
+import org.elasticsearch.action.admin.indices.flush.FlushResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyFlushRequestBuilder extends FlushRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyFlushRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().indices());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public FlushResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("flush", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public FlushResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public FlushResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<FlushResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES flush request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyGetRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyGetRequestBuilder.java
new file mode 100644 (file)
index 0000000..596b3bf
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.get.GetRequestBuilder;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyGetRequestBuilder extends GetRequestBuilder {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ProxyGetRequestBuilder.class);
+
+  private final Profiling profiling;
+
+  public ProxyGetRequestBuilder(Client client, Profiling profiling) {
+    super(client);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public GetResponse get() {
+    StopWatch fullProfile = profiling.start("get", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public GetResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public GetResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<GetResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder().append("ES get request");
+    message.append(String.format(" for key '%s'", request.id()));
+    message.append(String.format(" on index '%s'", request.index()));
+    message.append(String.format(" on type '%s'", request.type()));
+    return message.toString();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilder.java
new file mode 100644 (file)
index 0000000..b77ff5b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyIndicesExistsRequestBuilder extends IndicesExistsRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyIndicesExistsRequestBuilder(Client client, Profiling profiling, String... indices) {
+    super(client.admin().indices(), indices);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public IndicesExistsResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("indices exists", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public IndicesExistsResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public IndicesExistsResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<IndicesExistsResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES indices exists request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilder.java
new file mode 100644 (file)
index 0000000..b4f6889
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyIndicesStatsRequestBuilder extends IndicesStatsRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyIndicesStatsRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().indices());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public IndicesStatsResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("indices stats", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public IndicesStatsResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public IndicesStatsResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<IndicesStatsResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES indices stats request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilder.java
new file mode 100644 (file)
index 0000000..41bb0ae
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.get.MultiGetRequest;
+import org.elasticsearch.action.get.MultiGetRequestBuilder;
+import org.elasticsearch.action.get.MultiGetResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyMultiGetRequestBuilder extends MultiGetRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyMultiGetRequestBuilder(Client client, Profiling profiling) {
+    super(client);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public MultiGetResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("get", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public MultiGetResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public MultiGetResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<MultiGetResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES multi get request");
+    for (MultiGetRequest.Item item : request) {
+      message.append(String.format(" [key '%s'", item.id()));
+      message.append(String.format(", index '%s'", item.index()));
+      String type = item.type();
+      if (type != null) {
+        message.append(String.format(", type '%s'],", type));
+      }
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilder.java
new file mode 100644 (file)
index 0000000..d2742a7
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestBuilder;
+import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyNodesStatsRequestBuilder extends NodesStatsRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyNodesStatsRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().cluster());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public NodesStatsResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("nodes stats", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public NodesStatsResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public NodesStatsResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<NodesStatsResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES nodes stats request");
+    if (request.nodesIds().length > 0) {
+      message.append(String.format(" on nodes '%s'", StringUtils.join(request.nodesIds(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilder.java
new file mode 100644 (file)
index 0000000..6bca83a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyPutMappingRequestBuilder extends PutMappingRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyPutMappingRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().indices());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public PutMappingResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("put mapping", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public PutMappingResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public PutMappingResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<PutMappingResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES put mapping request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    String type = request.type();
+    if (type != null) {
+      message.append(String.format(" on type '%s'", type));
+    }
+    String source = request.source();
+    if (source != null) {
+      message.append(String.format(" with source '%s'", source));
+    }
+
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyRefreshRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxyRefreshRequestBuilder.java
new file mode 100644 (file)
index 0000000..fd2dca1
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequestBuilder;
+import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyRefreshRequestBuilder extends RefreshRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxyRefreshRequestBuilder(Client client, Profiling profiling) {
+    super(client.admin().indices());
+    this.profiling = profiling;
+  }
+
+  @Override
+  public RefreshResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("refresh", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public RefreshResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public RefreshResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<RefreshResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append("ES refresh request");
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+    }
+    return message.toString();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchRequestBuilder.java
new file mode 100644 (file)
index 0000000..08b68a8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+public class ProxySearchRequestBuilder extends SearchRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxySearchRequestBuilder(Client client, Profiling profiling) {
+    super(client);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public SearchResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("search", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public SearchResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public SearchResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<SearchResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    StringBuilder message = new StringBuilder();
+    message.append(String.format("ES search request '%s'", xContentToString(super.internalBuilder())));
+    if (request.indices().length > 0) {
+      message.append(String.format(" on indices '%s'", Arrays.toString(request.indices())));
+    }
+    if (request.types().length > 0) {
+      message.append(String.format(" on types '%s'", Arrays.toString(request.types())));
+    }
+    return message.toString();
+  }
+
+  private static String xContentToString(ToXContent toXContent) {
+    try {
+      XContentBuilder debugResponse = XContentFactory.jsonBuilder();
+      debugResponse.startObject();
+      toXContent.toXContent(debugResponse, ToXContent.EMPTY_PARAMS);
+      debugResponse.endObject();
+      return debugResponse.string();
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to convert request to string", e);
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilder.java
new file mode 100644 (file)
index 0000000..214832b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchScrollRequestBuilder;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxySearchScrollRequestBuilder extends SearchScrollRequestBuilder {
+
+  private final Profiling profiling;
+
+  public ProxySearchScrollRequestBuilder(String scrollId, Client client, Profiling profiling) {
+    super(client, scrollId);
+    this.profiling = profiling;
+  }
+
+  @Override
+  public SearchResponse get() throws ElasticsearchException {
+    StopWatch fullProfile = profiling.start("search", Profiling.Level.FULL);
+    try {
+      return super.execute().actionGet();
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+    } finally {
+      if (profiling.isProfilingEnabled(Profiling.Level.BASIC)) {
+        fullProfile.stop("%s", toString());
+      }
+    }
+  }
+
+  @Override
+  public SearchResponse get(TimeValue timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public SearchResponse get(String timeout) throws ElasticsearchException {
+    throw new IllegalStateException("Not yet implemented");
+  }
+
+  @Override
+  public ListenableActionFuture<SearchResponse> execute() {
+    throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+  }
+
+  public String toString() {
+    return String.format("ES search scroll request for scroll id '%s'", super.request().scroll());
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/SearchClientMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/SearchClientMediumTest.java
new file mode 100644 (file)
index 0000000..0da52d8
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * 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.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class SearchClientMediumTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @Test
+  public void prepare_multi_search_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMultiSearch();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_index_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareIndex();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+
+    try {
+      searchClient.prepareIndex("index", "type");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+
+    try {
+      searchClient.prepareIndex("index", "type", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_update_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareUpdate();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+
+    try {
+      searchClient.prepareUpdate("index", "type", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_delete_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareDelete();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+
+    try {
+      searchClient.prepareDelete("index", "type", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_percolate_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.preparePercolate();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_multi_percolate_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMultiPercolate();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_suggest_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareSuggest("index");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_more_like_this_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMoreLikeThis("index", "tpye", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_term_vector_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareTermVector("index", "tpye", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_multi_term_vectors_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMultiTermVectors();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_explain_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareExplain("index", "tpye", "id");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void prepare_clear_scroll_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareClearScroll();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyBulkRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyBulkRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..b5ab6fe
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.delete.DeleteRequest;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyBulkRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void bulk() {
+    BulkRequestBuilder bulkRequestBuilder = searchClient.prepareBulk();
+    bulkRequestBuilder.add(new UpdateRequest(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexName(), "rule1").doc(Collections.emptyMap()));
+
+    BulkResponse response = bulkRequestBuilder.get();
+    assertThat(response.getItems().length).isEqualTo(1);
+  }
+
+  @Test
+  public void fail_to_bulk_bad_query() throws Exception {
+    try {
+      BulkRequestBuilder bulkRequestBuilder = searchClient.prepareBulk();
+      bulkRequestBuilder.add(new UpdateRequest("unknown", IndexDefinition.RULE.getIndexName(), "rule1").doc(Collections.emptyMap()));
+      bulkRequestBuilder.add(new DeleteRequest("unknown", IndexDefinition.RULE.getIndexName(), "rule1"));
+      bulkRequestBuilder.add(new IndexRequest("unknown", IndexDefinition.RULE.getIndexName(), "rule1").source(Collections.emptyMap()));
+
+      bulkRequestBuilder.get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES bulk request for [Action 'UpdateRequest' for key 'rule1' on index 'unknown' on type 'rules'],")
+        .contains("[Action 'DeleteRequest' for key 'rule1' on index 'unknown' on type 'rules'],")
+        .contains("[Action 'IndexRequest' for key 'rule1' on index 'unknown' on type 'rules'],");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareBulk().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareBulk().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareBulk().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterHealthRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..e23acb2
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyClusterHealthRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void state() {
+    ClusterHealthRequestBuilder requestBuilder = searchClient.prepareHealth();
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareHealth("rules").toString()).isEqualTo("ES cluster health request on indices 'rules'");
+    assertThat(searchClient.prepareHealth().toString()).isEqualTo("ES cluster health request");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareHealth().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareHealth().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareHealth().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilderText.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStateRequestBuilderText.java
new file mode 100644 (file)
index 0000000..6321521
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.cluster.state.ClusterStateRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyClusterStateRequestBuilderText {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void state() {
+    ClusterStateRequestBuilder requestBuilder = searchClient.prepareState();
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareState().setIndices("rules").toString()).isEqualTo("ES cluster state request on indices 'rules'");
+    assertThat(searchClient.prepareState().toString()).isEqualTo("ES cluster state request");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareState().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareState().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareState().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilderText.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyClusterStatsRequestBuilderText.java
new file mode 100644 (file)
index 0000000..653bdc7
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyClusterStatsRequestBuilderText {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void stats() {
+    ClusterStatsRequestBuilder requestBuilder = searchClient.prepareClusterStats();
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareClusterStats().setNodesIds("node1").toString()).isEqualTo("ES cluster stats request on nodes 'node1'");
+    assertThat(searchClient.prepareClusterStats().toString()).isEqualTo("ES cluster stats request");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareClusterStats().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareClusterStats().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareClusterStats().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCountRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCountRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..9365d44
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.count.CountResponse;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyCountRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void count() {
+    tester.get(RuleDao.class).insert(dbSession, RuleTesting.newXooX1());
+    dbSession.commit();
+
+    CountResponse response = searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).get();
+    assertThat(response.getCount()).isEqualTo(1);
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).setTypes("rule").toString()).isEqualTo("ES count request on indices 'rules' on types 'rule'");
+    assertThat(searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).toString()).isEqualTo("ES count request on indices 'rules'");
+    assertThat(searchClient.prepareCount().toString()).isEqualTo("ES count request");
+  }
+
+  @Test
+  public void fail_to_count_bad_query() throws Exception {
+    try {
+      searchClient.prepareCount("unknown_index1, unknown_index2").setTypes("unknown_type").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES count request on indices 'unknown_index1, unknown_index2' on types 'unknown_type'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareCount(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilderText.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyCreateIndexRequestBuilderText.java
new file mode 100644 (file)
index 0000000..f44e2ef
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyCreateIndexRequestBuilderText {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void create_index() {
+    CreateIndexRequestBuilder requestBuilder = searchClient.prepareCreate("new");
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareCreate("new").toString()).isEqualTo("ES create index 'new'");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareCreate("new").get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareCreate("new").get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareCreate("new").execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyFlushRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyFlushRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..8bdf0d7
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyFlushRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void flush() {
+    FlushRequestBuilder requestBuilder = searchClient.prepareFlush(IndexDefinition.RULE.getIndexName());
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareFlush(IndexDefinition.RULE.getIndexName()).toString()).isEqualTo("ES flush request on indices 'rules'");
+    assertThat(searchClient.prepareFlush().toString()).isEqualTo("ES flush request");
+  }
+
+  @Test
+  public void fail_to_refresh() throws Exception {
+    try {
+      searchClient.prepareFlush("unknown").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES flush request on indices 'unknown'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareFlush(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareFlush(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareFlush(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyGetRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyGetRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..800a11e
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.get.GetRequestBuilder;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.indices.IndexMissingException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyGetRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void get() {
+    RuleDto rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(dbSession, rule);
+    dbSession.commit();
+
+    GetResponse response = searchClient.prepareGet()
+      .setIndex(IndexDefinition.RULE.getIndexName())
+      .setType(IndexDefinition.RULE.getIndexType())
+      .setId(rule.getKey().toString())
+      .get();
+    assertThat(response.getSource()).isNotEmpty();
+  }
+
+  @Test
+  public void get_with_index_type_and_id() {
+    RuleDto rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(dbSession, RuleTesting.newXooX1());
+    dbSession.commit();
+
+    GetResponse response = searchClient.prepareGet(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), rule.getKey().toString()).get();
+    assertThat(response.getSource()).isNotEmpty();
+  }
+
+  @Test
+  public void fail_to_get_bad_query() throws Exception {
+    GetRequestBuilder requestBuilder = searchClient.prepareGet()
+      .setIndex("unknown")
+      .setType("test")
+      .setId("rule1");
+    try {
+      requestBuilder.get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES get request for key 'rule1' on index 'unknown' on type 'test'");
+    }
+  }
+
+  @Test(expected = IndexMissingException.class)
+  public void fail_to_get_bad_query_using_new_builder() throws Exception {
+    GetRequestBuilder requestBuilder = new GetRequestBuilder(searchClient)
+      .setIndex("unknown")
+      .setType("test")
+      .setId("rule1");
+    requestBuilder.get();
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareGet().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareGet().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareGet().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesExistsRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..682710e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyIndicesExistsRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void exists() {
+    IndicesExistsRequestBuilder requestBuilder = searchClient.prepareExists(IndexDefinition.RULE.getIndexName());
+    requestBuilder.get();
+  }
+
+  @Test
+  public void fail_to_stats() throws Exception {
+    try {
+      searchClient.prepareExists().get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES indices exists request");
+    }
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareExists(IndexDefinition.RULE.getIndexName()).toString()).isEqualTo("ES indices exists request on indices 'rules'");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareExists().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareExists().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareExists().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyIndicesStatsRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..18a3c7c
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyIndicesStatsRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void stats() {
+    IndicesStatsRequestBuilder requestBuilder = searchClient.prepareStats(IndexDefinition.RULE.getIndexName());
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareStats(IndexDefinition.RULE.getIndexName()).setIndices("rules").toString()).isEqualTo("ES indices stats request on indices 'rules'");
+    assertThat(searchClient.prepareStats().toString()).isEqualTo("ES indices stats request");
+  }
+
+  @Test
+  public void fail_to_stats() throws Exception {
+    try {
+      searchClient.prepareStats("unknown").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES indices stats request on indices 'unknown'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareStats(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareStats(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareStats(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyMultiGetRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..9948ec3
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.get.MultiGetRequest;
+import org.elasticsearch.action.get.MultiGetRequestBuilder;
+import org.elasticsearch.action.get.MultiGetResponse;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.search.fetch.source.FetchSourceContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyMultiGetRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void multi_get() {
+    RuleDto rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(dbSession, RuleTesting.newXooX1());
+    dbSession.commit();
+
+    MultiGetRequestBuilder request = searchClient.prepareMultiGet();
+    request.add(new MultiGetRequest.Item(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), rule.getKey().toString())
+      .fetchSourceContext(FetchSourceContext.FETCH_SOURCE));
+
+    MultiGetResponse response = request.get();
+    assertThat(response.getResponses()).isNotEmpty();
+    assertThat(response.getResponses()[0].getResponse().getSource()).isNotEmpty();
+  }
+
+  @Test
+  public void to_string() {
+    MultiGetRequestBuilder request = searchClient.prepareMultiGet();
+    assertThat(request.toString()).isEqualTo("ES multi get request");
+
+    request.add(new MultiGetRequest.Item(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), "ruleKey")
+      .fetchSourceContext(FetchSourceContext.FETCH_SOURCE));
+    assertThat(request.toString()).isEqualTo("ES multi get request [key 'ruleKey', index 'rules', type 'rule'],");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMultiGet().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareMultiGet().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareMultiGet().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyNodesStatsRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..4b0e426
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyNodesStatsRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void stats() {
+    searchClient.prepareNodesStats().get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareNodesStats().setNodesIds("node1").toString()).isEqualTo("ES nodes stats request on nodes 'node1'");
+    assertThat(searchClient.prepareNodesStats().toString()).isEqualTo("ES nodes stats request");
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareNodesStats(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareNodesStats(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareNodesStats(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyPutMappingRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..8500f00
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.request;
+
+import com.google.common.collect.ImmutableMap;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyPutMappingRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void put_mapping() {
+    PutMappingRequestBuilder requestBuilder = searchClient.preparePutMapping(IndexDefinition.RULE.getIndexName())
+      .setType(IndexDefinition.RULE.getIndexType())
+      .setIgnoreConflicts(true)
+      .setSource(mapDomain());
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.preparePutMapping(IndexDefinition.RULE.getIndexName()).setSource(mapDomain()).toString())
+      .isEqualTo("ES put mapping request on indices 'rules' with source '{\"dynamic\":false,\"_all\":{\"enabled\":false}}'");
+    assertThat(searchClient.preparePutMapping(IndexDefinition.RULE.getIndexName()).setType(IndexDefinition.RULE.getIndexType()).setSource(mapDomain()).toString())
+      .isEqualTo("ES put mapping request on indices 'rules' on type 'rule' with source '{\"dynamic\":false,\"_all\":{\"enabled\":false}}'");
+  }
+
+  @Test
+  public void fail_on_bad_query() throws Exception {
+    try {
+      searchClient.preparePutMapping().get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES put mapping request");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.preparePutMapping().get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.preparePutMapping().get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.preparePutMapping().execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+  protected static Map mapDomain() {
+    Map<String, Object> mapping = new HashMap<String, Object>();
+    mapping.put("dynamic", false);
+    mapping.put("_all", ImmutableMap.of("enabled", false));
+    return mapping;
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyRefreshRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxyRefreshRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..aeb2889
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxyRefreshRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void refresh() {
+    RefreshRequestBuilder requestBuilder = searchClient.prepareRefresh(IndexDefinition.RULE.getIndexName());
+    requestBuilder.get();
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareRefresh(IndexDefinition.RULE.getIndexName()).toString()).isEqualTo("ES refresh request on indices 'rules'");
+    assertThat(searchClient.prepareRefresh().toString()).isEqualTo("ES refresh request");
+  }
+
+  @Test
+  public void fail_to_refresh() throws Exception {
+    try {
+      searchClient.prepareRefresh("unknown").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES refresh request on indices 'unknown'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareRefresh(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareRefresh(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareRefresh(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..15955eb
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxySearchRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void search() {
+    tester.get(RuleDao.class).insert(dbSession, RuleTesting.newXooX1());
+    dbSession.commit();
+
+    SearchResponse response = searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).get();
+    assertThat(response.getHits().getTotalHits()).isEqualTo(1);
+  }
+
+  @Test
+  public void to_string() {
+    assertThat(searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).setTypes("rule").toString()).contains("ES search request '").contains("' on indices '[rules]' on types '[rule]'");
+    assertThat(searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).toString()).contains("ES search request '").contains("' on indices '[rules]'");
+    assertThat(searchClient.prepareSearch().toString()).contains("ES search request");
+  }
+
+  @Test
+  public void fail_to_search_bad_query() throws Exception {
+    try {
+      searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).setQuery("bad query").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES search request '{").contains("}' on indices '[rules]'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    try {
+      searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    try {
+      searchClient.prepareSearch(IndexDefinition.RULE.getIndexName()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/request/ProxySearchScrollRequestBuilderTest.java
new file mode 100644 (file)
index 0000000..a5e89ce
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.request;
+
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchScrollRequestBuilder;
+import org.elasticsearch.action.search.SearchType;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
+import org.sonar.server.tester.ServerTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProxySearchScrollRequestBuilderTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbSession dbSession;
+
+  SearchClient searchClient;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    dbSession = tester.get(DbClient.class).openSession(false);
+    searchClient = tester.get(SearchClient.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void search_scroll() {
+    tester.get(RuleDao.class).insert(dbSession, RuleTesting.newXooX1());
+    dbSession.commit();
+
+    SearchResponse search = searchClient.prepareSearch(IndexDefinition.RULE.getIndexName())
+      .setSearchType(SearchType.SCAN)
+      .setScroll(TimeValue.timeValueSeconds(3L))
+      .get();
+
+    SearchScrollRequestBuilder scrollRequest = searchClient.prepareSearchScroll(search.getScrollId());
+
+    SearchResponse response = scrollRequest.get();
+    assertThat(response.getHits().getTotalHits()).isEqualTo(1);
+  }
+
+  @Test
+  public void fail_to_search_bad_query() throws Exception {
+    try {
+      searchClient.prepareSearchScroll("unknown").get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e.getMessage()).contains("Fail to execute ES search scroll request for scroll id 'null'");
+    }
+  }
+
+  @Test
+  public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+    SearchResponse search = searchClient.prepareSearch(IndexDefinition.RULE.getIndexName())
+      .setSearchType(SearchType.SCAN)
+      .setScroll(TimeValue.timeValueSeconds(3L))
+      .get();
+
+    try {
+      searchClient.prepareSearchScroll(search.getScrollId()).get("1");
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+    SearchResponse search = searchClient.prepareSearch(IndexDefinition.RULE.getIndexName())
+      .setSearchType(SearchType.SCAN)
+      .setScroll(TimeValue.timeValueSeconds(3L))
+      .get();
+
+    try {
+      searchClient.prepareSearchScroll(search.getScrollId()).get(TimeValue.timeValueMinutes(1));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+    }
+  }
+
+  @Test
+  public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+    SearchResponse search = searchClient.prepareSearch(IndexDefinition.RULE.getIndexName())
+      .setSearchType(SearchType.SCAN)
+      .setScroll(TimeValue.timeValueSeconds(3L))
+      .get();
+
+    try {
+      searchClient.prepareSearchScroll(search.getScrollId()).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+    }
+  }
+}