1 package org.apache.maven.plugin.announcement;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.io.UnsupportedEncodingException;
28 import java.util.List;
29
30 import javax.mail.internet.AddressException;
31 import javax.mail.internet.InternetAddress;
32
33 import org.apache.maven.model.Developer;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.announcement.mailsender.ProjectJavamailMailSender;
36 import org.apache.maven.plugins.annotations.Component;
37 import org.apache.maven.plugins.annotations.Execute;
38 import org.apache.maven.plugins.annotations.Mojo;
39 import org.apache.maven.plugins.annotations.Parameter;
40 import org.apache.maven.project.MavenProject;
41 import org.codehaus.plexus.logging.Logger;
42 import org.codehaus.plexus.logging.console.ConsoleLogger;
43 import org.codehaus.plexus.mailsender.MailMessage;
44 import org.codehaus.plexus.mailsender.MailSenderException;
45 import org.codehaus.plexus.util.IOUtil;
46 import org.codehaus.plexus.util.ReaderFactory;
47 import org.codehaus.plexus.util.StringUtils;
48
49
50
51
52
53
54
55
56 @Mojo( name = "announcement-mail", threadSafe = true )
57 @Execute( goal = "announcement-generate" )
58 public class AnnouncementMailMojo
59 extends AbstractAnnouncementMojo
60 {
61
62
63
64
65
66
67
68 @Parameter( property = "project.developers", required = true, readonly = true )
69 private List from;
70
71
72
73
74
75
76
77 @Parameter( property = "changes.fromDeveloperId" )
78 private String fromDeveloperId;
79
80
81
82
83
84
85 @Parameter( defaultValue = "text/plain", required = true )
86 private String mailContentType;
87
88
89
90
91
92
93
94
95 @Parameter( property = "changes.mailSender" )
96 private MailSender mailSender;
97
98
99
100
101
102
103
104
105
106
107 @Parameter( property = "changes.sender" )
108 private String senderString;
109
110
111
112
113 @Parameter( property = "changes.password" )
114 private String password;
115
116
117
118 @Component
119 private MavenProject project;
120
121
122
123
124 @Parameter( property = "changes.smtpHost", required = true )
125 private String smtpHost;
126
127
128
129
130 @Parameter( property = "changes.smtpPort", defaultValue = "25", required = true )
131 private int smtpPort;
132
133
134
135
136 @Parameter( property = "changes.sslMode", defaultValue = "false" )
137 private boolean sslMode;
138
139
140
141
142
143
144 @Parameter( property = "changes.startTls", defaultValue = "false" )
145 private boolean startTls;
146
147
148
149
150 @Parameter( property = "changes.subject",
151 defaultValue = "[ANNOUNCEMENT] - ${project.name} ${project.version} released", required = true )
152 private String subject;
153
154
155
156
157
158
159 @Parameter( property = "changes.announcementFile", defaultValue = "announcement.vm", required = true )
160 private String announcementFile;
161
162
163
164
165
166
167 @Parameter( defaultValue = "${project.build.directory}/announcement", required = true )
168 private File announcementDirectory;
169
170
171
172
173
174
175 @Parameter( property = "changes.templateEncoding", defaultValue = "${project.build.sourceEncoding}" )
176 private String templateEncoding;
177
178
179
180
181
182
183 @Parameter
184 private File templateOutputDirectory;
185
186
187
188
189 @Parameter( required = true )
190 private List toAddresses;
191
192
193
194
195
196
197 @Parameter
198 private List ccAddresses;
199
200
201
202
203
204
205 @Parameter
206 private List bccAddresses;
207
208
209
210
211 @Parameter( property = "changes.username" )
212 private String username;
213
214 private ProjectJavamailMailSender mailer = new ProjectJavamailMailSender();
215
216 public void execute()
217 throws MojoExecutionException
218 {
219
220 if ( templateOutputDirectory != null )
221 {
222 throw new MojoExecutionException( "You are using the old parameter 'templateOutputDirectory'. You must use 'announcementDirectory' instead." );
223 }
224
225
226 if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() )
227 {
228 getLog().info( "Skipping the announcement mail in this project because it's not the Execution Root" );
229 }
230 else
231 {
232 File file = new File( announcementDirectory, announcementFile );
233
234 ConsoleLogger logger = new ConsoleLogger( Logger.LEVEL_INFO, "base" );
235
236 if ( getLog().isDebugEnabled() )
237 {
238 logger.setThreshold( Logger.LEVEL_DEBUG );
239 }
240
241 mailer.enableLogging( logger );
242
243 mailer.setSmtpHost( getSmtpHost() );
244
245 mailer.setSmtpPort( getSmtpPort() );
246
247 mailer.setSslMode( sslMode, startTls );
248
249 if ( username != null )
250 {
251 mailer.setUsername( username );
252 }
253
254 if ( password != null )
255 {
256 mailer.setPassword( password );
257 }
258
259 mailer.initialize();
260
261 if ( getLog().isDebugEnabled() )
262 {
263 getLog().debug( "fromDeveloperId: " + getFromDeveloperId() );
264 }
265
266 if ( file.isFile() )
267 {
268 getLog().info( "Connecting to Host: " + getSmtpHost() + ":" + getSmtpPort() );
269
270 sendMessage();
271 }
272 else
273 {
274 throw new MojoExecutionException( "Announcement file " + file + " not found..." );
275 }
276 }
277 }
278
279
280
281
282
283
284 protected void sendMessage()
285 throws MojoExecutionException
286 {
287 File file = new File( announcementDirectory, announcementFile );
288 String email = "";
289 final MailSender ms = getActualMailSender();
290 final String fromName = ms.getName();
291 final String fromAddress = ms.getEmail();
292 if ( fromAddress == null || fromAddress.equals( "" ) )
293 {
294 throw new MojoExecutionException( "Invalid mail sender: name and email is mandatory (" + ms + ")." );
295 }
296 getLog().info( "Using this sender for email announcement: " + fromAddress + " < " + fromName + " > " );
297 try
298 {
299 MailMessage mailMsg = new MailMessage();
300 mailMsg.setSubject( getSubject() );
301 mailMsg.setContent( readAnnouncement( file ) );
302 mailMsg.setContentType( this.mailContentType );
303 mailMsg.setFrom( fromAddress, fromName );
304
305 for ( Object o1 : getToAddresses() )
306 {
307 email = o1.toString();
308 getLog().info( "Sending mail to " + email + "..." );
309 mailMsg.addTo( email, "" );
310 }
311
312 if ( getCcAddresses() != null )
313 {
314 for ( Object o : getCcAddresses() )
315 {
316 email = o.toString();
317 getLog().info( "Sending cc mail to " + email + "..." );
318 mailMsg.addCc( email, "" );
319 }
320 }
321
322 if ( getBccAddresses() != null )
323 {
324 for ( Object o : getBccAddresses() )
325 {
326 email = o.toString();
327 getLog().info( "Sending bcc mail to " + email + "..." );
328 mailMsg.addBcc( email, "" );
329 }
330 }
331
332 mailer.send( mailMsg );
333 getLog().info( "Sent..." );
334 }
335 catch ( MailSenderException e )
336 {
337 throw new MojoExecutionException( "Failed to send email < " + email + " >", e );
338 }
339 }
340
341
342
343
344
345
346
347
348 protected String readAnnouncement( File file )
349 throws MojoExecutionException
350 {
351 InputStreamReader reader = null;
352 FileInputStream inputStream = null;
353 try
354 {
355 inputStream = new FileInputStream( file );
356
357 if ( StringUtils.isEmpty( templateEncoding ) )
358 {
359 templateEncoding = ReaderFactory.FILE_ENCODING;
360 getLog().warn( "File encoding has not been set, using platform encoding '" + templateEncoding
361 + "', i.e. build is platform dependent!" );
362 }
363
364 reader = new InputStreamReader( inputStream, templateEncoding );
365 return IOUtil.toString( reader );
366 }
367 catch ( FileNotFoundException fnfe )
368 {
369 throw new MojoExecutionException( "File not found. " + file );
370 }
371 catch ( UnsupportedEncodingException uee )
372 {
373 throw new MojoExecutionException( "Unsupported encoding: '" + templateEncoding + "'" );
374 }
375 catch ( IOException ioe )
376 {
377 throw new MojoExecutionException( "Failed to read the announcement file.", ioe );
378 }
379 finally
380 {
381 IOUtil.close( inputStream );
382 IOUtil.close( reader );
383 }
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398 protected MailSender getActualMailSender()
399 throws MojoExecutionException
400 {
401 if ( senderString != null )
402 {
403 try
404 {
405 InternetAddress ia = new InternetAddress( senderString, true );
406 return new MailSender( ia.getPersonal(), ia.getAddress() );
407 }
408 catch ( AddressException e )
409 {
410 throw new MojoExecutionException( "Invalid value for change.sender: ", e );
411 }
412 }
413 if ( mailSender != null && mailSender.getEmail() != null )
414 {
415 return mailSender;
416 }
417 else if ( from == null || from.isEmpty() )
418 {
419 throw new MojoExecutionException(
420 "The <developers> section in your pom should not be empty. Add a <developer> entry or set the "
421 + "mailSender parameter." );
422 }
423 else if ( fromDeveloperId == null )
424 {
425 final Developer dev = (Developer) from.get( 0 );
426 return new MailSender( dev.getName(), dev.getEmail() );
427 }
428 else
429 {
430 for ( Object aFrom : from )
431 {
432 Developer developer = (Developer) aFrom;
433
434 if ( fromDeveloperId.equals( developer.getId() ) )
435 {
436 return new MailSender( developer.getName(), developer.getEmail() );
437 }
438 }
439 throw new MojoExecutionException(
440 "Missing developer with id '" + fromDeveloperId + "' in the <developers> section in your pom." );
441 }
442 }
443
444
445
446
447
448 public List getBccAddresses()
449 {
450 return bccAddresses;
451 }
452
453 public void setBccAddresses( List bccAddresses )
454 {
455 this.bccAddresses = bccAddresses;
456 }
457
458 public List getCcAddresses()
459 {
460 return ccAddresses;
461 }
462
463 public void setCcAddresses( List ccAddresses )
464 {
465 this.ccAddresses = ccAddresses;
466 }
467
468 public List getFrom()
469 {
470 return from;
471 }
472
473 public void setFrom( List from )
474 {
475 this.from = from;
476 }
477
478 public String getFromDeveloperId()
479 {
480 return fromDeveloperId;
481 }
482
483 public void setFromDeveloperId( String fromDeveloperId )
484 {
485 this.fromDeveloperId = fromDeveloperId;
486 }
487
488 public MailSender getMailSender()
489 {
490 return mailSender;
491 }
492
493 public void setMailSender( MailSender mailSender )
494 {
495 this.mailSender = mailSender;
496 }
497
498 public String getPassword()
499 {
500 return password;
501 }
502
503 public void setPassword( String password )
504 {
505 this.password = password;
506 }
507
508 public MavenProject getProject()
509 {
510 return project;
511 }
512
513 public void setProject( MavenProject project )
514 {
515 this.project = project;
516 }
517
518 public String getSmtpHost()
519 {
520 return smtpHost;
521 }
522
523 public void setSmtpHost( String smtpHost )
524 {
525 this.smtpHost = smtpHost;
526 }
527
528 public int getSmtpPort()
529 {
530 return smtpPort;
531 }
532
533 public void setSmtpPort( int smtpPort )
534 {
535 this.smtpPort = smtpPort;
536 }
537
538 public boolean isSslMode()
539 {
540 return sslMode;
541 }
542
543 public void setSslMode( boolean sslMode )
544 {
545 this.sslMode = sslMode;
546 }
547
548 public boolean isStartTls()
549 {
550 return startTls;
551 }
552
553 public void setStartTls( boolean startTls )
554 {
555 this.startTls = startTls;
556 }
557
558 public String getSubject()
559 {
560 return subject;
561 }
562
563 public void setSubject( String subject )
564 {
565 this.subject = subject;
566 }
567
568 public String getAnnouncementFile()
569 {
570 return announcementFile;
571 }
572
573 public void setAnnouncementFile( String announcementFile )
574 {
575 this.announcementFile = announcementFile;
576 }
577
578 public File getAnnouncementDirectory()
579 {
580 return announcementDirectory;
581 }
582
583 public void setAnnouncementDirectory( File announcementDirectory )
584 {
585 this.announcementDirectory = announcementDirectory;
586 }
587
588 public List getToAddresses()
589 {
590 return toAddresses;
591 }
592
593 public void setToAddresses( List toAddresses )
594 {
595 this.toAddresses = toAddresses;
596 }
597
598 public String getUsername()
599 {
600 return username;
601 }
602
603 public void setUsername( String username )
604 {
605 this.username = username;
606 }
607 }