// NavigationWs.class, no Web Service in CE
};
private static final Object[] STARTUP_COMPONENTS = new Object[] {
- // IndexSynchronizer.class, ES maintenance, responsibility of Web Server
+ // IndexerStartupTask.class, ES maintenance, responsibility of Web Server
EsIndexerEnabler.class,
// RegisterMetrics.class, DB maintenance, responsibility of Web Server
// RegisterQualityGates.class, DB maintenance, responsibility of Web Server
import org.picocontainer.Startable;
import org.sonar.server.activity.index.ActivityIndexer;
+import org.sonar.server.es.IndexerStartupTask;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.test.index.TestIndexer;
import org.sonar.server.view.index.ViewIndexer;
/**
- * Replaces the {@link org.sonar.server.search.IndexSynchronizer} to enable indexers but without triggering a full
+ * Replaces the {@link IndexerStartupTask} to enable indexers but without triggering a full
* indexation (it's the WebServer's responsibility).
*/
public class EsIndexerEnabler implements Startable {
package org.sonar.server.activity.index;
import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.sonar.server.search.BaseDoc;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.sonar.server.es.BaseDoc;
public class ActivityDoc extends BaseDoc {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.es;
+
+import java.util.Date;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.server.search.IndexUtils;
+
+import static com.google.common.collect.Maps.newHashMap;
+
+/**
+ * Base implementation for business objects based on elasticsearch document
+ */
+public abstract class BaseDoc {
+
+ protected final Map<String, Object> fields;
+
+ protected BaseDoc() {
+ this.fields = newHashMap();
+ }
+
+ protected BaseDoc(Map<String, Object> fields) {
+ this.fields = fields;
+ }
+
+ public String keyField() {
+ return (String) fields.get("key");
+ }
+
+ /**
+ * Use this method when field value can be null. See warning in {@link #getField(String)}
+ */
+ @CheckForNull
+ public <K> K getNullableField(String key) {
+ if (!fields.containsKey(key)) {
+ throw new IllegalStateException(String.format("Field %s not specified in query options", key));
+ }
+ return (K) fields.get(key);
+ }
+
+ @CheckForNull
+ public Date getNullableFieldAsDate(String key) {
+ Object val = getNullableField(key);
+ if (val != null) {
+ if (val instanceof Date) {
+ return (Date)val;
+ }
+ return IndexUtils.parseDateTime((String) val);
+ }
+ return null;
+ }
+
+ /**
+ * Use this method when you are sure that the value can't be null in ES document.
+ * <p/>
+ * Warning with numbers - even if mapping declares long field, value can be an Integer
+ * instead of an expected Long. The reason is that ES delegates the deserialization of JSON
+ * to Jackson, which doesn't know the field type declared in mapping. See
+ * https://groups.google.com/forum/#!searchin/elasticsearch/getsource$20integer$20long/elasticsearch/jxIY22TmA8U/PyqZPPyYQ0gJ
+ * for more details. Workaround is to cast to java.lang.Number and then to call {@link Number#longValue()}
+ */
+ public <K> K getField(String key) {
+ K value = getNullableField(key);
+ if (value == null) {
+ throw new IllegalStateException("Value of index field is null: " + key);
+ }
+ return value;
+ }
+
+ public Date getFieldAsDate(String key) {
+ Object value = getField(key);
+ if (value instanceof Date) {
+ return (Date)value;
+ }
+ return IndexUtils.parseDateTime((String)value);
+ }
+
+ public void setField(String key, @Nullable Object value) {
+ fields.put(key, value);
+ }
+
+ public Map<String, Object> getFields() {
+ return fields;
+ }
+}
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Uninterruptibles;
-import org.picocontainer.Startable;
-import org.sonar.api.server.ServerSide;
-
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import org.picocontainer.Startable;
+import org.sonar.api.server.ServerSide;
@ServerSide
public abstract class BaseIndexer implements Startable {
* asks for index refresh -> big performance hit.
*
* Indices are populated and refreshed when all startup components have been executed. See
- * {@link org.sonar.server.search.IndexSynchronizer}
+ * {@link IndexerStartupTask}
*/
private boolean enabled = false;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
-import org.sonar.server.search.BaseDoc;
public class EsUtils {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.es;
+
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.activity.index.ActivityIndexer;
+import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.test.index.TestIndexer;
+import org.sonar.server.user.index.UserIndexer;
+import org.sonar.server.view.index.ViewIndexer;
+
+public class IndexerStartupTask {
+
+ private static final Logger LOG = Loggers.get(IndexerStartupTask.class);
+
+ private final TestIndexer testIndexer;
+ private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final IssueIndexer issueIndexer;
+ private final UserIndexer userIndexer;
+ private final ViewIndexer viewIndexer;
+ private final ActivityIndexer activityIndexer;
+ private final Settings settings;
+
+ /**
+ * Limitation - {@link org.sonar.server.es.BaseIndexer} are not injected through an array or a collection
+ * because we need {@link org.sonar.server.issue.index.IssueAuthorizationIndexer} to be executed before
+ * {@link org.sonar.server.issue.index.IssueIndexer}
+ */
+ public IndexerStartupTask(TestIndexer testIndexer, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ UserIndexer userIndexer, ViewIndexer viewIndexer, ActivityIndexer activityIndexer,
+ Settings settings) {
+ this.testIndexer = testIndexer;
+ this.issueAuthorizationIndexer = issueAuthorizationIndexer;
+ this.issueIndexer = issueIndexer;
+ this.userIndexer = userIndexer;
+ this.viewIndexer = viewIndexer;
+ this.activityIndexer = activityIndexer;
+ this.settings = settings;
+ }
+
+ public void execute() {
+ if (!settings.getBoolean("sonar.internal.es.disableIndexes")) {
+ LOG.info("Index activities");
+ activityIndexer.setEnabled(true).index();
+
+ LOG.info("Index issues");
+ issueAuthorizationIndexer.setEnabled(true).index();
+ issueIndexer.setEnabled(true).index();
+
+ LOG.info("Index tests");
+ testIndexer.setEnabled(true).index();
+
+ LOG.info("Index users");
+ userIndexer.setEnabled(true).index();
+
+ LOG.info("Index views");
+ viewIndexer.setEnabled(true).index();
+ }
+ }
+
+}
package org.sonar.server.es;
import com.google.common.base.Function;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.elasticsearch.action.search.SearchResponse;
-import org.sonar.server.search.BaseDoc;
-
import java.util.List;
import java.util.Map;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.elasticsearch.action.search.SearchResponse;
public class SearchResult<DOC extends BaseDoc> {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.es;
+
+import com.google.common.base.Joiner;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.ArrayUtils;
+import org.elasticsearch.index.query.BoolFilterBuilder;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
+import org.elasticsearch.search.aggregations.AggregationBuilder;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms.Order;
+import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
+
+public class StickyFacetBuilder {
+
+ private static final int FACET_DEFAULT_MIN_DOC_COUNT = 1;
+ private static final int FACET_DEFAULT_SIZE = 10;
+ private static final Order FACET_DEFAULT_ORDER = Terms.Order.count(false);
+
+ private final QueryBuilder query;
+ private final Map<String, FilterBuilder> filters;
+ private final AbstractAggregationBuilder subAggregation;
+ private final Order order;
+
+ public StickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters) {
+ this(query, filters, null, FACET_DEFAULT_ORDER);
+ }
+
+ public StickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters, @Nullable AbstractAggregationBuilder subAggregation, @Nullable Order order) {
+ this.query = query;
+ this.filters = filters;
+ this.subAggregation = subAggregation;
+ this.order = order;
+ }
+
+ public QueryBuilder query() {
+ return query;
+ }
+
+ public Map<String, FilterBuilder> filters() {
+ return filters;
+ }
+
+ public AggregationBuilder buildStickyFacet(String fieldName, String facetName, Object... selected) {
+ return buildStickyFacet(fieldName, facetName, FACET_DEFAULT_SIZE, selected);
+ }
+
+ public AggregationBuilder buildStickyFacet(String fieldName, String facetName, int size, Object... selected) {
+ BoolFilterBuilder facetFilter = getStickyFacetFilter(fieldName);
+ FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size);
+ facetTopAggregation = addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, selected);
+
+ return AggregationBuilders
+ .global(facetName)
+ .subAggregation(facetTopAggregation);
+ }
+
+ public BoolFilterBuilder getStickyFacetFilter(String... fieldNames) {
+ BoolFilterBuilder facetFilter = FilterBuilders.boolFilter().must(FilterBuilders.queryFilter(query));
+ for (Map.Entry<String, FilterBuilder> filter : filters.entrySet()) {
+ if (filter.getValue() != null && !ArrayUtils.contains(fieldNames, filter.getKey())) {
+ facetFilter.must(filter.getValue());
+ }
+ }
+ return facetFilter;
+ }
+
+ public FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter, int size) {
+ TermsBuilder termsAggregation = AggregationBuilders.terms(facetName)
+ .field(fieldName)
+ .order(order)
+ // .order(Terms.Order.aggregation("debt", false))
+ .size(size)
+ .minDocCount(FACET_DEFAULT_MIN_DOC_COUNT);
+ if (subAggregation != null) {
+ termsAggregation = termsAggregation.subAggregation(subAggregation);
+ }
+ return AggregationBuilders
+ .filter(facetName + "_filter")
+ .filter(facetFilter)
+ .subAggregation(termsAggregation);
+ }
+
+ public FilterAggregationBuilder addSelectedItemsToFacet(String fieldName, String facetName, FilterAggregationBuilder facetTopAggregation, Object... selected) {
+ if (selected.length > 0) {
+ TermsBuilder selectedTerms = AggregationBuilders.terms(facetName + "_selected")
+ .field(fieldName)
+ .include(Joiner.on('|').join(selected));
+ if (subAggregation != null) {
+ selectedTerms = selectedTerms.subAggregation(subAggregation);
+ }
+ facetTopAggregation.subAggregation(
+ selectedTerms);
+ }
+ return facetTopAggregation;
+ }
+}
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.server.search.BaseDoc;
+import org.sonar.server.es.BaseDoc;
public class IssueDoc extends BaseDoc implements Issue {
import org.sonar.server.es.SearchOptions;
import org.sonar.server.es.SearchResult;
import org.sonar.server.es.Sorting;
+import org.sonar.server.es.StickyFacetBuilder;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.rule.index.RuleIndexDefinition;
-import org.sonar.server.search.StickyFacetBuilder;
import org.sonar.server.user.UserSession;
import org.sonar.server.view.index.ViewIndexDefinition;
package org.sonar.server.platform.platformlevel;
import org.sonar.server.app.ProcessCommandWrapper;
+import org.sonar.server.es.IndexerStartupTask;
import org.sonar.server.issue.filter.RegisterIssueFilters;
import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.qualitygate.RegisterQualityGates;
import org.sonar.server.qualityprofile.RegisterQualityProfiles;
import org.sonar.server.rule.RegisterRules;
-import org.sonar.server.search.IndexSynchronizer;
import org.sonar.server.startup.ClearRulesOverloadedDebt;
import org.sonar.server.startup.DisplayLogOnDeprecatedProjects;
import org.sonar.server.startup.FeedUsersLocalStartupTask;
@Override
protected void configureLevel() {
add(
- IndexSynchronizer.class,
+ IndexerStartupTask.class,
RegisterMetrics.class,
RegisterQualityGates.class,
RegisterRules.class,
@Override
protected void doPrivileged() {
PlatformLevelStartup.super.start();
- getComponentByType(IndexSynchronizer.class).execute();
+ getComponentByType(IndexerStartupTask.class).execute();
getComponentByType(ServerLifecycleNotifier.class).notifyStart();
getComponentByType(ProcessCommandWrapper.class).notifyOperational();
}
import com.google.common.collect.Maps;
import javax.annotation.Nullable;
import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.server.es.BaseDoc;
import org.sonar.server.qualityprofile.ActiveRule;
-import org.sonar.server.search.BaseDoc;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rules.RuleType;
-import org.sonar.server.search.BaseDoc;
+import org.sonar.server.es.BaseDoc;
/**
* Implementation of Rule based on an Elasticsearch document
import org.sonar.server.es.EsClient;
import org.sonar.server.es.SearchIdResult;
import org.sonar.server.es.SearchOptions;
-import org.sonar.server.search.StickyFacetBuilder;
+import org.sonar.server.es.StickyFacetBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.query.QueryBuilders.simpleQueryStringQuery;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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 javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Date;
-import java.util.Map;
-
-import static com.google.common.collect.Maps.newHashMap;
-
-/**
- * Base implementation for business objects based on elasticsearch document
- */
-public abstract class BaseDoc {
-
- protected final Map<String, Object> fields;
-
- protected BaseDoc() {
- this.fields = newHashMap();
- }
-
- protected BaseDoc(Map<String, Object> fields) {
- this.fields = fields;
- }
-
- public String keyField() {
- return (String) fields.get("key");
- }
-
- /**
- * Use this method when field value can be null. See warning in {@link #getField(String)}
- */
- @CheckForNull
- public <K> K getNullableField(String key) {
- if (!fields.containsKey(key)) {
- throw new IllegalStateException(String.format("Field %s not specified in query options", key));
- }
- return (K) fields.get(key);
- }
-
- @CheckForNull
- public Date getNullableFieldAsDate(String key) {
- Object val = getNullableField(key);
- if (val != null) {
- if (val instanceof Date) {
- return (Date)val;
- }
- return IndexUtils.parseDateTime((String) val);
- }
- return null;
- }
-
- /**
- * Use this method when you are sure that the value can't be null in ES document.
- * <p/>
- * Warning with numbers - even if mapping declares long field, value can be an Integer
- * instead of an expected Long. The reason is that ES delegates the deserialization of JSON
- * to Jackson, which doesn't know the field type declared in mapping. See
- * https://groups.google.com/forum/#!searchin/elasticsearch/getsource$20integer$20long/elasticsearch/jxIY22TmA8U/PyqZPPyYQ0gJ
- * for more details. Workaround is to cast to java.lang.Number and then to call {@link Number#longValue()}
- */
- public <K> K getField(String key) {
- K value = getNullableField(key);
- if (value == null) {
- throw new IllegalStateException("Value of index field is null: " + key);
- }
- return value;
- }
-
- public Date getFieldAsDate(String key) {
- Object value = getField(key);
- if (value instanceof Date) {
- return (Date)value;
- }
- return IndexUtils.parseDateTime((String)value);
- }
-
- public void setField(String key, @Nullable Object value) {
- fields.put(key, value);
- }
-
- public Map<String, Object> getFields() {
- return fields;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.search;
-
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.activity.index.ActivityIndexer;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
-import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.view.index.ViewIndexer;
-
-public class IndexSynchronizer {
-
- private static final Logger LOG = Loggers.get(IndexSynchronizer.class);
-
- private final TestIndexer testIndexer;
- private final IssueAuthorizationIndexer issueAuthorizationIndexer;
- private final IssueIndexer issueIndexer;
- private final UserIndexer userIndexer;
- private final ViewIndexer viewIndexer;
- private final ActivityIndexer activityIndexer;
- private final Settings settings;
-
- /**
- * Limitation - {@link org.sonar.server.es.BaseIndexer} are not injected through an array or a collection
- * because we need {@link org.sonar.server.issue.index.IssueAuthorizationIndexer} to be executed before
- * {@link org.sonar.server.issue.index.IssueIndexer}
- */
- public IndexSynchronizer(TestIndexer testIndexer, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
- UserIndexer userIndexer, ViewIndexer viewIndexer, ActivityIndexer activityIndexer,
- Settings settings) {
- this.testIndexer = testIndexer;
- this.issueAuthorizationIndexer = issueAuthorizationIndexer;
- this.issueIndexer = issueIndexer;
- this.userIndexer = userIndexer;
- this.viewIndexer = viewIndexer;
- this.activityIndexer = activityIndexer;
- this.settings = settings;
- }
-
- public void execute() {
- if (!settings.getBoolean("sonar.internal.es.disableIndexes")) {
- LOG.info("Index activities");
- activityIndexer.setEnabled(true).index();
-
- LOG.info("Index issues");
- issueAuthorizationIndexer.setEnabled(true).index();
- issueIndexer.setEnabled(true).index();
-
- LOG.info("Index tests");
- testIndexer.setEnabled(true).index();
-
- LOG.info("Index users");
- userIndexer.setEnabled(true).index();
-
- LOG.info("Index views");
- viewIndexer.setEnabled(true).index();
- }
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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 com.google.common.base.Joiner;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.ArrayUtils;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
-import org.elasticsearch.search.aggregations.AggregationBuilder;
-import org.elasticsearch.search.aggregations.AggregationBuilders;
-import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
-import org.elasticsearch.search.aggregations.bucket.terms.Terms;
-import org.elasticsearch.search.aggregations.bucket.terms.Terms.Order;
-import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
-
-public class StickyFacetBuilder {
-
- private static final int FACET_DEFAULT_MIN_DOC_COUNT = 1;
- private static final int FACET_DEFAULT_SIZE = 10;
- private static final Order FACET_DEFAULT_ORDER = Terms.Order.count(false);
-
- private final QueryBuilder query;
- private final Map<String, FilterBuilder> filters;
- private final AbstractAggregationBuilder subAggregation;
- private final Order order;
-
- public StickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters) {
- this(query, filters, null, FACET_DEFAULT_ORDER);
- }
-
- public StickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters, @Nullable AbstractAggregationBuilder subAggregation, @Nullable Order order) {
- this.query = query;
- this.filters = filters;
- this.subAggregation = subAggregation;
- this.order = order;
- }
-
- public QueryBuilder query() {
- return query;
- }
-
- public Map<String, FilterBuilder> filters() {
- return filters;
- }
-
- public AggregationBuilder buildStickyFacet(String fieldName, String facetName, Object... selected) {
- return buildStickyFacet(fieldName, facetName, FACET_DEFAULT_SIZE, selected);
- }
-
- public AggregationBuilder buildStickyFacet(String fieldName, String facetName, int size, Object... selected) {
- BoolFilterBuilder facetFilter = getStickyFacetFilter(fieldName);
- FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size);
- facetTopAggregation = addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, selected);
-
- return AggregationBuilders
- .global(facetName)
- .subAggregation(facetTopAggregation);
- }
-
- public BoolFilterBuilder getStickyFacetFilter(String... fieldNames) {
- BoolFilterBuilder facetFilter = FilterBuilders.boolFilter().must(FilterBuilders.queryFilter(query));
- for (Map.Entry<String, FilterBuilder> filter : filters.entrySet()) {
- if (filter.getValue() != null && !ArrayUtils.contains(fieldNames, filter.getKey())) {
- facetFilter.must(filter.getValue());
- }
- }
- return facetFilter;
- }
-
- public FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter, int size) {
- TermsBuilder termsAggregation = AggregationBuilders.terms(facetName)
- .field(fieldName)
- .order(order)
- // .order(Terms.Order.aggregation("debt", false))
- .size(size)
- .minDocCount(FACET_DEFAULT_MIN_DOC_COUNT);
- if (subAggregation != null) {
- termsAggregation = termsAggregation.subAggregation(subAggregation);
- }
- return AggregationBuilders
- .filter(facetName + "_filter")
- .filter(facetFilter)
- .subAggregation(termsAggregation);
- }
-
- public FilterAggregationBuilder addSelectedItemsToFacet(String fieldName, String facetName, FilterAggregationBuilder facetTopAggregation, Object... selected) {
- if (selected.length > 0) {
- TermsBuilder selectedTerms = AggregationBuilders.terms(facetName + "_selected")
- .field(fieldName)
- .include(Joiner.on('|').join(selected));
- if (subAggregation != null) {
- selectedTerms = selectedTerms.subAggregation(subAggregation);
- }
- facetTopAggregation.subAggregation(
- selectedTerms);
- }
- return facetTopAggregation;
- }
-}
import javax.annotation.Nullable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.search.BaseDoc;
+import org.sonar.server.es.BaseDoc;
import org.sonar.server.search.IndexUtils;
import org.sonar.server.search.QueryContext;
/**
- * Mapping of search documents (see {@link org.sonar.server.search.BaseDoc}) to WS JSON responses
+ * Mapping of search documents (see {@link BaseDoc}) to WS JSON responses
*/
@ServerSide
+@Deprecated
public abstract class BaseMapping<DOC extends BaseDoc, CTX> {
private final Multimap<String, String> indexFieldsByWsFields = LinkedHashMultimap.create();
*/
package org.sonar.server.search.ws;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
/**
* Generic options for search web services
- *
*/
+@Deprecated
public class SearchOptions {
private int pageSize;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
-import org.sonar.server.search.BaseDoc;
-
import java.util.List;
import java.util.Map;
+import org.sonar.server.es.BaseDoc;
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES;
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
-import org.sonar.server.search.BaseDoc;
-
-import javax.annotation.CheckForNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import javax.annotation.CheckForNull;
+import org.sonar.server.es.BaseDoc;
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES;
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS;
package org.sonar.server.user.index;
import com.google.common.collect.Maps;
-import org.sonar.api.user.User;
-import org.sonar.server.search.BaseDoc;
-
-import javax.annotation.Nullable;
-
import java.util.List;
import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.api.user.User;
+import org.sonar.server.es.BaseDoc;
public class UserDoc extends BaseDoc implements User {
package org.sonar.server.view.index;
import com.google.common.collect.Maps;
-import org.sonar.server.search.BaseDoc;
-
import java.util.List;
import java.util.Map;
+import org.sonar.server.es.BaseDoc;
public class ViewDoc extends BaseDoc {
import org.junit.rules.ExternalResource;
import org.sonar.api.config.Settings;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.search.BaseDoc;
import org.sonar.test.TestUtils;
import static com.google.common.collect.Lists.newArrayList;
package org.sonar.server.es;
import com.google.common.base.Function;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.server.issue.index.IssueDoc;
-import org.sonar.server.search.BaseDoc;
import org.sonar.test.TestUtils;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
package org.sonar.server.search;
import com.google.common.collect.Maps;
-import org.junit.Test;
-
import java.util.Collections;
import java.util.Date;
import java.util.Map;
+import org.junit.Test;
+import org.sonar.server.es.BaseDoc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;