Coverage Report - org.apache.maven.plugin.war.packaging.WarProjectPackagingTask
 
Classes in this File Line Coverage Branch Coverage Complexity
WarProjectPackagingTask
80%
80/99
64%
36/56
5,222
 
 1  
 package org.apache.maven.plugin.war.packaging;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.model.Resource;
 23  
 import org.apache.maven.plugin.MojoExecutionException;
 24  
 import org.apache.maven.plugin.MojoFailureException;
 25  
 import org.apache.maven.plugin.war.Overlay;
 26  
 import org.apache.maven.plugin.war.util.PathSet;
 27  
 import org.apache.maven.shared.filtering.MavenFilteringException;
 28  
 import org.codehaus.plexus.util.DirectoryScanner;
 29  
 import org.codehaus.plexus.util.StringUtils;
 30  
 
 31  
 import java.io.File;
 32  
 import java.io.IOException;
 33  
 import java.util.Iterator;
 34  
 
 35  
 /**
 36  
  * Handles the project own resources, that is:
 37  
  * <ul
 38  
  * <li>The list of web resources, if any</li>
 39  
  * <li>The content of the webapp directory if it exists</li>
 40  
  * <li>The custom deployment descriptor(s), if any</li>
 41  
  * <li>The content of the classes directory if it exists</li>
 42  
  * <li>The dependencies of the project</li>
 43  
  * </ul>
 44  
  *
 45  
  * @author Stephane Nicoll
 46  
  * @version $Id: WarProjectPackagingTask.java 1390132 2012-09-25 21:02:10Z dennisl $
 47  
  */
 48  
 public class WarProjectPackagingTask
 49  
     extends AbstractWarPackagingTask
 50  
 {
 51  
     private final Resource[] webResources;
 52  
 
 53  
     private final File webXml;
 54  
 
 55  
     private final File containerConfigXML;
 56  
 
 57  
     private final String id;
 58  
 
 59  
     private Overlay currentProjectOverlay;
 60  
 
 61  
 
 62  
     public WarProjectPackagingTask( Resource[] webResources, File webXml, File containerConfigXml,
 63  
                                     Overlay currentProjectOverlay )
 64  124
     {
 65  124
         if ( webResources != null )
 66  
         {
 67  12
             this.webResources = webResources;
 68  
         }
 69  
         else
 70  
         {
 71  112
             this.webResources = new Resource[0];
 72  
         }
 73  124
         this.webXml = webXml;
 74  124
         this.containerConfigXML = containerConfigXml;
 75  124
         this.currentProjectOverlay = currentProjectOverlay;
 76  124
         this.id = currentProjectOverlay.getId();
 77  124
     }
 78  
 
 79  
     public void performPackaging( WarPackagingContext context )
 80  
         throws MojoExecutionException, MojoFailureException
 81  
     {
 82  
 
 83  124
         context.getLog().info( "Processing war project" );
 84  
         // Prepare the INF directories
 85  124
         File webinfDir = new File( context.getWebappDirectory(), WEB_INF_PATH );
 86  124
         webinfDir.mkdirs();
 87  124
         File metainfDir = new File( context.getWebappDirectory(), META_INF_PATH );
 88  124
         metainfDir.mkdirs();
 89  
 
 90  124
         handleWebResources( context );
 91  
 
 92  124
         handeWebAppSourceDirectory( context );
 93  
 
 94  
         // Debug mode: dump the path set for the current build
 95  124
         PathSet pathSet = context.getWebappStructure().getStructure( "currentBuild" );
 96  124
         context.getLog().debug( "Dump of the current build pathSet content -->" );
 97  124
         for ( Iterator iterator = pathSet.iterator(); iterator.hasNext(); )
 98  
         {
 99  256
             context.getLog().debug( "" + iterator.next() );
 100  
         }
 101  124
         context.getLog().debug( "-- end of dump --" );
 102  
 
 103  124
         handleDeploymentDescriptors( context, webinfDir, metainfDir );
 104  
 
 105  124
         handleClassesDirectory( context );
 106  
 
 107  124
         handleArtifacts( context );
 108  124
     }
 109  
 
 110  
 
 111  
     /**
 112  
      * Handles the web resources.
 113  
      *
 114  
      * @param context the packaging context
 115  
      * @throws MojoExecutionException if a resource could not be copied
 116  
      */
 117  
     protected void handleWebResources( WarPackagingContext context )
 118  
         throws MojoExecutionException
 119  
     {
 120  136
         for ( int i = 0; i < webResources.length; i++ )
 121  
         {
 122  12
             Resource resource = webResources[i];
 123  
 
 124  
             // MWAR-246
 125  12
             if ( resource.getDirectory() == null )
 126  
             {
 127  0
                 throw new MojoExecutionException( "The <directory> tag is missing from the <resource> tag." );
 128  
             }
 129  
 
 130  12
             if ( !( new File( resource.getDirectory() ) ).isAbsolute() )
 131  
             {
 132  0
                 resource.setDirectory( context.getProject().getBasedir() + File.separator + resource.getDirectory() );
 133  
             }
 134  
 
 135  
             // Make sure that the resource directory is not the same as the webappDirectory
 136  12
             if ( !resource.getDirectory().equals( context.getWebappDirectory().getPath() ) )
 137  
             {
 138  
 
 139  
                 try
 140  
                 {
 141  12
                     copyResources( context, resource );
 142  
                 }
 143  0
                 catch ( IOException e )
 144  
                 {
 145  0
                     throw new MojoExecutionException( "Could not copy resource [" + resource.getDirectory() + "]", e );
 146  12
                 }
 147  
             }
 148  
         }
 149  124
     }
 150  
 
 151  
     /**
 152  
      * Handles the webapp sources.
 153  
      *
 154  
      * @param context the packaging context
 155  
      * @throws MojoExecutionException if the sources could not be copied
 156  
      */
 157  
     protected void handeWebAppSourceDirectory( WarPackagingContext context )
 158  
         throws MojoExecutionException
 159  
     {
 160  124
         if ( !context.getWebappSourceDirectory().exists() )
 161  
         {
 162  0
             context.getLog().debug( "webapp sources directory does not exist - skipping." );
 163  
         }
 164  124
         else if ( !context.getWebappSourceDirectory().getAbsolutePath().equals(
 165  
             context.getWebappDirectory().getPath() ) )
 166  
         {
 167  122
             context.getLog().info( "Copying webapp resources [" + context.getWebappSourceDirectory() + "]" );
 168  122
             final PathSet sources =
 169  
                 getFilesToIncludes( context.getWebappSourceDirectory(), context.getWebappSourceIncludes(),
 170  
                                     context.getWebappSourceExcludes() );
 171  
 
 172  
             try
 173  
             {
 174  122
                 copyFiles( id, context, context.getWebappSourceDirectory(), sources, false );
 175  
             }
 176  0
             catch ( IOException e )
 177  
             {
 178  0
                 throw new MojoExecutionException(
 179  
                     "Could not copy webapp sources [" + context.getWebappDirectory().getAbsolutePath() + "]", e );
 180  122
             }
 181  
         }
 182  124
     }
 183  
 
 184  
     /**
 185  
      * Handles the webapp artifacts.
 186  
      *
 187  
      * @param context the packaging context
 188  
      * @throws MojoExecutionException if the artifacts could not be packaged
 189  
      */
 190  
     protected void handleArtifacts( WarPackagingContext context )
 191  
         throws MojoExecutionException
 192  
     {
 193  124
         ArtifactsPackagingTask task = new ArtifactsPackagingTask( context.getProject().getArtifacts(),
 194  
                                                                   currentProjectOverlay );
 195  124
         task.performPackaging( context );
 196  124
     }
 197  
 
 198  
     /**
 199  
      * Handles the webapp classes.
 200  
      *
 201  
      * @param context the packaging context
 202  
      * @throws MojoExecutionException if the classes could not be packaged
 203  
      */
 204  
     protected void handleClassesDirectory( WarPackagingContext context )
 205  
         throws MojoExecutionException
 206  
     {
 207  124
         ClassesPackagingTask task = new ClassesPackagingTask( currentProjectOverlay );
 208  124
         task.performPackaging( context );
 209  124
     }
 210  
 
 211  
     /**
 212  
      * Handles the deployment descriptors, if specified. Note that the behavior
 213  
      * here is slightly different since the customized entry always win, even if
 214  
      * an overlay has already packaged a web.xml previously.
 215  
      *
 216  
      * @param context    the packaging context
 217  
      * @param webinfDir  the web-inf directory
 218  
      * @param metainfDir the meta-inf directory
 219  
      * @throws MojoFailureException   if the web.xml is specified but does not exist
 220  
      * @throws MojoExecutionException if an error occurred while copying the descriptors
 221  
      */
 222  
     protected void handleDeploymentDescriptors( WarPackagingContext context, File webinfDir, File metainfDir )
 223  
         throws MojoFailureException, MojoExecutionException
 224  
     {
 225  
         try
 226  
         {
 227  124
             if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
 228  
             {
 229  46
                 if ( !webXml.exists() )
 230  
                 {
 231  0
                     throw new MojoFailureException( "The specified web.xml file '" + webXml + "' does not exist" );
 232  
                 }
 233  
 
 234  
                 // Making sure that it won't get overlayed
 235  46
                 context.getWebappStructure().registerFileForced( id, WEB_INF_PATH + "/web.xml" );
 236  
 
 237  46
                 if ( context.isFilteringDeploymentDescriptors() )
 238  
                 {
 239  0
                     context.getMavenFileFilter().copyFile( webXml, new File( webinfDir, "web.xml" ), true,
 240  
                                                            context.getFilterWrappers(), getEncoding( webXml ) );
 241  
                 }
 242  
                 else
 243  
                 {
 244  46
                     copyFile( context, webXml, new File( webinfDir, "web.xml" ), "WEB-INF/web.xml", true );
 245  
                 }
 246  
             }
 247  
             else
 248  
             {
 249  
                 // the webXml can be the default one
 250  78
                 File defaultWebXml = new File( context.getWebappSourceDirectory(), WEB_INF_PATH + "/web.xml" );
 251  
                 // if exists we can filter it
 252  78
                 if ( defaultWebXml.exists() && context.isFilteringDeploymentDescriptors() )
 253  
                 {
 254  0
                     context.getWebappStructure().registerFile( id, WEB_INF_PATH + "/web.xml" );
 255  0
                     context.getMavenFileFilter().copyFile( defaultWebXml, new File( webinfDir, "web.xml" ), true,
 256  
                                                            context.getFilterWrappers(), getEncoding( defaultWebXml ) );
 257  
                 }
 258  
             }
 259  
 
 260  124
             if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
 261  
             {
 262  4
                 String xmlFileName = containerConfigXML.getName();
 263  
 
 264  4
                 context.getWebappStructure().registerFileForced( id, META_INF_PATH + "/" + xmlFileName );
 265  
 
 266  4
                 if ( context.isFilteringDeploymentDescriptors() )
 267  
                 {
 268  0
                     context.getMavenFileFilter().copyFile( containerConfigXML, new File( metainfDir, xmlFileName ),
 269  
                                                            true, context.getFilterWrappers(),
 270  
                                                            getEncoding( containerConfigXML ) );
 271  
                 }
 272  
                 else
 273  
                 {
 274  4
                     copyFile( context, containerConfigXML, new File( metainfDir, xmlFileName ),
 275  
                               "META-INF/" + xmlFileName, true );
 276  
                 }
 277  
             }
 278  
         }
 279  0
         catch ( IOException e )
 280  
         {
 281  0
             throw new MojoExecutionException( "Failed to copy deployment descriptor", e );
 282  
         }
 283  0
         catch ( MavenFilteringException e )
 284  
         {
 285  0
             throw new MojoExecutionException( "Failed to copy deployment descriptor", e );
 286  124
         }
 287  124
     }
 288  
 
 289  
     /**
 290  
      * Copies webapp webResources from the specified directory.
 291  
      *
 292  
      * @param context  the WAR packaging context to use
 293  
      * @param resource the resource to copy
 294  
      * @throws IOException            if an error occurred while copying the resources
 295  
      * @throws MojoExecutionException if an error occurred while retrieving the filter properties
 296  
      */
 297  
     public void copyResources( WarPackagingContext context, Resource resource )
 298  
         throws IOException, MojoExecutionException
 299  
     {
 300  12
         if ( !context.getWebappDirectory().exists() )
 301  
         {
 302  0
             context.getLog().warn(
 303  
                 "Not copying webapp webResources [" + resource.getDirectory() + "]: webapp directory ["
 304  
                     + context.getWebappDirectory().getAbsolutePath() + "] does not exist!" );
 305  
         }
 306  
 
 307  12
         context.getLog().info( "Copying webapp webResources [" + resource.getDirectory() + "] to ["
 308  
             + context.getWebappDirectory().getAbsolutePath() + "]" );
 309  12
         String[] fileNames = getFilesToCopy( resource );
 310  30
         for ( int i = 0; i < fileNames.length; i++ )
 311  
         {
 312  18
             String targetFileName = fileNames[i];
 313  18
             if ( resource.getTargetPath() != null )
 314  
             {
 315  
                 //TODO make sure this thing is 100% safe
 316  
                 // MWAR-129 if targetPath is only a dot <targetPath>.</targetPath> or ./
 317  
                 // and the Resource is in a part of the warSourceDirectory the file from sources will override this
 318  
                 // that's we don't have to add the targetPath yep not nice but works
 319  2
                 if ( !StringUtils.equals( ".", resource.getTargetPath() )
 320  
                     && !StringUtils.equals( "./", resource.getTargetPath() ) )
 321  
                 {
 322  2
                     targetFileName = resource.getTargetPath() + File.separator + targetFileName;
 323  
                 }
 324  
             }
 325  18
             if ( resource.isFiltering() && !context.isNonFilteredExtension( fileNames[i] ) )
 326  
             {
 327  12
                 copyFilteredFile( id, context, new File( resource.getDirectory(), fileNames[i] ), targetFileName );
 328  
             }
 329  
             else
 330  
             {
 331  6
                 copyFile( id, context, new File( resource.getDirectory(), fileNames[i] ), targetFileName );
 332  
             }
 333  
         }
 334  12
     }
 335  
 
 336  
 
 337  
     /**
 338  
      * Returns a list of filenames that should be copied
 339  
      * over to the destination directory.
 340  
      *
 341  
      * @param resource the resource to be scanned
 342  
      * @return the array of filenames, relative to the sourceDir
 343  
      */
 344  
     private String[] getFilesToCopy( Resource resource )
 345  
     {
 346  12
         DirectoryScanner scanner = new DirectoryScanner();
 347  12
         scanner.setBasedir( resource.getDirectory() );
 348  12
         if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
 349  
         {
 350  0
             scanner.setIncludes(
 351  
                 (String[]) resource.getIncludes().toArray( new String[resource.getIncludes().size()] ) );
 352  
         }
 353  
         else
 354  
         {
 355  12
             scanner.setIncludes( DEFAULT_INCLUDES );
 356  
         }
 357  12
         if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
 358  
         {
 359  0
             scanner.setExcludes(
 360  
                 (String[]) resource.getExcludes().toArray( new String[resource.getExcludes().size()] ) );
 361  
         }
 362  
 
 363  12
         scanner.addDefaultExcludes();
 364  
 
 365  12
         scanner.scan();
 366  
 
 367  12
         return scanner.getIncludedFiles();
 368  
     }
 369  
 }