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