summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java')
-rw-r--r--java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java177
1 files changed, 177 insertions, 0 deletions
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
new file mode 100644
index 0000000000..9a49ffe327
--- /dev/null
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
@@ -0,0 +1,177 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.query.change;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.gerrit.server.query.change.ChangeQueryBuilder.FIELD_LIMIT;
+
+import com.google.gerrit.extensions.common.PluginDefinedInfo;
+import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.query.IndexPredicate;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryProcessor;
+import com.google.gerrit.metrics.MetricMaker;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.AnonymousUser;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.DynamicOptions;
+import com.google.gerrit.server.DynamicOptions.DynamicBean;
+import com.google.gerrit.server.account.AccountLimits;
+import com.google.gerrit.server.index.change.ChangeIndexCollection;
+import com.google.gerrit.server.index.change.ChangeIndexRewriter;
+import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
+import com.google.gerrit.server.index.change.IndexedChangeQuery;
+import com.google.gerrit.server.notedb.ChangeNotes;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Query processor for the change index.
+ *
+ * <p>Instances are one-time-use. Other singleton classes should inject a Provider rather than
+ * holding on to a single instance.
+ */
+public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
+ implements DynamicOptions.BeanReceiver, PluginDefinedAttributesFactory {
+ /**
+ * Register a ChangeAttributeFactory in a config Module like this:
+ *
+ * <p>bind(ChangeAttributeFactory.class) .annotatedWith(Exports.named("export-name"))
+ * .to(YourClass.class);
+ */
+ public interface ChangeAttributeFactory {
+ PluginDefinedInfo create(ChangeData a, ChangeQueryProcessor qp, String plugin);
+ }
+
+ private final Provider<ReviewDb> db;
+ private final Provider<CurrentUser> userProvider;
+ private final ChangeNotes.Factory notesFactory;
+ private final DynamicMap<ChangeAttributeFactory> attributeFactories;
+ private final PermissionBackend permissionBackend;
+ private final ProjectCache projectCache;
+ private final Provider<AnonymousUser> anonymousUserProvider;
+ private final Map<String, DynamicBean> dynamicBeans = new HashMap<>();
+
+ static {
+ // It is assumed that basic rewrites do not touch visibleto predicates.
+ checkState(
+ !ChangeIsVisibleToPredicate.class.isAssignableFrom(IndexPredicate.class),
+ "ChangeQueryProcessor assumes visibleto is not used by the index rewriter.");
+ }
+
+ @Inject
+ ChangeQueryProcessor(
+ Provider<CurrentUser> userProvider,
+ AccountLimits.Factory limitsFactory,
+ MetricMaker metricMaker,
+ IndexConfig indexConfig,
+ ChangeIndexCollection indexes,
+ ChangeIndexRewriter rewriter,
+ Provider<ReviewDb> db,
+ ChangeNotes.Factory notesFactory,
+ DynamicMap<ChangeAttributeFactory> attributeFactories,
+ PermissionBackend permissionBackend,
+ ProjectCache projectCache,
+ Provider<AnonymousUser> anonymousUserProvider) {
+ super(
+ metricMaker,
+ ChangeSchemaDefinitions.INSTANCE,
+ indexConfig,
+ indexes,
+ rewriter,
+ FIELD_LIMIT,
+ () -> limitsFactory.create(userProvider.get()).getQueryLimit());
+ this.db = db;
+ this.userProvider = userProvider;
+ this.notesFactory = notesFactory;
+ this.attributeFactories = attributeFactories;
+ this.permissionBackend = permissionBackend;
+ this.projectCache = projectCache;
+ this.anonymousUserProvider = anonymousUserProvider;
+ }
+
+ @Override
+ public ChangeQueryProcessor enforceVisibility(boolean enforce) {
+ super.enforceVisibility(enforce);
+ return this;
+ }
+
+ @Override
+ protected QueryOptions createOptions(
+ IndexConfig indexConfig, int start, int limit, Set<String> requestedFields) {
+ return IndexedChangeQuery.createOptions(indexConfig, start, limit, requestedFields);
+ }
+
+ @Override
+ public void setDynamicBean(String plugin, DynamicBean dynamicBean) {
+ dynamicBeans.put(plugin, dynamicBean);
+ }
+
+ public DynamicBean getDynamicBean(String plugin) {
+ return dynamicBeans.get(plugin);
+ }
+
+ @Override
+ public List<PluginDefinedInfo> create(ChangeData cd) {
+ List<PluginDefinedInfo> plugins = new ArrayList<>(attributeFactories.plugins().size());
+ for (String plugin : attributeFactories.plugins()) {
+ for (Provider<ChangeAttributeFactory> provider :
+ attributeFactories.byPlugin(plugin).values()) {
+ PluginDefinedInfo pda = null;
+ try {
+ pda = provider.get().create(cd, this, plugin);
+ } catch (RuntimeException e) {
+ /* Eat runtime exceptions so that queries don't fail. */
+ }
+ if (pda != null) {
+ pda.name = plugin;
+ plugins.add(pda);
+ }
+ }
+ }
+ if (plugins.isEmpty()) {
+ plugins = null;
+ }
+ return plugins;
+ }
+
+ @Override
+ protected Predicate<ChangeData> enforceVisibility(Predicate<ChangeData> pred) {
+ return new AndChangeSource(
+ pred,
+ new ChangeIsVisibleToPredicate(
+ db,
+ notesFactory,
+ userProvider.get(),
+ permissionBackend,
+ projectCache,
+ anonymousUserProvider),
+ start);
+ }
+
+ @Override
+ protected String formatForLogging(ChangeData changeData) {
+ return changeData.getId().toString();
+ }
+}