1 package org.apache.maven.plugins.jar;
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.execution.MavenSession;
25 import org.apache.maven.plugin.AbstractMojo;
26 import org.apache.maven.plugin.MojoExecutionException;
27 import org.apache.maven.plugins.annotations.Component;
28 import org.apache.maven.plugins.annotations.Parameter;
29 import org.apache.maven.project.MavenProject;
30 import org.apache.maven.project.MavenProjectHelper;
31 import org.apache.maven.shared.model.fileset.FileSet;
32 import org.apache.maven.shared.model.fileset.util.FileSetManager;
33 import org.codehaus.plexus.archiver.Archiver;
34 import org.codehaus.plexus.archiver.jar.JarArchiver;
35
36 import java.io.File;
37 import java.util.Arrays;
38 import java.util.Map;
39
40
41
42
43
44
45
46 public abstract class AbstractJarMojo
47 extends AbstractMojo
48 {
49
50 private static final String[] DEFAULT_EXCLUDES = new String[] { "**/package.html" };
51
52 private static final String[] DEFAULT_INCLUDES = new String[] { "**/**" };
53
54 private static final String MODULE_DESCRIPTOR_FILE_NAME = "module-info.class";
55
56
57
58
59
60 @Parameter
61 private String[] includes;
62
63
64
65
66
67 @Parameter
68 private String[] excludes;
69
70
71
72
73 @Parameter( defaultValue = "${project.build.directory}", required = true )
74 private File outputDirectory;
75
76
77
78
79 @Parameter( defaultValue = "${project.build.finalName}", readonly = true )
80 private String finalName;
81
82
83
84
85 @Component
86 private Map<String, Archiver> archivers;
87
88
89
90
91 @Parameter( defaultValue = "${project}", readonly = true, required = true )
92 private MavenProject project;
93
94
95
96
97 @Parameter( defaultValue = "${session}", readonly = true, required = true )
98 private MavenSession session;
99
100
101
102
103
104 @Parameter
105 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
106
107
108
109
110
111
112
113
114 @Parameter( property = "jar.useDefaultManifestFile", defaultValue = "false" )
115 private boolean useDefaultManifestFile;
116
117
118
119
120 @Component
121 private MavenProjectHelper projectHelper;
122
123
124
125
126
127
128
129
130
131
132
133
134 @Parameter( property = "maven.jar.forceCreation", defaultValue = "false" )
135 private boolean forceCreation;
136
137
138
139
140 @Parameter( defaultValue = "false" )
141 private boolean skipIfEmpty;
142
143
144
145
146
147
148
149
150
151 @Parameter( defaultValue = "${project.build.outputTimestamp}" )
152 private String outputTimestamp;
153
154
155
156
157
158 protected abstract File getClassesDirectory();
159
160
161
162
163 protected final MavenProject getProject()
164 {
165 return project;
166 }
167
168
169
170
171
172 protected abstract String getClassifier();
173
174
175
176
177
178 protected abstract String getType();
179
180
181
182
183
184
185
186
187
188 protected File getJarFile( File basedir, String resultFinalName, String classifier )
189 {
190 if ( basedir == null )
191 {
192 throw new IllegalArgumentException( "basedir is not allowed to be null" );
193 }
194 if ( resultFinalName == null )
195 {
196 throw new IllegalArgumentException( "finalName is not allowed to be null" );
197 }
198
199 String fileName;
200 if ( hasClassifier() )
201 {
202 fileName = resultFinalName + "-" + classifier + ".jar";
203 }
204 else
205 {
206 fileName = resultFinalName + ".jar";
207 }
208
209 return new File( basedir, fileName );
210 }
211
212
213
214
215
216
217 public File createArchive()
218 throws MojoExecutionException
219 {
220 File jarFile = getJarFile( outputDirectory, finalName, getClassifier() );
221
222 FileSetManager fileSetManager = new FileSetManager();
223 FileSet jarContentFileSet = new FileSet();
224 jarContentFileSet.setDirectory( getClassesDirectory().getAbsolutePath() );
225 jarContentFileSet.setIncludes( Arrays.asList( getIncludes() ) );
226 jarContentFileSet.setExcludes( Arrays.asList( getExcludes() ) );
227
228 boolean containsModuleDescriptor = false;
229 String[] includedFiles = fileSetManager.getIncludedFiles( jarContentFileSet );
230 for ( String includedFile : includedFiles )
231 {
232
233
234
235
236
237
238
239
240 if ( includedFile.endsWith( MODULE_DESCRIPTOR_FILE_NAME ) )
241 {
242 containsModuleDescriptor = true;
243 break;
244 }
245 }
246
247 String archiverName = containsModuleDescriptor ? "mjar" : "jar";
248
249 MavenArchiver archiver = new MavenArchiver();
250 archiver.setCreatedBy( "Maven JAR Plugin", "org.apache.maven.plugins", "maven-jar-plugin" );
251 archiver.setArchiver( (JarArchiver) archivers.get( archiverName ) );
252 archiver.setOutputFile( jarFile );
253
254
255 archiver.configureReproducibleBuild( outputTimestamp );
256
257 archive.setForced( forceCreation );
258
259 try
260 {
261 File contentDirectory = getClassesDirectory();
262 if ( !contentDirectory.exists() )
263 {
264 if ( !forceCreation )
265 {
266 getLog().warn( "JAR will be empty - no content was marked for inclusion!" );
267 }
268 }
269 else
270 {
271 archiver.getArchiver().addDirectory( contentDirectory, getIncludes(), getExcludes() );
272 }
273
274 archiver.createArchive( session, project, archive );
275
276 return jarFile;
277 }
278 catch ( Exception e )
279 {
280
281 throw new MojoExecutionException( "Error assembling JAR", e );
282 }
283 }
284
285
286
287
288
289 public void execute()
290 throws MojoExecutionException
291 {
292 if ( useDefaultManifestFile )
293 {
294 throw new MojoExecutionException( "You are using 'useDefaultManifestFile' which has been removed"
295 + " from the maven-jar-plugin. "
296 + "Please see the >>Major Version Upgrade to version 3.0.0<< on the plugin site." );
297 }
298
299 if ( skipIfEmpty && ( !getClassesDirectory().exists() || getClassesDirectory().list().length < 1 ) )
300 {
301 getLog().info( "Skipping packaging of the " + getType() );
302 }
303 else
304 {
305 File jarFile = createArchive();
306
307 if ( hasClassifier() )
308 {
309 projectHelper.attachArtifact( getProject(), getType(), getClassifier(), jarFile );
310 }
311 else
312 {
313 if ( projectHasAlreadySetAnArtifact() )
314 {
315 throw new MojoExecutionException( "You have to use a classifier "
316 + "to attach supplemental artifacts to the project instead of replacing them." );
317 }
318 getProject().getArtifact().setFile( jarFile );
319 }
320 }
321 }
322
323 private boolean projectHasAlreadySetAnArtifact()
324 {
325 if ( getProject().getArtifact().getFile() == null )
326 {
327 return false;
328 }
329
330 return getProject().getArtifact().getFile().isFile();
331 }
332
333
334
335
336 protected boolean hasClassifier()
337 {
338 return getClassifier() != null && getClassifier().trim().length() > 0;
339 }
340
341 private String[] getIncludes()
342 {
343 if ( includes != null && includes.length > 0 )
344 {
345 return includes;
346 }
347 return DEFAULT_INCLUDES;
348 }
349
350 private String[] getExcludes()
351 {
352 if ( excludes != null && excludes.length > 0 )
353 {
354 return excludes;
355 }
356 return DEFAULT_EXCLUDES;
357 }
358 }