You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sn...@apache.org on 2007/08/12 12:26:18 UTC

svn commit: r565036 [1/2] - in /maven/plugins/trunk/maven-war-plugin: ./ src/main/java/org/apache/maven/plugin/war/ src/main/java/org/apache/maven/plugin/war/overlay/ src/main/java/org/apache/maven/plugin/war/packaging/ src/main/java/org/apache/maven/p...

Author: snicoll
Date: Sun Aug 12 03:26:14 2007
New Revision: 565036

URL: http://svn.apache.org/viewvc?view=rev&rev=565036
Log:
MWAR-97: Merged overlay work in the Trunk

Added:
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/Overlay.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/Overlay.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/overlay/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/overlay/
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/overlay/DefaultOverlay.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/overlay/DefaultOverlay.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/overlay/InvalidOverlayConfigurationException.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/overlay/InvalidOverlayConfigurationException.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/overlay/OverlayManager.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/overlay/OverlayManager.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/AbstractWarPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/AbstractWarPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/ArtifactsPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/ArtifactsPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/ClassesPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/ClassesPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/OverlayPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/OverlayPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/SaveWebappStructurePostPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/SaveWebappStructurePostPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingContext.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingContext.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/WarPostPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/WarPostPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/packaging/WarProjectPackagingTask.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/packaging/WarProjectPackagingTask.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/MappingUtils.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/MappingUtils.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PathSet.java
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PathSet.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/WebappStructure.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/WebappStructure.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/WebappStructureSerializer.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/WebappStructureSerializer.java
    maven/plugins/trunk/maven-war-plugin/src/site/apt/overlays.apt
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/site/apt/overlays.apt
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/WarOverlaysTest.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/WarOverlaysTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/overlay/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/overlay/
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/overlay/OverlayManagerTest.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/overlay/OverlayManagerTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/WarArtifact4CCStub.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/stub/WarArtifact4CCStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/WarArtifactStub.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/stub/WarArtifactStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/WarOverlayStub.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/stub/WarOverlayStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/util/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/util/
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/util/MappingUtilsTest.java
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/util/MappingUtilsTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/util/PathSetTest.java
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/util/PathSetTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/util/PropertyUtilsTest.java   (contents, props changed)
      - copied, changed from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/util/PropertyUtilsTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-one/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-one/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-one/WEB-INF/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-one/WEB-INF/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-one/WEB-INF/web.xml
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-one/WEB-INF/web.xml
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-one/index.jsp
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-one/index.jsp
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-one/login.jsp
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-one/login.jsp
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-two/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-two/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-two/WEB-INF/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-two/WEB-INF/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-two/WEB-INF/web.xml
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-two/WEB-INF/web.xml
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-two/admin.jsp
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-two/admin.jsp
    maven/plugins/trunk/maven-war-plugin/src/test/resources/overlays/overlay-two/index.jsp
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/overlays/overlay-two/index.jsp
    maven/plugins/trunk/maven-war-plugin/src/test/resources/unit/waroverlays/
      - copied from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/unit/waroverlays/
    maven/plugins/trunk/maven-war-plugin/src/test/resources/unit/waroverlays/default.xml
      - copied unchanged from r565032, maven/plugins/branches/MWAR-97-2/src/test/resources/unit/waroverlays/default.xml
Removed:
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/CompositeMap.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/MappingUtils.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/PropertyUtils.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/ReflectionProperties.java
    maven/plugins/trunk/maven-war-plugin/src/site/apt/examples/war-overlay.apt
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/MappingUtilsTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/PropertyUtilsTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/SimpleWarArtifact4CCStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/SimpleWarArtifactStub.java
Modified:
    maven/plugins/trunk/maven-war-plugin/pom.xml
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java
    maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarMojo.java
    maven/plugins/trunk/maven-war-plugin/src/site/apt/index.apt
    maven/plugins/trunk/maven-war-plugin/src/site/site.xml
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/WarExplodedMojoTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/WarMojoTest.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/AbstractArtifactStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/IncludeExcludeWarArtifactStub.java
    maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/stub/MavenProjectArtifactsStub.java

Modified: maven/plugins/trunk/maven-war-plugin/pom.xml
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/pom.xml?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/pom.xml (original)
+++ maven/plugins/trunk/maven-war-plugin/pom.xml Sun Aug 12 03:26:14 2007
@@ -17,7 +17,9 @@
 under the License.
 
 -->
-<project xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd' xmlns='http://maven.apache.org/POM/4.0.0'>
+<project xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+         xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'
+         xmlns='http://maven.apache.org/POM/4.0.0'>
   <parent>
     <artifactId>maven-plugins</artifactId>
     <groupId>org.apache.maven.plugins</groupId>
@@ -27,7 +29,7 @@
   <artifactId>maven-war-plugin</artifactId>
   <packaging>maven-plugin</packaging>
   <name>Maven War Plugin</name>
-  <version>2.0.3-SNAPSHOT</version>
+  <version>2.1-alpha-1-SNAPSHOT</version>
   <prerequisites>
     <maven>2.0.1</maven>
   </prerequisites>
@@ -55,6 +57,11 @@
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
       <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>com.thoughtworks.xstream</groupId>
+      <artifactId>xstream</artifactId>
+      <version>1.2.2</version>
     </dependency>
     <dependency>
       <groupId>junit</groupId>

Modified: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java Sun Aug 12 03:26:14 2007
@@ -20,43 +20,36 @@
  */
 
 import org.apache.maven.archiver.MavenArchiveConfiguration;
-import org.apache.maven.archiver.MavenArchiver;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.war.overlay.OverlayManager;
+import org.apache.maven.plugin.war.packaging.OverlayPackagingTask;
+import org.apache.maven.plugin.war.packaging.SaveWebappStructurePostPackagingTask;
+import org.apache.maven.plugin.war.packaging.WarPackagingContext;
+import org.apache.maven.plugin.war.packaging.WarPackagingTask;
+import org.apache.maven.plugin.war.packaging.WarPostPackagingTask;
+import org.apache.maven.plugin.war.packaging.WarProjectPackagingTask;
+import org.apache.maven.plugin.war.util.CompositeMap;
+import org.apache.maven.plugin.war.util.PropertyUtils;
+import org.apache.maven.plugin.war.util.ReflectionProperties;
+import org.apache.maven.plugin.war.util.WebappStructure;
+import org.apache.maven.plugin.war.util.WebappStructureSerializer;
 import org.apache.maven.project.MavenProject;
-import org.codehaus.plexus.archiver.ArchiverException;
-import org.codehaus.plexus.archiver.UnArchiver;
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
-import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
-import org.codehaus.plexus.util.DirectoryScanner;
-import org.codehaus.plexus.util.FileUtils;
-import org.codehaus.plexus.util.IOUtil;
-import org.codehaus.plexus.util.InterpolationFilterReader;
 import org.codehaus.plexus.util.StringUtils;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 
 public abstract class AbstractWarMojo
     extends AbstractMojo
