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