1 package org.apache.maven.plugin.war;
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.Collections;
27 import java.util.List;
28
29 import org.apache.maven.archiver.MavenArchiveConfiguration;
30 import org.apache.maven.artifact.factory.ArtifactFactory;
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.plugin.MojoFailureException;
36 import org.apache.maven.plugin.logging.Log;
37 import org.apache.maven.plugin.war.overlay.OverlayManager;
38 import org.apache.maven.plugin.war.packaging.DependenciesAnalysisPackagingTask;
39 import org.apache.maven.plugin.war.packaging.OverlayPackagingTask;
40 import org.apache.maven.plugin.war.packaging.SaveWebappStructurePostPackagingTask;
41 import org.apache.maven.plugin.war.packaging.WarPackagingContext;
42 import org.apache.maven.plugin.war.packaging.WarPackagingTask;
43 import org.apache.maven.plugin.war.packaging.WarPostPackagingTask;
44 import org.apache.maven.plugin.war.packaging.WarProjectPackagingTask;
45 import org.apache.maven.plugin.war.util.WebappStructure;
46 import org.apache.maven.plugin.war.util.WebappStructureSerializer;
47 import org.apache.maven.plugins.annotations.Component;
48 import org.apache.maven.plugins.annotations.Parameter;
49 import org.apache.maven.project.MavenProject;
50 import org.apache.maven.shared.filtering.MavenFileFilter;
51 import org.apache.maven.shared.filtering.MavenFilteringException;
52 import org.apache.maven.shared.filtering.MavenResourcesExecution;
53 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
54 import org.apache.maven.shared.utils.StringUtils;
55 import org.apache.maven.shared.utils.io.FileUtils;
56 import org.codehaus.plexus.archiver.Archiver;
57 import org.codehaus.plexus.archiver.jar.JarArchiver;
58 import org.codehaus.plexus.archiver.manager.ArchiverManager;
59
60
61
62
63
64
65 public abstract class AbstractWarMojo
66 extends AbstractMojo
67 {
68 private static final String[] EMPTY_STRING_ARRAY = {};
69
70 private static final String META_INF = "META-INF";
71
72 private static final String WEB_INF = "WEB-INF";
73
74
75
76
77 @Parameter( defaultValue = "${project}", readonly = true, required = true )
78 private MavenProject project;
79
80
81
82
83 @Parameter( defaultValue = "${project.build.outputDirectory}", required = true, readonly = true )
84 private File classesDirectory;
85
86
87
88
89
90
91
92
93 @Parameter( property = "archiveClasses", defaultValue = "false" )
94 private boolean archiveClasses;
95
96
97
98
99
100
101 @Parameter( property = "resourceEncoding", defaultValue = "${project.build.sourceEncoding}" )
102 private String resourceEncoding;
103
104
105
106
107 @Component( role = Archiver.class, hint = "jar" )
108 private JarArchiver jarArchiver;
109
110
111
112
113 @Parameter( defaultValue = "${project.build.directory}/${project.build.finalName}", required = true )
114 private File webappDirectory;
115
116
117
118
119 @Parameter( defaultValue = "${basedir}/src/main/webapp", required = true )
120 private File warSourceDirectory;
121
122
123
124
125 @Parameter
126 private Resource[] webResources;
127
128
129
130
131 @Parameter
132 private List<String> filters;
133
134
135
136
137 @Parameter( property = "maven.war.webxml" )
138 private File webXml;
139
140
141
142
143
144
145 @Parameter( property = "maven.war.containerConfigXML" )
146 private File containerConfigXML;
147
148
149
150
151 @Parameter( defaultValue = "${project.build.directory}/war/work", required = true )
152 private File workDirectory;
153
154
155
156
157
158
159
160 @Parameter
161 private String outputFileNameMapping;
162
163
164
165
166
167
168 @Parameter( defaultValue = "${project.build.directory}/war/work/webapp-cache.xml", required = true )
169 private File cacheFile;
170
171
172
173
174
175
176
177 @Parameter( property = "useCache", defaultValue = "false" )
178 private boolean useCache = false;
179
180
181
182 @Component( role = ArtifactFactory.class )
183 private ArtifactFactory artifactFactory;
184
185
186
187
188 @Component( role = ArchiverManager.class )
189 private ArchiverManager archiverManager;
190
191
192
193 @Component( role = MavenFileFilter.class, hint = "default" )
194 private MavenFileFilter mavenFileFilter;
195
196
197
198 @Component( role = MavenResourcesFiltering.class, hint = "default" )
199 private MavenResourcesFiltering mavenResourcesFiltering;
200
201
202
203
204 @Parameter( alias = "includes", defaultValue = "**" )
205 private String warSourceIncludes;
206
207
208
209
210 @Parameter( alias = "excludes" )
211 private String warSourceExcludes;
212
213
214
215
216
217
218 @Parameter
219 private String dependentWarIncludes = "**/**";
220
221
222
223
224
225
226 @Parameter
227 private String dependentWarExcludes = "META-INF/**";
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246 @Parameter
247 private List<Overlay> overlays = new ArrayList<Overlay>();
248
249
250
251
252
253
254
255 @Parameter
256 private List<String> nonFilteredFileExtensions;
257
258
259
260
261 @Parameter( defaultValue = "${session}", readonly = true, required = true )
262 private MavenSession session;
263
264
265
266
267
268
269 @Parameter( property = "maven.war.filteringDeploymentDescriptors", defaultValue = "false" )
270 private boolean filteringDeploymentDescriptors = false;
271
272
273
274
275
276
277
278 @Parameter( property = "maven.war.escapedBackslashesInFilePath", defaultValue = "false" )
279 private boolean escapedBackslashesInFilePath = false;
280
281
282
283
284
285
286
287 @Parameter( property = "maven.war.escapeString" )
288 protected String escapeString;
289
290
291
292
293
294
295
296 @Parameter( defaultValue = "true" )
297 private boolean recompressZippedFiles;
298
299
300
301
302 @Parameter( defaultValue = "false" )
303 private boolean includeEmptyDirectories;
304
305
306
307
308
309
310 @Parameter( property = "maven.war.supportMultiLineFiltering", defaultValue = "false" )
311 private boolean supportMultiLineFiltering = false;
312
313
314
315
316
317
318 @Parameter( property = "maven.war.useJvmChmod", defaultValue = "true" )
319 private boolean useJvmChmod;
320
321
322
323
324
325 @Parameter
326 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
327
328 private final WebappStructureSerializer webappStructureSerialier = new WebappStructureSerializer();
329
330 private final Overlay currentProjectOverlay = Overlay.createInstance();
331
332 public Overlay getCurrentProjectOverlay()
333 {
334 return currentProjectOverlay;
335 }
336
337
338
339
340
341
342 protected String[] getExcludes()
343 {
344 List<String> excludeList = new ArrayList<String>();
345 if ( StringUtils.isNotEmpty( warSourceExcludes ) )
346 {
347 excludeList.addAll( Arrays.asList( StringUtils.split( warSourceExcludes, "," ) ) );
348 }
349
350
351 if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
352 {
353 excludeList.add( "**/" + WEB_INF + "/web.xml" );
354 }
355
356
357 if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
358 {
359 excludeList.add( "**/" + META_INF + "/" + containerConfigXML.getName() );
360 }
361
362 return excludeList.toArray( new String[excludeList.size()] );
363 }
364
365
366
367
368
369
370 protected String[] getIncludes()
371 {
372 return StringUtils.split( StringUtils.defaultString( warSourceIncludes ), "," );
373 }
374
375
376
377
378
379
380 protected String[] getDependentWarExcludes()
381 {
382 String[] excludes;
383 if ( StringUtils.isNotEmpty( dependentWarExcludes ) )
384 {
385 excludes = StringUtils.split( dependentWarExcludes, "," );
386 }
387 else
388 {
389 excludes = EMPTY_STRING_ARRAY;
390 }
391 return excludes;
392 }
393
394
395
396
397
398
399 protected String[] getDependentWarIncludes()
400 {
401 return StringUtils.split( StringUtils.defaultString( dependentWarIncludes ), "," );
402 }
403
404 public void buildExplodedWebapp( File webapplicationDirectory )
405 throws MojoExecutionException, MojoFailureException
406 {
407 webapplicationDirectory.mkdirs();
408
409 try
410 {
411 buildWebapp( project, webapplicationDirectory );
412 }
413 catch ( IOException e )
414 {
415 throw new MojoExecutionException( "Could not build webapp", e );
416 }
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430 @SuppressWarnings( "unchecked" )
431 public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory )
432 throws MojoExecutionException, MojoFailureException, IOException
433 {
434
435 WebappStructure cache;
436 if ( useCache && cacheFile.exists() )
437 {
438 cache = new WebappStructure( mavenProject.getDependencies(), webappStructureSerialier.fromXml( cacheFile ) );
439 }
440 else
441 {
442 cache = new WebappStructure( mavenProject.getDependencies(), null );
443 }
444
445 final long startTime = System.currentTimeMillis();
446 getLog().info( "Assembling webapp [" + mavenProject.getArtifactId() + "] in [" + webapplicationDirectory + "]" );
447
448 final OverlayManager overlayManager =
449 new OverlayManager( overlays, mavenProject, dependentWarIncludes, dependentWarExcludes, currentProjectOverlay );
450 final List<WarPackagingTask> packagingTasks = getPackagingTasks( overlayManager );
451 List<FileUtils.FilterWrapper> defaultFilterWrappers;
452 try
453 {
454 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
455 mavenResourcesExecution.setEscapeString( escapeString );
456 mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
457 mavenResourcesExecution.setMavenProject( mavenProject );
458 if ( filters == null )
459 {
460 filters = getProject().getBuild().getFilters();
461 }
462 mavenResourcesExecution.setFilters( filters );
463 mavenResourcesExecution.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
464 mavenResourcesExecution.setMavenSession( this.session );
465 mavenResourcesExecution.setEscapeString( this.escapeString );
466 mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
467
468 defaultFilterWrappers = mavenFileFilter.getDefaultFilterWrappers( mavenResourcesExecution );
469
470 }
471 catch ( MavenFilteringException e )
472 {
473 getLog().error( "fail to build filering wrappers " + e.getMessage() );
474 throw new MojoExecutionException( e.getMessage(), e );
475 }
476
477 final WarPackagingContext context =
478 new DefaultWarPackagingContext( webapplicationDirectory, cache, overlayManager, defaultFilterWrappers,
479 getNonFilteredFileExtensions(), filteringDeploymentDescriptors,
480 this.artifactFactory, resourceEncoding, useJvmChmod );
481 for ( WarPackagingTask warPackagingTask : packagingTasks )
482 {
483 warPackagingTask.performPackaging( context );
484 }
485
486
487 final List<WarPostPackagingTask> postPackagingTasks = getPostPackagingTasks();
488 for ( WarPostPackagingTask task : postPackagingTasks )
489 {
490 task.performPostPackaging( context );
491 }
492 getLog().info( "Webapp assembled in [" + ( System.currentTimeMillis() - startTime ) + " msecs]" );
493
494 }
495
496
497
498
499
500
501
502
503
504 private List<WarPackagingTask> getPackagingTasks( OverlayManager overlayManager )
505 throws MojoExecutionException
506 {
507 final List<WarPackagingTask> packagingTasks = new ArrayList<WarPackagingTask>();
508 if ( useCache )
509 {
510 packagingTasks.add( new DependenciesAnalysisPackagingTask() );
511 }
512
513 final List<Overlay> resolvedOverlays = overlayManager.getOverlays();
514 for ( Overlay overlay : resolvedOverlays )
515 {
516 if ( overlay.isCurrentProject() )
517 {
518 packagingTasks.add( new WarProjectPackagingTask( webResources, webXml, containerConfigXML,
519 currentProjectOverlay ) );
520 }
521 else
522 {
523 packagingTasks.add( new OverlayPackagingTask( overlay, currentProjectOverlay ) );
524 }
525 }
526 return packagingTasks;
527 }
528
529
530
531
532
533
534
535 private List<WarPostPackagingTask> getPostPackagingTasks()
536 {
537 final List<WarPostPackagingTask> postPackagingTasks = new ArrayList<WarPostPackagingTask>();
538 if ( useCache )
539 {
540 postPackagingTasks.add( new SaveWebappStructurePostPackagingTask( cacheFile ) );
541 }
542
543 return postPackagingTasks;
544 }
545
546
547
548
549 private class DefaultWarPackagingContext
550 implements WarPackagingContext
551 {
552
553 private final ArtifactFactory artifactFactory;
554
555 private final String resourceEncoding;
556
557 private final WebappStructure webappStructure;
558
559 private final File webappDirectory;
560
561 private final OverlayManager overlayManager;
562
563 private final List<FileUtils.FilterWrapper> filterWrappers;
564
565 private List<String> nonFilteredFileExtensions;
566
567 private boolean filteringDeploymentDescriptors;
568
569 private boolean useJvmChmod = true;
570
571 public DefaultWarPackagingContext( File webappDirectory, final WebappStructure webappStructure,
572 final OverlayManager overlayManager,
573 List<FileUtils.FilterWrapper> filterWrappers,
574 List<String> nonFilteredFileExtensions,
575 boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory,
576 String resourceEncoding, boolean useJvmChmod )
577 {
578 this.webappDirectory = webappDirectory;
579 this.webappStructure = webappStructure;
580 this.overlayManager = overlayManager;
581 this.filterWrappers = filterWrappers;
582 this.artifactFactory = artifactFactory;
583 this.filteringDeploymentDescriptors = filteringDeploymentDescriptors;
584 this.nonFilteredFileExtensions =
585 nonFilteredFileExtensions == null ? Collections.<String> emptyList() : nonFilteredFileExtensions;
586 this.resourceEncoding = resourceEncoding;
587
588
589 for ( String overlayId : overlayManager.getOverlayIds() )
590 {
591 webappStructure.getStructure( overlayId );
592 }
593 this.useJvmChmod = useJvmChmod;
594 }
595
596 public MavenProject getProject()
597 {
598 return project;
599 }
600
601 public File getWebappDirectory()
602 {
603 return webappDirectory;
604 }
605
606 public File getClassesDirectory()
607 {
608 return classesDirectory;
609 }
610
611 public Log getLog()
612 {
613 return AbstractWarMojo.this.getLog();
614 }
615
616 public String getOutputFileNameMapping()
617 {
618 return outputFileNameMapping;
619 }
620
621 public File getWebappSourceDirectory()
622 {
623 return warSourceDirectory;
624 }
625
626 public String[] getWebappSourceIncludes()
627 {
628 return getIncludes();
629 }
630
631 public String[] getWebappSourceExcludes()
632 {
633 return getExcludes();
634 }
635
636 public boolean isWebappSourceIncludeEmptyDirectories()
637 {
638 return includeEmptyDirectories;
639 }
640
641 public boolean archiveClasses()
642 {
643 return archiveClasses;
644 }
645
646 public File getOverlaysWorkDirectory()
647 {
648 return workDirectory;
649 }
650
651 public ArchiverManager getArchiverManager()
652 {
653 return archiverManager;
654 }
655
656 public MavenArchiveConfiguration getArchive()
657 {
658 return archive;
659 }
660
661 public JarArchiver getJarArchiver()
662 {
663 return jarArchiver;
664 }
665
666 public List<String> getFilters()
667 {
668 return filters;
669 }
670
671 public WebappStructure getWebappStructure()
672 {
673 return webappStructure;
674 }
675
676 public List<String> getOwnerIds()
677 {
678 return overlayManager.getOverlayIds();
679 }
680
681 public MavenFileFilter getMavenFileFilter()
682 {
683 return mavenFileFilter;
684 }
685
686 public List<FileUtils.FilterWrapper> getFilterWrappers()
687 {
688 return filterWrappers;
689 }
690
691 public boolean isNonFilteredExtension( String fileName )
692 {
693 return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
694 }
695
696 public boolean isFilteringDeploymentDescriptors()
697 {
698 return filteringDeploymentDescriptors;
699 }
700
701 public ArtifactFactory getArtifactFactory()
702 {
703 return this.artifactFactory;
704 }
705
706 public MavenSession getSession()
707 {
708 return session;
709 }
710
711 public String getResourceEncoding()
712 {
713 return resourceEncoding;
714 }
715
716 public boolean isUseJvmChmod()
717 {
718 return useJvmChmod;
719 }
720 }
721
722 public MavenProject getProject()
723 {
724 return project;
725 }
726
727 public void setProject( MavenProject project )
728 {
729 this.project = project;
730 }
731
732 public File getClassesDirectory()
733 {
734 return classesDirectory;
735 }
736
737 public void setClassesDirectory( File classesDirectory )
738 {
739 this.classesDirectory = classesDirectory;
740 }
741
742 public File getWebappDirectory()
743 {
744 return webappDirectory;
745 }
746
747 public void setWebappDirectory( File webappDirectory )
748 {
749 this.webappDirectory = webappDirectory;
750 }
751
752 public File getWarSourceDirectory()
753 {
754 return warSourceDirectory;
755 }
756
757 public void setWarSourceDirectory( File warSourceDirectory )
758 {
759 this.warSourceDirectory = warSourceDirectory;
760 }
761
762 public File getWebXml()
763 {
764 return webXml;
765 }
766
767 public void setWebXml( File webXml )
768 {
769 this.webXml = webXml;
770 }
771
772 public File getContainerConfigXML()
773 {
774 return containerConfigXML;
775 }
776
777 public void setContainerConfigXML( File containerConfigXML )
778 {
779 this.containerConfigXML = containerConfigXML;
780 }
781
782 public String getOutputFileNameMapping()
783 {
784 return outputFileNameMapping;
785 }
786
787 public void setOutputFileNameMapping( String outputFileNameMapping )
788 {
789 this.outputFileNameMapping = outputFileNameMapping;
790 }
791
792 public List<Overlay> getOverlays()
793 {
794 return overlays;
795 }
796
797 public void setOverlays( List<Overlay> overlays )
798 {
799 this.overlays = overlays;
800 }
801
802 public void addOverlay( Overlay overlay )
803 {
804 overlays.add( overlay );
805 }
806
807 public boolean isArchiveClasses()
808 {
809 return archiveClasses;
810 }
811
812 public void setArchiveClasses( boolean archiveClasses )
813 {
814 this.archiveClasses = archiveClasses;
815 }
816
817 public JarArchiver getJarArchiver()
818 {
819 return jarArchiver;
820 }
821
822 public void setJarArchiver( JarArchiver jarArchiver )
823 {
824 this.jarArchiver = jarArchiver;
825 }
826
827 public Resource[] getWebResources()
828 {
829 return webResources;
830 }
831
832 public void setWebResources( Resource[] webResources )
833 {
834 this.webResources = webResources;
835 }
836
837 public List<String> getFilters()
838 {
839 return filters;
840 }
841
842 public void setFilters( List<String> filters )
843 {
844 this.filters = filters;
845 }
846
847 public File getWorkDirectory()
848 {
849 return workDirectory;
850 }
851
852 public void setWorkDirectory( File workDirectory )
853 {
854 this.workDirectory = workDirectory;
855 }
856
857 public File getCacheFile()
858 {
859 return cacheFile;
860 }
861
862 public void setCacheFile( File cacheFile )
863 {
864 this.cacheFile = cacheFile;
865 }
866
867 public String getWarSourceIncludes()
868 {
869 return warSourceIncludes;
870 }
871
872 public void setWarSourceIncludes( String warSourceIncludes )
873 {
874 this.warSourceIncludes = warSourceIncludes;
875 }
876
877 public String getWarSourceExcludes()
878 {
879 return warSourceExcludes;
880 }
881
882 public void setWarSourceExcludes( String warSourceExcludes )
883 {
884 this.warSourceExcludes = warSourceExcludes;
885 }
886
887 public boolean isUseCache()
888 {
889 return useCache;
890 }
891
892 public void setUseCache( boolean useCache )
893 {
894 this.useCache = useCache;
895 }
896
897 public MavenArchiveConfiguration getArchive()
898 {
899 return archive;
900 }
901
902 public List<String> getNonFilteredFileExtensions()
903 {
904 return nonFilteredFileExtensions;
905 }
906
907 public void setNonFilteredFileExtensions( List<String> nonFilteredFileExtensions )
908 {
909 this.nonFilteredFileExtensions = nonFilteredFileExtensions;
910 }
911
912 public ArtifactFactory getArtifactFactory()
913 {
914 return this.artifactFactory;
915 }
916
917 public void setArtifactFactory( ArtifactFactory artifactFactory )
918 {
919 this.artifactFactory = artifactFactory;
920 }
921
922 protected MavenSession getSession()
923 {
924 return this.session;
925 }
926
927 protected boolean isRecompressZippedFiles()
928 {
929 return recompressZippedFiles;
930 }
931
932 protected boolean isIncludeEmptyDirectories()
933 {
934 return includeEmptyDirectories;
935 }
936 }