1 package org.apache.maven.plugin.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.plugin.war.util.PathSet;
29 import org.apache.maven.plugin.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
337 protected boolean copyFile( WarPackagingContext context, File source, File destination, String targetFilename,
338 boolean onlyIfModified )
339 throws IOException
340 {
341 if ( onlyIfModified && destination.lastModified() >= source.lastModified() )
342 {
343 context.getLog().debug( " * " + targetFilename + " is up to date." );
344 return false;
345 }
346 else
347 {
348 if ( source.isDirectory() )
349 {
350 context.getLog().warn( " + " + targetFilename + " is packaged from the source folder" );
351
352 try
353 {
354 JarArchiver archiver = context.getJarArchiver();
355 archiver.addDirectory( source );
356 archiver.setDestFile( destination );
357 archiver.createArchive();
358 }
359 catch ( ArchiverException e )
360 {
361 String msg = "Failed to create " + targetFilename;
362 context.getLog().error( msg, e );
363 IOException ioe = new IOException( msg );
364 ioe.initCause( e );
365 throw ioe;
366 }
367 }
368 else
369 {
370 FileUtils.copyFile( source.getCanonicalFile(), destination );
371
372 destination.setLastModified( source.lastModified() );
373 context.getLog().debug( " + " + targetFilename + " has been copied." );
374 }
375 return true;
376 }
377 }
378
379
380
381
382
383
384
385
386 protected String getEncoding( File webXml )
387 throws IOException
388 {
389 XmlStreamReader xmlReader = new XmlStreamReader( webXml );
390 try
391 {
392 return xmlReader.getEncoding();
393 }
394 finally
395 {
396 IOUtil.close( xmlReader );
397 }
398 }
399
400
401
402
403
404
405
406
407
408 protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes )
409 {
410 return getFilesToIncludes( baseDir, includes, excludes, false );
411 }
412
413
414
415
416
417
418
419
420
421
422
423 protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes, boolean includeDirectories )
424
425 {
426 final DirectoryScanner scanner = new DirectoryScanner();
427 scanner.setBasedir( baseDir );
428
429 if ( excludes != null )
430 {
431 scanner.setExcludes( excludes );
432 }
433 scanner.addDefaultExcludes();
434
435 if ( includes != null && includes.length > 0 )
436 {
437 scanner.setIncludes( includes );
438 }
439 else
440 {
441 scanner.setIncludes( DEFAULT_INCLUDES );
442 }
443
444 scanner.scan();
445
446 PathSet pathSet = new PathSet( scanner.getIncludedFiles() );
447
448 if ( includeDirectories )
449 {
450 pathSet.addAll( scanner.getIncludedDirectories() );
451 }
452
453 return pathSet;
454 }
455
456
457
458
459
460
461
462
463
464
465
466 protected String getArtifactFinalName( WarPackagingContext context, Artifact artifact )
467 throws InterpolationException
468 {
469 if ( context.getOutputFileNameMapping() != null )
470 {
471 return MappingUtils.evaluateFileNameMapping( context.getOutputFileNameMapping(), artifact );
472 }
473
474 String classifier = artifact.getClassifier();
475 if ( ( classifier != null ) && !( "".equals( classifier.trim() ) ) )
476 {
477 return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, artifact );
478 }
479 else
480 {
481 return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING, artifact );
482 }
483
484 }
485
486
487
488
489
490
491
492
493
494 private boolean isXmlFile( File file )
495 {
496 return file != null && file.isFile() && file.getName().endsWith( ".xml" );
497 }
498 }