blob: 5b209ce6094751ae4e0a7f13815cf846fa3433cc [file] [log] [blame]
// 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.mail.send;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.NotifyConfig.NotifyType;
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.mail.MailHeader;
import com.google.gerrit.server.mail.send.ProjectWatch.Watchers;
import com.google.gerrit.server.mail.send.ProjectWatch.Watchers.WatcherList;
import java.util.HashMap;
import java.util.Map;
/** Common class for notifications that are related to a project and branch */
public abstract class NotificationEmail extends OutgoingEmail {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected BranchNameKey branch;
protected NotificationEmail(EmailArguments args, String messageClass, BranchNameKey branch) {
super(args, messageClass);
this.branch = branch;
}
@Override
protected void init() throws EmailException {
super.init();
setListIdHeader();
}
private void setListIdHeader() {
// Set a reasonable list id so that filters can be used to sort messages
setHeader(
"List-Id",
"<gerrit-" + branch.project().get().replace('/', '-') + "." + getGerritHost() + ">");
if (getSettingsUrl() != null) {
setHeader("List-Unsubscribe", "<" + getSettingsUrl() + ">");
}
}
/** Include users and groups that want notification of events. */
protected void includeWatchers(NotifyType type) {
includeWatchers(type, true);
}
/** Include users and groups that want notification of events. */
protected void includeWatchers(NotifyType type, boolean includeWatchersFromNotifyConfig) {
try {
Watchers matching = getWatchers(type, includeWatchersFromNotifyConfig);
add(RecipientType.TO, matching.to);
add(RecipientType.CC, matching.cc);
add(RecipientType.BCC, matching.bcc);
} catch (StorageException err) {
// Just don't CC everyone. Better to send a partial message to those
// we already have queued up then to fail deliver entirely to people
// who have a lower interest in the change.
logger.atWarning().withCause(err).log("Cannot BCC watchers for %s", type);
}
}
/** Returns all watchers that are relevant */
protected abstract Watchers getWatchers(NotifyType type, boolean includeWatchersFromNotifyConfig);
/** Add users or email addresses to the TO, CC, or BCC list. */
protected void add(RecipientType type, WatcherList watcherList) {
for (Account.Id user : watcherList.accounts) {
addWatcher(type, user);
}
for (Address addr : watcherList.emails) {
add(type, addr);
}
}
protected abstract void addWatcher(RecipientType type, Account.Id to);
public String getSshHost() {
String host = Iterables.getFirst(args.sshAddresses, null);
if (host == null) {
return null;
}
if (host.startsWith("*:")) {
return getGerritHost() + host.substring(1);
}
return host;
}
@Override
protected void setupSoyContext() {
super.setupSoyContext();
String projectName = branch.project().get();
soyContext.put("projectName", projectName);
// shortProjectName is the project name with the path abbreviated.
soyContext.put("shortProjectName", getShortProjectName(projectName));
// instanceAndProjectName is the instance's name followed by the abbreviated project path
soyContext.put(
"instanceAndProjectName",
getInstanceAndProjectName(args.instanceNameProvider.get(), projectName));
soyContext.put("addInstanceNameInSubject", args.addInstanceNameInSubject);
soyContextEmailData.put("sshHost", getSshHost());
Map<String, String> branchData = new HashMap<>();
branchData.put("shortName", branch.shortName());
soyContext.put("branch", branchData);
footers.add(MailHeader.PROJECT.withDelimiter() + branch.project().get());
footers.add(MailHeader.BRANCH.withDelimiter() + branch.shortName());
}
@VisibleForTesting
protected static String getShortProjectName(String projectName) {
int lastIndexSlash = projectName.lastIndexOf('/');
if (lastIndexSlash == 0) {
return projectName.substring(1); // Remove the first slash
}
if (lastIndexSlash == -1) { // No slash in the project name
return projectName;
}
return "..." + projectName.substring(lastIndexSlash + 1);
}
@VisibleForTesting
protected static String getInstanceAndProjectName(String instanceName, String projectName) {
if (instanceName == null || instanceName.isEmpty()) {
return getShortProjectName(projectName);
}
// Extract the project name (everything after the last slash) and prepends it with gerrit's
// instance name
return instanceName + "/" + projectName.substring(projectName.lastIndexOf('/') + 1);
}
}