@@ -158,6 +151,24 @@
     private String outputFileNameMapping;
 
     /**
+     * The file containing the webapp structure cache.
+     *
+     * @parameter expression="${project.build.directory}/war/work/webapp-cache.xml"
+     * @required
+     * @since 2.1
+     */
+    private File cacheFile;
+
+    /**
+     * Whether the cache should be used to save the status of the webapp
+     * accross multiple runs.
+     *
+     * @parameter expression="${useCache}" default-value="true"
+     * @since 2.1
+     */
+    private boolean useCache = true;
+
+    /**
      * To look up Archiver/UnArchiver implementations
      *
      * @parameter expression="${component.org.codehaus.plexus.archiver.manager.ArchiverManager}"
@@ -169,12 +180,10 @@
 
     private static final String META_INF = "META-INF";
 
-    private static final String[] DEFAULT_INCLUDES = {"**/**"};
-
-    private static final String DEFAULT_FILE_NAME_MAPPING_CLASSIFIER =
+    public static final String DEFAULT_FILE_NAME_MAPPING_CLASSIFIER =
         "${artifactId}-${version}-${classifier}.${extension}";
 
-    private static final String DEFAULT_FILE_NAME_MAPPING = "${artifactId}-${version}.${extension}";
+    public static final String DEFAULT_FILE_NAME_MAPPING = "${artifactId}-${version}.${extension}";
 
     /**
      * The comma separated list of tokens to include in the WAR.
@@ -198,7 +207,7 @@
      *
      * @parameter
      */
-    private String dependentWarIncludes = "**";
+    private String dependentWarIncludes = "**/**";
 
     /**
      * The comma separated list of tokens to exclude when doing
@@ -206,7 +215,15 @@
      *
      * @parameter
      */
-    private String dependentWarExcludes;
+    private String dependentWarExcludes = "META-INF/**";
+
+    /**
+     * The overlays to apply.
+     *
+     * @parameter
+     * @since 2.1
+     */
+    private List overlays = new ArrayList();
 
     /**
      * The maven archive configuration to use.
@@ -217,76 +234,7 @@
 
     private static final String[] EMPTY_STRING_ARRAY = {};
 
-
-    public MavenProject getProject()
-    {
-        return project;
-    }
-
-    public void setProject( MavenProject project )
-    {
-        this.project = project;
-    }
-
-    public File getClassesDirectory()
-    {
-        return classesDirectory;
-    }
-
-    public void setClassesDirectory( File classesDirectory )
-    {
-        this.classesDirectory = classesDirectory;
-    }
-
-    public File getWebappDirectory()
-    {
-        return webappDirectory;
-    }
-
-    public void setWebappDirectory( File webappDirectory )
-    {
-        this.webappDirectory = webappDirectory;
-    }
-
-    public File getWarSourceDirectory()
-    {
-        return warSourceDirectory;
-    }
-
-    public void setWarSourceDirectory( File warSourceDirectory )
-    {
-        this.warSourceDirectory = warSourceDirectory;
-    }
-
-    public File getWebXml()
-    {
-        return webXml;
-    }
-
-    public void setWebXml( File webXml )
-    {
-        this.webXml = webXml;
-    }
-
-    public File getContainerConfigXML()
-    {
-        return containerConfigXML;
-    }
-
-    public void setContainerConfigXML( File containerConfigXML )
-    {
-        this.containerConfigXML = containerConfigXML;
-    }
-
-    public String getOutputFileNameMapping()
-    {
-        return outputFileNameMapping;
-    }
-
-    public void setOutputFileNameMapping( String outputFileNameMapping )
-    {
-        this.outputFileNameMapping = outputFileNameMapping;
-    }
+    private final WebappStructureSerializer webappStructureSerialier = new WebappStructureSerializer();
 
     /**
      * Returns a string array of the excludes to be used
@@ -362,8 +310,6 @@
     public void buildExplodedWebapp( File webappDirectory )
         throws MojoExecutionException, MojoFailureException
     {
-        getLog().info( "Exploding webapp..." );
-
         webappDirectory.mkdirs();
 
         try
@@ -372,715 +318,427 @@
         }
         catch ( IOException e )
         {
-            throw new MojoExecutionException( "Could not explode webapp...", e );
+            throw new MojoExecutionException( "Could not build webapp", e );
         }
     }
 
-    private Map getBuildFilterProperties()
-        throws MojoExecutionException
-    {
 
-        Map filterProperties = new Properties();
+    /**
+     * Builds the webapp for the specified project with the new packaging task
+     * thingy
+     * <p/>
+     * Classes, libraries and tld files are copied to
+     * the <tt>webappDirectory</tt> during this phase.
+     *
+     * @param project         the maven project
+     * @param webappDirectory the target directory
+     * @throws MojoExecutionException if an error occured while packaging the webapp
+     * @throws MojoFailureException   if an unexpected error occured while packaging the webapp
+     * @throws IOException            if an error occured while copying the files
+     */
+    public void buildWebapp( MavenProject project, File webappDirectory )
+        throws MojoExecutionException, MojoFailureException, IOException
+    {
 
-        // System properties
-        filterProperties.putAll( System.getProperties() );
+        WebappStructure cache;
+        if ( useCache && cacheFile.exists() )
+        {
+            cache = new WebappStructure( webappStructureSerialier.fromXml( cacheFile ) );
+        }
+        else
+        {
+            cache = new WebappStructure( null );
+        }
 
-        // Project properties
-        filterProperties.putAll( project.getProperties() );
+        final long startTime = System.currentTimeMillis();
+        getLog().info( "Assembling webapp[" + project.getArtifactId() + "] in [" + webappDirectory + "]" );
 
-        for ( Iterator i = filters.iterator(); i.hasNext(); )
+        final OverlayManager overlayManager =
+            new OverlayManager( overlays, project, dependentWarIncludes, dependentWarExcludes );
+        final List packagingTasks = getPackagingTasks( overlayManager );
+        final WarPackagingContext context = new DefaultWarPackagingContext( webappDirectory, cache, overlayManager );
+        final Iterator it = packagingTasks.iterator();
+        while ( it.hasNext() )
         {
-            String filtersfile = (String) i.next();
+            WarPackagingTask warPackagingTask = (WarPackagingTask) it.next();
+            warPackagingTask.performPackaging( context );
+        }
 
-            try
-            {
-                Properties properties = PropertyUtils.loadPropertyFile( new File( filtersfile ), true, true );
+        // Post packaging
+        final List postPackagingTasks = getPostPackagingTasks();
+        final Iterator it2 = postPackagingTasks.iterator();
+        while ( it2.hasNext() )
+        {
+            WarPostPackagingTask task = (WarPostPackagingTask) it2.next();
+            task.performPostPackaging( context );
 
-                filterProperties.putAll( properties );
-            }
-            catch ( IOException e )
-            {
-                throw new MojoExecutionException( "Error loading property file '" + filtersfile + "'", e );
-            }
         }
+        getLog().info( "Webapp assembled in[" + ( System.currentTimeMillis() - startTime ) + " msecs]" );
 
-        // can't putAll, as ReflectionProperties doesn't enumerate - so we make a composite map with the project variables as dominant
-        return new CompositeMap( new ReflectionProperties( project ), filterProperties );
     }
 
     /**
-     * Copies webapp webResources from the specified directory.
-     * <p/>
-     * Note that the <tt>webXml</tt> parameter could be null and may
-     * specify a file which is not named <tt>web.xml<tt>. If the file
-     * exists, it will be copied to the <tt>META-INF</tt> directory and
-     * renamed accordingly.
-     *
-     * @param resource         the resource to copy
-     * @param webappDirectory  the target directory
-     * @param filterProperties
-     * @throws java.io.IOException if an error occured while copying webResources
+     * Returns a <tt>List</tt> of the {@link org.apache.maven.plugin.war.packaging.WarPackagingTask}
+     * instances to invoke to perform the packaging.
+     *
+     * @param overlayManager the overlay manager
+     * @return the list of packaging tasks
+     * @throws MojoExecutionException if the packaging tasks could not be built
      */
