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.plugins.war.Overlay;
import org.apache.maven.plugins.war.overlay.DefaultOverlay;
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.
     * 
     * 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).
     * 
     * 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).
     * 
     * 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 );
        }

    }

    // Helpers

    /**
     * Asserts that the content of an overlayed file is correct.
     * 
     * 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.
     * 
     * 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 );
    }
}