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 org.apache.maven.archiver.MavenArchiveConfiguration;
23 import org.apache.maven.artifact.factory.ArtifactFactory;
24 import org.apache.maven.execution.MavenSession;
25 import org.apache.maven.model.Resource;
26 import org.apache.maven.plugin.AbstractMojo;
27 import org.apache.maven.plugin.MojoExecutionException;
28 import org.apache.maven.plugin.MojoFailureException;
29 import org.apache.maven.plugin.logging.Log;
30 import org.apache.maven.plugin.war.overlay.OverlayManager;
31 import org.apache.maven.plugin.war.packaging.DependenciesAnalysisPackagingTask;
32 import org.apache.maven.plugin.war.packaging.OverlayPackagingTask;
33 import org.apache.maven.plugin.war.packaging.SaveWebappStructurePostPackagingTask;
34 import org.apache.maven.plugin.war.packaging.WarPackagingContext;
35 import org.apache.maven.plugin.war.packaging.WarPackagingTask;
36 import org.apache.maven.plugin.war.packaging.WarPostPackagingTask;
37 import org.apache.maven.plugin.war.packaging.WarProjectPackagingTask;
38 import org.apache.maven.plugin.war.util.WebappStructure;
39 import org.apache.maven.plugin.war.util.WebappStructureSerializer;
40 import org.apache.maven.plugins.annotations.Component;
41 import org.apache.maven.plugins.annotations.Parameter;
42 import org.apache.maven.project.MavenProject;
43 import org.apache.maven.shared.filtering.MavenFileFilter;
44 import org.apache.maven.shared.filtering.MavenFilteringException;
45 import org.apache.maven.shared.filtering.MavenResourcesExecution;
46 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
47 import org.codehaus.plexus.archiver.Archiver;
48 import org.codehaus.plexus.archiver.jar.JarArchiver;
49 import org.codehaus.plexus.archiver.manager.ArchiverManager;
50 import org.codehaus.plexus.util.FileUtils;
51 import org.codehaus.plexus.util.StringUtils;
52
53 import java.io.File;
54 import java.io.IOException;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Collections;
58 import java.util.List;
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}@-@{version}@.@{extension}@";
69
70 public static final String DEFAULT_FILE_NAME_MAPPING_CLASSIFIER =
71 "@{artifactId}@-@{version}@-@{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 = "false" )
315 private boolean recompressZippedFiles;
316
317
318
319
320
321 @Parameter
322 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
323
324 private final WebappStructureSerializer webappStructureSerialier = new WebappStructureSerializer();
325
326 private final Overlay currentProjectOverlay = Overlay.createInstance();
327
328
329 public Overlay getCurrentProjectOverlay()
330 {
331 return currentProjectOverlay;
332 }
333
334
335
336
337
338
339
340 protected String[] getExcludes()
341 {
342 List<String> excludeList = new ArrayList<String>();
343 if ( StringUtils.isNotEmpty( warSourceExcludes ) )
344 {
345 excludeList.addAll( Arrays.asList( StringUtils.split( warSourceExcludes, "," ) ) );
346 }
347
348
349 if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
350 {
351 excludeList.add( "**/" + WEB_INF + "/web.xml" );
352 }
353
354
355 if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
356 {
357 excludeList.add( "**/" + META_INF + "/" + containerConfigXML.getName() );
358 }
359
360 return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY );
361 }
362
363
364
365
366
367
368
369 protected String[] getIncludes()
370 {
371 return StringUtils.split( StringUtils.defaultString( warSourceIncludes ), "," );
372 }
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
400 protected String[] getDependentWarIncludes()
401 {
402 return StringUtils.split( StringUtils.defaultString( dependentWarIncludes ), "," );
403 }
404
405 public void buildExplodedWebapp( File webappDirectory )
406 throws MojoExecutionException, MojoFailureException
407 {
408 webappDirectory.mkdirs();
409
410 try
411 {
412 buildWebapp( project, webappDirectory );
413 }
414 catch ( IOException e )
415 {
416 throw new MojoExecutionException( "Could not build webapp", e );
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434 @SuppressWarnings( "unchecked" )
435 public void buildWebapp( MavenProject project, File webappDirectory )
436 throws MojoExecutionException, MojoFailureException, IOException
437 {
438
439 WebappStructure cache;
440 if ( useCache && cacheFile.exists() )
441 {
442 cache = new WebappStructure( project.getDependencies(), webappStructureSerialier.fromXml( cacheFile ) );
443 }
444 else
445 {
446 cache = new WebappStructure( project.getDependencies(), null );
447 }
448
449 final long startTime = System.currentTimeMillis();
450 getLog().info( "Assembling webapp [" + project.getArtifactId() + "] in [" + webappDirectory + "]" );
451
452 final OverlayManager overlayManager =
453 new OverlayManager( overlays, project, dependentWarIncludes, dependentWarExcludes, currentProjectOverlay );
454 final List<WarPackagingTask> packagingTasks = getPackagingTasks( overlayManager );
455 List<FileUtils.FilterWrapper> defaultFilterWrappers = null;
456 try
457 {
458 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
459 mavenResourcesExecution.setEscapeString( escapeString );
460
461 defaultFilterWrappers = mavenFileFilter.getDefaultFilterWrappers( project, filters,
462 escapedBackslashesInFilePath,
463 this.session, mavenResourcesExecution );
464
465 }
466 catch ( MavenFilteringException e )
467 {
468 getLog().error( "fail to build filering wrappers " + e.getMessage() );
469 throw new MojoExecutionException( e.getMessage(), e );
470 }
471
472 final WarPackagingContext context = new DefaultWarPackagingContext( webappDirectory, cache, overlayManager,
473 defaultFilterWrappers,
474 getNonFilteredFileExtensions(),
475 filteringDeploymentDescriptors,
476 this.artifactFactory, resourceEncoding);
477 for ( WarPackagingTask warPackagingTask : packagingTasks )
478 {
479 warPackagingTask.performPackaging( context );
480 }
481
482
483 final List<WarPostPackagingTask> postPackagingTasks = getPostPackagingTasks();
484 for( WarPostPackagingTask task : postPackagingTasks )
485 {
486 task.performPostPackaging( context );
487 }
488 getLog().info( "Webapp assembled in [" + ( System.currentTimeMillis() - startTime ) + " msecs]" );
489
490 }
491
492
493
494
495
496
497
498
499
500 private List<WarPackagingTask> getPackagingTasks( OverlayManager overlayManager )
501 throws MojoExecutionException
502 {
503 final List<WarPackagingTask> packagingTasks = new ArrayList<WarPackagingTask>();
504 if ( useCache )
505 {
506 packagingTasks.add( new DependenciesAnalysisPackagingTask() );
507 }
508
509 final List<Overlay> resolvedOverlays = overlayManager.getOverlays();
510 for ( Overlay overlay : resolvedOverlays )
511 {
512 if ( overlay.isCurrentProject() )
513 {
514 packagingTasks.add( new WarProjectPackagingTask( webResources, webXml, containerConfigXML,
515 currentProjectOverlay ) );
516 }
517 else
518 {
519 packagingTasks.add( new OverlayPackagingTask( overlay, currentProjectOverlay ) );
520 }
521 }
522 return packagingTasks;
523 }
524
525
526
527
528
529
530
531
532 private List<WarPostPackagingTask> getPostPackagingTasks()
533 {
534 final List<WarPostPackagingTask> postPackagingTasks = new ArrayList<WarPostPackagingTask>();
535 if ( useCache )
536 {
537 postPackagingTasks.add( new SaveWebappStructurePostPackagingTask( cacheFile ) );
538 }
539
540 return postPackagingTasks;
541 }
542
543
544
545
546 private class DefaultWarPackagingContext
547 implements WarPackagingContext
548 {
549
550 private final ArtifactFactory artifactFactory;
551
552 private final String resourceEncoding;
553
554 private final WebappStructure webappStructure;
555
556 private final File webappDirectory;
557
558 private final OverlayManager overlayManager;
559
560 private final List<FileUtils.FilterWrapper> filterWrappers;
561
562 private List<String> nonFilteredFileExtensions;
563
564 private boolean filteringDeploymentDescriptors;
565
566 public DefaultWarPackagingContext( File webappDirectory, final WebappStructure webappStructure,
567 final OverlayManager overlayManager, List<FileUtils.FilterWrapper> filterWrappers,
568 List<String> nonFilteredFileExtensions, boolean filteringDeploymentDescriptors,
569 ArtifactFactory artifactFactory, String resourceEncoding )
570 {
571 this.webappDirectory = webappDirectory;
572 this.webappStructure = webappStructure;
573 this.overlayManager = overlayManager;
574 this.filterWrappers = filterWrappers;
575 this.artifactFactory = artifactFactory;
576 this.filteringDeploymentDescriptors = filteringDeploymentDescriptors;
577 this.nonFilteredFileExtensions = nonFilteredFileExtensions == null ? Collections.<String>emptyList()
578 : nonFilteredFileExtensions;
579 this.resourceEncoding = resourceEncoding;
580
581
582 for ( String overlayId : overlayManager.getOverlayIds() )
583 {
584 webappStructure.getStructure( overlayId );
585 }
586 }
587
588 public MavenProject getProject()
589 {
590 return project;
591 }
592
593 public File getWebappDirectory()
594 {
595 return webappDirectory;
596 }
597
598 public File getClassesDirectory()
599 {
600 return classesDirectory;
601 }
602
603 public Log getLog()
604 {
605 return AbstractWarMojo.this.getLog();
606 }
607
608 public String getOutputFileNameMapping()
609 {
610 return outputFileNameMapping;
611 }
612
613 public File getWebappSourceDirectory()
614 {
615 return warSourceDirectory;
616 }
617
618 public String[] getWebappSourceIncludes()
619 {
620 return getIncludes();
621 }
622
623 public String[] getWebappSourceExcludes()
624 {
625 return getExcludes();
626 }
627
628 public boolean archiveClasses()
629 {
630 return archiveClasses;
631 }
632
633 public File getOverlaysWorkDirectory()
634 {
635 return workDirectory;
636 }
637
638 public ArchiverManager getArchiverManager()
639 {
640 return archiverManager;
641 }
642
643 public MavenArchiveConfiguration getArchive()
644 {
645 return archive;
646 }
647
648 public JarArchiver getJarArchiver()
649 {
650 return jarArchiver;
651 }
652
653 public List<String> getFilters()
654 {
655 return filters;
656 }
657
658 public WebappStructure getWebappStructure()
659 {
660 return webappStructure;
661 }
662
663 public List<String> getOwnerIds()
664 {
665 return overlayManager.getOverlayIds();
666 }
667
668 public MavenFileFilter getMavenFileFilter()
669 {
670 return mavenFileFilter;
671 }
672
673 public List<FileUtils.FilterWrapper> getFilterWrappers()
674 {
675 return filterWrappers;
676 }
677
678 public boolean isNonFilteredExtension( String fileName )
679 {
680 return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
681 }
682
683 public boolean isFilteringDeploymentDescriptors()
684 {
685 return filteringDeploymentDescriptors;
686 }
687
688 public ArtifactFactory getArtifactFactory()
689 {
690 return this.artifactFactory;
691 }
692
693 public MavenSession getSession()
694 {
695 return session;
696 }
697
698 public String getResourceEncoding()
699 {
700 return resourceEncoding;
701 }
702 }
703
704 public MavenProject getProject()
705 {
706 return project;
707 }
708
709 public void setProject( MavenProject project )
710 {
711 this.project = project;
712 }
713
714 public File getClassesDirectory()
715 {
716 return classesDirectory;
717 }
718
719 public void setClassesDirectory( File classesDirectory )
720 {
721 this.classesDirectory = classesDirectory;
722 }
723
724 public File getWebappDirectory()
725 {
726 return webappDirectory;
727 }
728
729 public void setWebappDirectory( File webappDirectory )
730 {
731 this.webappDirectory = webappDirectory;
732 }
733
734 public File getWarSourceDirectory()
735 {
736 return warSourceDirectory;
737 }
738
739 public void setWarSourceDirectory( File warSourceDirectory )
740 {
741 this.warSourceDirectory = warSourceDirectory;
742 }
743
744 public File getWebXml()
745 {
746 return webXml;
747 }
748
749 public void setWebXml( File webXml )
750 {
751 this.webXml = webXml;
752 }
753
754 public File getContainerConfigXML()
755 {
756 return containerConfigXML;
757 }
758
759 public void setContainerConfigXML( File containerConfigXML )
760 {
761 this.containerConfigXML = containerConfigXML;
762 }
763
764 public String getOutputFileNameMapping()
765 {
766 return outputFileNameMapping;
767 }
768
769 public void setOutputFileNameMapping( String outputFileNameMapping )
770 {
771 this.outputFileNameMapping = outputFileNameMapping;
772 }
773
774 public List<Overlay> getOverlays()
775 {
776 return overlays;
777 }
778
779 public void setOverlays( List<Overlay> overlays )
780 {
781 this.overlays = overlays;
782 }
783
784 public void addOverlay( Overlay overlay )
785 {
786 overlays.add( overlay );
787 }
788
789 public boolean isArchiveClasses()
790 {
791 return archiveClasses;
792 }
793
794 public void setArchiveClasses( boolean archiveClasses )
795 {
796 this.archiveClasses = archiveClasses;
797 }
798
799 public JarArchiver getJarArchiver()
800 {
801 return jarArchiver;
802 }
803
804 public void setJarArchiver( JarArchiver jarArchiver )
805 {
806 this.jarArchiver = jarArchiver;
807 }
808
809 public Resource[] getWebResources()
810 {
811 return webResources;
812 }
813
814 public void setWebResources( Resource[] webResources )
815 {
816 this.webResources = webResources;
817 }
818
819 public List<String> getFilters()
820 {
821 return filters;
822 }
823
824 public void setFilters( List<String> filters )
825 {
826 this.filters = filters;
827 }
828
829 public File getWorkDirectory()
830 {
831 return workDirectory;
832 }
833
834 public void setWorkDirectory( File workDirectory )
835 {
836 this.workDirectory = workDirectory;
837 }
838
839 public File getCacheFile()
840 {
841 return cacheFile;
842 }
843
844 public void setCacheFile( File cacheFile )
845 {
846 this.cacheFile = cacheFile;
847 }
848
849 public String getWarSourceIncludes()
850 {
851 return warSourceIncludes;
852 }
853
854 public void setWarSourceIncludes( String warSourceIncludes )
855 {
856 this.warSourceIncludes = warSourceIncludes;
857 }
858
859 public String getWarSourceExcludes()
860 {
861 return warSourceExcludes;
862 }
863
864 public void setWarSourceExcludes( String warSourceExcludes )
865 {
866 this.warSourceExcludes = warSourceExcludes;
867 }
868
869
870 public boolean isUseCache()
871 {
872 return useCache;
873 }
874
875 public void setUseCache( boolean useCache )
876 {
877 this.useCache = useCache;
878 }
879
880 public MavenArchiveConfiguration getArchive()
881 {
882 return archive;
883 }
884
885 public List<String> getNonFilteredFileExtensions()
886 {
887 return nonFilteredFileExtensions;
888 }
889
890 public void setNonFilteredFileExtensions( List<String> nonFilteredFileExtensions )
891 {
892 this.nonFilteredFileExtensions = nonFilteredFileExtensions;
893 }
894
895 public ArtifactFactory getArtifactFactory()
896 {
897 return this.artifactFactory;
898 }
899
900 public void setArtifactFactory( ArtifactFactory artifactFactory )
901 {
902 this.artifactFactory = artifactFactory;
903 }
904
905 protected MavenSession getSession()
906 {
907 return this.session;
908 }
909
910 protected boolean isRecompressZippedFiles()
911 {
912 return recompressZippedFiles;
913 }
914 }