-    public void copyResources( Resource resource, File webappDirectory, Map filterProperties )
-        throws IOException
+    private List getPackagingTasks( OverlayManager overlayManager )
+        throws MojoExecutionException
     {
-        if ( !resource.getDirectory().equals( webappDirectory.getPath() ) )
+        final List packagingTasks = new ArrayList();
+        final List resolvedOverlays = overlayManager.getOverlays();
+        final Iterator it = resolvedOverlays.iterator();
+        while ( it.hasNext() )
         {
-            getLog().info( "Copy webapp webResources to " + webappDirectory.getAbsolutePath() );
-            if ( webappDirectory.exists() )
+            Overlay overlay = (Overlay) it.next();
+            if ( overlay.isCurrentProject() )
             {
-                String[] fileNames = getWarFiles( resource );
-                String targetPath = ( resource.getTargetPath() == null ) ? "" : resource.getTargetPath();
-                File destination = new File( webappDirectory, targetPath );
-                for ( int i = 0; i < fileNames.length; i++ )
-                {
-                    if ( resource.isFiltering() )
-                    {
-                        copyFilteredFile( new File( resource.getDirectory(), fileNames[i] ),
-                                          new File( destination, fileNames[i] ), null, getFilterWrappers(),
-                                          filterProperties );
-                    }
-                    else
-                    {
-                        copyFileIfModified( new File( resource.getDirectory(), fileNames[i] ),
-                                            new File( destination, fileNames[i] ) );
-                    }
-                }
+                packagingTasks.add( new WarProjectPackagingTask( webResources, webXml, containerConfigXML ) );
+            }
+            else
+            {
+                packagingTasks.add( new OverlayPackagingTask( overlay ) );
             }
         }
+        return packagingTasks;
     }
 
+
     /**
-     * Copies webapp webResources from the specified directory.
-     * <p/>
-     * Note that the <tt>webXml</tt> parameter could be null and may
-     * specify a file which is not named <tt>web.xml<tt>. If the file
-     * exists, it will be copied to the <tt>META-INF</tt> directory and
-     * renamed accordingly.
+     * Returns a <tt>List</tt> of the {@link org.apache.maven.plugin.war.packaging.WarPostPackagingTask}
+     * instances to invoke to perform the post-packaging.
      *
-     * @param sourceDirectory the source directory
-     * @param webappDirectory the target directory
-     * @throws java.io.IOException if an error occured while copying webResources
+     * @return the list of post packaging tasks
      */
-    public void copyResources( File sourceDirectory, File webappDirectory )
-        throws IOException
+    private List getPostPackagingTasks()
     {
-        if ( !sourceDirectory.equals( webappDirectory ) )
+        final List postPackagingTasks = new ArrayList();
+        if ( useCache )
         {
-            getLog().info( "Copy webapp webResources to " + webappDirectory.getAbsolutePath() );
-            if ( warSourceDirectory.exists() )
-            {
-                String[] fileNames = getWarFiles( sourceDirectory );
-                for ( int i = 0; i < fileNames.length; i++ )
-                {
-                    copyFileIfModified( new File( sourceDirectory, fileNames[i] ),
-                                        new File( webappDirectory, fileNames[i] ) );
-                }
-            }
+            postPackagingTasks.add( new SaveWebappStructurePostPackagingTask( cacheFile ) );
         }
+        // TODO add lib scanning to detect duplicates
+        return postPackagingTasks;
     }
 
