View Javadoc

1   package org.apache.maven.plugin.announcement;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileNotFoundException;
24  import java.io.FileReader;
25  import java.io.IOException;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import javax.mail.internet.AddressException;
30  import javax.mail.internet.InternetAddress;
31  
32  import org.apache.maven.model.Developer;
33  import org.apache.maven.plugin.MojoExecutionException;
34  import org.apache.maven.plugin.announcement.mailsender.ProjectJavamailMailSender;
35  import org.apache.maven.plugins.annotations.Component;
36  import org.apache.maven.plugins.annotations.Execute;
37  import org.apache.maven.plugins.annotations.Mojo;
38  import org.apache.maven.plugins.annotations.Parameter;
39  import org.apache.maven.project.MavenProject;
40  import org.codehaus.plexus.logging.Logger;
41  import org.codehaus.plexus.logging.console.ConsoleLogger;
42  import org.codehaus.plexus.mailsender.MailMessage;
43  import org.codehaus.plexus.mailsender.MailSenderException;
44  import org.codehaus.plexus.util.IOUtil;
45  
46  /**
47   * Goal which sends an announcement through email.
48   *
49   * @author aramirez@exist.com
50   * @version $Id: AnnouncementMailMojo.java 1355880 2012-07-01 13:13:15Z olamy $
51   * @since 2.0-beta-2
52   */
53  @Mojo( name = "announcement-mail", threadSafe = true )
54  @Execute( goal = "announcement-generate" )
55  public class AnnouncementMailMojo
56      extends AbstractAnnouncementMojo
57  {
58      //=========================================
59      // announcement-mail goal fields
60      //=========================================
61  
62      /**
63       * Possible senders.
64       */
65      @Parameter( property = "project.developers", required = true, readonly = true )
66      private List from;
67  
68      /**
69       * The id of the developer sending the announcement mail. Only used if the <tt>mailSender</tt>
70       * attribute is not set. In this case, this should match the id of one of the developers in
71       * the pom. If a matching developer is not found, then the first developer in the pom will be
72       * used.
73       */
74      @Parameter( property = "changes.fromDeveloperId" )
75      private String fromDeveloperId;
76  
77      /**
78       * Mail content type to use.
79       *
80       * @since 2.1
81       */
82      @Parameter( defaultValue = "text/plain", required = true )
83      private String mailContentType;
84  
85      /**
86       * Defines the sender of the announcement email. This takes precedence over the list
87       * of developers specified in the POM.
88       * if the sender is not a member of the development team. Note that since this is a bean type,
89       * you cannot specify it from command level with <pre>-D</pre>. Use
90       * <pre>-Dchanges.sender='Your Name &lt;you@domain>'</pre> instead.
91       */
92      @Parameter( property = "changes.mailSender" )
93      private MailSender mailSender;
94  
95      /**
96       * Defines the sender of the announcement. This takes precedence over both ${changes.mailSender}
97       * and the list of developers in the POM.
98       * <p/>
99       * This parameter parses an email address in standard RFC822 format, e.g.
100      * <pre>-Dchanges.sender='Your Name &lt;you@domain>'</pre>.
101      *
102      * @since 2.7
103      */
104     @Parameter( property = "changes.sender" )
105     private String senderString;
106 
107     /**
108      * The password used to send the email.
109      */
110     @Parameter( property = "changes.password" )
111     private String password;
112 
113     /**
114      */
115     @Component
116     private MavenProject project;
117 
118     /**
119      * Smtp Server.
120      */
121     @Parameter( property = "changes.smtpHost", required = true )
122     private String smtpHost;
123 
124     /**
125      * Port.
126      */
127     @Parameter( property = "changes.smtpPort", defaultValue = "25", required = true )
128     private int smtpPort;
129 
130     /**
131      * If the email should be sent in SSL mode.
132      */
133     @Parameter( property = "changes.sslMode", defaultValue = "false" )
134     private boolean sslMode;
135 
136 
137     /**
138      * Subject for the email.
139      */
140     @Parameter( property = "changes.subject",
141                 defaultValue = "[ANNOUNCEMENT] - ${project.name} ${project.version} released", required = true )
142     private String subject;
143 
144     /**
145      * The Velocity template used to format the announcement.
146      */
147     @Parameter( property = "changes.template", defaultValue = "announcement.vm", required = true )
148     private String template;
149 
150     /**
151      * Directory which contains the template for announcement email.
152      */
153     @Parameter( defaultValue = "${project.build.directory}/announcement", required = true )
154     private File templateOutputDirectory;
155 
156     /**
157      * Recipient email address.
158      */
159     @Parameter( required = true )
160     private List toAddresses;
161 
162     /**
163      * Recipient cc email address.
164      *
165      * @since 2.5
166      */
167     @Parameter
168     private List ccAddresses;
169 
170     /**
171      * Recipient bcc email address.
172      *
173      * @since 2.5
174      */
175     @Parameter
176     private List bccAddresses;
177 
178     /**
179      * The username used to send the email.
180      */
181     @Parameter( property = "changes.username" )
182     private String username;
183 
184     private ProjectJavamailMailSender mailer = new ProjectJavamailMailSender();
185 
186     public void execute()
187         throws MojoExecutionException
188     {
189         // Run only at the execution root
190         if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() )
191         {
192             getLog().info( "Skipping the announcement mail in this project because it's not the Execution Root" );
193         }
194         else
195         {
196             File templateFile = new File( templateOutputDirectory, template );
197 
198             ConsoleLogger logger = new ConsoleLogger( Logger.LEVEL_INFO, "base" );
199 
200             if ( getLog().isDebugEnabled() )
201             {
202                 logger.setThreshold( Logger.LEVEL_DEBUG );
203             }
204 
205             mailer.enableLogging( logger );
206 
207             mailer.setSmtpHost( getSmtpHost() );
208 
209             mailer.setSmtpPort( getSmtpPort() );
210 
211             mailer.setSslMode( sslMode );
212 
213             if ( username != null )
214             {
215                 mailer.setUsername( username );
216             }
217 
218             if ( password != null )
219             {
220                 mailer.setPassword( password );
221             }
222 
223             mailer.initialize();
224 
225             if ( getLog().isDebugEnabled() )
226             {
227                 getLog().debug( "fromDeveloperId: " + getFromDeveloperId() );
228             }
229 
230             if ( templateFile.isFile() )
231             {
232                 getLog().info( "Connecting to Host: " + getSmtpHost() + ":" + getSmtpPort() );
233 
234                 sendMessage();
235             }
236             else
237             {
238                 throw new MojoExecutionException( "Announcement template " + templateFile + " not found..." );
239             }
240         }
241     }
242 
243     /**
244      * Send the email.
245      *
246      * @throws MojoExecutionException if the mail could not be sent
247      */
248     protected void sendMessage()
249         throws MojoExecutionException
250     {
251         File templateFile = new File( templateOutputDirectory, template );
252         String email = "";
253         final MailSender ms = getActualMailSender();
254         final String fromName = ms.getName();
255         final String fromAddress = ms.getEmail();
256         if ( fromAddress == null || fromAddress.equals( "" ) )
257         {
258             throw new MojoExecutionException( "Invalid mail sender: name and email is mandatory (" + ms + ")." );
259         }
260         getLog().info( "Using this sender for email announcement: " + fromAddress + " < " + fromName + " > " );
261         try
262         {
263             MailMessage mailMsg = new MailMessage();
264             mailMsg.setSubject( getSubject() );
265             mailMsg.setContent( IOUtil.toString( readAnnouncement( templateFile ) ) );
266             mailMsg.setContentType( this.mailContentType );
267             mailMsg.setFrom( fromAddress, fromName );
268 
269             final Iterator it = getToAddresses().iterator();
270             while ( it.hasNext() )
271             {
272                 email = it.next().toString();
273                 getLog().info( "Sending mail to " + email + "..." );
274                 mailMsg.addTo( email, "" );
275             }
276 
277             if ( getCcAddresses() != null )
278             {
279                 final Iterator it2 = getCcAddresses().iterator();
280                 while ( it2.hasNext() )
281                 {
282                     email = it2.next().toString();
283                     getLog().info( "Sending cc mail to " + email + "..." );
284                     mailMsg.addCc( email, "" );
285                 }
286             }
287 
288             if ( getBccAddresses() != null )
289             {
290                 final Iterator it3 = getBccAddresses().iterator();
291                 while ( it3.hasNext() )
292                 {
293                     email = it3.next().toString();
294                     getLog().info( "Sending bcc mail to " + email + "..." );
295                     mailMsg.addBcc( email, "" );
296                 }
297             }
298 
299             mailer.send( mailMsg );
300             getLog().info( "Sent..." );
301         }
302         catch ( IOException ioe )
303         {
304             throw new MojoExecutionException( "Failed to send email.", ioe );
305         }
306         catch ( MailSenderException e )
307         {
308             throw new MojoExecutionException( "Failed to send email < " + email + " >", e );
309         }
310     }
311 
312     /**
313      * Read the announcement generated file.
314      *
315      * @param file the file to be read
316      * @return fileReader Return the FileReader
317      * @throws MojoExecutionException if the file could not be found
318      */
319     protected FileReader readAnnouncement( File file )
320         throws MojoExecutionException
321     {
322         FileReader fileReader;
323         try
324         {
325             fileReader = new FileReader( file );
326         }
327         catch ( FileNotFoundException fnfe )
328         {
329             throw new MojoExecutionException( "File not found. " + file );
330         }
331         return fileReader;
332     }
333 
334     /**
335      * Returns the identify of the mail sender according to the plugin's configuration:
336      * <ul>
337      * <li>if the <tt>mailSender</tt> parameter is set, it is returned</li>
338      * <li>if no <tt>fromDeveloperId</tt> is set, the first developer in the list is returned</li>
339      * <li>if a <tt>fromDeveloperId</tt> is set, the developer with that id is returned</li>
340      * <li>if the developers list is empty or if the specified id does not exist, an exception is thrown</li>
341      * </ul>
342      *
343      * @return the mail sender to use
344      * @throws MojoExecutionException if the mail sender could not be retrieved
345      */
346     protected MailSender getActualMailSender()
347         throws MojoExecutionException
348     {
349         if ( senderString != null )
350         {
351             try
352             {
353                 InternetAddress ia = new InternetAddress( senderString, true );
354                 return new MailSender( ia.getPersonal(), ia.getAddress() );
355             }
356             catch ( AddressException e )
357             {
358                 throw new MojoExecutionException( "Invalid value for change.sender: ", e );
359             }
360         }
361         if ( mailSender != null && mailSender.getEmail() != null )
362         {
363             return mailSender;
364         }
365         else if ( from == null || from.isEmpty() )
366         {
367             throw new MojoExecutionException(
368                 "The <developers> section in your pom should not be empty. Add a <developer> entry or set the "
369                     + "mailSender parameter." );
370         }
371         else if ( fromDeveloperId == null )
372         {
373             final Developer dev = (Developer) from.get( 0 );
374             return new MailSender( dev.getName(), dev.getEmail() );
375         }
376         else
377         {
378             final Iterator it = from.iterator();
379             while ( it.hasNext() )
380             {
381                 Developer developer = (Developer) it.next();
382 
383                 if ( fromDeveloperId.equals( developer.getId() ) )
384                 {
385                     return new MailSender( developer.getName(), developer.getEmail() );
386                 }
387             }
388             throw new MojoExecutionException(
389                 "Missing developer with id '" + fromDeveloperId + "' in the <developers> section in your pom." );
390         }
391     }
392 
393     //================================
394     // announcement-mail accessors
395     //================================
396 
397     public List getBccAddresses()
398     {
399         return bccAddresses;
400     }
401 
402     public void setBccAddresses( List bccAddresses )
403     {
404         this.bccAddresses = bccAddresses;
405     }
406 
407     public List getCcAddresses()
408     {
409         return ccAddresses;
410     }
411 
412     public void setCcAddresses( List ccAddresses )
413     {
414         this.ccAddresses = ccAddresses;
415     }
416 
417     public List getFrom()
418     {
419         return from;
420     }
421 
422     public void setFrom( List from )
423     {
424         this.from = from;
425     }
426 
427     public String getFromDeveloperId()
428     {
429         return fromDeveloperId;
430     }
431 
432     public void setFromDeveloperId( String fromDeveloperId )
433     {
434         this.fromDeveloperId = fromDeveloperId;
435     }
436 
437     public MailSender getMailSender()
438     {
439         return mailSender;
440     }
441 
442     public void setMailSender( MailSender mailSender )
443     {
444         this.mailSender = mailSender;
445     }
446 
447     public String getPassword()
448     {
449         return password;
450     }
451 
452     public void setPassword( String password )
453     {
454         this.password = password;
455     }
456 
457     public MavenProject getProject()
458     {
459         return project;
460     }
461 
462     public void setProject( MavenProject project )
463     {
464         this.project = project;
465     }
466 
467     public String getSmtpHost()
468     {
469         return smtpHost;
470     }
471 
472     public void setSmtpHost( String smtpHost )
473     {
474         this.smtpHost = smtpHost;
475     }
476 
477     public int getSmtpPort()
478     {
479         return smtpPort;
480     }
481 
482     public void setSmtpPort( int smtpPort )
483     {
484         this.smtpPort = smtpPort;
485     }
486 
487     public boolean isSslMode()
488     {
489         return sslMode;
490     }
491 
492     public void setSslMode( boolean sslMode )
493     {
494         this.sslMode = sslMode;
495     }
496 
497     public String getSubject()
498     {
499         return subject;
500     }
501 
502     public void setSubject( String subject )
503     {
504         this.subject = subject;
505     }
506 
507     public String getTemplate()
508     {
509         return template;
510     }
511 
512     public void setTemplate( String template )
513     {
514         this.template = template;
515     }
516 
517     public File getTemplateOutputDirectory()
518     {
519         return templateOutputDirectory;
520     }
521 
522     public void setTemplateOutputDirectory( File templateOutputDirectory )
523     {
524         this.templateOutputDirectory = templateOutputDirectory;
525     }
526 
527     public List getToAddresses()
528     {
529         return toAddresses;
530     }
531 
532     public void setToAddresses( List toAddresses )
533     {
534         this.toAddresses = toAddresses;
535     }
536 
537     public String getUsername()
538     {
539         return username;
540     }
541 
542     public void setUsername( String username )
543     {
544         this.username = username;
545     }
546 }