Merge stable-2.12

00f2c66 Merge branch stable-2.11 into stable-2.12
6dce1d7 Allow to specify amqp passwords in etc/secure.config
3f65399 Build with API version 2.11.8
ca93bcc Build with plugin API version 2.12.1
5558190 Organize imports
3ed04fb Build with API version 2.11.7
993a2aa Build with plugin API version 2.12 final release

Change-Id: I65c01da0f578af25087144aed5c8b4e374c898af
diff --git a/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/Module.java b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/Module.java
index c07fcdc..762d78e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/Module.java
@@ -17,7 +17,9 @@
 import com.google.gerrit.common.EventListener;
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gson.Gson;
 import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.multibindings.Multibinder;
 
@@ -30,6 +32,7 @@
 import com.googlesource.gerrit.plugins.rabbitmq.config.section.Message;
 import com.googlesource.gerrit.plugins.rabbitmq.config.section.Monitor;
 import com.googlesource.gerrit.plugins.rabbitmq.config.section.Section;
+import com.googlesource.gerrit.plugins.rabbitmq.message.GsonProvider;
 import com.googlesource.gerrit.plugins.rabbitmq.message.MessagePublisher;
 import com.googlesource.gerrit.plugins.rabbitmq.message.Publisher;
 import com.googlesource.gerrit.plugins.rabbitmq.message.PublisherFactory;
@@ -56,6 +59,7 @@
     install(new FactoryModuleBuilder().implement(Publisher.class, MessagePublisher.class).build(PublisherFactory.class));
     install(new FactoryModuleBuilder().implement(Properties.class, PluginProperties.class).build(PropertiesFactory.class));
     install(new FactoryModuleBuilder().implement(EventWorker.class, UserEventWorker.class).build(EventWorkerFactory.class));
+    bind(Gson.class).toProvider(GsonProvider.class).in(Singleton.class);
 
     DynamicSet.bind(binder(), LifecycleListener.class).to(Manager.class);
     DynamicSet.bind(binder(), EventListener.class).to(DefaultEventWorker.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/message/GsonProvider.java b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/message/GsonProvider.java
new file mode 100644
index 0000000..9aa38ed
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/message/GsonProvider.java
@@ -0,0 +1,30 @@
+// 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.googlesource.gerrit.plugins.rabbitmq.message;
+
+import com.google.common.base.Supplier;
+import com.google.gerrit.server.events.SupplierSerializer;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.Provider;
+
+public class GsonProvider implements Provider<Gson> {
+
+  @Override
+  public Gson get() {
+    return new GsonBuilder().registerTypeAdapter(Supplier.class,
+        new SupplierSerializer()).create();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/worker/UserEventWorker.java b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/worker/UserEventWorker.java
index 2beee41..2debaac 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/worker/UserEventWorker.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/rabbitmq/worker/UserEventWorker.java
@@ -14,13 +14,16 @@
 
 package com.googlesource.gerrit.plugins.rabbitmq.worker;
 
-import com.google.gerrit.common.EventSource;
+import com.google.gerrit.common.UserScopedEventListener;
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.extensions.registration.RegistrationHandle;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.PluginUser;
 import com.google.gerrit.server.account.AccountResolver;
+import com.google.gerrit.server.events.Event;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
@@ -35,34 +38,39 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class UserEventWorker implements EventWorker {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(UserEventWorker.class);
 
-  private final EventSource source;
+  private final DynamicSet<UserScopedEventListener> eventListeners;
   private final WorkQueue workQueue;
   private final AccountResolver accountResolver;
   private final IdentifiedUser.GenericFactory userFactory;
   private final ThreadLocalRequestContext threadLocalRequestContext;
   private final PluginUser pluginUser;
   private final SchemaFactory<ReviewDb> schemaFactory;
+  private final Map<Publisher, RegistrationHandle> eventListenerRegistrations;
 
   @Inject
   public UserEventWorker(
-      EventSource source,
+      DynamicSet<UserScopedEventListener> eventListeners,
       WorkQueue workQueue,
       AccountResolver accountResolver,
       IdentifiedUser.GenericFactory userFactory,
       ThreadLocalRequestContext threadLocalRequestContext,
       PluginUser pluginUser,
       SchemaFactory<ReviewDb> schemaFactory) {
-    this.source = source;
+    this.eventListeners = eventListeners;
     this.workQueue = workQueue;
     this.accountResolver = accountResolver;
     this.userFactory = userFactory;
     this.threadLocalRequestContext = threadLocalRequestContext;
     this.pluginUser = pluginUser;
     this.schemaFactory = schemaFactory;
+    eventListenerRegistrations = new HashMap<>();
   }
 
   @Override
@@ -104,14 +112,24 @@
               }
             });
         try {
-          userAccount = accountResolver.find(userName);
+          userAccount = accountResolver.find(db, userName);
           if (userAccount == null) {
             LOGGER.error("No single user could be found when searching for listenAs: {}", userName);
             return;
           }
-
-          IdentifiedUser user = userFactory.create(userAccount.getId());
-          source.addEventListener(publisher, user);
+          final IdentifiedUser user = userFactory.create(userAccount.getId());
+          RegistrationHandle registration =
+              eventListeners.add(new UserScopedEventListener() {
+                @Override
+                public void onEvent(Event event) {
+                  publisher.onEvent(event);
+                }
+                @Override
+                public CurrentUser getUser() {
+                  return user;
+                }
+              });
+          eventListenerRegistrations.put(publisher, registration);
           LOGGER.info("Listen events as : {}", userName);
         } catch (OrmException e) {
           LOGGER.error("Could not query database for listenAs", e);
@@ -129,7 +147,11 @@
 
   @Override
   public void removePublisher(final Publisher publisher) {
-    source.removeEventListener(publisher);
+    RegistrationHandle registration =
+        eventListenerRegistrations.remove(publisher);
+    if (registration != null) {
+      registration.remove();
+    }
   }
 
   @Override