-    /**
-     * Generates the JAR.
-     *
-     * @todo Add license files in META-INF directory.
-     */
-    public void createJarArchive( File libDirectory )
-        throws MojoExecutionException
+    // War packaging implementation
+
+    private class DefaultWarPackagingContext
+        implements WarPackagingContext
     {
-        String archiveName = project.getBuild().getFinalName() + ".jar";
 
-        File jarFile = new File( libDirectory, archiveName );
 
-        MavenArchiver archiver = new MavenArchiver();
+        private final WebappStructure webappStructure;
 
-        archiver.setArchiver( jarArchiver );
+        private final File webappDirectory;
 
-        archiver.setOutputFile( jarFile );
+        private final OverlayManager overlayManager;
 
-        try
+        public DefaultWarPackagingContext( File webappDirectory, final WebappStructure webappStructure,
+                                           final OverlayManager overlayManager )
         {
-            archiver.getArchiver().addDirectory( classesDirectory, getIncludes(), getExcludes() );
+            this.webappDirectory = webappDirectory;
+            this.webappStructure = webappStructure;
+            this.overlayManager = overlayManager;
 
-            archiver.createArchive( project, archive );
+            // This is kinda stupid but if we loop over the current overlays and we request the path structure
+            // it will register it. This will avoid wrong warning messages in a later phase
+            final Iterator it = overlayManager.getOverlayIds().iterator();
+            while ( it.hasNext() )
+            {
+                String overlayId = (String) it.next();
+                webappStructure.getStructure( overlayId );
+            }
         }
-        catch ( Exception e )
+
+        public MavenProject getProject()
         {
-            // TODO: improve error handling
-            throw new MojoExecutionException( "Error assembling JAR", e );
+            return project;
         }
-    }
-
-    /**
-     * Builds the webapp for the specified project.
-     * <p/>
-     * Classes, libraries and tld files are copied to
-     * the <tt>webappDirectory</tt> during this phase.
-     *
-     * @param project         the maven project
-     * @param webappDirectory
-     * @throws java.io.IOException if an error occured while building the webapp
-     */
-    public void buildWebapp( MavenProject project, File webappDirectory )
-        throws MojoExecutionException, IOException, MojoFailureException
-    {
-        getLog().info( "Assembling webapp " + project.getArtifactId() + " in " + webappDirectory );
-
-        File webinfDir = new File( webappDirectory, WEB_INF );
-        webinfDir.mkdirs();
 
-        File metainfDir = new File( webappDirectory, META_INF );
-        metainfDir.mkdirs();
-
-        List webResources = this.webResources != null ? Arrays.asList( this.webResources ) : null;
-        if ( webResources != null && webResources.size() > 0 )
+        public File getWebappDirectory()
         {
-            Map filterProperties = getBuildFilterProperties();
-            for ( Iterator it = webResources.iterator(); it.hasNext(); )
-            {
-                Resource resource = (Resource) it.next();
-                if ( !( new File( resource.getDirectory() ) ).isAbsolute() )
-                {
-                    resource.setDirectory( project.getBasedir() + File.separator + resource.getDirectory() );
-                }
-                copyResources( resource, webappDirectory, filterProperties );
-            }
+            return webappDirectory;
         }
 
-        copyResources( warSourceDirectory, webappDirectory );
+        public File getClassesDirectory()
+        {
+            return classesDirectory;
+        }
 
-        if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
+        public Log getLog()
         {
-            if ( !webXml.exists() )
-            {
-                throw new MojoFailureException( "The specified web.xml file '" + webXml + "' does not exist" );
-            }
+            return AbstractWarMojo.this.getLog();
+        }
 
-            //rename to web.xml
-            copyFileIfModified( webXml, new File( webinfDir, "/web.xml" ) );
+        public String getOutputFileNameMapping()
+        {
+            return outputFileNameMapping;
         }
 
-        if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
+        public File getWebappSourceDirectory()
         {
-            metainfDir = new File( webappDirectory, META_INF );
-            String xmlFileName = containerConfigXML.getName();
-            copyFileIfModified( containerConfigXML, new File( metainfDir, xmlFileName ) );
+            return warSourceDirectory;
         }
 
-        File libDirectory = new File( webinfDir, "lib" );
+        public String[] getWebappSourceIncludes()
+        {
+            return getIncludes();
+        }
 
-        File servicesDirectory = new File( webinfDir, "services" );
+        public String[] getWebappSourceExcludes()
+        {
+            return getExcludes();
+        }
 
-        File tldDirectory = new File( webinfDir, "tld" );
+        public boolean archiveClasses()
+        {
+            return archiveClasses;
+        }
 
-        File webappClassesDirectory = new File( webappDirectory, WEB_INF + "/classes" );
+        public File getOverlaysWorkDirectory()
+        {
+            return workDirectory;
+        }
 
-        if ( classesDirectory.exists() && !classesDirectory.equals( webappClassesDirectory ) )
+        public ArchiverManager getArchiverManager()
         {
-            if ( archiveClasses )
-            {
-                createJarArchive( libDirectory );
-            }
-            else
-            {
-                copyDirectoryStructureIfModified( classesDirectory, webappClassesDirectory );
-            }
+            return archiverManager;
         }
 
-        Set artifacts = project.getArtifacts();
+        public MavenArchiveConfiguration getArchive()
+        {
+            return archive;
+        }
 
-        List duplicates = findDuplicates( artifacts );
+        public JarArchiver getJarArchiver()
+        {
+            return jarArchiver;
+        }
 
-        List dependentWarDirectories = new ArrayList();
+        public List getFilters()
+        {
+            return filters;
+        }
 
-        for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+        public Map getFilterProperties()
+            throws MojoExecutionException
         {
-            Artifact artifact = (Artifact) iter.next();
-            String targetFileName = getFinalName( artifact );
+            Map filterProperties = new Properties();
 
-            getLog().debug( "Processing: " + targetFileName );
+            // System properties
+            filterProperties.putAll( System.getProperties() );
 
-            if ( duplicates.contains( targetFileName ) )
-            {
-                getLog().debug( "Duplicate found: " + targetFileName );
-                targetFileName = artifact.getGroupId() + "-" + targetFileName;
-                getLog().debug( "Renamed to: " + targetFileName );
-            }
+            // Project properties
+            filterProperties.putAll( project.getProperties() );
 
-            // TODO: utilise appropriate methods from project builder
-            ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
-            if ( !artifact.isOptional() && filter.include( artifact ) )
+            for ( Iterator i = filters.iterator(); i.hasNext(); )
             {
-                String type = artifact.getType();
-                if ( "tld".equals( type ) )
-                {
-                    copyFileIfModified( artifact.getFile(), new File( tldDirectory, targetFileName ) );
-                }
-                else if ( "aar".equals( type ) )
+                String filtersfile = (String) i.next();
+
+                try
                 {
-                    copyFileIfModified( artifact.getFile(), new File( servicesDirectory, targetFileName ) );
+                    Properties properties = PropertyUtils.loadPropertyFile( new File( filtersfile ), true, true );
+
+                    filterProperties.putAll( properties );
                 }
-                else
+                catch ( IOException e )
                 {
-                    if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type ) ||
-                        "test-jar".equals( type ) )
-                    {
-                        copyFileIfModified( artifact.getFile(), new File( libDirectory, targetFileName ) );
-                    }
-                    else
-                    {
-                        if ( "par".equals( type ) )
-                        {
-                            targetFileName = targetFileName.substring( 0, targetFileName.lastIndexOf( '.' ) ) + ".jar";
-
-                            getLog().debug(
-                                "Copying " + artifact.getFile() + " to " + new File( libDirectory, targetFileName ) );
-
-                            copyFileIfModified( artifact.getFile(), new File( libDirectory, targetFileName ) );
-                        }
-                        else
-                        {
-                            if ( "war".equals( type ) )
-                            {
-                                dependentWarDirectories.add( unpackWarToTempDirectory( artifact ) );
-                            }
-                            else
-                            {
-                                getLog().debug( "Skipping artifact of type " + type + " for WEB-INF/lib" );
-                            }
-                        }
-                    }
+                    throw new MojoExecutionException( "Error loading property file '" + filtersfile + "'", e );
                 }
             }
+
+            // can't putAll, as ReflectionProperties doesn't enumerate - so we make a composite map with the project variables as dominant
+            return new CompositeMap( new ReflectionProperties( project ), filterProperties );
         }
 
-        if ( dependentWarDirectories.size() > 0 )
+        public WebappStructure getWebappStructure()
         {
-            getLog().info( "Overlaying " + dependentWarDirectories.size() + " war(s)." );
-
-            // overlay dependent wars
-            for ( Iterator iter = dependentWarDirectories.iterator(); iter.hasNext(); )
-            {
-                copyDependentWarContents( (File) iter.next(), webappDirectory );
-            }
+            return webappStructure;
         }
-    }
 
-    /**
-     * Searches a set of artifacts for duplicate filenames and returns a list of duplicates.
-     *
-     * @param artifacts set of artifacts
-     * @return List of duplicated artifacts
-     */
-    private List findDuplicates( Set artifacts )
-    {
-        List duplicates = new ArrayList();
-        List identifiers = new ArrayList();
-        for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+        public List getOwnerIds()
         {
-            Artifact artifact = (Artifact) iter.next();
-            String candidate = getFinalName( artifact );
-            if ( identifiers.contains( candidate ) )
-            {
-                duplicates.add( candidate );
-            }
-            else
-            {
-                identifiers.add( candidate );
-            }
+            return overlayManager.getOverlayIds();
         }
-        return duplicates;
     }
 
