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