1 package org.apache.maven.plugins.war.packaging;
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
25 import org.apache.commons.io.input.XmlStreamReader;
26 import org.apache.maven.artifact.Artifact;
27 import org.apache.maven.plugin.MojoExecutionException;
28 import org.apache.maven.plugins.war.util.PathSet;
29 import org.apache.maven.plugins.war.util.WebappStructure;
30 import org.apache.maven.shared.filtering.MavenFilteringException;
31 import org.apache.maven.shared.mapping.MappingUtils;
32 import org.codehaus.plexus.archiver.ArchiverException;
33 import org.codehaus.plexus.archiver.UnArchiver;
34 import org.codehaus.plexus.archiver.jar.JarArchiver;
35 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
36 import org.codehaus.plexus.interpolation.InterpolationException;
37 import org.codehaus.plexus.util.DirectoryScanner;
38 import org.codehaus.plexus.util.FileUtils;
39
40
41
42
43 public abstract class AbstractWarPackagingTask
44 implements WarPackagingTask
45 {
46
47
48
49 public static final String[] DEFAULT_INCLUDES = { "**/**" };
50
51
52
53
54 public static final String WEB_INF_PATH = "WEB-INF";
55
56
57
58
59 public static final String META_INF_PATH = "META-INF";
60
61
62
63
64 public static final String CLASSES_PATH = "WEB-INF/classes/";
65
66
67
68
69 public static final String LIB_PATH = "WEB-INF/lib/";
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet,
91 String targetPrefix, boolean filtered )
92 throws IOException, MojoExecutionException
93 {
94 for ( String fileToCopyName : sourceFilesSet.paths() )
95 {
96 final File sourceFile = new File( sourceBaseDir, fileToCopyName );
97
98 String destinationFileName;
99 if ( targetPrefix == null )
100 {
101 destinationFileName = fileToCopyName;
102 }
103 else
104 {
105 destinationFileName = targetPrefix + fileToCopyName;
106 }
107
108 if ( filtered && !context.isNonFilteredExtension( sourceFile.getName() ) )
109 {
110 copyFilteredFile( sourceId, context, sourceFile, destinationFileName );
111 }
112 else
113 {
114 copyFile( sourceId, context, sourceFile, destinationFileName );
115 }
116 }
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet,
134 boolean filtered )
135 throws IOException, MojoExecutionException
136 {
137 copyFiles( sourceId, context, sourceBaseDir, sourceFilesSet, null, filtered );
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152 protected void copyFile( String sourceId, final WarPackagingContext context, final File file, String targetFilename )
153 throws IOException
154
155 {
156 final File targetFile = new File( context.getWebappDirectory(), targetFilename );
157
158 if ( file.isFile() )
159 {
160 context.getWebappStructure().registerFile( sourceId, targetFilename,
161 new WebappStructure.RegistrationCallback()
162 {
163 public void registered( String ownerId, String targetFilename )
164 throws IOException
165 {
166 copyFile( context, file, targetFile, targetFilename,
167 false );
168 }
169
170 public void alreadyRegistered( String ownerId,
171 String targetFilename )
172 throws IOException
173 {
174 copyFile( context, file, targetFile, targetFilename,
175 true );
176 }
177
178 public void refused( String ownerId, String targetFilename,
179 String actualOwnerId )
180 throws IOException
181 {
182 context.getLog().debug( " - "
183 + targetFilename
184 + " wasn't copied because it has "
185 + "already been packaged for overlay ["
186 + actualOwnerId + "]." );
187 }
188
189 public void superseded( String ownerId,
190 String targetFilename,
191 String deprecatedOwnerId )
192 throws IOException
193 {
194 context.getLog().info( "File ["
195 + targetFilename
196 + "] belonged to overlay ["
197 + deprecatedOwnerId
198 + "] so it will be overwritten." );
199 copyFile( context, file, targetFile, targetFilename,
200 false );
201 }
202
203 public void supersededUnknownOwner( String ownerId,
204 String targetFilename,
205 String unknownOwnerId )
206 throws IOException
207 {
208
209 context.getLog().warn( "File ["
210 + targetFilename
211 + "] belonged to overlay ["
212 + unknownOwnerId
213 + "] which does not exist anymore in the current project. It is recommended to invoke "
214 + "clean if the dependencies of the project changed." );
215
216 copyFile( context, file, targetFile, targetFilename,
217 false );
218 }
219 } );
220 }
221 else if ( !targetFile.exists() && !targetFile.mkdirs() )
222 {
223 context.getLog().info( "Failed to create directory " + targetFile.getAbsolutePath() );
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 protected boolean copyFilteredFile( String sourceId, final WarPackagingContext context, File file,
242 String targetFilename )
243 throws IOException, MojoExecutionException
244 {
245 context.getOutdatedResources().remove( targetFilename.replace( '/', File.separatorChar ) );
246
247 if ( context.getWebappStructure().registerFile( sourceId, targetFilename ) )
248 {
249 final File targetFile = new File( context.getWebappDirectory(), targetFilename );
250 final String encoding;
251 try
252 {
253 if ( isXmlFile( file ) )
254 {
255
256 encoding = getEncoding( file );
257 }
258 else
259 {
260
261 encoding = context.getResourceEncoding();
262 }
263
264 targetFile.getParentFile().mkdirs();
265
266 context.getMavenFileFilter().copyFile( file, targetFile, true, context.getFilterWrappers(), encoding );
267 }
268 catch ( MavenFilteringException e )
269 {
270 throw new MojoExecutionException( e.getMessage(), e );
271 }
272
273
274 context.getLog().debug( " + " + targetFilename + " has been copied (filtered encoding='" + encoding + "')." );
275
276 return true;
277 }
278 else
279 {
280 context.getLog().debug( " - " + targetFilename
281 + " wasn't copied because it has already been packaged (filtered)." );
282 return false;
283 }
284 }
285
286
287
288
289
290
291
292
293
294 protected void doUnpack( WarPackagingContext context, File file, File unpackDirectory )
295 throws MojoExecutionException
296 {
297 String archiveExt = FileUtils.getExtension( file.getAbsolutePath() ).toLowerCase();
298
299 try
300 {
301 UnArchiver unArchiver = context.getArchiverManager().getUnArchiver( archiveExt );
302 unArchiver.setSourceFile( file );
303 unArchiver.setDestDirectory( unpackDirectory );
304 unArchiver.setOverwrite( true );
305 unArchiver.extract();
306 }
307 catch ( ArchiverException e )
308 {
309 throw new MojoExecutionException( "Error unpacking file [" + file.getAbsolutePath() + "]" + " to ["
310 + unpackDirectory.getAbsolutePath() + "]", e );
311 }
312 catch ( NoSuchArchiverException e )
313 {
314 context.getLog().warn( "Skip unpacking dependency file [" + file.getAbsolutePath()
315 + " with unknown extension [" + archiveExt + "]" );
316 }
317 }
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 protected boolean copyFile( WarPackagingContext context, File source, File destination, String targetFilename,
335 boolean onlyIfModified )
336 throws IOException
337 {
338 context.getOutdatedResources().remove( targetFilename.replace( '/', File.separatorChar ) );
339
340 if ( onlyIfModified && destination.lastModified() >= source.lastModified() )
341 {
342 context.getLog().debug( " * " + targetFilename + " is up to date." );
343 return false;
344 }
345 else
346 {
347 if ( source.isDirectory() )
348 {
349 context.getLog().warn( " + " + targetFilename + " is packaged from the source folder" );
350
351 try
352 {
353 JarArchiver archiver = context.getJarArchiver();
354 archiver.addDirectory( source );
355 archiver.setDestFile( destination );
356 archiver.createArchive();
357 }
358 catch ( ArchiverException e )
359 {
360 String msg = "Failed to create " + targetFilename;
361 context.getLog().error( msg, e );
362 IOException ioe = new IOException( msg );
363 ioe.initCause( e );
364 throw ioe;
365 }
366 }
367 else
368 {
369 FileUtils.copyFile( source.getCanonicalFile(), destination );
370
371 destination.setLastModified( source.lastModified() );
372 context.getLog().debug( " + " + targetFilename + " has been copied." );
373 }
374 return true;
375 }
376 }
377
378
379
380
381
382
383
384
385 protected String getEncoding( File webXml )
386 throws IOException
387 {
388 try ( XmlStreamReader xmlReader = new XmlStreamReader( webXml ) )
389 {
390 return xmlReader.getEncoding();
391 }
392 }
393
394
395
396
397
398
399
400
401
402 protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes )
403 {
404 return getFilesToIncludes( baseDir, includes, excludes, false );
405 }
406
407
408
409
410
411
412
413
414
415
416
417 protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes, boolean includeDirectories )
418
419 {
420 final DirectoryScanner scanner = new DirectoryScanner();
421 scanner.setBasedir( baseDir );
422
423 if ( excludes != null )
424 {
425 scanner.setExcludes( excludes );
426 }
427 scanner.addDefaultExcludes();
428
429 if ( includes != null && includes.length > 0 )
430 {
431 scanner.setIncludes( includes );
432 }
433 else
434 {
435 scanner.setIncludes( DEFAULT_INCLUDES );
436 }
437
438 scanner.scan();
439
440 PathSet pathSet = new PathSet( scanner.getIncludedFiles() );
441
442 if ( includeDirectories )
443 {
444 pathSet.addAll( scanner.getIncludedDirectories() );
445 }
446
447 return pathSet;
448 }
449
450
451
452
453
454
455
456
457
458
459
460 protected String getArtifactFinalName( WarPackagingContext context, Artifact artifact )
461 throws InterpolationException
462 {
463 if ( context.getOutputFileNameMapping() != null )
464 {
465 return MappingUtils.evaluateFileNameMapping( context.getOutputFileNameMapping(), artifact );
466 }
467
468 String classifier = artifact.getClassifier();
469 if ( ( classifier != null ) && !( "".equals( classifier.trim() ) ) )
470 {
471 return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, artifact );
472 }
473 else
474 {
475 return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING, artifact );
476 }
477
478 }
479
480
481
482
483
484
485
486
487
488 private boolean isXmlFile( File file )
489 {
490 return file != null && file.isFile() && file.getName().endsWith( ".xml" );
491 }
492 }