-    /**
-     * Unpacks war artifacts into a temporary directory inside <tt>workDirectory</tt>
-     * named with the name of the war.
-     *
-     * @param artifact War artifact to unpack.
-     * @return Directory containing the unpacked war.
-     * @throws MojoExecutionException
-     */
-    private File unpackWarToTempDirectory( Artifact artifact )
-        throws MojoExecutionException
+    public MavenProject getProject()
     {
-        String name = artifact.getFile().getName();
-        File tempLocation = new File( workDirectory, name.substring( 0, name.length() - 4 ) );
-
-        boolean process = false;
-        if ( !tempLocation.exists() )
-        {
-            tempLocation.mkdirs();
-            process = true;
-        }
-        else if ( artifact.getFile().lastModified() > tempLocation.lastModified() )
-        {
-            process = true;
-        }
-
-        if ( process )
-        {
-            File file = artifact.getFile();
-            try
-            {
-                unpack( file, tempLocation );
-            }
-            catch ( NoSuchArchiverException e )
-            {
-                this.getLog().info( "Skip unpacking dependency file with unknown extension: " + file.getPath() );
-            }
-        }
-
-        return tempLocation;
+        return project;
     }
 
-    /**
-     * Unpacks the archive file.
-     *
-     * @param file     File to be unpacked.
-     * @param location Location where to put the unpacked files.
-     */
-    private void unpack( File file, File location )
-        throws MojoExecutionException, NoSuchArchiverException
+    public void setProject( MavenProject project )
     {
-        String archiveExt = FileUtils.getExtension( file.getAbsolutePath() ).toLowerCase();
-
-        try
-        {
-            UnArchiver unArchiver = archiverManager.getUnArchiver( archiveExt );
-            unArchiver.setSourceFile( file );
-            unArchiver.setDestDirectory( location );
-            unArchiver.setOverwrite( true );
-            unArchiver.extract();
-        }
-        catch ( IOException e )
-        {
-            throw new MojoExecutionException( "Error unpacking file: " + file + "to: " + location, e );
-        }
-        catch ( ArchiverException e )
-        {
-            throw new MojoExecutionException( "Error unpacking file: " + file + "to: " + location, e );
-        }
+        this.project = project;
     }
 
-    /**
-     * Recursively copies contents of <tt>srcDir</tt> into <tt>targetDir</tt>.
-     * This will not overwrite any existing files.
-     *
-     * @param srcDir    Directory containing unpacked dependent war contents
-     * @param targetDir Directory to overlay srcDir into
-     */
-    private void copyDependentWarContents( File srcDir, File targetDir )
-        throws MojoExecutionException
+    public File getClassesDirectory()
     {
-        DirectoryScanner scanner = new DirectoryScanner();
-        scanner.setBasedir( srcDir );
-        scanner.setExcludes( getDependentWarExcludes() );
-        scanner.addDefaultExcludes();
-
-        scanner.setIncludes( getDependentWarIncludes() );
-
-        scanner.scan();
-
-        String[] dirs = scanner.getIncludedDirectories();
-        for ( int j = 0; j < dirs.length; j++ )
-        {
-            new File( targetDir, dirs[j] ).mkdirs();
-        }
-
-        String[] files = scanner.getIncludedFiles();
-
-        for ( int j = 0; j < files.length; j++ )
-        {
-            File targetFile = new File( targetDir, files[j] );
-
-            try
-            {
-                // Don't copy if it is in the source directory
-                if ( !new File( warSourceDirectory, files[j] ).exists() )
-                {
-                    targetFile.getParentFile().mkdirs();
-                    copyFileIfModified( new File( srcDir, files[j] ), targetFile );
-                }
-            }
-            catch ( IOException e )
-            {
-                throw new MojoExecutionException( "Error copying file '" + files[j] + "' to '" + targetFile + "'", e );
-            }
-        }
+        return classesDirectory;
     }
 
-    /**
-     * Returns a list of filenames that should be copied
-     * over to the destination directory.
-     *
-     * @param sourceDir the directory to be scanned
-     * @return the array of filenames, relative to the sourceDir
-     */
-    private String[] getWarFiles( File sourceDir )
+    public void setClassesDirectory( File classesDirectory )
     {
-        DirectoryScanner scanner = new DirectoryScanner();
-        scanner.setBasedir( sourceDir );
-        scanner.setExcludes( getExcludes() );
-        scanner.addDefaultExcludes();
-
-        scanner.setIncludes( getIncludes() );
+        this.classesDirectory = classesDirectory;
+    }
 
-        scanner.scan();
+    public File getWebappDirectory()
+    {
+        return webappDirectory;
+    }
 
-        return scanner.getIncludedFiles();
+    public void setWebappDirectory( File webappDirectory )
+    {
+        this.webappDirectory = webappDirectory;
     }
 
-    /**
-     * Returns a list of filenames that should be copied
-     * over to the destination directory.
-     *
-     * @param resource the resource to be scanned
-     * @return the array of filenames, relative to the sourceDir
-     */
-    private String[] getWarFiles( Resource resource )
+    public File getWarSourceDirectory()
     {
-        DirectoryScanner scanner = new DirectoryScanner();
-        scanner.setBasedir( resource.getDirectory() );
-        if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
-        {
-            scanner.setIncludes( (String[]) resource.getIncludes().toArray( EMPTY_STRING_ARRAY ) );
-        }
-        else
-        {
-            scanner.setIncludes( DEFAULT_INCLUDES );
-        }
-        if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
-        {
-            scanner.setExcludes( (String[]) resource.getExcludes().toArray( EMPTY_STRING_ARRAY ) );
-        }
+        return warSourceDirectory;
+    }
 
-        scanner.addDefaultExcludes();
+    public void setWarSourceDirectory( File warSourceDirectory )
+    {
+        this.warSourceDirectory = warSourceDirectory;
+    }
 
-        scanner.scan();
+    public File getWebXml()
+    {
+        return webXml;
+    }
 
-        return scanner.getIncludedFiles();
+    public void setWebXml( File webXml )
+    {
+        this.webXml = webXml;
     }
 
-    /**
-     * Copy file from source to destination only if source is newer than the target file.
-     * If <code>destinationDirectory</code> does not exist, it
-     * (and any parent directories) will be created. If a file <code>source</code> in
-     * <code>destinationDirectory</code> exists, it will be overwritten.
-     *
-     * @param source               An existing <code>File</code> to copy.
-     * @param destinationDirectory A directory to copy <code>source</code> into.
-     * @throws java.io.FileNotFoundException if <code>source</code> isn't a normal file.
-     * @throws IllegalArgumentException      if <code>destinationDirectory</code> isn't a directory.
-     * @throws java.io.IOException           if <code>source</code> does not exist, the file in
-     *                                       <code>destinationDirectory</code> cannot be written to, or an IO error occurs during copying.
-     *                                       <p/>
-     *                                       TO DO: Remove this method when Maven moves to plexus-utils version 1.4
-     */
-    private static void copyFileToDirectoryIfModified( File source, File destinationDirectory )
-        throws IOException
+    public File getContainerConfigXML()
     {
-        // TO DO: Remove this method and use the method in WarFileUtils when Maven 2 changes
-        // to plexus-utils 1.2.
-        if ( destinationDirectory.exists() && !destinationDirectory.isDirectory() )
-        {
-            throw new IllegalArgumentException( "Destination is not a directory" );
-        }
+        return containerConfigXML;
+    }
 
