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