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