blob: efc1ef9f13d4fea43401eea965d79ae769ffc3c0 [file] [log] [blame]
package org.apache.maven.continuum.notification.mail;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import org.apache.continuum.model.project.ProjectScmRoot;
import org.apache.maven.continuum.Continuum;
import org.apache.maven.continuum.configuration.ConfigurationService;
import org.apache.maven.continuum.execution.ExecutorConfigurator;
import org.apache.maven.continuum.execution.ant.AntBuildExecutor;
import org.apache.maven.continuum.execution.maven.m1.MavenOneBuildExecutor;
import org.apache.maven.continuum.execution.maven.m2.MavenTwoBuildExecutor;
import org.apache.maven.continuum.installation.InstallationException;
import org.apache.maven.continuum.installation.InstallationService;
import org.apache.maven.continuum.model.project.BuildDefinition;
import org.apache.maven.continuum.model.project.BuildResult;
import org.apache.maven.continuum.model.project.Project;
import org.apache.maven.continuum.model.project.ProjectDeveloper;
import org.apache.maven.continuum.model.project.ProjectGroup;
import org.apache.maven.continuum.model.project.ProjectNotifier;
import org.apache.maven.continuum.model.scm.ChangeSet;
import org.apache.maven.continuum.model.scm.ScmResult;
import org.apache.maven.continuum.model.system.Installation;
import org.apache.maven.continuum.model.system.Profile;
import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
import org.apache.maven.continuum.notification.MessageContext;
import org.apache.maven.continuum.notification.NotificationException;
import org.apache.maven.continuum.project.ContinuumProjectState;
import org.apache.maven.continuum.reports.surefire.ReportTestResult;
import org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.velocity.VelocityComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
* @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
* @version $Id$
*/
public class MailContinuumNotifier
extends AbstractContinuumNotifier
implements Initializable
{
private static final Logger log = LoggerFactory.getLogger( MailContinuumNotifier.class );
// ----------------------------------------------------------------------
// Requirements
// ----------------------------------------------------------------------
/**
* @plexus.requirement
*/
private VelocityComponent velocity;
/**
* @plexus.requirement
*/
private ConfigurationService configurationService;
/**
* @plexus.requirement
*/
private Continuum continuum;
/**
* @plexus.requirement
*/
private JavaMailSender javaMailSender;
/**
* @plexus.requirement
*/
private ReportTestSuiteGenerator reportTestSuiteGenerator;
// ----------------------------------------------------------------------
// Configuration
// ----------------------------------------------------------------------
/**
* @plexus.configuration
*/
private String fromMailbox;
/**
* @plexus.configuration
*/
private String fromName;
/**
* @plexus.configuration
*/
private String toOverride;
/**
* @plexus.configuration
*/
private String timestampFormat;
/**
* @plexus.configuration
*/
private boolean includeBuildSummary = true;
/**
* @plexus.configuration
*/
private boolean includeTestSummary = true;
/**
* @plexus.configuration
*/
private boolean includeBuildOutput = false;
/**
* Customizable mail subject. Use any combination of literal text, project or build attributes.
* Examples:
* "[continuum] BUILD ${state}: ${project.groupId} ${project.name}" results in "[continuum] BUILD SUCCESSFUL: foo.bar Hello World"
* "[continuum] BUILD ${state}: ${project.name} ${project.scmTag}" results in "[continuum] BUILD SUCCESSFUL: Hello World Branch001"
* "[continuum] BUILD ${state}: ${project.name} ${build.durationTime}" results in "[continuum] BUILD SUCCESSFUL: Hello World 2 sec"
* "[continuum] BUILD ${state}: ${project.name}, Build Def - ${build.buildDefinition.description}" results in "[continuum] BUILD SUCCESSFUL: Hello World, Build Def - Nightly Test Build"
*
* @plexus.configuration
*/
private String buildSubjectFormat = "[continuum] BUILD ${state}: ${project.groupId} ${project.name}";
/**
* Customizable mail subject
*
* @plexus.configuration
*/
private String prepareBuildSubjectFormat =
"[continuum] PREPARE BUILD ${state]: ${projectScmRoot.projectGroup.name}";
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
private String buildHost;
private FormatterTool formatterTool;
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
private static final String FALLBACK_FROM_MAILBOX = "continuum@localhost";
// ----------------------------------------------------------------------
// Component Lifecycle
// ----------------------------------------------------------------------
public void initialize()
{
try
{
InetAddress address = InetAddress.getLocalHost();
buildHost = StringUtils.clean( address.getHostName() );
if ( buildHost == null )
{
buildHost = "localhost";
}
}
catch ( UnknownHostException ex )
{
fromName = "Continuum";
}
// ----------------------------------------------------------------------
// From mailbox
// ----------------------------------------------------------------------
if ( StringUtils.isEmpty( fromMailbox ) )
{
log.info( "The from mailbox is not configured, will use the nag email address from the project." );
fromMailbox = null;
}
else
{
log.info( "Using '" + fromMailbox + "' as the from mailbox for all emails." );
}
if ( StringUtils.isEmpty( fromName ) )
{
fromName = "Continuum@" + buildHost;
}
log.info( "From name: " + fromName );
log.info( "Build host name: " + buildHost );
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
formatterTool = new FormatterTool( timestampFormat );
}
// ----------------------------------------------------------------------
// Notifier Implementation
// ----------------------------------------------------------------------
public String getType()
{
return "mail";
}
public void sendMessage( String messageId, MessageContext context )
throws NotificationException
{
Project project = context.getProject();
List<ProjectNotifier> notifiers = context.getNotifiers();
BuildResult build = context.getBuildResult();
if ( build != null )
{
log.error( "br state=" + build.getState() );
}
if ( project != null )
{
log.error( "project state=" + project.getState() );
}
BuildDefinition buildDefinition = context.getBuildDefinition();
ProjectScmRoot projectScmRoot = context.getProjectScmRoot();
boolean isPrepareBuildComplete = messageId.equals(
ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
if ( projectScmRoot == null && isPrepareBuildComplete )
{
return;
}
// ----------------------------------------------------------------------
// If there wasn't any building done, don't notify
// ----------------------------------------------------------------------
if ( build == null && !isPrepareBuildComplete )
{
return;
}
// ----------------------------------------------------------------------
// Generate and send email
// ----------------------------------------------------------------------
if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
{
buildComplete( project, notifiers, build, messageId, context, buildDefinition );
}
else if ( isPrepareBuildComplete )
{
prepareBuildComplete( projectScmRoot, notifiers, messageId, context );
}
}
private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build, String messageId,
MessageContext context, BuildDefinition buildDefinition )
throws NotificationException
{
BuildResult previousBuild = getPreviousBuild( project, buildDefinition, build );
List<ProjectNotifier> notifiersList = new ArrayList<ProjectNotifier>();
for ( ProjectNotifier notifier : notifiers )
{
// ----------------------------------------------------------------------
// Check if the mail should be sent at all
// ----------------------------------------------------------------------
if ( shouldNotify( build, previousBuild, notifier ) )
{
notifiersList.add( notifier );
}
}
buildComplete( project, notifiersList, build, previousBuild, messageId, context, buildDefinition );
}
private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build,
BuildResult previousBuild, String messageId, MessageContext messageContext,
BuildDefinition buildDefinition )
throws NotificationException
{
// ----------------------------------------------------------------------
// Generate the mail contents
// ----------------------------------------------------------------------
String packageName = getClass().getPackage().getName().replace( '.', '/' );
String templateName = packageName + "/templates/" + project.getExecutorId() + "/" + messageId + ".vm";
StringWriter writer = new StringWriter();
String content;
try
{
VelocityContext context = new VelocityContext();
context.put( "includeTestSummary", includeTestSummary );
context.put( "includeOutput", includeBuildOutput );
if ( includeBuildOutput )
{
context.put( "buildOutput", getBuildOutput( project, build ) );
}
if ( includeBuildSummary )
{
context.put( "build", build );
ReportTestResult reportTestResult = reportTestSuiteGenerator.generateReportTestResult( build.getId(),
project.getId() );
context.put( "testResult", reportTestResult );
context.put( "project", project );
context.put( "changesSinceLastSuccess", continuum.getChangesSinceLastSuccess( project.getId(),
build.getId() ) );
context.put( "previousBuild", previousBuild );
// ----------------------------------------------------------------------
// Tools
// ----------------------------------------------------------------------
context.put( "formatter", formatterTool );
// TODO: Make the build host a part of the build
context.put( "buildHost", buildHost );
String osName = System.getProperty( "os.name" );
String osPatchLevel = System.getProperty( "sun.os.patch.level" );
if ( osPatchLevel != null )
{
osName = osName + "(" + osPatchLevel + ")";
}
context.put( "osName", osName );
context.put( "javaVersion", System.getProperty( "java.version" ) + "(" + System.getProperty(
"java.vendor" ) + ")" );
// TODO only in case of a java project ?
context.put( "javaHomeInformations", getJavaHomeInformations( buildDefinition ) );
context.put( "builderVersions", getBuilderVersion( buildDefinition, project ) );
}
// ----------------------------------------------------------------------
// Data objects
// ----------------------------------------------------------------------
context.put( "reportUrl", getReportUrl( project, build, configurationService ) );
// TODO put other profile env var could be a security if they provide passwords ?
// ----------------------------------------------------------------------
// Generate
// ----------------------------------------------------------------------
velocity.getEngine().mergeTemplate( templateName, context, writer );
content = writer.getBuffer().toString();
}
catch ( ResourceNotFoundException e )
{
log.info( "No such template: '" + templateName + "'." );
return;
}
catch ( Exception e )
{
throw new NotificationException( "Error while generating mail contents.", e );
}
// ----------------------------------------------------------------------
// Send the mail
// ----------------------------------------------------------------------
String subject;
try
{
subject = generateSubject( project, build );
}
catch ( Exception e )
{
throw new NotificationException( "Error while generating mail subject.", e );
}
sendMessage( project, notifiers, subject, content, messageContext );
}
private void prepareBuildComplete( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, String messageId,
MessageContext messageContext )
throws NotificationException
{
// ----------------------------------------------------------------------
// Generate the mail contents
// ----------------------------------------------------------------------
String packageName = getClass().getPackage().getName().replace( '.', '/' );
String templateName = packageName + "/templates/" + messageId + ".vm";
StringWriter writer = new StringWriter();
String content;
try
{
VelocityContext context = new VelocityContext();
// ----------------------------------------------------------------------
// Data objects
// ----------------------------------------------------------------------
context.put( "reportUrl", getReportUrl( projectScmRoot.getProjectGroup(), projectScmRoot,
configurationService ) );
context.put( "projectScmRoot", projectScmRoot );
// TODO put other profile env var could be a security if they provide passwords ?
// ----------------------------------------------------------------------
// Generate
// ----------------------------------------------------------------------
velocity.getEngine().mergeTemplate( templateName, context, writer );
content = writer.getBuffer().toString();
}
catch ( ResourceNotFoundException e )
{
log.info( "No such template: '" + templateName + "'." );
return;
}
catch ( Exception e )
{
throw new NotificationException( "Error while generating mail contents.", e );
}
// ----------------------------------------------------------------------
// Send the mail
// ----------------------------------------------------------------------
String subject;
try
{
subject = generateSubject( projectScmRoot );
}
catch ( Exception e )
{
throw new NotificationException( "Error while generating mail subject.", e );
}
sendMessage( projectScmRoot, notifiers, subject, content, messageContext );
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
private List<String> getJavaHomeInformations( BuildDefinition buildDefinition )
throws InstallationException
{
if ( buildDefinition == null )
{
return continuum.getInstallationService().getDefaultJavaVersionInfo();
}
Profile profile = buildDefinition.getProfile();
if ( profile == null )
{
return continuum.getInstallationService().getDefaultJavaVersionInfo();
}
return continuum.getInstallationService().getJavaVersionInfo( profile.getJdk() );
}
private List<String> getBuilderVersion( BuildDefinition buildDefinition, Project project )
throws InstallationException
{
ExecutorConfigurator executorConfigurator;
Installation builder = null;
Profile profile = null;
if ( buildDefinition != null )
{
profile = buildDefinition.getProfile();
if ( profile != null )
{
builder = profile.getBuilder();
}
}
if ( builder != null )
{
executorConfigurator = continuum.getInstallationService().getExecutorConfigurator( builder.getType() );
}
else
{
// depends on ExecutorId
if ( MavenTwoBuildExecutor.ID.equals( project.getExecutorId() ) )
{
executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
InstallationService.MAVEN2_TYPE );
}
else if ( MavenOneBuildExecutor.ID.equals( project.getExecutorId() ) )
{
executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
InstallationService.MAVEN1_TYPE );
}
else if ( AntBuildExecutor.ID.equals( project.getExecutorId() ) )
{
executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
InstallationService.ANT_TYPE );
}
else
{
return Arrays.asList( "No builder defined" );
}
}
return continuum.getInstallationService().getExecutorVersionInfo(
builder == null ? null : builder.getVarValue(), executorConfigurator, profile );
}
private String generateSubject( Project project, BuildResult build )
throws Exception
{
String state = getState( project, build );
VelocityContext context = new VelocityContext();
context.put( "project", project );
context.put( "build", build );
context.put( "state", state );
StringWriter writer = new StringWriter();
boolean velocityRes = velocity.getEngine().evaluate( context, writer, "subjectPattern", buildSubjectFormat );
return writer.toString();
}
private String generateSubject( ProjectScmRoot projectScmRoot )
throws Exception
{
String state = getState( projectScmRoot );
VelocityContext context = new VelocityContext();
context.put( "projectScmRoot", projectScmRoot );
context.put( "state", state );
StringWriter writer = new StringWriter();
boolean velocityResults = velocity.getEngine().evaluate( context, writer, "subjectPattern",
prepareBuildSubjectFormat );
return writer.toString();
}
private String getState( Project project, BuildResult build )
{
int state = project.getState();
if ( build != null )
{
state = build.getState();
}
if ( state == ContinuumProjectState.OK )
{
return "SUCCESSFUL";
}
else if ( state == ContinuumProjectState.FAILED )
{
return "FAILURE";
}
else if ( state == ContinuumProjectState.ERROR )
{
return "ERROR";
}
else
{
log.warn( "Unknown build state " + state + " for project " + project.getId() );
return "ERROR: Unknown build state " + state;
}
}
private String getState( ProjectScmRoot projectScmRoot )
{
int state = projectScmRoot.getState();
if ( state == ContinuumProjectState.UPDATED )
{
return "SUCCESSFUL";
}
else if ( state == ContinuumProjectState.ERROR )
{
return "ERROR";
}
else
{
log.warn(
"Unknown prepare build state " + state + " for SCM Root URL " + projectScmRoot.getScmRootAddress() +
" in projectGroup " + projectScmRoot.getProjectGroup().getId() );
return "ERROR: Unknown build state " + state;
}
}
private void sendMessage( Project project, List<ProjectNotifier> notifiers, String subject, String content,
MessageContext context )
throws NotificationException
{
if ( notifiers.size() == 0 )
{
// This is a useful message for the users when debugging why they don't
// receive any mails
log.info( "No mail notifier for '" + project.getName() + "'." );
return;
}
String fromMailbox = getFromMailbox( notifiers );
if ( fromMailbox == null )
{
log.warn( project.getName() +
": Project is missing nag email and global from mailbox is missing, not sending mail." );
return;
}
try
{
MimeMessage message = javaMailSender.createMimeMessage();
message.addHeader( "X-Continuum-Build-Host", buildHost );
message.addHeader( "X-Continuum-Project-Id", Integer.toString( project.getId() ) );
message.addHeader( "X-Continuum-Project-Name", project.getName() );
message.setSubject( subject );
log.info( "Message Subject: '" + subject + "'." );
message.setText( content );
InternetAddress from = new InternetAddress( fromMailbox, fromName );
message.setFrom( from );
log.info( "Sending message: From '" + from + "'." );
if ( StringUtils.isEmpty( toOverride ) )
{
Set<String> listRecipents = new HashSet<String>();
for ( ProjectNotifier notifier : notifiers )
{
Map<String, String> conf = notifier.getConfiguration();
if ( conf != null )
{
String addressField = conf.get( ADDRESS_FIELD );
if ( StringUtils.isNotEmpty( addressField ) )
{
String[] addresses = StringUtils.split( addressField, "," );
for ( String address : addresses )
{
if ( !listRecipents.contains( address.trim() ) )
{
// [CONTINUUM-2281] Dont repeat addesss in recipents.
// TODO: set a proper name
InternetAddress to = new InternetAddress( address.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
listRecipents.add( address.trim() );
}
}
}
if ( context.getBuildResult() != null )
{
String committerField = (String) notifier.getConfiguration().get( COMMITTER_FIELD );
String developerField = (String) notifier.getConfiguration().get( DEVELOPER_FIELD );
// Developers constains committers.
if ( StringUtils.isNotEmpty( developerField ) && Boolean.parseBoolean( developerField ) )
{
List<ProjectDeveloper> developers = project.getDevelopers();
if ( developers == null || developers.isEmpty() )
{
log.warn(
"No developers have been configured...notifcation email will not be sent" );
return;
}
Map<String, String> developerToEmailMap = mapDevelopersToRecipients( developers );
for ( String email : developerToEmailMap.values() )
{
if ( !listRecipents.contains( email.trim() ) )
{
InternetAddress to = new InternetAddress( email.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
listRecipents.add( email.trim() );
}
}
}
else if ( StringUtils.isNotEmpty( committerField ) && Boolean.parseBoolean(
committerField ) )
{
ScmResult scmResult = context.getBuildResult().getScmResult();
if ( scmResult != null && scmResult.getChanges() != null &&
!scmResult.getChanges().isEmpty() )
{
List<ProjectDeveloper> developers = project.getDevelopers();
if ( developers == null || developers.isEmpty() )
{
log.warn( "No developers have been configured...notifcation email " +
"will not be sent" );
return;
}
Map<String, String> developerToEmailMap = mapDevelopersToRecipients( developers );
List<ChangeSet> changes = scmResult.getChanges();
for ( ChangeSet changeSet : changes )
{
String scmId = changeSet.getAuthor();
if ( StringUtils.isNotEmpty( scmId ) )
{
String email = developerToEmailMap.get( scmId );
if ( StringUtils.isEmpty( email ) )
{
//TODO: Add a default domain so mail address won't be required
log.warn(
"no email address is defined in developers list for '" + scmId +
"' scm id." );
}
else if ( !listRecipents.contains( email.trim() ) )
{
// [CONTINUUM-2281] Dont repeat addesss in recipents.)
// TODO: set a proper name
InternetAddress to = new InternetAddress( email.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
listRecipents.add( email.trim() );
}
}
}
}
}
}
}
}
}
else
{
// TODO: use configuration file instead of to load it fron component configuration
// TODO: set a proper name
InternetAddress to = new InternetAddress( toOverride.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
}
message.setSentDate( new Date() );
if ( message.getAllRecipients() != null && ( message.getAllRecipients() ).length > 0 )
{
javaMailSender.send( message );
}
}
catch ( AddressException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
catch ( MessagingException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
catch ( UnsupportedEncodingException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
}
private void sendMessage( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, String subject,
String content, MessageContext context )
throws NotificationException
{
ProjectGroup projectGroup = projectScmRoot.getProjectGroup();
if ( notifiers.size() == 0 )
{
// This is a useful message for the users when debugging why they don't
// receive any mails
log.info( "No mail notifier for '" + projectGroup.getName() + "'." );
return;
}
String fromMailbox = getFromMailbox( notifiers );
if ( fromMailbox == null )
{
log.warn( projectGroup.getName() +
": ProjectGroup is missing nag email and global from mailbox is missing, not sending mail." );
return;
}
MimeMessage message = javaMailSender.createMimeMessage();
try
{
message.setSubject( subject );
log.info( "Message Subject: '" + subject + "'." );
message.setText( content );
InternetAddress from = new InternetAddress( fromMailbox, fromName );
message.setFrom( from );
log.info( "Sending message: From '" + from + "'." );
if ( StringUtils.isEmpty( toOverride ) )
{
for ( ProjectNotifier notifier : notifiers )
{
if ( !shouldNotify( projectScmRoot, notifier ) )
{
continue;
}
Map<String, String> conf = notifier.getConfiguration();
if ( conf != null )
{
String addressField = conf.get( ADDRESS_FIELD );
if ( StringUtils.isNotEmpty( addressField ) )
{
String[] addresses = StringUtils.split( addressField, "," );
for ( String address : addresses )
{
// TODO: set a proper name
InternetAddress to = new InternetAddress( address.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
}
}
}
}
}
else
{
// TODO: use configuration file instead of to load it fron component configuration
// TODO: set a proper name
InternetAddress to = new InternetAddress( toOverride.trim() );
log.info( "Recipient: To '" + to + "'." );
message.addRecipient( Message.RecipientType.TO, to );
}
message.setSentDate( new Date() );
if ( message.getAllRecipients() != null && ( message.getAllRecipients() ).length > 0 )
{
javaMailSender.send( message );
}
}
catch ( AddressException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
catch ( MessagingException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
catch ( UnsupportedEncodingException ex )
{
throw new NotificationException( "Exception while sending message.", ex );
}
}
private Map<String, String> mapDevelopersToRecipients( List<ProjectDeveloper> developers )
{
Map<String, String> developersMap = new HashMap<String, String>();
for ( ProjectDeveloper developer : developers )
{
if ( StringUtils.isNotEmpty( developer.getScmId() ) && StringUtils.isNotEmpty( developer.getEmail() ) )
{
developersMap.put( developer.getScmId(), developer.getEmail() );
}
}
return developersMap;
}
private String getFromMailbox( List<ProjectNotifier> notifiers )
{
if ( fromMailbox != null )
{
return fromMailbox;
}
String address = null;
for ( ProjectNotifier notifier : notifiers )
{
Map<String, String> configuration = notifier.getConfiguration();
if ( configuration != null && StringUtils.isNotEmpty( configuration.get( ADDRESS_FIELD ) ) )
{
address = configuration.get( ADDRESS_FIELD );
break;
}
}
if ( StringUtils.isEmpty( address ) )
{
return FALLBACK_FROM_MAILBOX;
}
// olamy : CONTINUUM-860 if address contains commas we use only the first one
if ( address != null && address.contains( "," ) )
{
String[] addresses = StringUtils.split( address, "," );
return addresses[0];
}
return address;
}
public String getBuildHost()
{
return buildHost;
}
public void setBuildHost( String buildHost )
{
this.buildHost = buildHost;
}
public String getToOverride()
{
return toOverride;
}
public void setToOverride( String toOverride )
{
this.toOverride = toOverride;
}
}