Merge "Allow plugins to output change query attributes"

This commit is contained in:
Martin Fick
2017-04-18 21:48:23 +00:00
committed by Gerrit Code Review
12 changed files with 172 additions and 4 deletions

View File

@@ -118,6 +118,7 @@ import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeData.ChangedLines;
import com.google.gerrit.server.query.change.PluginDefinedAttributesFactory;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -213,6 +214,7 @@ public class ChangeJson {
private boolean lazyLoad = true;
private AccountLoader accountLoader;
private FixInput fix;
private PluginDefinedAttributesFactory pluginDefinedAttributesFactory;
@Inject
ChangeJson(
@@ -276,6 +278,10 @@ public class ChangeJson {
return this;
}
public void setPluginDefinedAttributesFactory(PluginDefinedAttributesFactory pluginsFactory) {
this.pluginDefinedAttributesFactory = pluginsFactory;
}
public ChangeInfo format(ChangeResource rsrc) throws OrmException {
return format(changeDataFactory.create(db.get(), rsrc.getControl()));
}
@@ -520,6 +526,8 @@ public class ChangeJson {
out.labels = labelsFor(perm, ctl, cd, has(LABELS), has(DETAILED_LABELS));
out.submitted = getSubmittedOn(cd);
out.plugins =
pluginDefinedAttributesFactory != null ? pluginDefinedAttributesFactory.create(cd) : null;
if (out.labels != null && has(DETAILED_LABELS)) {
// If limited to specific patch sets but not the current patch set, don't

View File

@@ -166,6 +166,7 @@ import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.SectionSortCache;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gerrit.server.query.change.ConflictsCacheImpl;
import com.google.gerrit.server.ssh.SshAddressesModule;
import com.google.gerrit.server.tools.ToolsCatalog;
@@ -378,6 +379,8 @@ public class GerritGlobalModule extends FactoryModule {
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeOperatorFactory.class);
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeHasOperandFactory.class);
DynamicMap.mapOf(binder(), ChangeQueryProcessor.ChangeAttributeFactory.class);
install(new GitwebConfig.LegacyModule(cfg));
bind(AnonymousUser.class);

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.data;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.reviewdb.client.Change;
import java.util.List;
@@ -43,4 +44,5 @@ public class ChangeAttribute {
public List<DependencyAttribute> neededBy;
public List<SubmitRecordAttribute> submitRecords;
public List<AccountAttribute> allReviewers;
public List<PluginDefinedInfo> plugins;
}

View File

@@ -17,6 +17,8 @@ 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.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.index.IndexConfig;
@@ -32,12 +34,26 @@ import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryProcessor;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ChangeQueryProcessor extends QueryProcessor<ChangeData> {
public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
implements 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 ChangeControl.GenericFactory changeControlFactory;
private final ChangeNotes.Factory notesFactory;
private final DynamicMap<ChangeAttributeFactory> attributeFactories;
static {
// It is assumed that basic rewrites do not touch visibleto predicates.
@@ -55,7 +71,8 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData> {
ChangeIndexRewriter rewriter,
Provider<ReviewDb> db,
ChangeControl.GenericFactory changeControlFactory,
ChangeNotes.Factory notesFactory) {
ChangeNotes.Factory notesFactory,
DynamicMap<ChangeAttributeFactory> attributeFactories) {
super(
userProvider,
metrics,
@@ -67,6 +84,7 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData> {
this.db = db;
this.changeControlFactory = changeControlFactory;
this.notesFactory = notesFactory;
this.attributeFactories = attributeFactories;
}
@Override
@@ -81,6 +99,30 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData> {
return IndexedChangeQuery.createOptions(indexConfig, start, limit, requestedFields);
}
@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(

View File

@@ -313,6 +313,7 @@ public class OutputStreamQuery {
eventFactory.addDependencies(rw, c, d.change(), d.currentPatchSet());
}
c.plugins = queryProcessor.create(d);
return c;
}

View File

@@ -0,0 +1,22 @@
// Copyright (C) 2016 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 com.google.gerrit.extensions.common.PluginDefinedInfo;
import java.util.List;
public interface PluginDefinedAttributesFactory {
List<PluginDefinedInfo> create(ChangeData cd);
}

View File

@@ -137,13 +137,18 @@ public class QueryChanges implements RestReadView<TopLevelResource> {
int cnt = queries.size();
List<QueryResult<ChangeData>> results = imp.query(qb.parse(queries));
boolean requireLazyLoad =
containsAnyOf(options, ImmutableSet.of(DETAILED_LABELS, LABELS))
&& !qb.getArgs().getSchema().hasField(ChangeField.STORED_SUBMIT_RECORD_LENIENT);
ChangeJson cjson = json.create(options);
cjson.setPluginDefinedAttributesFactory(this.imp);
List<List<ChangeInfo>> res =
json.create(options)
cjson
.lazyLoad(requireLazyLoad || containsAnyOf(options, ChangeJson.REQUIRE_LAZY_LOAD))
.formatQueryResults(results);
for (int n = 0; n < cnt; n++) {
List<ChangeInfo> info = res.get(n);
if (results.get(n).more()) {