package org.apache.maven.j2ee;

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache Maven" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache Maven", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;

import junit.framework.TestCase;

import org.apache.maven.TestConstants;

/**
 * Unit test for {@link WarFile}.
 *
 * @author <a href="mailto:dion@multitask.com.au">dIon Gillard</a>
 * @version $Id$
 */
public class WarFileTest extends TestCase
{
    /** instance used for testing */
    private WarFile instance;
    /** file name for the empty war used during testing */
    private String emptyWarFile;
    /** file name for manifest-only war used during testing */
    private String manifestOnlyWarFile;
    /** file name for simple war (manifest & web.xml) used during testing */
    private String simpleWarFile;
    /** file name for dummy war (two dummy servlets) */
    private String dummyWarFile;
    /** file name for dummy jsp war (dummy war + a jsp-file entry) */
    private String dummyJspWarFile;
    /** file name for dummy taglib war (dummy war + 2 taglibs) */
    private String dummyTaglibWarFile;
    /** file name for error pages war (dummy war + 2 error pages) */
    private String errorPagesWarFile;
    /** file name for form login config war (dummy war + login config) */
    private String loginPagesWarFile;

    /** Creates a new instance of WarFileTest
     * @param testName the name of the test
     */
    public WarFileTest(String testName)
    {
        super(testName);
    }

    /**
     * Initialize per test data
     * @throws Exception when there is an unexpected problem
     */
    public void setUp() throws Exception
    {
        String baseDir = System.getProperty("basedir");
        assertNotNull("The system property basedir was not defined.", baseDir);
        final String j2eeDir = baseDir + TestConstants.J2EE_DIR ;
        emptyWarFile = j2eeDir + "empty.war";
        manifestOnlyWarFile = j2eeDir + "manifest-only.war";
        simpleWarFile = j2eeDir + "simple.war";
        dummyWarFile = j2eeDir + "dummy-servlet.war";
        dummyJspWarFile = j2eeDir + "dummy-jsp.war";
        dummyTaglibWarFile = j2eeDir + "dummy-taglib.war";
        errorPagesWarFile = j2eeDir + "error-pages.war";
        loginPagesWarFile = j2eeDir + "login-pages.war";
    }

    /**
     * test that an empty war file produces an error
     * @throws Exception when there is an unexpected problem
     */
    public void testEmptyWar() throws Exception
    {
        try
        {
            instance = new WarFile(emptyWarFile);
            fail("Empty war file (with no META-INF, or WEB-INF/web.xml) has"
                + " succeeded");
        }
        catch (IOException ioe)
        {
            // this is the expected behaviour
        }
    }

    /** test that a manifest only war (no web.xml) returns null for the web.xml!
     * @throws Exception when there is an unexpected problem
     */
     public void testManifestOnlyWar() throws Exception
     {
         instance = new WarFile(manifestOnlyWarFile);
         assertNull("web.xml for manifest only war is not null",
            instance.getWebXmlEntry());
     }

    /** test that a simple war (web.xml + manifest) returns an entry for web.xml
     * test that a simple war returns zero servlets
     * @throws Exception when there is an unexpected problem
     */
    public void testSimpleWar() throws Exception
    {
        instance = new WarFile(simpleWarFile);
         assertNotNull("web.xml for simple war is null",
            instance.getWebXmlEntry());
         assertEquals("number of servlets for simple war is not zero", 0,
            instance.getServlets().size());
     }

    /** test that the dummy war returns two servlets
     * @throws Exception when there is an unexpected problem
     */
    public void testDummyWarServlets() throws Exception
    {
        instance = new WarFile(dummyWarFile);
        assertEquals("number of servlets for dummy war is not two", 2,
           instance.getServlets().size());
        assertTrue("servlet list doesn't contain 'dummy servlet'",
           instance.getServlets().keySet().contains("dummy servlet"));
        assertTrue("servlet list doesn't contain 'dummy number 2'",
           instance.getServlets().keySet().contains("dummy number 2"));
        assertTrue("servlet list doesn't contain HttpServlet",
           instance.getServlets().containsValue(
           "javax.servlet.http.HttpServlet"));
        assertTrue("servlet list doesn't contain Servlet",
           instance.getServlets().containsValue(
           "java.servlet.Servlet"));
    }

