Merge changes I2459a3ea,Ie7639e2d

* changes:
  Make EmailArguments a singleton
  Document EmailArguments
diff --git a/java/com/google/gerrit/server/mail/send/EmailArguments.java b/java/com/google/gerrit/server/mail/send/EmailArguments.java
index ede5765..808d6a4 100644
--- a/java/com/google/gerrit/server/mail/send/EmailArguments.java
+++ b/java/com/google/gerrit/server/mail/send/EmailArguments.java
@@ -45,11 +45,24 @@
 import com.google.gerrit.server.validators.OutgoingEmailValidationListener;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import com.google.inject.Singleton;
 import com.google.template.soy.jbcsrc.api.SoySauce;
 import java.util.List;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.PersonIdent;
 
+/**
+ * Arguments used for sending notification emails.
+ *
+ * <p>Notification emails are sent by out by {@link OutgoingEmail} and it's subclasses, so called
+ * senders. To construct an email the sender class needs to get various other classes injected.
+ * Instead of injecting these classes into the sender classes directly, they only get {@code
+ * EmailArguments} injected and {@code EmailArguments} provides them all dependencies that they
+ * need.
+ *
+ * <p>This class is public because plugins need access to it for sending emails.
+ */
+@Singleton
 @UsedAt(UsedAt.Project.PLUGINS_ALL)
 public class EmailArguments {
   final GitRepositoryManager server;
@@ -60,22 +73,22 @@
   final PatchListCache patchListCache;
   final PatchSetUtil patchSetUtil;
   final ApprovalsUtil approvalsUtil;
-  final FromAddressGenerator fromAddressGenerator;
+  final Provider<FromAddressGenerator> fromAddressGenerator;
   final EmailSender emailSender;
   final PatchSetInfoFactory patchSetInfoFactory;
   final IdentifiedUser.GenericFactory identifiedUserFactory;
   final ChangeNotes.Factory changeNotesFactory;
-  final AnonymousUser anonymousUser;
+  final Provider<AnonymousUser> anonymousUser;
   final String anonymousCowardName;
-  final PersonIdent gerritPersonIdent;
+  final Provider<PersonIdent> gerritPersonIdent;
   final DynamicItem<UrlFormatter> urlFormatter;
   final AllProjectsName allProjectsName;
   final List<String> sshAddresses;
   final SitePaths site;
 
-  final ChangeQueryBuilder queryBuilder;
+  final Provider<ChangeQueryBuilder> queryBuilder;
   final ChangeData.Factory changeDataFactory;
-  final SoySauce soySauce;
+  final Provider<SoySauce> soySauce;
   final EmailSettings settings;
   final DynamicSet<OutgoingEmailValidationListener> outgoingEmailValidationListeners;
   final Provider<InternalAccountQuery> accountQueryProvider;
@@ -93,19 +106,19 @@
       PatchListCache patchListCache,
       PatchSetUtil patchSetUtil,
       ApprovalsUtil approvalsUtil,
-      FromAddressGenerator fromAddressGenerator,
+      Provider<FromAddressGenerator> fromAddressGenerator,
       EmailSender emailSender,
       PatchSetInfoFactory patchSetInfoFactory,
       GenericFactory identifiedUserFactory,
       ChangeNotes.Factory changeNotesFactory,
-      AnonymousUser anonymousUser,
+      Provider<AnonymousUser> anonymousUser,
       @AnonymousCowardName String anonymousCowardName,
-      GerritPersonIdentProvider gerritPersonIdentProvider,
+      GerritPersonIdentProvider gerritPersonIdent,
       DynamicItem<UrlFormatter> urlFormatter,
       AllProjectsName allProjectsName,
-      ChangeQueryBuilder queryBuilder,
+      Provider<ChangeQueryBuilder> queryBuilder,
       ChangeData.Factory changeDataFactory,
-      @MailTemplates SoySauce soySauce,
+      @MailTemplates Provider<SoySauce> soySauce,
       EmailSettings settings,
       @SshAdvertisedAddresses List<String> sshAddresses,
       SitePaths site,
@@ -129,7 +142,7 @@
     this.changeNotesFactory = changeNotesFactory;
     this.anonymousUser = anonymousUser;
     this.anonymousCowardName = anonymousCowardName;
-    this.gerritPersonIdent = gerritPersonIdentProvider.get();
+    this.gerritPersonIdent = gerritPersonIdent;
     this.urlFormatter = urlFormatter;
     this.allProjectsName = allProjectsName;
     this.queryBuilder = queryBuilder;
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index e81f7f4..d48ed59 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -52,6 +52,7 @@
 import java.util.Set;
 import java.util.StringJoiner;
 import org.apache.james.mime4j.dom.field.FieldName;
+import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.util.SystemReader;
 
 /** Sends an email to one or more interested parties. */
@@ -256,7 +257,7 @@
   protected void init() throws EmailException {
     setupSoyContext();
 
-    smtpFromAddress = args.fromAddressGenerator.from(fromId);
+    smtpFromAddress = args.fromAddressGenerator.get().from(fromId);
     setHeader(FieldName.DATE, new Date());
     headers.put(FieldName.FROM, new EmailHeader.AddressList(smtpFromAddress));
     headers.put(FieldName.TO, new EmailHeader.AddressList());
@@ -273,7 +274,7 @@
     textBody = new StringBuilder();
     htmlBody = new StringBuilder();
 
-    if (fromId != null && args.fromAddressGenerator.isGenericAddress(fromId)) {
+    if (fromId != null && args.fromAddressGenerator.get().isGenericAddress(fromId)) {
       appendText(getFromLine());
     }
   }
@@ -353,7 +354,7 @@
   /** Lookup a human readable name for an account, usually the "full name". */
   protected String getNameFor(@Nullable Account.Id accountId) {
     if (accountId == null) {
-      return args.gerritPersonIdent.getName();
+      return args.gerritPersonIdent.get().getName();
     }
 
     Optional<Account> account = args.accountCache.get(accountId).map(AccountState::account);
@@ -379,10 +380,8 @@
    */
   protected String getNameEmailFor(@Nullable Account.Id accountId) {
     if (accountId == null) {
-      return args.gerritPersonIdent.getName()
-          + " <"
-          + args.gerritPersonIdent.getEmailAddress()
-          + ">";
+      PersonIdent gerritIdent = args.gerritPersonIdent.get();
+      return gerritIdent.getName() + " <" + gerritIdent.getEmailAddress() + ">";
     }
 
     Optional<Account> account = args.accountCache.get(accountId).map(AccountState::account);
@@ -591,7 +590,10 @@
 
   /** Configures a soy renderer for the given template name and rendering data map. */
   private SoySauce.Renderer configureRenderer(String templateName) {
-    return args.soySauce.renderTemplate(SOY_TEMPLATE_NAMESPACE + templateName).setData(soyContext);
+    return args.soySauce
+        .get()
+        .renderTemplate(SOY_TEMPLATE_NAMESPACE + templateName)
+        .setData(soyContext);
   }
 
   protected void removeUser(Account user) {
diff --git a/java/com/google/gerrit/server/mail/send/ProjectWatch.java b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
index 934a0a0..be36f55 100644
--- a/java/com/google/gerrit/server/mail/send/ProjectWatch.java
+++ b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
@@ -241,9 +241,9 @@
     Predicate<ChangeData> p = null;
 
     if (user == null) {
-      qb = args.queryBuilder.asUser(args.anonymousUser);
+      qb = args.queryBuilder.get().asUser(args.anonymousUser.get());
     } else {
-      qb = args.queryBuilder.asUser(user);
+      qb = args.queryBuilder.get().asUser(user);
       p = qb.is_visible();
     }