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 java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.war.WarMojo;
import org.apache.maven.plugins.war.stub.JarArtifactStub;
import org.apache.maven.plugins.war.stub.MavenProject4CopyConstructor;
import org.apache.maven.plugins.war.stub.MavenProjectArtifactsStub;
import org.apache.maven.plugins.war.stub.ProjectHelperStub;
import org.apache.maven.plugins.war.stub.WarArtifact4CCStub;
import org.codehaus.plexus.util.IOUtil;

/**
 * comprehensive test on buildExplodedWebApp is done on WarExplodedMojoTest
 */
public class WarMojoTest
    extends AbstractWarMojoTest
{
    WarMojo mojo;

    private static File pomFile = new File( getBasedir(),
                                            "target/test-classes/unit/warmojotest/plugin-config-primary-artifact.xml" );

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

    public void setUp()
        throws Exception
    {
        super.setUp();
        mojo = (WarMojo) lookupMojo( "war", pomFile );
    }

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

    public void testSimpleWar()
        throws Exception
    {
        String testId = "SimpleWar";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp",
            "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testSimpleWarPackagingExcludeWithIncludesRegEx()
        throws Exception
    {
        String testId = "SimpleWarPackagingExcludeWithIncludesRegEx";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );
        setVariableValueToObject( mojo, "packagingIncludes", "%regex[(.(?!exile))+]" );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null,
            mojo.getWebXml().toString(), null, null, null, }, new String[] { "org/web/app/last-exile.jsp" } );
    }

    public void testClassifier()
        throws Exception
    {
        String testId = "Classifier";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        ProjectHelperStub projectHelper = new ProjectHelperStub();
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "projectHelper", projectHelper );
        setVariableValueToObject( mojo, "classifier", "test-classifier" );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple-test-classifier.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp",
            "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testPrimaryArtifact()
        throws Exception
    {
        String testId = "PrimaryArtifact";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        ProjectHelperStub projectHelper = new ProjectHelperStub();
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        warArtifact.setFile( new File( "error.war" ) );
        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "projectHelper", projectHelper );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp",
            "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testNotPrimaryArtifact()
        throws Exception
    {
        // use a different pom
        File pom = new File( getBasedir(), "target/test-classes/unit/warmojotest/not-primary-artifact.xml" );
        mojo = (WarMojo) lookupMojo( "war", pom );

        String testId = "NotPrimaryArtifact";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        ProjectHelperStub projectHelper = new ProjectHelperStub();
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        warArtifact.setFile( new File( "error.war" ) );
        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "projectHelper", projectHelper );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp",
            "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testMetaInfContent()
        throws Exception
    {
        String testId = "SimpleWarWithMetaInfContent";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        // Create the sample config.xml
        final File configFile = new File( webAppSource, "META-INF/config.xml" );
        createFile( configFile, "<config></config>" );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "META-INF/config.xml",
            "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null, null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testMetaInfContentWithContainerConfig()
        throws Exception
    {
        String testId = "SimpleWarWithContainerConfig";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        // Create the sample config.xml
        final File configFile = new File( webAppSource, "META-INF/config.xml" );
        createFile( configFile, "<config></config>" );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );
        mojo.setContainerConfigXML( configFile );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "META-INF/config.xml",
            "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
            "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null, null,
            mojo.getWebXml().toString(), null, null, null, null } );
    }

    public void testFailOnMissingWebXmlFalse()
        throws Exception
    {

        String testId = "SimpleWarMissingWebXmlFalse";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setFailOnMissingWebXml( false );
        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple.war" );
        final Map<String, JarEntry> jarContent =
            assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "pansit.jsp",
                "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
                "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" }, new String[] { null, null,
                null, null, null } );

        assertFalse( "web.xml should be missing", jarContent.containsKey( "WEB-INF/web.xml" ) );
    }

    public void testFailOnMissingWebXmlTrue()
        throws Exception
    {

        String testId = "SimpleWarMissingWebXmlTrue";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setFailOnMissingWebXml( true );

        try
        {
            mojo.execute();
            fail( "Building of the war isn't possible because web.xml is missing" );
        }
        catch ( MojoExecutionException e )
        {
            // expected behaviour
        }
    }
    
    public void testFailOnMissingWebXmlNotSpecifiedAndServlet30Used()
        throws Exception
    {
        String testId = "SimpleWarUnderServlet30";
        MavenProjectArtifactsStub project = new MavenProjectArtifactsStub();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );

        final ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" );
        JarArtifactStub jarArtifactStub = new JarArtifactStub( getBasedir(), artifactHandler );
        jarArtifactStub.setFile( new File( getBasedir(),
                                           "/target/test-classes/unit/sample_wars/javax.servlet-api-3.0.1.jar" ) );
        jarArtifactStub.setScope( Artifact.SCOPE_PROVIDED );
        project.addArtifact( jarArtifactStub );

        project.setArtifact( warArtifact );
        project.setFile( warArtifact.getFile() );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );

        mojo.execute();

        // validate war file
        File expectedWarFile = new File( outputDir, "simple.war" );
        final Map<String, JarEntry> jarContent =
            assertJarContent( expectedWarFile,
                              new String[] { "META-INF/MANIFEST.MF", "pansit.jsp", "org/web/app/last-exile.jsp",
                                  "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.xml",
                                  "META-INF/maven/org.apache.maven.plugin.test/maven-war-plugin-test/pom.properties" },
                              new String[] { null, null, null, null, null } );

        assertFalse( "web.xml should be missing", jarContent.containsKey( "WEB-INF/web.xml" ) );
    }

    public void testFailOnMissingWebXmlNotSpecifiedAndServlet30NotUsed()
        throws Exception
    {
        String testId = "SimpleWarNotUnderServlet30";
        MavenProjectArtifactsStub project = new MavenProjectArtifactsStub();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, true );

        project.setArtifact( warArtifact );
        project.setFile( warArtifact.getFile() );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );

        try
        {
            mojo.execute();
            fail( "Building of the war isn't possible because no 'failOnMissingWebXml' policy was set and the project "
                + "does not depend on Servlet 3.0" );
        }
        catch ( MojoExecutionException e )
        {
            // expected behaviour
        }
    }

    public void testAttachClasses()
        throws Exception
    {
        String testId = "AttachClasses";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, false );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );
        mojo.setAttachClasses( true );
        mojo.setClassesClassifier( "classes" );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple-classes.jar" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "sample-servlet.class" },
                          new String[] { null, null } );
    }

    public void testAttachClassesWithCustomClassifier()
        throws Exception
    {
        String testId = "AttachClassesCustomClassifier";
        MavenProject4CopyConstructor project = new MavenProject4CopyConstructor();
        String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output";
        File webAppDirectory = new File( getTestDirectory(), testId );
        WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() );
        String warName = "simple";
        File webAppSource = createWebAppSource( testId );
        File classesDir = createClassesDir( testId, false );
        File xmlSource = createXMLConfigDir( testId, new String[] { "web.xml" } );

        project.setArtifact( warArtifact );
        this.configureMojo( mojo, new LinkedList<String>(), classesDir, webAppSource, webAppDirectory, project );
        setVariableValueToObject( mojo, "outputDirectory", outputDir );
        setVariableValueToObject( mojo, "warName", warName );
        mojo.setWebXml( new File( xmlSource, "web.xml" ) );
        mojo.setAttachClasses( true );
        mojo.setClassesClassifier( "mystuff" );

        mojo.execute();

        // validate jar file
        File expectedJarFile = new File( outputDir, "simple-mystuff.jar" );
        assertJarContent( expectedJarFile, new String[] { "META-INF/MANIFEST.MF", "sample-servlet.class" },
                          new String[] { null, null } );
    }

    protected Map<String, JarEntry> assertJarContent( final File expectedJarFile, final String[] files,
                                                      final String[] filesContent )
        throws IOException
    {
        return assertJarContent( expectedJarFile, files, filesContent, null );
    }

    protected Map<String, JarEntry> assertJarContent( final File expectedJarFile, final String[] files,
                                                      final String[] filesContent, final String[] mustNotBeInJar )
        throws IOException
    {
        // Sanity check
        assertEquals( "Could not test, files and filesContent lenght does not match", files.length, filesContent.length );

        assertTrue( "war file not created: " + expectedJarFile.toString(), expectedJarFile.exists() );
        final Map<String, JarEntry> jarContent = new HashMap<String, JarEntry>();
        final JarFile jarFile = new JarFile( expectedJarFile );

        JarEntry entry;
        Enumeration<JarEntry> enumeration = jarFile.entries();
        while ( enumeration.hasMoreElements() )
        {
            entry = (JarEntry) enumeration.nextElement();
            Object previousValue = jarContent.put( entry.getName(), entry );
            assertNull( "Duplicate Entry in Jar File: " + entry.getName(), previousValue );
        }

        for ( int i = 0; i < files.length; i++ )
        {
            String file = files[i];

            assertTrue( "File[" + file + "] not found in archive", jarContent.containsKey( file ) );
            if ( filesContent[i] != null )
            {
                assertEquals( "Content of file[" + file + "] does not match", filesContent[i],
                              IOUtil.toString( jarFile.getInputStream( (ZipEntry) jarContent.get( file ) ) ) );
            }
        }
        if ( mustNotBeInJar != null )
        {
            for ( String file : mustNotBeInJar )
            {
                assertFalse( "File[" + file + "]  found in archive", jarContent.containsKey( file ) );

            }
        }
        return jarContent;
    }

}