    /** test the getLibEntries method
     * @throws Exception when there is an unexpected problem
     */
    public void testDummyWarLib() throws Exception
    {
        instance = new WarFile(dummyWarFile);
        assertEquals("number of lib entries for dummy war is not two", 2,
           instance.getLibEntries().size());
        JarEntry entry = null;
        List list = new ArrayList();
        for (Iterator entries = instance.getLibEntries().iterator();
            entries.hasNext();)
        {
            entry = (JarEntry) entries.next();
            list.add(entry.getName());
        }
        Collections.sort(list);
        assertEquals("First entry is a.jar", "WEB-INF/lib/a.jar",
            list.get(0));
        assertEquals("Second entry is b.jar", "WEB-INF/lib/b.jar",
            list.get(1));
    }

    /** test the file extraction
     * @throws Exception when there is an unexpected problem
     */
    public void testDummyWarExtract() throws Exception
    {
        instance = new WarFile(dummyWarFile);
        Set libs = instance.getLibEntries();
        File[] files = new File[libs.size()];
        JarEntry entry = null;
        int i = 0;
        for (Iterator entries = instance.getLibEntries().iterator();
            entries.hasNext();)
        {
            entry = (JarEntry) entries.next();
            files[i] = instance.extract(entry);
            assertTrue("Extracted file " + files[i].getAbsolutePath()
                + " doesn't exist", files[i].exists());
            i++;
        }
    }

    /** test that the dummy jsp war returns two servlets
     * @throws Exception when there is an unexpected problem
     */
    public void testDummyJspWar() throws Exception
    {
        instance = new WarFile(dummyJspWarFile);
        assertEquals("Number of jsps is wrong", 1,
            instance.getJSPs().size());
        assertTrue("List of jsps doesn't contain /a.jsp",
            instance.getJSPs().values().contains("/a.jsp"));
        assertEquals("Number of taglibs is wrong", 0,
            instance.getTaglibs().size());
    }

    /** test that the dummy taglib war returns two taglibs
     * @throws Exception when there is an unexpected problem
     */
    public void testDummyTaglibWar() throws Exception
    {
        instance = new WarFile(dummyTaglibWarFile);
        assertEquals("Number of taglibs is wrong", 2,
            instance.getTaglibs().size());
        assertEquals("Number of error pages is wrong", 0,
            instance.getErrorPages().size());
        assertNull("Form Login Config isn't null",
            instance.getFormLoginConfig());
        assertTrue("List of taglibs doesn't contain /WEB-INF/a.tld",
            instance.getTaglibs().values().contains("/WEB-INF/a.tld"));
        assertTrue("List of taglibs doesn't contain /WEB-INF/b.tld",
            instance.getTaglibs().values().contains("/WEB-INF/b.tld"));
    }

    /** test the error pages war contains 2 error pages
     * @throws Exception when there is an unexpected problem
     */
    public void testErrorPagesWar() throws Exception
    {
        instance = new WarFile(errorPagesWarFile);
        assertEquals("Number of error pages is wrong", 2,
            instance.getErrorPages().size());
        assertTrue("Error page list doesn't contain error.jsp",
            instance.getErrorPages().values().contains("/error.jsp"));
        assertTrue("Error page list doesn't contain error404.jsp",
            instance.getErrorPages().values().contains("/error404.jsp"));
    }

    /** test the login pages war contains a form login config object with the
     * login and error pages set
     * @throws Exception when there is an unexpected problem
     */
    public void testLoginPagesWar() throws Exception
    {
        instance = new WarFile(loginPagesWarFile);
        assertNotNull("Form login config is null",
            instance.getFormLoginConfig());
        assertEquals("Login page is not /login.html",
            "/login.html", instance.getFormLoginConfig().getLoginPage());
        assertEquals("Error page is not /error.jsp",
            "/error.jsp", instance.getFormLoginConfig().getErrorPage());
    }

    /** test the servlet mappings comes back with the correct entries
     * @throws Exception when there is an unexpected problem
     */
    public void testServletMappings() throws Exception
    {
        instance = new WarFile(dummyWarFile);
        assertEquals("# of servlet mappings for dummy war file is wrong", 2,
            instance.getServletMappings().size());
        instance = new WarFile(loginPagesWarFile);
        assertEquals("# of servlet mappings in login pages war is wrong", 0,
            instance.getServletMappings().size());
    }
}
