LCOV - code coverage report
Current view: top level - server/mail - MailUtil.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 43 59 72.9 %
Date: 2022-11-19 15:00:39 Functions: 10 14 71.4 %

          Line data    Source code
       1             : // Copyright (C) 2013 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;
      16             : 
      17             : import static com.google.gerrit.server.notedb.ReviewerStateInternal.CC;
      18             : import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
      19             : 
      20             : import com.google.common.flogger.FluentLogger;
      21             : import com.google.gerrit.common.FooterConstants;
      22             : import com.google.gerrit.entities.Account;
      23             : import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
      24             : import com.google.gerrit.server.ReviewerSet;
      25             : import com.google.gerrit.server.account.AccountResolver;
      26             : import java.io.IOException;
      27             : import java.util.Collections;
      28             : import java.util.HashSet;
      29             : import java.util.List;
      30             : import java.util.Set;
      31             : import java.util.regex.Pattern;
      32             : import org.eclipse.jgit.errors.ConfigInvalidException;
      33             : import org.eclipse.jgit.revwalk.FooterKey;
      34             : import org.eclipse.jgit.revwalk.FooterLine;
      35             : 
      36           0 : public class MailUtil {
      37          89 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      38             : 
      39             :   public static MailRecipients getRecipientsFromFooters(
      40             :       AccountResolver accountResolver, List<FooterLine> footerLines)
      41             :       throws IOException, ConfigInvalidException {
      42          88 :     MailRecipients recipients = new MailRecipients();
      43          88 :     for (FooterLine footerLine : footerLines) {
      44             :       try {
      45          88 :         if (isReviewer(footerLine)) {
      46           4 :           Account.Id accountId = toAccountId(accountResolver, footerLine.getValue().trim());
      47           4 :           recipients.reviewers.add(accountId);
      48           4 :           logger.atFine().log(
      49           4 :               "Added account %d from footer line \"%s\" as reviewer", accountId.get(), footerLine);
      50          88 :         } else if (footerLine.matches(FooterKey.CC)) {
      51           0 :           Account.Id accountId = toAccountId(accountResolver, footerLine.getValue().trim());
      52           0 :           recipients.cc.add(accountId);
      53           0 :           logger.atFine().log(
      54           0 :               "Added account %d from footer line \"%s\" as cc", accountId.get(), footerLine);
      55             :         }
      56           3 :       } catch (UnprocessableEntityException e) {
      57           3 :         logger.atFine().log(
      58           3 :             "Skip adding reviewer/cc from footer line \"%s\": %s", footerLine, e.getMessage());
      59           3 :         continue;
      60          88 :       }
      61          88 :     }
      62          88 :     return recipients;
      63             :   }
      64             : 
      65             :   public static MailRecipients getRecipientsFromReviewers(ReviewerSet reviewers) {
      66          37 :     MailRecipients recipients = new MailRecipients();
      67          37 :     recipients.reviewers.addAll(reviewers.byState(REVIEWER));
      68          37 :     recipients.cc.addAll(reviewers.byState(CC));
      69          37 :     return recipients;
      70             :   }
      71             : 
      72             :   @SuppressWarnings("deprecation")
      73             :   private static Account.Id toAccountId(AccountResolver accountResolver, String nameOrEmail)
      74             :       throws UnprocessableEntityException, IOException, ConfigInvalidException {
      75           4 :     return accountResolver.resolveByExactNameOrEmail(nameOrEmail).asUnique().account().id();
      76             :   }
      77             : 
      78             :   private static boolean isReviewer(FooterLine candidateFooterLine) {
      79          88 :     return candidateFooterLine.matches(FooterKey.SIGNED_OFF_BY)
      80          88 :         || candidateFooterLine.matches(FooterKey.ACKED_BY)
      81          88 :         || candidateFooterLine.matches(FooterConstants.REVIEWED_BY)
      82          88 :         || candidateFooterLine.matches(FooterConstants.TESTED_BY);
      83             :   }
      84             : 
      85             :   public static class MailRecipients {
      86             :     private final Set<Account.Id> reviewers;
      87             :     private final Set<Account.Id> cc;
      88             : 
      89          88 :     public MailRecipients() {
      90          88 :       this.reviewers = new HashSet<>();
      91          88 :       this.cc = new HashSet<>();
      92          88 :     }
      93             : 
      94           0 :     public MailRecipients(Set<Account.Id> reviewers, Set<Account.Id> cc) {
      95           0 :       this.reviewers = new HashSet<>(reviewers);
      96           0 :       this.cc = new HashSet<>(cc);
      97           0 :     }
      98             : 
      99             :     public void add(MailRecipients recipients) {
     100           0 :       reviewers.addAll(recipients.reviewers);
     101           0 :       cc.addAll(recipients.cc);
     102           0 :     }
     103             : 
     104             :     public void remove(Account.Id toRemove) {
     105          88 :       reviewers.remove(toRemove);
     106          88 :       cc.remove(toRemove);
     107          88 :     }
     108             : 
     109             :     public Set<Account.Id> getReviewers() {
     110          88 :       return Collections.unmodifiableSet(reviewers);
     111             :     }
     112             : 
     113             :     public Set<Account.Id> getCcOnly() {
     114          88 :       final Set<Account.Id> cc = new HashSet<>(this.cc);
     115          88 :       cc.removeAll(reviewers);
     116          88 :       return Collections.unmodifiableSet(cc);
     117             :     }
     118             : 
     119             :     public Set<Account.Id> getAll() {
     120           0 :       final Set<Account.Id> all = new HashSet<>(reviewers.size() + cc.size());
     121           0 :       all.addAll(reviewers);
     122           0 :       all.addAll(cc);
     123           0 :       return Collections.unmodifiableSet(all);
     124             :     }
     125             :   }
     126             : 
     127             :   /** allow wildcard matching for {@code domains} */
     128             :   public static Pattern glob(String[] domains) {
     129             :     // if domains is not set, match anything
     130           1 :     if (domains == null || domains.length == 0) {
     131           1 :       return Pattern.compile(".*");
     132             :     }
     133             : 
     134           1 :     StringBuilder sb = new StringBuilder();
     135           1 :     for (String domain : domains) {
     136           1 :       String quoted = "\\Q" + domain.replace("\\E", "\\E\\\\E\\Q") + "\\E|";
     137           1 :       sb.append(quoted.replace("*", "\\E.*\\Q"));
     138             :     }
     139           1 :     return Pattern.compile(sb.substring(0, sb.length() - 1));
     140             :   }
     141             : }

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