| package org.apache.maven.plugin.announcement; |
| |
| /* |
| * 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 java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.util.List; |
| |
| import javax.mail.internet.AddressException; |
| import javax.mail.internet.InternetAddress; |
| |
| import org.apache.maven.model.Developer; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.announcement.mailsender.ProjectJavamailMailSender; |
| import org.apache.maven.plugins.annotations.Component; |
| import org.apache.maven.plugins.annotations.Execute; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.project.MavenProject; |
| import org.codehaus.plexus.logging.Logger; |
| import org.codehaus.plexus.logging.console.ConsoleLogger; |
| import org.codehaus.plexus.mailsender.MailMessage; |
| import org.codehaus.plexus.mailsender.MailSenderException; |
| import org.codehaus.plexus.util.IOUtil; |
| |
| /** |
| * Goal which sends an announcement through email. |
| * |
| * @author aramirez@exist.com |
| * @version $Id$ |
| * @since 2.0-beta-2 |
| */ |
| @Mojo( name = "announcement-mail", threadSafe = true ) |
| @Execute( goal = "announcement-generate" ) |
| public class AnnouncementMailMojo |
| extends AbstractAnnouncementMojo |
| { |
| //========================================= |
| // announcement-mail goal fields |
| //========================================= |
| |
| /** |
| * Possible senders. |
| */ |
| @Parameter( property = "project.developers", required = true, readonly = true ) |
| private List from; |
| |
| /** |
| * The id of the developer sending the announcement mail. Only used if the <tt>mailSender</tt> |
| * attribute is not set. In this case, this should match the id of one of the developers in |
| * the pom. If a matching developer is not found, then the first developer in the pom will be |
| * used. |
| */ |
| @Parameter( property = "changes.fromDeveloperId" ) |
| private String fromDeveloperId; |
| |
| /** |
| * Mail content type to use. |
| * |
| * @since 2.1 |
| */ |
| @Parameter( defaultValue = "text/plain", required = true ) |
| private String mailContentType; |
| |
| /** |
| * Defines the sender of the announcement email. This takes precedence over the list |
| * of developers specified in the POM. |
| * if the sender is not a member of the development team. Note that since this is a bean type, |
| * you cannot specify it from command level with <pre>-D</pre>. Use |
| * <pre>-Dchanges.sender='Your Name <you@domain>'</pre> instead. |
| */ |
| @Parameter( property = "changes.mailSender" ) |
| private MailSender mailSender; |
| |
| /** |
| * Defines the sender of the announcement. This takes precedence over both ${changes.mailSender} |
| * and the list of developers in the POM. |
| * <p/> |
| * This parameter parses an email address in standard RFC822 format, e.g. |
| * <pre>-Dchanges.sender='Your Name <you@domain>'</pre>. |
| * |
| * @since 2.7 |
| */ |
| @Parameter( property = "changes.sender" ) |
| private String senderString; |
| |
| /** |
| * The password used to send the email. |
| */ |
| @Parameter( property = "changes.password" ) |
| private String password; |
| |
| /** |
| */ |
| @Component |
| private MavenProject project; |
| |
| /** |
| * Smtp Server. |
| */ |
| @Parameter( property = "changes.smtpHost", required = true ) |
| private String smtpHost; |
| |
| /** |
| * Port. |
| */ |
| @Parameter( property = "changes.smtpPort", defaultValue = "25", required = true ) |
| private int smtpPort; |
| |
| /** |
| * If the email should be sent in SSL mode. |
| */ |
| @Parameter( property = "changes.sslMode", defaultValue = "false" ) |
| private boolean sslMode; |
| |
| /** |
| * If the option startTls should be used. |
| */ |
| @Parameter( property = "changes.startTls", defaultValue = "false" ) |
| private boolean startTls; |
| |
| /** |
| * Subject for the email. |
| */ |
| @Parameter( property = "changes.subject", |
| defaultValue = "[ANNOUNCEMENT] - ${project.name} ${project.version} released", required = true ) |
| private String subject; |
| |
| /** |
| * The file that contains the generated announcement. |
| * |
| * @since 2.10 |
| */ |
| @Parameter( property = "changes.announcementFile", defaultValue = "announcement.vm", required = true ) |
| private String announcementFile; |
| |
| /** |
| * Directory where the generated announcement file exists. |
| * |
| * @since 2.10 |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/announcement", required = true ) |
| private File announcementDirectory; |
| |
| /** |
| * Directory which contains the template for announcement email. |
| * |
| * @deprecated Starting with version 2.10 this parameter is no longer used. You must use {@link #announcementDirectory} instead. |
| */ |
| @Parameter |
| private File templateOutputDirectory; |
| |
| /** |
| * Recipient email address. |
| */ |
| @Parameter( required = true ) |
| private List toAddresses; |
| |
| /** |
| * Recipient cc email address. |
| * |
| * @since 2.5 |
| */ |
| @Parameter |
| private List ccAddresses; |
| |
| /** |
| * Recipient bcc email address. |
| * |
| * @since 2.5 |
| */ |
| @Parameter |
| private List bccAddresses; |
| |
| /** |
| * The username used to send the email. |
| */ |
| @Parameter( property = "changes.username" ) |
| private String username; |
| |
| private ProjectJavamailMailSender mailer = new ProjectJavamailMailSender(); |
| |
| public void execute() |
| throws MojoExecutionException |
| { |
| // Fail build fast if it is using deprecated parameters |
| if( templateOutputDirectory != null ) |
| { |
| throw new MojoExecutionException( "You are using the old parameter 'templateOutputDirectory'. You must use 'announcementDirectory' instead." ); |
| } |
| |
| // Run only at the execution root |
| if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() ) |
| { |
| getLog().info( "Skipping the announcement mail in this project because it's not the Execution Root" ); |
| } |
| else |
| { |
| File file = new File( announcementDirectory, announcementFile ); |
| |
| ConsoleLogger logger = new ConsoleLogger( Logger.LEVEL_INFO, "base" ); |
| |
| if ( getLog().isDebugEnabled() ) |
| { |
| logger.setThreshold( Logger.LEVEL_DEBUG ); |
| } |
| |
| mailer.enableLogging( logger ); |
| |
| mailer.setSmtpHost( getSmtpHost() ); |
| |
| mailer.setSmtpPort( getSmtpPort() ); |
| |
| mailer.setSslMode( sslMode, startTls ); |
| |
| if ( username != null ) |
| { |
| mailer.setUsername( username ); |
| } |
| |
| if ( password != null ) |
| { |
| mailer.setPassword( password ); |
| } |
| |
| mailer.initialize(); |
| |
| if ( getLog().isDebugEnabled() ) |
| { |
| getLog().debug( "fromDeveloperId: " + getFromDeveloperId() ); |
| } |
| |
| if ( file.isFile() ) |
| { |
| getLog().info( "Connecting to Host: " + getSmtpHost() + ":" + getSmtpPort() ); |
| |
| sendMessage(); |
| } |
| else |
| { |
| throw new MojoExecutionException( "Announcement file " + file + " not found..." ); |
| } |
| } |
| } |
| |
| /** |
| * Send the email. |
| * |
| * @throws MojoExecutionException if the mail could not be sent |
| */ |
| protected void sendMessage() |
| throws MojoExecutionException |
| { |
| File file = new File( announcementDirectory, announcementFile ); |
| String email = ""; |
| final MailSender ms = getActualMailSender(); |
| final String fromName = ms.getName(); |
| final String fromAddress = ms.getEmail(); |
| if ( fromAddress == null || fromAddress.equals( "" ) ) |
| { |
| throw new MojoExecutionException( "Invalid mail sender: name and email is mandatory (" + ms + ")." ); |
| } |
| getLog().info( "Using this sender for email announcement: " + fromAddress + " < " + fromName + " > " ); |
| try |
| { |
| MailMessage mailMsg = new MailMessage(); |
| mailMsg.setSubject( getSubject() ); |
| mailMsg.setContent( IOUtil.toString( readAnnouncement( file ) ) ); |
| mailMsg.setContentType( this.mailContentType ); |
| mailMsg.setFrom( fromAddress, fromName ); |
| |
| for (Object o1 : getToAddresses()) { |
| email = o1.toString(); |
| getLog().info("Sending mail to " + email + "..."); |
| mailMsg.addTo(email, ""); |
| } |
| |
| if ( getCcAddresses() != null ) |
| { |
| for (Object o : getCcAddresses()) { |
| email = o.toString(); |
| getLog().info("Sending cc mail to " + email + "..."); |
| mailMsg.addCc(email, ""); |
| } |
| } |
| |
| if ( getBccAddresses() != null ) |
| { |
| for (Object o : getBccAddresses()) { |
| email = o.toString(); |
| getLog().info("Sending bcc mail to " + email + "..."); |
| mailMsg.addBcc(email, ""); |
| } |
| } |
| |
| mailer.send( mailMsg ); |
| getLog().info( "Sent..." ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new MojoExecutionException( "Failed to send email.", ioe ); |
| } |
| catch ( MailSenderException e ) |
| { |
| throw new MojoExecutionException( "Failed to send email < " + email + " >", e ); |
| } |
| } |
| |
| /** |
| * Read the announcement generated file. |
| * |
| * @param file the file to be read |
| * @return fileReader Return the FileReader |
| * @throws MojoExecutionException if the file could not be found |
| */ |
| protected FileReader readAnnouncement( File file ) |
| throws MojoExecutionException |
| { |
| FileReader fileReader; |
| try |
| { |
| fileReader = new FileReader( file ); |
| } |
| catch ( FileNotFoundException fnfe ) |
| { |
| throw new MojoExecutionException( "File not found. " + file ); |
| } |
| return fileReader; |
| } |
| |
| /** |
| * Returns the identify of the mail sender according to the plugin's configuration: |
| * <ul> |
| * <li>if the <tt>mailSender</tt> parameter is set, it is returned</li> |
| * <li>if no <tt>fromDeveloperId</tt> is set, the first developer in the list is returned</li> |
| * <li>if a <tt>fromDeveloperId</tt> is set, the developer with that id is returned</li> |
| * <li>if the developers list is empty or if the specified id does not exist, an exception is thrown</li> |
| * </ul> |
| * |
| * @return the mail sender to use |
| * @throws MojoExecutionException if the mail sender could not be retrieved |
| */ |
| protected MailSender getActualMailSender() |
| throws MojoExecutionException |
| { |
| if ( senderString != null ) |
| { |
| try |
| { |
| InternetAddress ia = new InternetAddress( senderString, true ); |
| return new MailSender( ia.getPersonal(), ia.getAddress() ); |
| } |
| catch ( AddressException e ) |
| { |
| throw new MojoExecutionException( "Invalid value for change.sender: ", e ); |
| } |
| } |
| if ( mailSender != null && mailSender.getEmail() != null ) |
| { |
| return mailSender; |
| } |
| else if ( from == null || from.isEmpty() ) |
| { |
| throw new MojoExecutionException( |
| "The <developers> section in your pom should not be empty. Add a <developer> entry or set the " |
| + "mailSender parameter." ); |
| } |
| else if ( fromDeveloperId == null ) |
| { |
| final Developer dev = (Developer) from.get( 0 ); |
| return new MailSender( dev.getName(), dev.getEmail() ); |
| } |
| else |
| { |
| for (Object aFrom : from) { |
| Developer developer = (Developer) aFrom; |
| |
| if (fromDeveloperId.equals(developer.getId())) { |
| return new MailSender(developer.getName(), developer.getEmail()); |
| } |
| } |
| throw new MojoExecutionException( |
| "Missing developer with id '" + fromDeveloperId + "' in the <developers> section in your pom." ); |
| } |
| } |
| |
| //================================ |
| // announcement-mail accessors |
| //================================ |
| |
| public List getBccAddresses() |
| { |
| return bccAddresses; |
| } |
| |
| public void setBccAddresses( List bccAddresses ) |
| { |
| this.bccAddresses = bccAddresses; |
| } |
| |
| public List getCcAddresses() |
| { |
| return ccAddresses; |
| } |
| |
| public void setCcAddresses( List ccAddresses ) |
| { |
| this.ccAddresses = ccAddresses; |
| } |
| |
| public List getFrom() |
| { |
| return from; |
| } |
| |
| public void setFrom( List from ) |
| { |
| this.from = from; |
| } |
| |
| public String getFromDeveloperId() |
| { |
| return fromDeveloperId; |
| } |
| |
| public void setFromDeveloperId( String fromDeveloperId ) |
| { |
| this.fromDeveloperId = fromDeveloperId; |
| } |
| |
| public MailSender getMailSender() |
| { |
| return mailSender; |
| } |
| |
| public void setMailSender( MailSender mailSender ) |
| { |
| this.mailSender = mailSender; |
| } |
| |
| public String getPassword() |
| { |
| return password; |
| } |
| |
| public void setPassword( String password ) |
| { |
| this.password = password; |
| } |
| |
| public MavenProject getProject() |
| { |
| return project; |
| } |
| |
| public void setProject( MavenProject project ) |
| { |
| this.project = project; |
| } |
| |
| public String getSmtpHost() |
| { |
| return smtpHost; |
| } |
| |
| public void setSmtpHost( String smtpHost ) |
| { |
| this.smtpHost = smtpHost; |
| } |
| |
| public int getSmtpPort() |
| { |
| return smtpPort; |
| } |
| |
| public void setSmtpPort( int smtpPort ) |
| { |
| this.smtpPort = smtpPort; |
| } |
| |
| public boolean isSslMode() |
| { |
| return sslMode; |
| } |
| |
| public void setSslMode( boolean sslMode ) |
| { |
| this.sslMode = sslMode; |
| } |
| |
| public boolean isStartTls() |
| { |
| return startTls; |
| } |
| |
| public void setStartTls( boolean startTls ) |
| { |
| this.startTls = startTls; |
| } |
| |
| public String getSubject() |
| { |
| return subject; |
| } |
| |
| public void setSubject( String subject ) |
| { |
| this.subject = subject; |
| } |
| |
| public String getAnnouncementFile() |
| { |
| return announcementFile; |
| } |
| |
| public void setAnnouncementFile( String announcementFile ) |
| { |
| this.announcementFile = announcementFile; |
| } |
| |
| public File getAnnouncementDirectory() |
| { |
| return announcementDirectory; |
| } |
| |
| public void setAnnouncementDirectory( File announcementDirectory ) |
| { |
| this.announcementDirectory = announcementDirectory; |
| } |
| |
| public List getToAddresses() |
| { |
| return toAddresses; |
| } |
| |
| public void setToAddresses( List toAddresses ) |
| { |
| this.toAddresses = toAddresses; |
| } |
| |
| public String getUsername() |
| { |
| return username; |
| } |
| |
| public void setUsername( String username ) |
| { |
| this.username = username; |
| } |
| } |