LCOV - code coverage report
Current view: top level - server/mail/send - NotificationEmail.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 56 58 96.6 %
Date: 2022-11-19 15:00:39 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2012 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.mail.send;
      16             : 
      17             : import com.google.common.annotations.VisibleForTesting;
      18             : import com.google.common.collect.Iterables;
      19             : import com.google.common.flogger.FluentLogger;
      20             : import com.google.gerrit.common.Nullable;
      21             : import com.google.gerrit.entities.Account;
      22             : import com.google.gerrit.entities.Address;
      23             : import com.google.gerrit.entities.BranchNameKey;
      24             : import com.google.gerrit.entities.NotifyConfig.NotifyType;
      25             : import com.google.gerrit.exceptions.EmailException;
      26             : import com.google.gerrit.exceptions.StorageException;
      27             : import com.google.gerrit.extensions.api.changes.RecipientType;
      28             : import com.google.gerrit.mail.MailHeader;
      29             : import com.google.gerrit.server.mail.send.ProjectWatch.Watchers;
      30             : import com.google.gerrit.server.mail.send.ProjectWatch.Watchers.WatcherList;
      31             : import java.util.HashMap;
      32             : import java.util.Map;
      33             : 
      34             : /** Common class for notifications that are related to a project and branch */
      35             : public abstract class NotificationEmail extends OutgoingEmail {
      36         152 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      37             : 
      38             :   protected BranchNameKey branch;
      39             : 
      40             :   protected NotificationEmail(EmailArguments args, String messageClass, BranchNameKey branch) {
      41         103 :     super(args, messageClass);
      42         103 :     this.branch = branch;
      43         103 :   }
      44             : 
      45             :   @Override
      46             :   protected void init() throws EmailException {
      47         103 :     super.init();
      48         103 :     setListIdHeader();
      49         103 :   }
      50             : 
      51             :   private void setListIdHeader() {
      52             :     // Set a reasonable list id so that filters can be used to sort messages
      53         103 :     setHeader(
      54             :         "List-Id",
      55         103 :         "<gerrit-" + branch.project().get().replace('/', '-') + "." + getGerritHost() + ">");
      56         103 :     if (getSettingsUrl() != null) {
      57         103 :       setHeader("List-Unsubscribe", "<" + getSettingsUrl() + ">");
      58             :     }
      59         103 :   }
      60             : 
      61             :   /** Include users and groups that want notification of events. */
      62             :   protected void includeWatchers(NotifyType type) {
      63          57 :     includeWatchers(type, true);
      64          57 :   }
      65             : 
      66             :   /** Include users and groups that want notification of events. */
      67             :   protected void includeWatchers(NotifyType type, boolean includeWatchersFromNotifyConfig) {
      68             :     try {
      69         103 :       Watchers matching = getWatchers(type, includeWatchersFromNotifyConfig);
      70         103 :       add(RecipientType.TO, matching.to);
      71         103 :       add(RecipientType.CC, matching.cc);
      72         103 :       add(RecipientType.BCC, matching.bcc);
      73           0 :     } catch (StorageException err) {
      74             :       // Just don't CC everyone. Better to send a partial message to those
      75             :       // we already have queued up then to fail deliver entirely to people
      76             :       // who have a lower interest in the change.
      77           0 :       logger.atWarning().withCause(err).log("Cannot BCC watchers for %s", type);
      78         103 :     }
      79         103 :   }
      80             : 
      81             :   /** Returns all watchers that are relevant */
      82             :   protected abstract Watchers getWatchers(NotifyType type, boolean includeWatchersFromNotifyConfig);
      83             : 
      84             :   /** Add users or email addresses to the TO, CC, or BCC list. */
      85             :   protected void add(RecipientType type, WatcherList watcherList) {
      86         103 :     for (Account.Id user : watcherList.accounts) {
      87           8 :       addWatcher(type, user);
      88           8 :     }
      89         103 :     for (Address addr : watcherList.emails) {
      90           2 :       add(type, addr);
      91           2 :     }
      92         103 :   }
      93             : 
      94             :   protected abstract void addWatcher(RecipientType type, Account.Id to);
      95             : 
      96             :   @Nullable
      97             :   public String getSshHost() {
      98         103 :     String host = Iterables.getFirst(args.sshAddresses, null);
      99         103 :     if (host == null) {
     100          84 :       return null;
     101             :     }
     102          20 :     if (host.startsWith("*:")) {
     103           8 :       return getGerritHost() + host.substring(1);
     104             :     }
     105          12 :     return host;
     106             :   }
     107             : 
     108             :   @Override
     109             :   protected void setupSoyContext() {
     110         103 :     super.setupSoyContext();
     111             : 
     112         103 :     String projectName = branch.project().get();
     113         103 :     soyContext.put("projectName", projectName);
     114             :     // shortProjectName is the project name with the path abbreviated.
     115         103 :     soyContext.put("shortProjectName", getShortProjectName(projectName));
     116             : 
     117             :     // instanceAndProjectName is the instance's name followed by the abbreviated project path
     118         103 :     soyContext.put(
     119             :         "instanceAndProjectName",
     120         103 :         getInstanceAndProjectName(args.instanceNameProvider.get(), projectName));
     121         103 :     soyContext.put("addInstanceNameInSubject", args.addInstanceNameInSubject);
     122             : 
     123         103 :     soyContextEmailData.put("sshHost", getSshHost());
     124             : 
     125         103 :     Map<String, String> branchData = new HashMap<>();
     126         103 :     branchData.put("shortName", branch.shortName());
     127         103 :     soyContext.put("branch", branchData);
     128             : 
     129         103 :     footers.add(MailHeader.PROJECT.withDelimiter() + branch.project().get());
     130         103 :     footers.add(MailHeader.BRANCH.withDelimiter() + branch.shortName());
     131         103 :   }
     132             : 
     133             :   @VisibleForTesting
     134             :   protected static String getShortProjectName(String projectName) {
     135         103 :     int lastIndexSlash = projectName.lastIndexOf('/');
     136         103 :     if (lastIndexSlash == 0) {
     137           1 :       return projectName.substring(1); // Remove the first slash
     138             :     }
     139         103 :     if (lastIndexSlash == -1) { // No slash in the project name
     140         103 :       return projectName;
     141             :     }
     142             : 
     143           1 :     return "..." + projectName.substring(lastIndexSlash + 1);
     144             :   }
     145             : 
     146             :   @VisibleForTesting
     147             :   protected static String getInstanceAndProjectName(String instanceName, String projectName) {
     148         103 :     if (instanceName == null || instanceName.isEmpty()) {
     149           1 :       return getShortProjectName(projectName);
     150             :     }
     151             :     // Extract the project name (everything after the last slash) and prepends it with gerrit's
     152             :     // instance name
     153         103 :     return instanceName + "/" + projectName.substring(projectName.lastIndexOf('/') + 1);
     154             :   }
     155             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750