package org.apache.maven.plugins.war;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.maven.plugin.testing.stubs.ArtifactStub;
import org.apache.maven.plugin.war.overlay.DefaultOverlay;
import org.apache.maven.plugins.war.Overlay;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Stephane Nicoll
 */
public class WarOverlaysTest
    extends AbstractWarExplodedMojoTest
{

    private static File pomFile = new File( getBasedir(), "target/test-classes/unit/waroverlays/default.xml" );

    public void setUp()
        throws Exception
    {
        super.setUp();
        generateFullOverlayWar( "overlay-full-1" );
        generateFullOverlayWar( "overlay-full-2" );
        generateFullOverlayWar( "overlay-full-3" );
    }

    protected File getPomFile()
    {
        return pomFile;
    }

    protected File getTestDirectory()
    {
        return new File( getBasedir(), "target/test-classes/unit/waroverlays" );
    }

    public void testEnvironment()
        throws Exception
    {
        // see setup
    }

    public void testNoOverlay()
        throws Exception
    {
        // setup test data
        final String testId = "no-overlay";
        final File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        final File webAppDirectory = setUpMojo( testId, null );
        try
        {
            mojo.setWebXml( new File( xmlSource, "web.xml" ) );
            mojo.execute();

            // Validate content of the webapp
            assertDefaultContent( webAppDirectory );
            assertWebXml( webAppDirectory );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    public void testDefaultOverlay()
        throws Exception
    {
        // setup test data
        final String testId = "default-overlay";

        // Add an overlay
        final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" );

        final File webAppDirectory = setUpMojo( testId, new ArtifactStub[] { overlay } );
        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            mojo.execute();
            assertedFiles.addAll( assertDefaultContent( webAppDirectory ) );
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "index.jsp", "login.jsp" },
                                                       "overlay file not found" ) );

            // index and login come from overlay1
            assertOverlayedFile( webAppDirectory, "overlay-one", "index.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    public void testDefaultOverlays()
        throws Exception
    {
        // setup test data
        final String testId = "default-overlays";

        // Add an overlay
        final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" );

        final File webAppDirectory = setUpMojo( testId, new ArtifactStub[] { overlay, overlay2 } );
        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            mojo.execute();
            assertedFiles.addAll( assertDefaultContent( webAppDirectory ) );
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "index.jsp", "login.jsp",
                "admin.jsp" }, "overlay file not found" ) );

            // index and login come from overlay1
            assertOverlayedFile( webAppDirectory, "overlay-one", "index.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" );

            // admin comes from overlay2
            // index and login comes from overlay1
            assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    /**
     * Merge a dependent WAR when a file in the war source directory overrides one found in the WAR.
     * <p/>
     * It also tests completeness of the resulting war as well as the proper order of dependencies.
     *
     * @throws Exception if any error occurs
     */
    public void testScenarioOneWithDefaulSettings()
        throws Exception
    {
        // setup test data
        final String testId = "scenario-one-default-settings";

        // Add an overlay
        final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" );
        final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" );

        final File webAppDirectory =
            setUpMojo( testId, new ArtifactStub[] { overlay1, overlay2, overlay3 }, new String[] {
                "org/sample/company/test.jsp", "jsp/b.jsp" } );

        assertScenariOne( testId, webAppDirectory );
    }

    /**
     * Tests that specifying the overlay explicitely has the same behavior as the default (i.e. order, etc).
     * <p/>
     * The default project is not specified in this case so it is processed first by default
     *
     * @throws Exception if an error occurs
     */
    public void testScenarioOneWithOverlaySettings()
        throws Exception
    {
        // setup test data
        final String testId = "scenario-one-overlay-settings";

        // Add an overlay
        final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" );
        final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" );

        final File webAppDirectory =
            setUpMojo( testId, new ArtifactStub[] { overlay1, overlay2, overlay3 }, new String[] {
                "org/sample/company/test.jsp", "jsp/b.jsp" } );

        // Add the tags
        final List<Overlay> overlays = new ArrayList<Overlay>();
        overlays.add( new DefaultOverlay( overlay1 ) );
        overlays.add( new DefaultOverlay( overlay2 ) );
        overlays.add( new DefaultOverlay( overlay3 ) );
        mojo.setOverlays( overlays );

        // current project ignored. Should be on top of the list
        assertScenariOne( testId, webAppDirectory );
    }

    /**
     * Tests that specifying the overlay explicitely has the same behavior as the default (i.e. order, etc).
     * <p/>
     * The default project is explicitely specified so this should match the default.
     *
     * @throws Exception if an error occurs
     */
    public void testScenarioOneWithFullSettings()
        throws Exception
    {
        // setup test data
        final String testId = "scenario-one-full-settings";

        // Add an overlay
        final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" );
        final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" );

        final File webAppDirectory =
            setUpMojo( testId, new ArtifactStub[] { overlay1, overlay2, overlay3 }, new String[] {
                "org/sample/company/test.jsp", "jsp/b.jsp" } );

        // Add the tags
        final List<Overlay> overlays = new ArrayList<Overlay>();

        // Add the default project explicitely
        overlays.add( mojo.getCurrentProjectOverlay() );

        // Other overlays
        overlays.add( new DefaultOverlay( overlay1 ) );
        overlays.add( new DefaultOverlay( overlay2 ) );
        overlays.add( new DefaultOverlay( overlay3 ) );
        mojo.setOverlays( overlays );

        // current project ignored. Should be on top of the list
        assertScenariOne( testId, webAppDirectory );
    }

    /**
     * Runs the mojo and asserts a scenerio with 3 overlays and no includes/excludes settings.
     *
     * @param testId thie id of the test
     * @param webAppDirectory the webapp directory
     * @throws Exception if an exception occurs
     */
    private void assertScenariOne( String testId, File webAppDirectory )
        throws Exception
    {
        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            mojo.execute();
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "jsp/a.jsp", "jsp/b.jsp",
                "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.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" }, "overlay file not found" ) );

            // Those files should come from the source webapp without any config
            assertDefaultFileContent( testId, webAppDirectory, "jsp/b.jsp" );
            assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" );

            // Everything else comes from overlay1 (order of addition in the dependencies)
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/a.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/c.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/a.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/b.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/web.xml" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/a.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/b.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/c.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/a.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/b.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/c.jar" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    public void testOverlaysIncludesExcludesWithMultipleDefinitions()
        throws Exception
    {
        // setup test data
        final String testId = "overlays-includes-excludes-multiple-defs";

        // Add an overlay
        final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" );
        final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" );

        final File webAppDirectory =
            setUpMojo( testId, new ArtifactStub[] { overlay1, overlay2, overlay3 }, new String[] {
                "org/sample/company/test.jsp", "jsp/b.jsp" } );

        Overlay over1 = new DefaultOverlay( overlay3 );
        over1.setExcludes( "**/a.*,**/c.*,**/*.xml" );

        Overlay over2 = new DefaultOverlay( overlay1 );
        over2.setIncludes( "jsp/d/*" );
        over2.setExcludes( "jsp/d/a.jsp" );

        Overlay over3 = new DefaultOverlay( overlay3 );
        over3.setIncludes( "**/*.jsp" );

        Overlay over4 = new DefaultOverlay( overlay2 );

        mojo.setOverlays( new LinkedList<Overlay>() );
        mojo.addOverlay( over1 );
        mojo.addOverlay( over2 );
        mojo.addOverlay( over3 );
        mojo.addOverlay( mojo.getCurrentProjectOverlay() );
        mojo.addOverlay( over4 );

        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            mojo.execute();
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "jsp/a.jsp", "jsp/b.jsp",
                "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.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" }, "overlay file not found" ) );

            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/a.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/b.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/c.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/a.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/b.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" );
            assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/web.xml" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/a.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/classes/b.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/c.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/a.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/lib/b.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/c.jar" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    public void testOverlaysIncludesExcludesWithMultipleDefinitions2()
        throws Exception
    {
        // setup test data
        final String testId = "overlays-includes-excludes-multiple-defs2";

        // Add an overlay
        final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" );
        final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" );

        final File webAppDirectory =
            setUpMojo( testId, new ArtifactStub[] { overlay1, overlay2, overlay3 }, new String[] {
                "org/sample/company/test.jsp", "jsp/b.jsp" } );

        Overlay over1 = new DefaultOverlay( overlay3 );
        over1.setExcludes( "**/a.*,**/c.*,**/*.xml,jsp/b.jsp" );

        Overlay over2 = new DefaultOverlay( overlay1 );
        over2.setIncludes( "jsp/d/*" );
        over2.setExcludes( "jsp/d/a.jsp" );

        Overlay over3 = new DefaultOverlay( overlay3 );
        over3.setIncludes( "**/*.jsp" );
        over3.setExcludes( "jsp/b.jsp" );

        Overlay over4 = new DefaultOverlay( overlay2 );

        mojo.setOverlays( new LinkedList<Overlay>() );
        mojo.addOverlay( over1 );
        mojo.addOverlay( over2 );
        mojo.addOverlay( over3 );
        mojo.addOverlay( mojo.getCurrentProjectOverlay() );
        mojo.addOverlay( over4 );

        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            mojo.execute();
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "jsp/a.jsp", "jsp/b.jsp",
                "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.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" }, "overlay file not found" ) );

            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/a.jsp" );
            assertDefaultFileContent( testId, webAppDirectory, "jsp/b.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/c.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/a.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/b.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" );
            assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/web.xml" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/a.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/classes/b.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/c.class" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/a.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/lib/b.jar" );
            assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/c.jar" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }

    }

    public void testCacheWithUpdatedOverlay()
        throws Exception
    {
        // setup test data
        final String testId = "cache-updated-overlay";

        // Add an overlay
        final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" );

        final File webAppDirectory = setUpMojo( testId, new ArtifactStub[] { overlay, overlay2 } );
        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            // Use the cache
            setVariableValueToObject( mojo, "useCache", Boolean.TRUE );
            setVariableValueToObject( mojo, "cacheFile", new File( mojo.getWorkDirectory(), "cache.xml" ) );

            final LinkedList<Overlay> overlays = new LinkedList<Overlay>();
            overlays.add( new DefaultOverlay( overlay ) );
            overlays.add( new DefaultOverlay( overlay2 ) );
            mojo.setOverlays( overlays );

            mojo.execute();

            // Now change the overlay order and make sure the right file is overwritten
            final LinkedList<Overlay> updatedOverlays = new LinkedList<Overlay>();
            updatedOverlays.add( new DefaultOverlay( overlay2 ) );
            updatedOverlays.add( new DefaultOverlay( overlay ) );
            mojo.setOverlays( updatedOverlays );

            mojo.execute();

            assertedFiles.addAll( assertDefaultContent( webAppDirectory ) );
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "index.jsp", "login.jsp",
                "admin.jsp" }, "overlay file not found" ) );

            // index and login come from overlay2 now
            assertOverlayedFile( webAppDirectory, "overlay-two", "index.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    public void testCacheWithRemovedOverlay()
        throws Exception
    {
        // setup test data
        final String testId = "cache-removed-overlay";

        // Add an overlay
        final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" );
        final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" );

        final File webAppDirectory = setUpMojo( testId, new ArtifactStub[] { overlay, overlay2 } );
        final List<File> assertedFiles = new ArrayList<File>();
        try
        {
            // Use the cache
            setVariableValueToObject( mojo, "useCache", Boolean.TRUE );
            setVariableValueToObject( mojo, "cacheFile", new File( mojo.getWorkDirectory(), "cache.xml" ) );

            final LinkedList<Overlay> overlays = new LinkedList<Overlay>();
            overlays.add( new DefaultOverlay( overlay ) );
            overlays.add( new DefaultOverlay( overlay2 ) );
            mojo.setOverlays( overlays );

            mojo.execute();

            // Now remove overlay one the right file is overwritten
            final LinkedList<Overlay> updatedOverlays = new LinkedList<Overlay>();
            updatedOverlays.add( new DefaultOverlay( overlay2 ) );
            mojo.setOverlays( updatedOverlays );

            // Remove overlay one as a dep
            mojo.getProject().getArtifacts().remove( overlay );

            mojo.execute();

            assertedFiles.addAll( assertDefaultContent( webAppDirectory ) );
            assertedFiles.addAll( assertWebXml( webAppDirectory ) );
            assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[] { "index.jsp", "login.jsp",
                "admin.jsp" }, "overlay file not found" ) );

            // index and login come from overlay2 now
            assertOverlayedFile( webAppDirectory, "overlay-two", "index.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" );
            assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" );

            // Ok now check that there is no more files/directories
            final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[] { MANIFEST_PATH } );
            assertWebAppContent( webAppDirectory, assertedFiles, filter );
        }
        finally
        {
            cleanDirectory( webAppDirectory );
        }
    }

    // Helpers

    /**
     * Asserts that the content of an overlayed file is correct.
     * <p/>
     * Note that the <tt>filePath</tt> is relative to both the webapp directory and the overlayed directory, defined by
     * the <tt>overlayId</tt>.
     *
     * @param webAppDirectory the webapp directory
     * @param overlayId the id of the overlay
     * @param filePath the relative path
     * @throws IOException if an error occurred while reading the files
     */
    protected void assertOverlayedFile( File webAppDirectory, String overlayId, String filePath )
        throws IOException
    {
        final File webAppFile = new File( webAppDirectory, filePath );
        final File overlayFile = getOverlayFile( overlayId, filePath );
        assertEquals( "Wrong content for overlayed file " + filePath, FileUtils.fileRead( overlayFile ),
                      FileUtils.fileRead( webAppFile ) );

    }

    /**
     * Asserts that the content of an overlayed file is correct.
     * <p/>
     * Note that the <tt>filePath</tt> is relative to both the webapp directory and the overlayed directory, defined by
     * the <tt>overlayId</tt>.
     *
     * @param testId te id of the test
     * @param webAppDirectory the webapp directory
     * @param filePath the relative path
     * @throws IOException if an error occurred while reading the files
     */
    protected void assertDefaultFileContent( String testId, File webAppDirectory, String filePath )
        throws Exception
    {
        final File webAppFile = new File( webAppDirectory, filePath );
        final File sourceFile = new File( getWebAppSource( testId ), filePath );
        final String expectedContent = sourceFile.toString();
        assertEquals( "Wrong content for file " + filePath, expectedContent, FileUtils.fileRead( webAppFile ) );

    }

    protected ArtifactStub generateSimpleWarArtifactStub( String id )
        throws Exception
    {
        return buildWarOverlayStub( id );
    }
}