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