-        copyFileIfModified( source, new File( destinationDirectory, source.getName() ) );
+    public void setContainerConfigXML( File containerConfigXML )
+    {
+        this.containerConfigXML = containerConfigXML;
     }
 
-    private FilterWrapper[] getFilterWrappers()
+    public String getOutputFileNameMapping()
     {
-        return new FilterWrapper[]{
-            // support ${token}
-            new FilterWrapper()
-            {
-                public Reader getReader( Reader fileReader, Map filterProperties )
-                {
-                    return new InterpolationFilterReader( fileReader, filterProperties, "${", "}" );
-                }
-            },
-            // support @token@
-            new FilterWrapper()
-            {
-                public Reader getReader( Reader fileReader, Map filterProperties )
-                {
-                    return new InterpolationFilterReader( fileReader, filterProperties, "@", "@" );
-                }
-            }};
+        return outputFileNameMapping;
     }
 
-    /**
-     * @param from
-     * @param to
-     * @param encoding
-     * @param wrappers
-     * @param filterProperties
-     * @throws IOException TO DO: Remove this method when Maven moves to plexus-utils version 1.4
-     */
-    private static void copyFilteredFile( File from, File to, String encoding, FilterWrapper[] wrappers,
-                                          Map filterProperties )
-        throws IOException
+    public void setOutputFileNameMapping( String outputFileNameMapping )
     {
-        // buffer so it isn't reading a byte at a time!
-        Reader fileReader = null;
-        Writer fileWriter = null;
-        try
-        {
-            // fix for MWAR-36, ensures that the parent dir are created first
-            to.getParentFile().mkdirs();
+        this.outputFileNameMapping = outputFileNameMapping;
+    }
 
-            if ( encoding == null || encoding.length() < 1 )
-            {
-                fileReader = new BufferedReader( new FileReader( from ) );
-                fileWriter = new FileWriter( to );
-            }
-            else
-            {
-                FileInputStream instream = new FileInputStream( from );
+    public List getOverlays()
+    {
+        return overlays;
+    }
 
-                FileOutputStream outstream = new FileOutputStream( to );
+    public void setOverlays( List overlays )
+    {
+        this.overlays = overlays;
+    }
 
-                fileReader = new BufferedReader( new InputStreamReader( instream, encoding ) );
+    public void addOverlay( Overlay overlay )
+    {
+        overlays.add( overlay );
+    }
 
-                fileWriter = new OutputStreamWriter( outstream, encoding );
-            }
+    public boolean isArchiveClasses()
+    {
+        return archiveClasses;
+    }
 
-            Reader reader = fileReader;
-            for ( int i = 0; i < wrappers.length; i++ )
-            {
-                FilterWrapper wrapper = wrappers[i];
-                reader = wrapper.getReader( reader, filterProperties );
-            }
+    public void setArchiveClasses( boolean archiveClasses )
+    {
+        this.archiveClasses = archiveClasses;
+    }
 
-            IOUtil.copy( reader, fileWriter );
-        }
-        finally
-        {
-            IOUtil.close( fileReader );
-            IOUtil.close( fileWriter );
-        }
+    public JarArchiver getJarArchiver()
+    {
+        return jarArchiver;
     }
 
-    /**
-     * Copy file from source to destination only if source timestamp is later than the destination timestamp.
-     * The directories up to <code>destination</code> will be created if they don't already exist.
-     * <code>destination</code> will be overwritten if it already exists.
-     *
-     * @param source      An existing non-directory <code>File</code> to copy bytes from.
-     * @param destination A non-directory <code>File</code> to write bytes to (possibly
-     *                    overwriting).
-     * @throws IOException                   if <code>source</code> does not exist, <code>destination</code> cannot be
-     *                                       written to, or an IO error occurs during copying.
-     * @throws java.io.FileNotFoundException if <code>destination</code> is a directory
-     *                                       <p/>
-     *                                       TO DO: Remove this method when Maven moves to plexus-utils version 1.4
-     */
-    private static void copyFileIfModified( File source, File destination )
-        throws IOException
+    public void setJarArchiver( JarArchiver jarArchiver )
     {
-        // TO DO: Remove this method and use the method in WarFileUtils when Maven 2 changes
-        // to plexus-utils 1.2.
-        if ( destination.lastModified() < source.lastModified() )
-        {
-            FileUtils.copyFile( source.getCanonicalFile(), destination );
-            // preserve timestamp
-            destination.setLastModified( source.lastModified() );
-        }
+        this.jarArchiver = jarArchiver;
     }
 
-    /**
-     * Copies a entire directory structure but only source files with timestamp later than the destinations'.
-     * <p/>
-     * Note:
-     * <ul>
-     * <li>It will include empty directories.
-     * <li>The <code>sourceDirectory</code> must exists.
-     * </ul>
-     *
-     * @param sourceDirectory
-     * @param destinationDirectory
-     * @throws IOException TO DO: Remove this method when Maven moves to plexus-utils version 1.4
-     */
-    private static void copyDirectoryStructureIfModified( File sourceDirectory, File destinationDirectory )
-        throws IOException
+    public Resource[] getWebResources()
     {
-        if ( !sourceDirectory.exists() )
-        {
-            throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." );
-        }
+        return webResources;
+    }
 
-        File[] files = sourceDirectory.listFiles();
+    public void setWebResources( Resource[] webResources )
+    {
+        this.webResources = webResources;
+    }
 
-        String sourcePath = sourceDirectory.getAbsolutePath();
+    public List getFilters()
+    {
+        return filters;
+    }
 
-        for ( int i = 0; i < files.length; i++ )
-        {
-            File file = files[i];
+    public void setFilters( List filters )
+    {
+        this.filters = filters;
+    }
 
-            String dest = file.getAbsolutePath();
+    public File getWorkDirectory()
+    {
+        return workDirectory;
+    }
 
-            dest = dest.substring( sourcePath.length() + 1 );
+    public void setWorkDirectory( File workDirectory )
+    {
+        this.workDirectory = workDirectory;
+    }
 
-            File destination = new File( destinationDirectory, dest );
+    public File getCacheFile()
+    {
+        return cacheFile;
+    }
 
-            if ( file.isFile() )
-            {
-                destination = destination.getParentFile();
+    public void setCacheFile( File cacheFile )
+    {
+        this.cacheFile = cacheFile;
+    }
 
-                copyFileToDirectoryIfModified( file, destination );
-            }
-            else if ( file.isDirectory() )
-            {
-                if ( !destination.exists() && !destination.mkdirs() )
-                {
-                    throw new IOException(
-                        "Could not create destination directory '" + destination.getAbsolutePath() + "'." );
-                }
+    public String getWarSourceIncludes()
+    {
+        return warSourceIncludes;
+    }
 
-                copyDirectoryStructureIfModified( file, destination );
-            }
-            else
-            {
-                throw new IOException( "Unknown file type: " + file.getAbsolutePath() );
-            }
-        }
+    public void setWarSourceIncludes( String warSourceIncludes )
+    {
+        this.warSourceIncludes = warSourceIncludes;
     }
 
