1 package org.apache.maven.plugins.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.LinkedHashSet;
28 import java.util.List;
29
30 import org.apache.maven.archiver.MavenArchiveConfiguration;
31 import org.apache.maven.artifact.factory.ArtifactFactory;
32 import org.apache.maven.execution.MavenSession;
33 import org.apache.maven.model.Resource;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugin.MojoFailureException;
37 import org.apache.maven.plugin.logging.Log;
38 import org.apache.maven.plugins.annotations.Component;
39 import org.apache.maven.plugins.annotations.Parameter;
40 import org.apache.maven.plugins.war.overlay.OverlayManager;
41 import org.apache.maven.plugins.war.packaging.CopyUserManifestTask;
42 import org.apache.maven.plugins.war.packaging.DependenciesAnalysisPackagingTask;
43 import org.apache.maven.plugins.war.packaging.OverlayPackagingTask;
44 import org.apache.maven.plugins.war.packaging.SaveWebappStructurePostPackagingTask;
45 import org.apache.maven.plugins.war.packaging.WarPackagingContext;
46 import org.apache.maven.plugins.war.packaging.WarPackagingTask;
47 import org.apache.maven.plugins.war.packaging.WarPostPackagingTask;
48 import org.apache.maven.plugins.war.packaging.WarProjectPackagingTask;
49 import org.apache.maven.plugins.war.util.WebappStructure;
50 import org.apache.maven.plugins.war.util.WebappStructureSerializer;
51 import org.apache.maven.project.MavenProject;
52 import org.apache.maven.shared.filtering.MavenFileFilter;
53 import org.apache.maven.shared.filtering.MavenFilteringException;
54 import org.apache.maven.shared.filtering.MavenResourcesExecution;
55 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
56 import org.apache.maven.shared.utils.StringUtils;
57 import org.apache.maven.shared.utils.io.FileUtils;
58 import org.codehaus.plexus.archiver.Archiver;
59 import org.codehaus.plexus.archiver.jar.JarArchiver;
60 import org.codehaus.plexus.archiver.manager.ArchiverManager;
61
62
63
64
65
66
67 public abstract class AbstractWarMojo
68 extends AbstractMojo
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( defaultValue = "false" )
94 private boolean archiveClasses;
95
96
97
98
99
100
101 @Parameter( 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @Parameter
156 private LinkedHashSet<String> delimiters;
157
158
159
160
161
162
163 @Parameter( defaultValue = "true" )
164 private boolean useDefaultDelimiters;
165
166
167
168
169 @Parameter
170 private File webXml;
171
172
173
174
175
176
177 @Parameter
178 private File containerConfigXML;
179
180
181
182
183 @Parameter( defaultValue = "${project.build.directory}/war/work", required = true )
184 private File workDirectory;
185
186
187
188
189
190
191
192 @Parameter
193 private String outputFileNameMapping;
194
195
196
197
198
199
200 @Parameter( defaultValue = "${project.build.directory}/war/work/webapp-cache.xml", required = true )
201 private File cacheFile;
202
203
204
205
206
207
208
209 @Parameter( defaultValue = "false" )
210 private boolean useCache;
211
212
213
214 @Component( role = ArtifactFactory.class )
215 private ArtifactFactory artifactFactory;
216
217
218
219
220 @Component( role = ArchiverManager.class )
221 private ArchiverManager archiverManager;
222
223
224
225 @Component( role = MavenFileFilter.class, hint = "default" )
226 private MavenFileFilter mavenFileFilter;
227
228
229
230 @Component( role = MavenResourcesFiltering.class, hint = "default" )
231 private MavenResourcesFiltering mavenResourcesFiltering;
232
233
234
235
236 @Parameter( defaultValue = "**" )
237 private String warSourceIncludes;
238
239
240
241
242 @Parameter
243 private String warSourceExcludes;
244
245
246
247
248
249
250 @Parameter
251 private String dependentWarIncludes = StringUtils.join( Overlay.DEFAULT_INCLUDES, "," );
252
253
254
255
256
257
258 @Parameter
259 private String dependentWarExcludes = StringUtils.join( Overlay.DEFAULT_EXCLUDES, "," );
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 @Parameter
279 private List<Overlay> overlays = new ArrayList<Overlay>();
280
281
282
283
284
285
286
287 @Parameter
288 private List<String> nonFilteredFileExtensions;
289
290
291
292
293 @Parameter( defaultValue = "${session}", readonly = true, required = true )
294 private MavenSession session;
295
296
297
298
299
300
301 @Parameter( defaultValue = "false" )
302 private boolean filteringDeploymentDescriptors;
303
304
305
306
307
308
309
310 @Parameter( defaultValue = "false" )
311 private boolean escapedBackslashesInFilePath;
312
313
314
315
316
317
318
319 @Parameter
320 protected String escapeString;
321
322
323
324
325
326
327
328 @Parameter( defaultValue = "true" )
329 private boolean recompressZippedFiles;
330
331
332
333
334 @Parameter( defaultValue = "false" )
335 private boolean includeEmptyDirectories;
336
337
338
339
340
341
342 @Parameter( defaultValue = "false" )
343 private boolean supportMultiLineFiltering;
344
345
346
347
348
349
350 @Parameter( defaultValue = "true" )
351 private boolean useJvmChmod;
352
353
354
355
356
357 @Parameter
358 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
359
360 private final WebappStructureSerializer webappStructureSerialier = new WebappStructureSerializer();
361
362 private final Overlay currentProjectOverlay = Overlay.createInstance();
363
364
365
366
367 public Overlay getCurrentProjectOverlay()
368 {
369 return currentProjectOverlay;
370 }
371
372
373
374
375
376
377 protected String[] getExcludes()
378 {
379 List<String> excludeList = new ArrayList<String>();
380 if ( StringUtils.isNotEmpty( warSourceExcludes ) )
381 {
382 excludeList.addAll( Arrays.asList( StringUtils.split( warSourceExcludes, "," ) ) );
383 }
384
385
386 if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
387 {
388 excludeList.add( "**/" + WEB_INF + "/web.xml" );
389 }
390
391
392 if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
393 {
394 excludeList.add( "**/" + META_INF + "/" + containerConfigXML.getName() );
395 }
396
397 return excludeList.toArray( new String[excludeList.size()] );
398 }
399
400
401
402
403
404
405 protected String[] getIncludes()
406 {
407 return StringUtils.split( StringUtils.defaultString( warSourceIncludes ), "," );
408 }
409
410
411
412
413
414
415 protected String[] getDependentWarExcludes()
416 {
417 return StringUtils.split( StringUtils.defaultString( dependentWarExcludes ), "," );
418 }
419
420
421
422
423
424
425 protected String[] getDependentWarIncludes()
426 {
427 return StringUtils.split( StringUtils.defaultString( dependentWarIncludes ), "," );
428 }
429
430
431
432
433
434
435 public void buildExplodedWebapp( File webapplicationDirectory )
436 throws MojoExecutionException, MojoFailureException
437 {
438 webapplicationDirectory.mkdirs();
439
440 try
441 {
442 buildWebapp( project, webapplicationDirectory );
443 }
444 catch ( IOException e )
445 {
446 throw new MojoExecutionException( "Could not build webapp", e );
447 }
448 }
449
450
451
452
453
454
455
456
457
458
459
460 public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory )
461 throws MojoExecutionException, MojoFailureException, IOException
462 {
463
464 WebappStructure cache;
465 if ( useCache && cacheFile.exists() )
466 {
467
468 cache = new WebappStructure( mavenProject.getDependencies(), webappStructureSerialier.fromXml( cacheFile ) );
469
470 }
471 else
472 {
473 cache = new WebappStructure( mavenProject.getDependencies(), null );
474 }
475
476
477 final long startTime = System.currentTimeMillis();
478 getLog().info( "Assembling webapp [" + mavenProject.getArtifactId() + "] in [" + webapplicationDirectory + "]" );
479
480 final OverlayManager overlayManager =
481 new OverlayManager( overlays, mavenProject, getDependentWarIncludes(), getDependentWarExcludes(),
482 currentProjectOverlay );
483 final List<WarPackagingTask> packagingTasks = getPackagingTasks( overlayManager );
484
485 List<FileUtils.FilterWrapper> defaultFilterWrappers;
486 try
487 {
488 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
489 mavenResourcesExecution.setEscapeString( escapeString );
490 mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
491 mavenResourcesExecution.setMavenProject( mavenProject );
492
493
494 mavenResourcesExecution.setDelimiters( delimiters, useDefaultDelimiters );
495
496 if ( nonFilteredFileExtensions != null )
497 {
498 mavenResourcesExecution.setNonFilteredFileExtensions( nonFilteredFileExtensions );
499 }
500
501 if ( filters == null )
502 {
503 filters = getProject().getBuild().getFilters();
504 }
505 mavenResourcesExecution.setFilters( filters );
506 mavenResourcesExecution.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
507 mavenResourcesExecution.setMavenSession( this.session );
508 mavenResourcesExecution.setEscapeString( this.escapeString );
509 mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
510
511 defaultFilterWrappers = mavenFileFilter.getDefaultFilterWrappers( mavenResourcesExecution );
512
513 }
514 catch ( MavenFilteringException e )
515 {
516 getLog().error( "fail to build filering wrappers " + e.getMessage() );
517 throw new MojoExecutionException( e.getMessage(), e );
518 }
519
520 final WarPackagingContext context =
521 new DefaultWarPackagingContext( webapplicationDirectory, cache, overlayManager, defaultFilterWrappers,
522 getNonFilteredFileExtensions(), filteringDeploymentDescriptors,
523 this.artifactFactory, resourceEncoding, useJvmChmod );
524 for ( WarPackagingTask warPackagingTask : packagingTasks )
525 {
526 warPackagingTask.performPackaging( context );
527 }
528
529
530 final List<WarPostPackagingTask> postPackagingTasks = getPostPackagingTasks();
531 for ( WarPostPackagingTask task : postPackagingTasks )
532 {
533 task.performPostPackaging( context );
534 }
535 getLog().info( "Webapp assembled in [" + ( System.currentTimeMillis() - startTime ) + " msecs]" );
536
537 }
538
539
540
541
542
543
544
545
546
547 private List<WarPackagingTask> getPackagingTasks( OverlayManager overlayManager )
548 throws MojoExecutionException
549 {
550 final List<WarPackagingTask> packagingTasks = new ArrayList<WarPackagingTask>();
551
552 packagingTasks.add( new CopyUserManifestTask() );
553
554 if ( useCache )
555 {
556 packagingTasks.add( new DependenciesAnalysisPackagingTask() );
557
558 }
559
560 final List<Overlay> resolvedOverlays = overlayManager.getOverlays();
561 for ( Overlay overlay : resolvedOverlays )
562 {
563 if ( overlay.isCurrentProject() )
564 {
565 packagingTasks.add( new WarProjectPackagingTask( webResources, webXml, containerConfigXML,
566 currentProjectOverlay ) );
567 }
568 else
569 {
570 packagingTasks.add( new OverlayPackagingTask( overlay, currentProjectOverlay ) );
571 }
572 }
573 return packagingTasks;
574 }
575
576
577
578
579
580
581
582 private List<WarPostPackagingTask> getPostPackagingTasks()
583 {
584 final List<WarPostPackagingTask> postPackagingTasks = new ArrayList<WarPostPackagingTask>();
585 if ( useCache )
586 {
587 postPackagingTasks.add( new SaveWebappStructurePostPackagingTask( cacheFile ) );
588 }
589
590 return postPackagingTasks;
591 }
592
593
594
595
596 private class DefaultWarPackagingContext
597 implements WarPackagingContext
598 {
599
600 private final ArtifactFactory artifactFactory;
601
602 private final String resourceEncoding;
603
604 private final WebappStructure webappStructure;
605
606 private final File webappDirectory;
607
608 private final OverlayManager overlayManager;
609
610 private final List<FileUtils.FilterWrapper> filterWrappers;
611
612 private List<String> nonFilteredFileExtensions;
613
614 private boolean filteringDeploymentDescriptors;
615
616 private boolean useJvmChmod = true;
617
618
619
620
621
622
623
624
625
626
627
628
629 DefaultWarPackagingContext( File webappDirectory, final WebappStructure webappStructure,
630 final OverlayManager overlayManager,
631 List<FileUtils.FilterWrapper> filterWrappers,
632 List<String> nonFilteredFileExtensions,
633 boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory,
634 String resourceEncoding, boolean useJvmChmod )
635 {
636 this.webappDirectory = webappDirectory;
637 this.webappStructure = webappStructure;
638 this.overlayManager = overlayManager;
639 this.filterWrappers = filterWrappers;
640 this.artifactFactory = artifactFactory;
641 this.filteringDeploymentDescriptors = filteringDeploymentDescriptors;
642 this.nonFilteredFileExtensions =
643 nonFilteredFileExtensions == null ? Collections.<String>emptyList() : nonFilteredFileExtensions;
644 this.resourceEncoding = resourceEncoding;
645
646
647 for ( String overlayId : overlayManager.getOverlayIds() )
648 {
649 webappStructure.getStructure( overlayId );
650 }
651 this.useJvmChmod = useJvmChmod;
652 }
653
654
655
656
657 public MavenProject getProject()
658 {
659 return project;
660 }
661
662
663
664
665 public File getWebappDirectory()
666 {
667 return webappDirectory;
668 }
669
670
671
672
673 public File getClassesDirectory()
674 {
675 return classesDirectory;
676 }
677
678
679
680
681 public Log getLog()
682 {
683 return AbstractWarMojo.this.getLog();
684 }
685
686
687
688
689 public String getOutputFileNameMapping()
690 {
691 return outputFileNameMapping;
692 }
693
694
695
696
697 public File getWebappSourceDirectory()
698 {
699 return warSourceDirectory;
700 }
701
702
703
704
705 public String[] getWebappSourceIncludes()
706 {
707 return getIncludes();
708 }
709
710
711
712
713 public String[] getWebappSourceExcludes()
714 {
715 return getExcludes();
716 }
717
718
719
720
721 public boolean isWebappSourceIncludeEmptyDirectories()
722 {
723 return includeEmptyDirectories;
724 }
725
726
727
728
729 public boolean archiveClasses()
730 {
731 return archiveClasses;
732 }
733
734
735
736
737 public File getOverlaysWorkDirectory()
738 {
739 return workDirectory;
740 }
741
742
743
744
745 public ArchiverManager getArchiverManager()
746 {
747 return archiverManager;
748 }
749
750
751
752
753 public MavenArchiveConfiguration getArchive()
754 {
755 return archive;
756 }
757
758
759
760
761 public JarArchiver getJarArchiver()
762 {
763 return jarArchiver;
764 }
765
766
767
768
769 public List<String> getFilters()
770 {
771 return filters;
772 }
773
774
775
776
777 public WebappStructure getWebappStructure()
778 {
779 return webappStructure;
780 }
781
782
783
784
785 public List<String> getOwnerIds()
786 {
787 return overlayManager.getOverlayIds();
788 }
789
790
791
792
793 public MavenFileFilter getMavenFileFilter()
794 {
795 return mavenFileFilter;
796 }
797
798
799
800
801 public List<FileUtils.FilterWrapper> getFilterWrappers()
802 {
803 return filterWrappers;
804 }
805
806
807
808
809 public boolean isNonFilteredExtension( String fileName )
810 {
811 return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
812 }
813
814
815
816
817 public boolean isFilteringDeploymentDescriptors()
818 {
819 return filteringDeploymentDescriptors;
820 }
821
822
823
824
825 public ArtifactFactory getArtifactFactory()
826 {
827 return this.artifactFactory;
828 }
829
830
831
832
833 public MavenSession getSession()
834 {
835 return session;
836 }
837
838
839
840
841 public String getResourceEncoding()
842 {
843 return resourceEncoding;
844 }
845
846
847
848
849 public boolean isUseJvmChmod()
850 {
851 return useJvmChmod;
852 }
853 }
854
855
856
857
858 public MavenProject getProject()
859 {
860 return project;
861 }
862
863
864
865
866 public void setProject( MavenProject project )
867 {
868 this.project = project;
869 }
870
871
872
873
874 public File getClassesDirectory()
875 {
876 return classesDirectory;
877 }
878
879
880
881
882 public void setClassesDirectory( File classesDirectory )
883 {
884 this.classesDirectory = classesDirectory;
885 }
886
887
888
889
890 public File getWebappDirectory()
891 {
892 return webappDirectory;
893 }
894
895
896
897
898 public void setWebappDirectory( File webappDirectory )
899 {
900 this.webappDirectory = webappDirectory;
901 }
902
903
904
905
906 public File getWarSourceDirectory()
907 {
908 return warSourceDirectory;
909 }
910
911
912
913
914 public void setWarSourceDirectory( File warSourceDirectory )
915 {
916 this.warSourceDirectory = warSourceDirectory;
917 }
918
919
920
921
922 public File getWebXml()
923 {
924 return webXml;
925 }
926
927
928
929
930 public void setWebXml( File webXml )
931 {
932 this.webXml = webXml;
933 }
934
935
936
937
938 public File getContainerConfigXML()
939 {
940 return containerConfigXML;
941 }
942
943
944
945
946 public void setContainerConfigXML( File containerConfigXML )
947 {
948 this.containerConfigXML = containerConfigXML;
949 }
950
951
952
953
954 public String getOutputFileNameMapping()
955 {
956 return outputFileNameMapping;
957 }
958
959
960
961
962 public void setOutputFileNameMapping( String outputFileNameMapping )
963 {
964 this.outputFileNameMapping = outputFileNameMapping;
965 }
966
967
968
969
970 public List<Overlay> getOverlays()
971 {
972 return overlays;
973 }
974
975
976
977
978 public void setOverlays( List<Overlay> overlays )
979 {
980 this.overlays = overlays;
981 }
982
983
984
985
986 public void addOverlay( Overlay overlay )
987 {
988 overlays.add( overlay );
989 }
990
991
992
993
994 public boolean isArchiveClasses()
995 {
996 return archiveClasses;
997 }
998
999
1000
1001
1002 public void setArchiveClasses( boolean archiveClasses )
1003 {
1004 this.archiveClasses = archiveClasses;
1005 }
1006
1007
1008
1009
1010 public JarArchiver getJarArchiver()
1011 {
1012 return jarArchiver;
1013 }
1014
1015
1016
1017
1018 public void setJarArchiver( JarArchiver jarArchiver )
1019 {
1020 this.jarArchiver = jarArchiver;
1021 }
1022
1023
1024
1025
1026 public Resource[] getWebResources()
1027 {
1028 return webResources;
1029 }
1030
1031
1032
1033
1034 public void setWebResources( Resource[] webResources )
1035 {
1036 this.webResources = webResources;
1037 }
1038
1039
1040
1041
1042 public List<String> getFilters()
1043 {
1044 return filters;
1045 }
1046
1047
1048
1049
1050 public void setFilters( List<String> filters )
1051 {
1052 this.filters = filters;
1053 }
1054
1055
1056
1057
1058 public File getWorkDirectory()
1059 {
1060 return workDirectory;
1061 }
1062
1063
1064
1065
1066 public void setWorkDirectory( File workDirectory )
1067 {
1068 this.workDirectory = workDirectory;
1069 }
1070
1071
1072
1073
1074 public File getCacheFile()
1075 {
1076 return cacheFile;
1077 }
1078
1079
1080
1081
1082 public void setCacheFile( File cacheFile )
1083 {
1084 this.cacheFile = cacheFile;
1085 }
1086
1087
1088
1089
1090 public String getWarSourceIncludes()
1091 {
1092 return warSourceIncludes;
1093 }
1094
1095
1096
1097
1098 public void setWarSourceIncludes( String warSourceIncludes )
1099 {
1100 this.warSourceIncludes = warSourceIncludes;
1101 }
1102
1103
1104
1105
1106 public String getWarSourceExcludes()
1107 {
1108 return warSourceExcludes;
1109 }
1110
1111
1112
1113
1114 public void setWarSourceExcludes( String warSourceExcludes )
1115 {
1116 this.warSourceExcludes = warSourceExcludes;
1117 }
1118
1119
1120
1121
1122 public boolean isUseCache()
1123 {
1124 return useCache;
1125 }
1126
1127
1128
1129
1130 public void setUseCache( boolean useCache )
1131 {
1132 this.useCache = useCache;
1133 }
1134
1135
1136
1137
1138 public MavenArchiveConfiguration getArchive()
1139 {
1140 return archive;
1141 }
1142
1143
1144
1145
1146 public List<String> getNonFilteredFileExtensions()
1147 {
1148 return nonFilteredFileExtensions;
1149 }
1150
1151
1152
1153
1154 public void setNonFilteredFileExtensions( List<String> nonFilteredFileExtensions )
1155 {
1156 this.nonFilteredFileExtensions = nonFilteredFileExtensions;
1157 }
1158
1159
1160
1161
1162 public ArtifactFactory getArtifactFactory()
1163 {
1164 return this.artifactFactory;
1165 }
1166
1167
1168
1169
1170 public void setArtifactFactory( ArtifactFactory artifactFactory )
1171 {
1172 this.artifactFactory = artifactFactory;
1173 }
1174
1175
1176
1177
1178 protected MavenSession getSession()
1179 {
1180 return this.session;
1181 }
1182
1183
1184
1185
1186 protected boolean isRecompressZippedFiles()
1187 {
1188 return recompressZippedFiles;
1189 }
1190
1191
1192
1193
1194 protected boolean isIncludeEmptyDirectories()
1195 {
1196 return includeEmptyDirectories;
1197 }
1198 }