1 package org.apache.maven.plugins.source;
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.IOException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27
28 import org.apache.maven.archiver.MavenArchiveConfiguration;
29 import org.apache.maven.archiver.MavenArchiver;
30 import org.apache.maven.artifact.DependencyResolutionRequiredException;
31 import org.apache.maven.execution.MavenSession;
32 import org.apache.maven.model.Resource;
33 import org.apache.maven.plugin.AbstractMojo;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.Parameter;
37 import org.apache.maven.project.MavenProject;
38 import org.apache.maven.project.MavenProjectHelper;
39 import org.codehaus.plexus.archiver.Archiver;
40 import org.codehaus.plexus.archiver.ArchiverException;
41 import org.codehaus.plexus.archiver.jar.JarArchiver;
42 import org.codehaus.plexus.archiver.jar.ManifestException;
43 import org.codehaus.plexus.util.FileUtils;
44
45
46
47
48
49
50 public abstract class AbstractSourceJarMojo
51 extends AbstractMojo
52 {
53 private static final String[] DEFAULT_INCLUDES = new String[] { "**/**" };
54
55 private static final String[] DEFAULT_EXCLUDES = new String[] {};
56
57
58
59
60
61
62
63 @Parameter
64 private String[] includes;
65
66
67
68
69
70
71
72 @Parameter
73 private String[] excludes;
74
75
76
77
78
79
80
81 @Parameter( property = "maven.source.useDefaultExcludes", defaultValue = "true" )
82 private boolean useDefaultExcludes;
83
84
85
86
87 @Parameter( defaultValue = "${project}", readonly = true, required = true )
88 private MavenProject project;
89
90
91
92
93 @Component( role = Archiver.class, hint = "jar" )
94 private JarArchiver jarArchiver;
95
96
97
98
99
100
101
102
103
104
105 @Parameter
106 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
107
108
109
110
111
112
113
114
115 @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/MANIFEST.MF", readonly = false, required = true )
116
117 private File defaultManifestFile;
118
119
120
121
122
123
124 @Parameter( property = "maven.source.useDefaultManifestFile", defaultValue = "false" )
125 private boolean useDefaultManifestFile;
126
127
128
129
130 @Parameter( property = "maven.source.attach", defaultValue = "true" )
131 private boolean attach;
132
133
134
135
136
137
138
139 @Parameter( property = "maven.source.excludeResources", defaultValue = "false" )
140 protected boolean excludeResources;
141
142
143
144
145
146
147 @Parameter( property = "maven.source.includePom", defaultValue = "false" )
148 protected boolean includePom;
149
150
151
152
153 @Component
154 private MavenProjectHelper projectHelper;
155
156
157
158
159 @Parameter( defaultValue = "${project.build.directory}" )
160 protected File outputDirectory;
161
162
163
164
165
166 @Parameter( defaultValue = "${project.build.finalName}" )
167 protected String finalName;
168
169
170
171
172 @Parameter( defaultValue = "${reactorProjects}", readonly = true )
173 protected List<MavenProject> reactorProjects;
174
175
176
177
178
179
180
181 @Parameter( property = "maven.source.forceCreation", defaultValue = "false" )
182 private boolean forceCreation;
183
184
185
186
187
188
189
190 @Parameter( property = "maven.source.skip", defaultValue = "false" )
191 private boolean skipSource;
192
193
194
195
196 @Parameter( defaultValue = "${session}", readonly = true, required = true )
197 private MavenSession session;
198
199
200
201
202
203
204
205
206 @Parameter( defaultValue = "${project.build.outputTimestamp}" )
207 private String outputTimestamp;
208
209
210
211
212
213
214
215
216 public void execute()
217 throws MojoExecutionException
218 {
219 if ( skipSource )
220 {
221 getLog().info( "Skipping source per configuration." );
222 return;
223 }
224
225 packageSources( project );
226 }
227
228
229
230
231
232
233
234
235 protected abstract String getClassifier();
236
237
238
239
240
241
242 protected abstract List<String> getSources( MavenProject p )
243 throws MojoExecutionException;
244
245
246
247
248
249
250 protected abstract List<Resource> getResources( MavenProject p )
251 throws MojoExecutionException;
252
253
254
255
256
257 protected void packageSources( MavenProject p )
258 throws MojoExecutionException
259 {
260 if ( !"pom".equals( p.getPackaging() ) )
261 {
262 packageSources( Arrays.asList( p ) );
263 }
264 }
265
266
267
268
269
270 protected void packageSources( List<MavenProject> theProjects )
271 throws MojoExecutionException
272 {
273 if ( project.getArtifact().getClassifier() != null )
274 {
275 getLog().warn( "NOT adding sources to artifacts with classifier as Maven only supports one classifier "
276 + "per artifact. Current artifact [" + project.getArtifact().getId() + "] has a ["
277 + project.getArtifact().getClassifier() + "] classifier." );
278
279 return;
280 }
281
282 MavenArchiver archiver = createArchiver();
283
284
285 archiver.configureReproducible( outputTimestamp );
286
287 for ( MavenProject pItem : theProjects )
288 {
289 MavenProject subProject = getProject( pItem );
290
291 if ( "pom".equals( subProject.getPackaging() ) )
292 {
293 continue;
294 }
295
296 archiveProjectContent( subProject, archiver.getArchiver() );
297 }
298
299 if ( archiver.getArchiver().getResources().hasNext() || forceCreation )
300 {
301
302 if ( useDefaultManifestFile && defaultManifestFile.exists() && archive.getManifestFile() == null )
303 {
304 getLog().info( "Adding existing MANIFEST to archive. Found under: " + defaultManifestFile.getPath() );
305 archive.setManifestFile( defaultManifestFile );
306 }
307
308 File outputFile = new File( outputDirectory, finalName + "-" + getClassifier() + getExtension() );
309
310 try
311 {
312 archiver.setOutputFile( outputFile );
313 archive.setForced( forceCreation );
314
315 archiver.createArchive( session, project, archive );
316 }
317 catch ( IOException e )
318 {
319 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
320 }
321 catch ( ArchiverException e )
322 {
323 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
324 }
325 catch ( DependencyResolutionRequiredException e )
326 {
327 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
328 }
329 catch ( ManifestException e )
330 {
331 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
332 }
333
334 if ( attach )
335 {
336 projectHelper.attachArtifact( project, getType(), getClassifier(), outputFile );
337 }
338 else
339 {
340 getLog().info( "NOT adding java-sources to attached artifacts list." );
341 }
342 }
343 else
344 {
345 getLog().info( "No sources in project. Archive not created." );
346 }
347 }
348
349
350
351
352
353
354 protected void archiveProjectContent( MavenProject p, Archiver archiver )
355 throws MojoExecutionException
356 {
357 if ( includePom )
358 {
359 try
360 {
361 archiver.addFile( p.getFile(), p.getFile().getName() );
362 }
363 catch ( ArchiverException e )
364 {
365 throw new MojoExecutionException( "Error adding POM file to target jar file.", e );
366 }
367 }
368
369 for ( String s : getSources( p ) )
370 {
371
372 File sourceDirectory = new File( s );
373
374 if ( sourceDirectory.exists() )
375 {
376 addDirectory( archiver, sourceDirectory, getCombinedIncludes( null ), getCombinedExcludes( null ) );
377 }
378 }
379
380
381 for ( Resource resource : getResources( p ) )
382 {
383
384 File sourceDirectory = new File( resource.getDirectory() );
385
386 if ( !sourceDirectory.exists() )
387 {
388 continue;
389 }
390
391 List<String> resourceIncludes = resource.getIncludes();
392
393 String[] combinedIncludes = getCombinedIncludes( resourceIncludes );
394
395 List<String> resourceExcludes = resource.getExcludes();
396
397 String[] combinedExcludes = getCombinedExcludes( resourceExcludes );
398
399 String targetPath = resource.getTargetPath();
400 if ( targetPath != null )
401 {
402 if ( !targetPath.trim().endsWith( "/" ) )
403 {
404 targetPath += "/";
405 }
406 addDirectory( archiver, sourceDirectory, targetPath, combinedIncludes, combinedExcludes );
407 }
408 else
409 {
410 addDirectory( archiver, sourceDirectory, combinedIncludes, combinedExcludes );
411 }
412 }
413 }
414
415
416
417
418
419 protected MavenArchiver createArchiver()
420 throws MojoExecutionException
421 {
422 MavenArchiver archiver = new MavenArchiver();
423 archiver.setArchiver( jarArchiver );
424 archiver.setCreatedBy( "Maven Source Plugin", "org.apache.maven.plugins", "maven-source-plugin" );
425 archiver.setBuildJdkSpecDefaultEntry( false );
426
427 if ( project.getBuild() != null )
428 {
429 List<Resource> resources = project.getBuild().getResources();
430
431 for ( Resource r : resources )
432 {
433
434 if ( r.getDirectory().endsWith( "maven-shared-archive-resources" ) )
435 {
436 addDirectory( archiver.getArchiver(), new File( r.getDirectory() ), getCombinedIncludes( null ),
437 getCombinedExcludes( null ) );
438 }
439 }
440 }
441
442 return archiver;
443 }
444
445
446
447
448
449
450
451
452 protected void addDirectory( Archiver archiver, File sourceDirectory, String[] pIncludes, String[] pExcludes )
453 throws MojoExecutionException
454 {
455 try
456 {
457
458 archiver.addDirectory( sourceDirectory, pIncludes, pExcludes );
459 }
460 catch ( ArchiverException e )
461 {
462 throw new MojoExecutionException( "Error adding directory to source archive.", e );
463 }
464 }
465
466
467
468
469
470
471
472
473
474 protected void addDirectory( Archiver archiver, File sourceDirectory, String prefix, String[] pIncludes,
475 String[] pExcludes )
476 throws MojoExecutionException
477 {
478 try
479 {
480 archiver.addDirectory( sourceDirectory, prefix, pIncludes, pExcludes );
481 }
482 catch ( ArchiverException e )
483 {
484 throw new MojoExecutionException( "Error adding directory to source archive.", e );
485 }
486 }
487
488
489
490
491 protected String getExtension()
492 {
493 return ".jar";
494 }
495
496
497
498
499
500 protected MavenProject getProject( MavenProject p )
501 {
502 if ( p.getExecutionProject() != null )
503 {
504 return p.getExecutionProject();
505 }
506
507 return p;
508 }
509
510
511
512
513 protected String getType()
514 {
515 return "java-source";
516 }
517
518
519
520
521
522
523
524
525 private String[] getCombinedIncludes( List<String> additionalIncludes )
526 {
527 List<String> combinedIncludes = new ArrayList<String>();
528
529 if ( includes != null && includes.length > 0 )
530 {
531 combinedIncludes.addAll( Arrays.asList( includes ) );
532 }
533
534 if ( additionalIncludes != null && additionalIncludes.size() > 0 )
535 {
536 combinedIncludes.addAll( additionalIncludes );
537 }
538
539
540 if ( combinedIncludes.size() == 0 )
541 {
542 combinedIncludes.addAll( Arrays.asList( DEFAULT_INCLUDES ) );
543 }
544
545 return combinedIncludes.toArray( new String[combinedIncludes.size()] );
546 }
547
548
549
550
551
552
553
554
555
556 private String[] getCombinedExcludes( List<String> additionalExcludes )
557 {
558 List<String> combinedExcludes = new ArrayList<String>();
559
560 if ( useDefaultExcludes )
561 {
562 combinedExcludes.addAll( FileUtils.getDefaultExcludesAsList() );
563 }
564
565 if ( excludes != null && excludes.length > 0 )
566 {
567 combinedExcludes.addAll( Arrays.asList( excludes ) );
568 }
569
570 if ( additionalExcludes != null && additionalExcludes.size() > 0 )
571 {
572 combinedExcludes.addAll( additionalExcludes );
573 }
574
575 if ( combinedExcludes.size() == 0 )
576 {
577 combinedExcludes.addAll( Arrays.asList( DEFAULT_EXCLUDES ) );
578 }
579
580 return combinedExcludes.toArray( new String[combinedExcludes.size()] );
581 }
582
583
584
585
586 protected MavenProject getProject()
587 {
588 return project;
589 }
590
591
592
593
594 protected void setProject( MavenProject project )
595 {
596 this.project = project;
597 }
598 }