From 9ec549cb65ad787328a9d3b1ff4dd0edd37a75d9 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 30 Oct 2012 15:47:45 +0100 Subject: [PATCH 1/8] Register @Listen annotated classes in Http and Ssh modules Current implementation of Web UI plugins allows auto register them using @Listen annotation. Unfortunately listeners can only be bind in system module. This patch enables binding listeners in Http and Ssh modules. Change-Id: I7569d0e743bd9e1c9bb8aded09a5740bb88c1cca Signed-off-by: Dariusz Luksza --- .../HttpAutoRegisterModuleGenerator.java | 22 ++++++++++ .../server/plugins/AutoRegisterModules.java | 17 +++----- .../server/plugins/AutoRegisterUtil.java | 41 +++++++++++++++++++ .../server/plugins/ModuleGenerator.java | 3 ++ .../sshd/SshAutoRegisterModuleGenerator.java | 23 +++++++++++ 5 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterUtil.java diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java index 2d957f275f..d1c617f069 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java @@ -14,14 +14,20 @@ package com.google.gerrit.httpd.plugins; +import static com.google.gerrit.server.plugins.AutoRegisterUtil.calculateBindAnnotation; + +import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.gerrit.extensions.annotations.Export; import com.google.gerrit.server.plugins.InvalidPluginException; import com.google.gerrit.server.plugins.ModuleGenerator; import com.google.inject.Module; import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; import com.google.inject.servlet.ServletModule; +import java.lang.annotation.Annotation; import java.util.Map; import javax.servlet.http.HttpServlet; @@ -29,6 +35,7 @@ import javax.servlet.http.HttpServlet; class HttpAutoRegisterModuleGenerator extends ServletModule implements ModuleGenerator { private final Map> serve = Maps.newHashMap(); + private final Multimap, Class> listeners = LinkedListMultimap.create(); @Override protected void configureServlets() { @@ -36,6 +43,16 @@ class HttpAutoRegisterModuleGenerator extends ServletModule bind(e.getValue()).in(Scopes.SINGLETON); serve(e.getKey()).with(e.getValue()); } + for (Map.Entry, Class> e : listeners.entries()) { + @SuppressWarnings("unchecked") + TypeLiteral type = (TypeLiteral) e.getKey(); + + @SuppressWarnings("unchecked") + Class impl = (Class) e.getValue(); + + Annotation n = calculateBindAnnotation(impl); + bind(type).annotatedWith(n).to(impl); + } } @Override @@ -62,6 +79,11 @@ class HttpAutoRegisterModuleGenerator extends ServletModule } } + @Override + public void listen(TypeLiteral tl, Class clazz) { + listeners.put(tl, clazz); + } + @Override public Module create() throws InvalidPluginException { return this; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterModules.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterModules.java index eacdfa0ed1..c2c23a3a0d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterModules.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterModules.java @@ -14,6 +14,7 @@ package com.google.gerrit.server.plugins; +import static com.google.gerrit.server.plugins.AutoRegisterUtil.calculateBindAnnotation; import static com.google.gerrit.server.plugins.PluginGuiceEnvironment.is; import com.google.common.collect.LinkedListMultimap; @@ -26,7 +27,6 @@ import com.google.inject.AbstractModule; import com.google.inject.Module; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; -import com.google.inject.internal.UniqueAnnotations; import org.eclipse.jgit.util.IO; import org.objectweb.asm.AnnotationVisitor; @@ -116,16 +116,7 @@ class AutoRegisterModules { @SuppressWarnings("unchecked") Class impl = (Class) e.getValue(); - Annotation n = impl.getAnnotation(Export.class); - if (n == null) { - n = impl.getAnnotation(javax.inject.Named.class); - } - if (n == null) { - n = impl.getAnnotation(com.google.inject.name.Named.class); - } - if (n == null) { - n = UniqueAnnotations.create(); - } + Annotation n = calculateBindAnnotation(impl); bind(type).annotatedWith(n).to(impl); } } @@ -248,6 +239,8 @@ class AutoRegisterModules { if (env.hasDynamicSet(tl)) { sysSingletons.add(clazz); sysListen.put(tl, clazz); + httpGen.listen(tl, clazz); + sshGen.listen(tl, clazz); } else if (env.hasDynamicMap(tl)) { if (clazz.getAnnotation(Export.class) == null) { throw new InvalidPluginException(String.format( @@ -256,6 +249,8 @@ class AutoRegisterModules { } sysSingletons.add(clazz); sysListen.put(tl, clazz); + httpGen.listen(tl, clazz); + sshGen.listen(tl, clazz); } else { throw new InvalidPluginException(String.format( "Cannot register %s, server does not accept %s", diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterUtil.java new file mode 100644 index 0000000000..3256d7f787 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/AutoRegisterUtil.java @@ -0,0 +1,41 @@ +// Copyright (C) 2012 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.plugins; + +import com.google.gerrit.extensions.annotations.Export; +import com.google.inject.internal.UniqueAnnotations; + +import java.lang.annotation.Annotation; + +public final class AutoRegisterUtil { + + public static Annotation calculateBindAnnotation(Class impl) { + Annotation n = impl.getAnnotation(Export.class); + if (n == null) { + n = impl.getAnnotation(javax.inject.Named.class); + } + if (n == null) { + n = impl.getAnnotation(com.google.inject.name.Named.class); + } + if (n == null) { + n = UniqueAnnotations.create(); + } + return n; + } + + private AutoRegisterUtil() { + // hide default constructor + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ModuleGenerator.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ModuleGenerator.java index 92e3b1dd6b..2011e9d198 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ModuleGenerator.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ModuleGenerator.java @@ -16,11 +16,14 @@ package com.google.gerrit.server.plugins; import com.google.gerrit.extensions.annotations.Export; import com.google.inject.Module; +import com.google.inject.TypeLiteral; public interface ModuleGenerator { void setPluginName(String name); void export(Export export, Class type) throws InvalidPluginException; + void listen(TypeLiteral tl, Class clazz); + Module create() throws InvalidPluginException; } diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java index 03485f71cb..afb2537bd5 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java @@ -14,22 +14,29 @@ package com.google.gerrit.sshd; +import static com.google.gerrit.server.plugins.AutoRegisterUtil.calculateBindAnnotation; + import com.google.common.base.Preconditions; +import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.gerrit.extensions.annotations.Export; import com.google.gerrit.server.plugins.InvalidPluginException; import com.google.gerrit.server.plugins.ModuleGenerator; import com.google.inject.AbstractModule; import com.google.inject.Module; +import com.google.inject.TypeLiteral; import org.apache.sshd.server.Command; +import java.lang.annotation.Annotation; import java.util.Map; class SshAutoRegisterModuleGenerator extends AbstractModule implements ModuleGenerator { private final Map> commands = Maps.newHashMap(); + private final Multimap, Class> listeners = LinkedListMultimap.create(); private CommandName command; @Override @@ -39,6 +46,16 @@ class SshAutoRegisterModuleGenerator for (Map.Entry> e : commands.entrySet()) { bind(Commands.key(command, e.getKey())).to(e.getValue()); } + for (Map.Entry, Class> e : listeners.entries()) { + @SuppressWarnings("unchecked") + TypeLiteral type = (TypeLiteral) e.getKey(); + + @SuppressWarnings("unchecked") + Class impl = (Class) e.getValue(); + + Annotation n = calculateBindAnnotation(impl); + bind(type).annotatedWith(n).to(impl); + } } public void setPluginName(String name) { @@ -66,6 +83,12 @@ class SshAutoRegisterModuleGenerator } } + + @Override + public void listen(TypeLiteral tl, Class clazz) { + listeners.put(tl, clazz); + } + @Override public Module create() throws InvalidPluginException { Preconditions.checkState(command != null, "pluginName must be provided"); From df52478ca924b428001b5b9ce7bbcf7bc75504b3 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 30 Oct 2012 16:20:39 +0100 Subject: [PATCH 2/8] Do not call onModuleLoad() second time onModuleLoad() method is automatically called by GWT framework. Calling it once again in PluginGenerator cause double plugin initialization. Change-Id: I86b179f0a2da99121c74d1c095281bdd7de30636 Signed-off-by: Dariusz Luksza --- .../main/java/com/google/gerrit/rebind/PluginGenerator.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/rebind/PluginGenerator.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/rebind/PluginGenerator.java index 71666f91e6..37c3e96c6f 100644 --- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/rebind/PluginGenerator.java +++ b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/rebind/PluginGenerator.java @@ -72,12 +72,6 @@ public class PluginGenerator extends Generator { // We really use a SourceWriter since it's convenient SourceWriter sw = f.createSourceWriter(context, out); - sw.println("public " + generatedSimpleSourceName + "() {"); - sw.indent(); - sw.println("onModuleLoad();"); - sw.outdent(); - sw.println("}"); - sw.commit(logger); } From aaf2c4f87a6aa6167d70dc93441716b45a7f583c Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 30 Oct 2012 16:46:40 +0100 Subject: [PATCH 3/8] Add ApiType.JS Adds JS ApiType to match current configuration in plugin-js-archetype. Change-Id: I5482fea8c74ff4489eb26323f81858ef48593e7d Signed-off-by: Dariusz Luksza --- .../main/java/com/google/gerrit/server/plugins/Plugin.java | 4 +++- .../java/com/google/gerrit/server/plugins/PluginLoader.java | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java index c67f18061e..5049e9fde0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java @@ -41,7 +41,7 @@ import javax.annotation.Nullable; public class Plugin { public static enum ApiType { - EXTENSION, PLUGIN; + EXTENSION, PLUGIN, JS; } /** Unique key that changes whenever a plugin reloads. */ @@ -74,6 +74,8 @@ public class Plugin { return ApiType.EXTENSION; } else if (ApiType.PLUGIN.name().equalsIgnoreCase(v)) { return ApiType.PLUGIN; + } else if (ApiType.JS.name().equalsIgnoreCase(v)) { + return ApiType.JS; } else { throw new InvalidPluginException("Invalid Gerrit-ApiType: " + v); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java index d1c2aa40b3..86bff38063 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java @@ -22,6 +22,7 @@ import com.google.common.collect.Sets; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.systemstatus.ServerInformation; +import com.google.gerrit.extensions.webui.JavaScriptPlugin; import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; @@ -464,6 +465,8 @@ public class PluginLoader implements LifecycleListener { return PluginName.class.getClassLoader(); case PLUGIN: return PluginLoader.class.getClassLoader(); + case JS: + return JavaScriptPlugin.class.getClassLoader(); default: throw new InvalidPluginException("Unsupported ApiType " + type); } From 9abe435ba3562aa0694ab693739170eff0940072 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 30 Oct 2012 16:48:14 +0100 Subject: [PATCH 4/8] Update plugin-js-archetype to match current implementation Use auto registering mechanism using @Listen annotation instead of binding in main Module. Change-Id: I3ece0066fb52cfae4e5913782b1cf43e71f1dc07 Signed-off-by: Dariusz Luksza --- .../src/main/resources/archetype-resources/pom.xml | 2 -- .../src/main/java/{Module.java => MyJsExtension.java} | 11 +++++------ 2 files changed, 5 insertions(+), 8 deletions(-) rename gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/{Module.java => MyJsExtension.java} (72%) diff --git a/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/pom.xml b/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/pom.xml index 6f0638aa1a..2a8b469aa0 100644 --- a/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/pom.xml +++ b/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/pom.xml @@ -42,8 +42,6 @@ limitations under the License. - ${package}.Module - ${Implementation-Vendor} ${Implementation-Url} diff --git a/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/Module.java b/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/MyJsExtension.java similarity index 72% rename from gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/Module.java rename to gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/MyJsExtension.java index 056afebefe..bec914dde7 100644 --- a/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/Module.java +++ b/gerrit-plugin-js-archetype/src/main/resources/archetype-resources/src/main/java/MyJsExtension.java @@ -14,13 +14,12 @@ package ${package}; -import com.google.inject.AbstractModule; -import com.google.gerrit.extensions.webui.WebUiPlugin; +import com.google.gerrit.extensions.annotations.Listen; import com.google.gerrit.extensions.webui.JavaScriptPlugin; -class Module extends AbstractModule { - @Override - protected void configure() { - bind(WebUiPlugin.class).toInstance(new JavaScriptPlugin("hello-js-plugins.js")); +@Listen +public class MyJsExtension extends JavaScriptPlugin { + public MyJsExtension() { + super("hello-js-plugins.js"); } } From 293021e700b704dba0e3bab560aca41db9f43854 Mon Sep 17 00:00:00 2001 From: Dariusz Luksza Date: Tue, 30 Oct 2012 17:06:06 +0100 Subject: [PATCH 5/8] Update plugin-gwt-archetype to match current implementation Update GWT plugin archetype to auto register its instance in Gerrit Change-Id: I7b1930871b21f5ae4850ee07f14cd430f9866036 Signed-off-by: Dariusz Luksza --- .../src/main/resources/archetype-resources/pom.xml | 2 -- .../src/main/java/{Module.java => MyExtension.java} | 11 +++++------ 2 files changed, 5 insertions(+), 8 deletions(-) rename gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/{Module.java => MyExtension.java} (72%) diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/pom.xml b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/pom.xml index 3904e2b13a..6e1ba210f0 100644 --- a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/pom.xml +++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/pom.xml @@ -41,8 +41,6 @@ limitations under the License. - ${package}.Module - ${Implementation-Vendor} ${Implementation-Url} diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/Module.java b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/MyExtension.java similarity index 72% rename from gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/Module.java rename to gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/MyExtension.java index d42545a76d..ebdbb2651a 100644 --- a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/Module.java +++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/java/MyExtension.java @@ -14,13 +14,12 @@ package ${package}; -import com.google.inject.AbstractModule; -import com.google.gerrit.extensions.webui.WebUiPlugin; import com.google.gerrit.extensions.webui.GwtPlugin; +import com.google.gerrit.extensions.annotations.Listen; -class Module extends AbstractModule { - @Override - protected void configure() { - bind(WebUiPlugin.class).toInstance(new GwtPlugin("hello_gwt_plugins")); +@Listen +public class MyExtension extends GwtPlugin { + public MyExtension() { + super("hello_gwt_plugins"); } } From b6efafdff6fec9b5354dfe8605f22c0d467ebabb Mon Sep 17 00:00:00 2001 From: Edwin Kempin Date: Tue, 13 Nov 2012 15:48:41 +0100 Subject: [PATCH 6/8] Allow seeing the submit type for patch sets which are not current When clicking on the 'Review' button for a patch set that is not current, the submit type in the change data on the PublishCommentScreen was shown as 'RULE_ERROR'. Now we compute the submit type for that patch set and display it. Always displaying the submit type of the current patch set would not work in case the current patch set is a draft patch set which is not visible to the user. Change-Id: I53c2515cf58b2fdf3a5ab6bdd6fc4c1e5853de2a Signed-off-by: Edwin Kempin --- .../java/com/google/gerrit/server/project/ChangeControl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java index 4494853c76..850bfb3852 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java @@ -446,11 +446,6 @@ public class ChangeControl { @SuppressWarnings("unchecked") public SubmitTypeRecord getSubmitTypeRecord(ReviewDb db, PatchSet patchSet, @Nullable ChangeData cd) { - if (!patchSet.getId().equals(change.currentPatchSetId())) { - return typeRuleError("Patch set " + patchSet.getPatchSetId() - + " is not current"); - } - try { if (change.getStatus() == Change.Status.DRAFT && !isDraftVisible(db, cd)) { return typeRuleError("Patch set " + patchSet.getPatchSetId() From b9f966f9309eafa3489626bb8db375f1f2fdc943 Mon Sep 17 00:00:00 2001 From: David Pursehouse Date: Wed, 14 Nov 2012 18:27:02 +0900 Subject: [PATCH 7/8] Only show submit type in change view for open changes Submit type is per project, not tied to specific changes. If the project's submit type is changed after a change has been merged, the displayed information will not be correct; it will show the current merge type, which is not necessarily the one that was used at submit time. If a change has been abandoned, the submit type is not relevant. Change-Id: I59f4e18a58f57dfea38ece3dccdeb6a8ee944626 --- .../java/com/google/gerrit/client/changes/ChangeInfoBlock.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java index c42ca8d1ea..7fb4f5943f 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java @@ -119,8 +119,10 @@ public class ChangeInfoBlock extends Composite { if (status.isClosed()) { table.getCellFormatter().addStyleName(R_STATUS, 1, Gerrit.RESOURCES.css().closedstate()); + table.getRowFormatter().setVisible(R_SUBMIT_TYPE, false); } else { table.getCellFormatter().removeStyleName(R_STATUS, 1, Gerrit.RESOURCES.css().closedstate()); + table.getRowFormatter().setVisible(R_SUBMIT_TYPE, true); } } } From 4b4ee71b0b9104b64f70f19a4d7a762cee9e0256 Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Wed, 14 Nov 2012 16:17:56 -0600 Subject: [PATCH 8/8] Fix NPE when abandoning change with invalid author If the author of a change isn't known to Gerrit (pushed with forgeAuthor permissions), we were NPE'ing when abandoning that change over SSH. We were also throwing an internal server error when pushing patches with unknown authors, which is also solved with this patch. Change-Id: I85c3a3ff059953a2e11f808a6f6b02f916ac7417 --- .../java/com/google/gerrit/server/events/EventFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java index cf2c5060c9..473f413804 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java @@ -403,6 +403,9 @@ public class EventFactory { * @return object suitable for serialization to JSON */ public AccountAttribute asAccountAttribute(Account.Id id) { + if (id == null) { + return null; + } return asAccountAttribute(accountCache.get(id).getAccount()); }