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