-    /**
-     * TO DO: Remove this interface when Maven moves to plexus-utils version 1.4
-     */
-    private interface FilterWrapper
+    public String getWarSourceExcludes()
     {
-        Reader getReader( Reader fileReader, Map filterProperties );
+        return warSourceExcludes;
     }
 
-    /**
-     * Returns the final name of the specified artifact.
-     * <p/>
-     * If the <tt>outputFileNameMapping</tt> is set, it is used, otherwise
-     * the standard naming scheme is used.
-     *
-     * @param artifact the artifact
-     * @return the converted filename of the artifact
-     */
-    private String getFinalName( Artifact artifact )
+    public void setWarSourceExcludes( String warSourceExcludes )
     {
-        if ( outputFileNameMapping != null )
-        {
-            return MappingUtils.evaluateFileNameMapping( outputFileNameMapping, artifact );
-        }
+        this.warSourceExcludes = warSourceExcludes;
+    }
 
-        String classifier = artifact.getClassifier();
-        if ( ( classifier != null ) && !( "".equals( classifier.trim() ) ) )
-        {
-            return MappingUtils.evaluateFileNameMapping( DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, artifact );
-        }
-        else
-        {
-            return MappingUtils.evaluateFileNameMapping( DEFAULT_FILE_NAME_MAPPING, artifact );
-        }
 
+    public boolean isUseCache()
+    {
+        return useCache;
     }
 
+    public void setUseCache( boolean useCache )
+    {
+        this.useCache = useCache;
+    }
 }

Modified: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java Sun Aug 12 03:26:14 2007
@@ -35,6 +35,8 @@
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
+        getLog().info( "Exploding webapp" );
+
         buildExplodedWebapp( getWebappDirectory() );
     }
 

Modified: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java Sun Aug 12 03:26:14 2007
@@ -34,7 +34,7 @@
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
-        getLog().info( "Generating webapp in source directory... " + getWarSourceDirectory() );
+        getLog().info( "Generating webapp in source directory[" + getWarSourceDirectory() + "]" );
 
         buildExplodedWebapp( getWarSourceDirectory() );
     }

Modified: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarMojo.java?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarMojo.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/WarMojo.java Sun Aug 12 03:26:14 2007
@@ -161,10 +161,9 @@
         throws IOException, ArchiverException, ManifestException, DependencyResolutionRequiredException,
         MojoExecutionException, MojoFailureException
     {
-        buildExplodedWebapp( getWebappDirectory() );
+        getLog().info( "Packaging webapp" );
 
-        //generate war file
-        getLog().info( "Generating war " + warFile.getAbsolutePath() );
+        buildExplodedWebapp( getWebappDirectory() );
 
         MavenArchiver archiver = new MavenArchiver();
 

Copied: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java (from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java)
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java?view=diff&rev=565036&p1=maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java&r1=565032&p2=maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java&r2=565036
==============================================================================
    (empty)

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/CompositeMap.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PathSet.java (from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PathSet.java)
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PathSet.java?view=diff&rev=565036&p1=maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PathSet.java&r1=565032&p2=maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PathSet.java&r2=565036
==============================================================================
--- maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PathSet.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PathSet.java Sun Aug 12 03:26:14 2007
@@ -278,7 +278,7 @@
         {
 
         }
-        return str.substring(i);
-	}
+        return str.substring( i );
+    }
 
 }

Copied: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java (from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java)
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java?view=diff&rev=565036&p1=maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java&r1=565032&p2=maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java&r2=565036
==============================================================================
    (empty)

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/PropertyUtils.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java (from r565032, maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java)
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java?view=diff&rev=565036&p1=maven/plugins/branches/MWAR-97-2/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java&r1=565032&p2=maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java&r2=565036
==============================================================================
    (empty)

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/plugins/trunk/maven-war-plugin/src/main/java/org/apache/maven/plugin/war/util/ReflectionProperties.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: maven/plugins/trunk/maven-war-plugin/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/site/apt/index.apt?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/site/apt/index.apt (original)
+++ maven/plugins/trunk/maven-war-plugin/src/site/apt/index.apt Sun Aug 12 03:26:14 2007
@@ -40,7 +40,8 @@
  
 * Usage
 
-  Instructions on how to use the Maven WAR Plugin can be found {{{usage.html}here}}.
+  Instructions on how to use the Maven WAR Plugin can be found {{{usage.html}here}}. Specific documentation
+  regarding overlays can be found {{{overlays.html}here}}  
 
 * Examples
  
@@ -48,8 +49,6 @@
  you can take a look into the following examples:
  
  * {{{examples/adding-filtering-webresources.html}Adding and Filtering External Web Resources}}
- 
- * {{{examples/war-overlay.html}Manipulating WAR Overlays}}
  
  * {{{examples/war-manifest-guide.html}War Manifest Customization}}
 

Modified: maven/plugins/trunk/maven-war-plugin/src/site/site.xml
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/site/site.xml?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/site/site.xml (original)
+++ maven/plugins/trunk/maven-war-plugin/src/site/site.xml Sun Aug 12 03:26:14 2007
@@ -27,9 +27,11 @@
       <item name="Usage" href="usage.html"/>
       <item name="FAQ" href="faq.html"/>
     </menu>
+    <menu name="Configuration">
+      <item name="Overlays" href="overlays.html"/>
+    </menu>
     <menu name="Examples">
-      <item name="Adding and Filtering External Web Resources" href="examples/adding-filtering-webresources.html"/>   
-      <item name="Manipulating WAR Overlays" href="examples/war-overlay.html"/>
+      <item name="Adding and Filtering External Web Resources" href="examples/adding-filtering-webresources.html"/>
       <item name="War Manifest Customization" href="examples/war-manifest-guide.html"/>
       <item name="Rapid Testing Using Jetty6" href="examples/rapid-testing-jetty6-plugin.html"/>
       <item name="Creating Skinny WARs" href="examples/skinny-wars.html"/>

Copied: maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java (from r565032, maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java)
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java?view=diff&rev=565036&p1=maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java&r1=565032&p2=maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java&r2=565036
==============================================================================
--- maven/plugins/branches/MWAR-97-2/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java Sun Aug 12 03:26:14 2007
@@ -71,7 +71,7 @@
      *
      * @param testId        the id of the test
      * @param artifactStubs the dependencies (may be null)
-     * @param sourceFiles the source files to create (may be null)
+     * @param sourceFiles   the source files to create (may be null)
      * @return the webapp directory
      * @throws Exception if an error occurs while configuring the mojo
      */
@@ -131,7 +131,7 @@
     protected File setUpMojo( final String testId, ArtifactStub[] artifactStubs )
         throws Exception
     {
-       return setUpMojo( testId, artifactStubs, null);
+        return setUpMojo( testId, artifactStubs, null );
     }
 
     /**

Modified: maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java?view=diff&rev=565036&r1=565035&r2=565036
==============================================================================
--- maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java (original)
+++ maven/plugins/trunk/maven-war-plugin/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java Sun Aug 12 03:26:14 2007
@@ -20,10 +20,16 @@
  */
 
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.apache.maven.plugin.testing.stubs.ArtifactStub;
 import org.apache.maven.plugin.war.stub.MavenProjectBasicStub;
