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