+import org.apache.maven.plugin.war.stub.WarOverlayStub;
+import org.codehaus.plexus.archiver.Archiver;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
 import org.codehaus.plexus.util.FileUtils;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -32,6 +38,10 @@
     extends AbstractMojoTestCase
 {
 
+    protected static final File OVERLAYS_TEMP_DIR = new File( getBasedir(), "target/test-overlays/" );
+
+    protected static final File OVERLAYS_ROOT_DIR = new File( getBasedir(), "target/test-classes/overlays/" );
+
     protected abstract File getTestDirectory()
         throws Exception;
 
@@ -51,6 +61,7 @@
         throws Exception
     {
         setVariableValueToObject( mojo, "filters", filters );
+        setVariableValueToObject( mojo, "useCache", Boolean.FALSE );
         mojo.setClassesDirectory( classesDir );
         mojo.setWarSourceDirectory( webAppSource );
         mojo.setWebappDirectory( webAppDir );
@@ -87,24 +98,47 @@
     }
 
     /**
+     * Returns the webapp source directory for the specified id.
+     *
+     * @param id the id of the test
+     * @return the source directory for that test
+     * @throws Exception if an exception occurs
+     */
+    protected File getWebAppSource( String id )
+        throws Exception
+    {
+        return new File( getTestDirectory(), "/" + id + "-test-data/source" );
+    }
+
+    /**
      * create an isolated web source with a sample jsp file
      *
      * @param id
      * @return
      * @throws Exception
      */
-    protected File createWebAppSource( String id )
+    protected File createWebAppSource( String id, boolean createSamples )
         throws Exception
     {
-        File webAppSource = new File( getTestDirectory(), "/" + id + "-test-data/source" );
-        File simpleJSP = new File( webAppSource, "pansit.jsp" );
-        File jspFile = new File( webAppSource, "org/web/app/last-exile.jsp" );
+        File webAppSource = getWebAppSource( id );
+        if ( createSamples )
+        {
+            File simpleJSP = new File( webAppSource, "pansit.jsp" );
+            File jspFile = new File( webAppSource, "org/web/app/last-exile.jsp" );
 
-        createFile( simpleJSP );
-        createFile( jspFile );
+            createFile( simpleJSP );
+            createFile( jspFile );
+        }
         return webAppSource;
     }
 
+    protected File createWebAppSource( String id )
+        throws Exception
+    {
+        return createWebAppSource( id, true );
+    }
+
+
     /**
      * create a class directory with or without a sample class
      *
@@ -136,12 +170,153 @@
         }
     }
 
-    protected void createFile( File testFile )
+    protected void createFile( File testFile, String body )
         throws Exception
     {
         createDir( testFile.getParentFile() );
-        FileUtils.fileWrite( testFile.toString(), testFile.toString() );
+        FileUtils.fileWrite( testFile.toString(), body );
 
         assertTrue( "could not create file: " + testFile, testFile.exists() );
     }
-}
+
+    protected void createFile( File testFile )
+        throws Exception
+    {
+        createFile( testFile, testFile.toString() );
+    }
+
+    /**
+     * Generates test war
+     * <p/>
+     * Generates war with such a structure:
+     * <ul>
+     * <li>jsp
+     * <ul>
+     * <li>d
+     * <ul>
+     * <li>a.jsp</li>
+     * <li>b.jsp</li>
+     * <li>c.jsp</li>
+     * </ul>
+     * </li>
+     * <li>a.jsp</li>
+     * <li>b.jsp</li>
+     * <li>c.jsp</li>
+     * </ul>
+     * </li>
+     * <li>WEB-INF
+     * <ul>
+     * <li>classes
+     * <ul>
+     * <li>a.class</li>
+     * <li>b.class</li>
+     * <li>c.class</li>
+     * </ul>
+     * </li>
+     * <li>lib
+     * <ul>
+     * <li>a.jar</li>
+     * <li>b.jar</li>
+     * <li>c.jar</li>
+     * </ul>
+     * </li>
+     * <li>web.xml</li>
+     * </ul>
+     * </li>
+     * </ul>
+     * <p/>
+     * Each of the files will contain: id+'-'+path
+     *
+     * @param id the id of the overlay containing the full structure
+     * @return the war file
+     * @throws Exception if an error occurs
+     */
+    protected File generateFullOverlayWar( String id )
+        throws Exception
+    {
+        final File destFile = new File( OVERLAYS_TEMP_DIR, id + ".war" );
+        if ( destFile.exists() )
+        {
+            return destFile;
+        }
+
+        // Archive was not yet created for that id so let's create it
+        final File rootDir = new File( OVERLAYS_ROOT_DIR, id );
+        rootDir.mkdirs();
+        String[] filePaths = new String[]{"jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "jsp/a.jsp", "jsp/b.jsp",
+            "jsp/c.jsp", "WEB-INF/classes/a.class", "WEB-INF/classes/b.class", "WEB-INF/classes/c.class",
+            "WEB-INF/lib/a.jar", "WEB-INF/lib/b.jar", "WEB-INF/lib/c.jar", "WEB-INF/web.xml"};
+
+        for ( int i = 0; i < filePaths.length; i++ )
+        {
+            createFile( new File( rootDir, filePaths[i] ), id + "-" + filePaths[i] );
+        }
+
+        createArchive( rootDir, destFile );
+        return destFile;
+    }
+
+    // Overlay utilities
+
+
+    /**
+     * Builds a test overlay.
+     *
+     * @param id the id of the overlay (see test/resources/overlays)
+     * @return a test war artifact with the content of the given test overlay
+     */
+    protected ArtifactStub buildWarOverlayStub( String id )
+    {
+        // Create war file
+        final File destFile = new File( OVERLAYS_TEMP_DIR, id + ".war" );
+        if ( !destFile.exists() )
+        {
+            createArchive( new File( OVERLAYS_ROOT_DIR, id ), destFile );
+        }
+
+        return new WarOverlayStub( getBasedir(), id, destFile );
+    }
+
+    protected File getOverlayFile( String id, String filePath )
+    {
+        final File overlayDir = new File( OVERLAYS_ROOT_DIR, id );
+        final File file = new File( overlayDir, filePath );
+
+        // Make sure the file exists
+        assertTrue( "Overlay file " + filePath + " does not exist for overlay " + id + " at " + file.getAbsolutePath(),
+                    file.exists() );
+        return file;
+
+    }
+
+    protected void createArchive( final File directory, final File destinationFile )
+    {
+        try
+        {
+            //WarArchiver archiver = new WarArchiver();
+
+            Archiver archiver = new JarArchiver();
+
+            archiver.setDestFile( destinationFile );
+            archiver.addDirectory( directory );
+
+            //archiver.setWebxml( new File(directory, "WEB-INF/web.xml"));
+
+            // create archive
+            archiver.createArchive();
+
+        }
+        catch ( ArchiverException e )
+        {
+            e.printStackTrace();
+            fail( "Failed to create overlay archive " + e.getMessage() );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            fail( "Unexpected exception " + e.getMessage() );
+        }
+    }
+
+
+}
\ No newline at end of file