/*
 *  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.
 *
 */

package org.apache.tools.ant.taskdefs;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Manifest.Section;
import org.apache.tools.ant.types.ArchiveFileSet;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.types.spi.Service;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.zip.JarMarker;
import org.apache.tools.zip.ZipExtraField;
import org.apache.tools.zip.ZipOutputStream;

/**
 * Creates a JAR archive.
 *
 * @since Ant 1.1
 *
 * @ant.task category="packaging"
 */
public class Jar extends Zip {
    /** The index file name. */
    private static final String INDEX_NAME = "META-INF/INDEX.LIST";

    /** The manifest file name. */
    private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";

    /**
     * List of all known SPI Services
     */
    private List<Service> serviceList = new ArrayList<Service>();

    /** merged manifests added through addConfiguredManifest */
    private Manifest configuredManifest;

    /** shadow of the above if upToDate check alters the value */
    private Manifest savedConfiguredManifest;

    /**  merged manifests added through filesets */
    private Manifest filesetManifest;

    /**
     * Manifest of original archive, will be set to null if not in
     * update mode.
     */
    private Manifest originalManifest;

    /**
     *  whether to merge fileset manifests;
     *  value is true if filesetmanifest is 'merge' or 'mergewithoutmain'
     */
    private FilesetManifestConfig filesetManifestConfig;

    /**
     * whether to merge the main section of fileset manifests;
     * value is true if filesetmanifest is 'merge'
     */
    private boolean mergeManifestsMain = true;

    /** the manifest specified by the 'manifest' attribute **/
    private Manifest manifest;

    /** The encoding to use when reading in a manifest file */
    private String manifestEncoding;

    /**
     * The file found from the 'manifest' attribute.  This can be
     * either the location of a manifest, or the name of a jar added
     * through a fileset.  If its the name of an added jar, the
     * manifest is looked for in META-INF/MANIFEST.MF
     */
    private File manifestFile;

    /** jar index is JDK 1.3+ only */
    private boolean index = false;

    /** Whether to index META-INF/ and its children */
    private boolean indexMetaInf = false;

    /**
     * whether to really create the archive in createEmptyZip, will
     * get set in getResourcesToAdd.
     */
    private boolean createEmpty = false;

    /**
     * Stores all files that are in the root of the archive (i.e. that
     * have a name that doesn't contain a slash) so they can get
     * listed in the index.
     *
     * Will not be filled unless the user has asked for an index.
     *
     * @since Ant 1.6
     */
    private Vector<String> rootEntries;

    /**
     * Path containing jars that shall be indexed in addition to this archive.
     *
     * @since Ant 1.6.2
     */
    private Path indexJars;

    // CheckStyle:LineLength OFF - Link is too long.
    /**
     * Strict mode for checking rules of the JAR-Specification.
     * @see http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning
     */
    private StrictMode strict = new StrictMode("ignore");

    // CheckStyle:LineLength ON

    /**
     * whether to merge Class-Path attributes.
     */
    private boolean mergeClassPaths = false;

    /**
     * whether to flatten Class-Path attributes into a single one.
     */
    private boolean flattenClassPaths = false;

    /**
     * Extra fields needed to make Solaris recognize the archive as a jar file.
     *
     * @since Ant 1.6.3
     */
    private static final ZipExtraField[] JAR_MARKER = new ZipExtraField[] {
        JarMarker.getInstance()
    };

    /** constructor */
    public Jar() {
        super();
        archiveType = "jar";
        emptyBehavior = "create";
        setEncoding("UTF8");
        setZip64Mode(Zip64ModeAttribute.NEVER);
        rootEntries = new Vector<String>();
    }

    /**
     * Not used for jar files.
     * @param we not used
     * @ant.attribute ignore="true"
     */
    public void setWhenempty(WhenEmpty we) {
        log("JARs are never empty, they contain at least a manifest file",
            Project.MSG_WARN);
    }

    /**
     * Indicates if a jar file should be created when it would only contain a
     * manifest file.
     * Possible values are: <code>fail</code> (throw an exception
     * and halt the build); <code>skip</code> (do not create
     * any archive, but issue a warning); <code>create</code>
     * (make an archive with only a manifest file).
     * Default is <code>create</code>;
     * @param we a <code>WhenEmpty</code> enumerated value
     */
    public void setWhenmanifestonly(WhenEmpty we) {
        emptyBehavior = we.getValue();
    }

    /**
     * Activate the strict mode. When set to <i>true</i> a BuildException
     * will be thrown if the Jar-Packaging specification was broken.
     * @param strict New value of the strict mode.
     * @since Ant 1.7.1
     */
    public void setStrict(StrictMode strict) {
        this.strict = strict;
    }

    /**
     * Set the destination file.
     * @param jarFile the destination file
     * @deprecated since 1.5.x.
     *             Use setDestFile(File) instead.
     */
    public void setJarfile(File jarFile) {
        setDestFile(jarFile);
    }

    /**
     * Set whether or not to create an index list for classes.
     * This may speed up classloading in some cases.
     * @param flag a <code>boolean</code> value
     */
    public void setIndex(boolean flag) {
        index = flag;
    }

    /**
     * Set whether or not to add META-INF and its children to the index.
     *
     * <p>Doesn't have any effect if index is false.</p>
     *
     * <p>Sun's jar implementation used to skip the META-INF directory
     * and Ant followed that example.  The behavior has been changed
     * with Java 5.  In order to avoid problems with Ant generated
     * jars on Java 1.4 or earlier Ant will not include META-INF
     * unless explicitly asked to.</p>
     *
     * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526">
     * jar -i omits service providers in index.list</a>
     * @since Ant 1.8.0
     * @param flag a <code>boolean</code> value, defaults to false
     */
    public void setIndexMetaInf(boolean flag) {
        indexMetaInf = flag;
    }

    /**
     * The character encoding to use in the manifest file.
     *
     * @param manifestEncoding the character encoding
     */
    public void setManifestEncoding(String manifestEncoding) {
        this.manifestEncoding = manifestEncoding;
    }

    /**
     * Allows the manifest for the archive file to be provided inline
     * in the build file rather than in an external file.
     *
     * @param newManifest an embedded manifest element
     * @throws ManifestException on error
     */
    public void addConfiguredManifest(Manifest newManifest)
        throws ManifestException {
        if (configuredManifest == null) {
            configuredManifest = newManifest;
        } else {
            configuredManifest.merge(newManifest, false, mergeClassPaths);
        }
        savedConfiguredManifest = configuredManifest;
    }

    /**
     * The manifest file to use. This can be either the location of a manifest,
     * or the name of a jar added through a fileset. If its the name of an added
     * jar, the task expects the manifest to be in the jar at META-INF/MANIFEST.MF.
     *
     * @param manifestFile the manifest file to use.
     */
    public void setManifest(File manifestFile) {
        if (!manifestFile.exists()) {
            throw new BuildException("Manifest file: " + manifestFile
                                     + " does not exist.", getLocation());
        }

        this.manifestFile = manifestFile;
    }

    private Manifest getManifest(File manifestFile) {

        Manifest newManifest = null;
        FileInputStream fis = null;
        InputStreamReader isr = null;
        try {
            fis = new FileInputStream(manifestFile);
            if (manifestEncoding == null) {
                isr = new InputStreamReader(fis);
            } else {
                isr = new InputStreamReader(fis, manifestEncoding);
            }
            newManifest = getManifest(isr);
        } catch (UnsupportedEncodingException e) {
            throw new BuildException("Unsupported encoding while reading manifest: "
                                     + e.getMessage(), e);
        } catch (IOException e) {
            throw new BuildException("Unable to read manifest file: "
                                     + manifestFile
                                     + " (" + e.getMessage() + ")", e);
        } finally {
            FileUtils.close(isr);
        }
        return newManifest;
    }

    /**
     * @return null if jarFile doesn't contain a manifest, the
     * manifest otherwise.
     * @since Ant 1.5.2
     */
    private Manifest getManifestFromJar(File jarFile) throws IOException {
        ZipFile zf = null;
        try {
            zf = new ZipFile(jarFile);

            // must not use getEntry as "well behaving" applications
            // must accept the manifest in any capitalization
            Enumeration<? extends ZipEntry> e = zf.entries();
            while (e.hasMoreElements()) {
                ZipEntry ze = e.nextElement();
                if (ze.getName().equalsIgnoreCase(MANIFEST_NAME)) {
                    InputStreamReader isr =
                        new InputStreamReader(zf.getInputStream(ze), "UTF-8");
                    return getManifest(isr);
                }
            }
            return null;
        } finally {
            if (zf != null) {
                try {
                    zf.close();
                } catch (IOException e) {
                    // TODO - log an error?  throw an exception?
                }
            }
        }
    }

    private Manifest getManifest(Reader r) {

        Manifest newManifest = null;
        try {
            newManifest = new Manifest(r);
        } catch (ManifestException e) {
            log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
            throw new BuildException("Invalid Manifest: " + manifestFile,
                                     e, getLocation());
        } catch (IOException e) {
            throw new BuildException("Unable to read manifest file"
                                     + " (" + e.getMessage() + ")", e);
        }
        return newManifest;
    }

    private boolean jarHasIndex(File jarFile) throws IOException {
        ZipFile zf = null;
        try {
            zf = new ZipFile(jarFile);
            Enumeration<? extends ZipEntry> e = zf.entries();
            while (e.hasMoreElements()) {
                ZipEntry ze = e.nextElement();
                if (ze.getName().equalsIgnoreCase(INDEX_NAME)) {
                    return true;
                }
            }
            return false;
        } finally {
            if (zf != null) {
                try {
                    zf.close();
                } catch (IOException e) {
                    // TODO - log an error?  throw an exception?
                }
            }
        }
    }

    /**
     * Behavior when a Manifest is found in a zipfileset or zipgroupfileset file.
     * Valid values are "skip", "merge", and "mergewithoutmain".
     * "merge" will merge all of manifests together, and merge this into any
     * other specified manifests.
     * "mergewithoutmain" merges everything but the Main section of the manifests.
     * Default value is "skip".
     *
     * Note: if this attribute's value is not "skip", the created jar will not
     * be readable by using java.util.jar.JarInputStream
     *
     * @param config setting for found manifest behavior.
     */
    public void setFilesetmanifest(FilesetManifestConfig config) {
        filesetManifestConfig = config;
        mergeManifestsMain = "merge".equals(config.getValue());

        if (filesetManifestConfig != null
            && !filesetManifestConfig.getValue().equals("skip")) {

            doubleFilePass = true;
        }
    }

    /**
     * Adds a zipfileset to include in the META-INF directory.
     *
     * @param fs zipfileset to add
     */
    public void addMetainf(ZipFileSet fs) {
        // We just set the prefix for this fileset, and pass it up.
        fs.setPrefix("META-INF/");
        super.addFileset(fs);
    }

    /**
     * Add a path to index jars.
     * @param p a path
     * @since Ant 1.6.2
     */
    public void addConfiguredIndexJars(Path p) {
        if (indexJars == null) {
            indexJars = new Path(getProject());
        }
        indexJars.append(p);
    }

    /**
     * A nested SPI service element.
     * @param service the nested element.
     * @since Ant 1.7
     */
    public void addConfiguredService(Service service) {
        // Check if the service is configured correctly
        service.check();
        serviceList.add(service);
    }

    /**
     * Write SPI Information to JAR
     */
    private void writeServices(ZipOutputStream zOut) throws IOException {
        for (Service service : serviceList) {
           InputStream is = null;
           try {
               is = service.getAsStream();
               //stolen from writeManifest
               super.zipFile(is, zOut,
                             "META-INF/services/" + service.getType(),
                             System.currentTimeMillis(), null,
                             ZipFileSet.DEFAULT_FILE_MODE);
           } finally {
               // technically this is unnecessary since
               // Service.getAsStream returns a ByteArrayInputStream
               // and not closing it wouldn't do any harm.
               FileUtils.close(is);
           }
        }
    }

    /**
     * Whether to merge Class-Path attributes.
     *
     * @since Ant 1.8.0
     */
    public void setMergeClassPathAttributes(boolean b) {
        mergeClassPaths = b;
    }

    /**
     * Whether to flatten multi-valued attributes (i.e. Class-Path)
     * into a single one.
     *
     * @since Ant 1.8.0
     */
    public void setFlattenAttributes(boolean b) {
        flattenClassPaths = b;
    }

    /**
     * Initialize the zip output stream.
     * @param zOut the zip output stream
     * @throws IOException on I/O errors
     * @throws BuildException on other errors
     */
    protected void initZipOutputStream(ZipOutputStream zOut)
        throws IOException, BuildException {

        if (!skipWriting) {
            Manifest jarManifest = createManifest();
            writeManifest(zOut, jarManifest);
            writeServices(zOut);
        }
    }

    private Manifest createManifest()
        throws BuildException {
        try {
            if (manifest == null) {
                if (manifestFile != null) {
                    // if we haven't got the manifest yet, attempt to
                    // get it now and have manifest be the final merge
                    manifest = getManifest(manifestFile);
                }
            }

            // fileset manifest must come even before the default
            // manifest if mergewithoutmain is selected and there is
            // no explicit manifest specified - otherwise the Main
            // section of the fileset manifest is still merged to the
            // final manifest.
            boolean mergeFileSetFirst = !mergeManifestsMain
                && filesetManifest != null
                && configuredManifest == null && manifest == null;

            Manifest finalManifest;
            if (mergeFileSetFirst) {
                finalManifest = new Manifest();
                finalManifest.merge(filesetManifest, false, mergeClassPaths);
                finalManifest.merge(Manifest.getDefaultManifest(),
                                    true, mergeClassPaths);
            } else {
                finalManifest = Manifest.getDefaultManifest();
            }

            /*
             * Precedence: manifestFile wins over inline manifest,
             * over manifests read from the filesets over the original
             * manifest.
             *
             * merge with null argument is a no-op
             */

            if (isInUpdateMode()) {
                finalManifest.merge(originalManifest, false, mergeClassPaths);
            }
            if (!mergeFileSetFirst) {
                finalManifest.merge(filesetManifest, false, mergeClassPaths);
            }
            finalManifest.merge(configuredManifest, !mergeManifestsMain,
                                mergeClassPaths);
            finalManifest.merge(manifest, !mergeManifestsMain,
                                mergeClassPaths);

            return finalManifest;

        } catch (ManifestException e) {
            log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
            throw new BuildException("Invalid Manifest", e, getLocation());
        }
    }

    private void writeManifest(ZipOutputStream zOut, Manifest manifest)
        throws IOException {
        for (Enumeration<String> e = manifest.getWarnings();
             e.hasMoreElements();) {
            log("Manifest warning: " + e.nextElement(),
                Project.MSG_WARN);
        }

        zipDir((Resource) null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE,
               JAR_MARKER);
        // time to write the manifest
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(baos, Manifest.JAR_ENCODING);
        PrintWriter writer = new PrintWriter(osw);
        manifest.write(writer, flattenClassPaths);
        if (writer.checkError()) {
            throw new IOException("Encountered an error writing the manifest");
        }
        writer.close();

        ByteArrayInputStream bais =
            new ByteArrayInputStream(baos.toByteArray());
        try {
            super.zipFile(bais, zOut, MANIFEST_NAME,
                          System.currentTimeMillis(), null,
                          ZipFileSet.DEFAULT_FILE_MODE);
        } finally {
            // not really required
            FileUtils.close(bais);
        }
        super.initZipOutputStream(zOut);
    }

    /**
     * Finalize the zip output stream.
     * This creates an index list if the index attribute is true.
     * @param zOut the zip output stream
     * @throws IOException on I/O errors
     * @throws BuildException on other errors
     */
    protected void finalizeZipOutputStream(ZipOutputStream zOut)
        throws IOException, BuildException {

        if (index) {
            createIndexList(zOut);
        }
    }

    /**
     * Create the index list to speed up classloading.
     * This is a JDK 1.3+ specific feature and is enabled by default. See
     * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index">
     * the JAR index specification</a> for more details.
     *
     * @param zOut the zip stream representing the jar being built.
     * @throws IOException thrown if there is an error while creating the
     * index and adding it to the zip stream.
     */
    private void createIndexList(ZipOutputStream zOut) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // encoding must be UTF8 as specified in the specs.
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos,
                                                                    "UTF8"));

        // version-info blankline
        writer.println("JarIndex-Version: 1.0");
        writer.println();

        // header newline
        writer.println(zipFile.getName());

        writeIndexLikeList(new ArrayList<String>(addedDirs.keySet()),
                           rootEntries, writer);
        writer.println();

        if (indexJars != null) {
            Manifest mf = createManifest();
            Manifest.Attribute classpath =
                mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
            String[] cpEntries = null;
            if (classpath != null && classpath.getValue() != null) {
                StringTokenizer tok = new StringTokenizer(classpath.getValue(),
                                                          " ");
                cpEntries = new String[tok.countTokens()];
                int c = 0;
                while (tok.hasMoreTokens()) {
                    cpEntries[c++] = tok.nextToken();
                }
            }
            String[] indexJarEntries = indexJars.list();
            for (int i = 0; i < indexJarEntries.length; i++) {
                String name = findJarName(indexJarEntries[i], cpEntries);
                if (name != null) {
                    ArrayList<String> dirs = new ArrayList<String>();
                    ArrayList<String> files = new ArrayList<String>();
                    grabFilesAndDirs(indexJarEntries[i], dirs, files);
                    if (dirs.size() + files.size() > 0) {
                        writer.println(name);
                        writeIndexLikeList(dirs, files, writer);
                        writer.println();
                    }
                }
            }
        }

        if (writer.checkError()) {
            throw new IOException("Encountered an error writing jar index");
        }
        writer.close();
        ByteArrayInputStream bais =
            new ByteArrayInputStream(baos.toByteArray());
        try {
            super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(),
                          null, ZipFileSet.DEFAULT_FILE_MODE);
        } finally {
            // not really required
            FileUtils.close(bais);
        }
    }

    /**
     * Overridden from Zip class to deal with manifests and index lists.
     * @param is the stream to read data for the entry from.  The
     * caller of the method is responsible for closing the stream.
     * @param zOut the zip output stream
     * @param vPath the name this entry shall have in the archive
     * @param lastModified last modification time for the entry.
     * @param fromArchive the original archive we are copying this
     *                    entry from, will be null if we are not copying from an archive.
     * @param mode the Unix permissions to set.
     * @throws IOException on error
     */
    protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath,
                           long lastModified, File fromArchive, int mode)
        throws IOException {
        if (MANIFEST_NAME.equalsIgnoreCase(vPath))  {
            if (isFirstPass()) {
                filesetManifest(fromArchive, is);
            }
        } else if (INDEX_NAME.equalsIgnoreCase(vPath) && index) {
            logWhenWriting("Warning: selected " + archiveType
                           + " files include a " + INDEX_NAME + " which will"
                           + " be replaced by a newly generated one.",
                           Project.MSG_WARN);
        } else {
            if (index && vPath.indexOf("/") == -1) {
                rootEntries.addElement(vPath);
            }
            super.zipFile(is, zOut, vPath, lastModified, fromArchive, mode);
        }
    }

    private void filesetManifest(File file, InputStream is) throws IOException {
        if (manifestFile != null && manifestFile.equals(file)) {
            // If this is the same name specified in 'manifest', this
            // is the manifest to use
            log("Found manifest " + file, Project.MSG_VERBOSE);
            try {
                if (is != null) {
                    InputStreamReader isr;
                    if (manifestEncoding == null) {
                        isr = new InputStreamReader(is);
                    } else {
                        isr = new InputStreamReader(is, manifestEncoding);
                    }
                    manifest = getManifest(isr);
                } else {
                    manifest = getManifest(file);
                }
            } catch (UnsupportedEncodingException e) {
                throw new BuildException("Unsupported encoding while reading "
                    + "manifest: " + e.getMessage(), e);
            }
        } else if (filesetManifestConfig != null
                    && !filesetManifestConfig.getValue().equals("skip")) {
            // we add this to our group of fileset manifests
            logWhenWriting("Found manifest to merge in file " + file,
                           Project.MSG_VERBOSE);

            try {
                Manifest newManifest = null;
                if (is != null) {
                    InputStreamReader isr;
                    if (manifestEncoding == null) {
                        isr = new InputStreamReader(is);
                    } else {
                        isr = new InputStreamReader(is, manifestEncoding);
                    }
                    newManifest = getManifest(isr);
                } else {
                    newManifest = getManifest(file);
                }

                if (filesetManifest == null) {
                    filesetManifest = newManifest;
                } else {
                    filesetManifest.merge(newManifest, false, mergeClassPaths);
                }
            } catch (UnsupportedEncodingException e) {
                throw new BuildException("Unsupported encoding while reading "
                    + "manifest: " + e.getMessage(), e);
            } catch (ManifestException e) {
                log("Manifest in file " + file + " is invalid: "
                    + e.getMessage(), Project.MSG_ERR);
                throw new BuildException("Invalid Manifest", e, getLocation());
            }
        } else {
            // assuming 'skip' otherwise
            // don't warn if skip has been requested explicitly, warn if user
            // didn't set the attribute

            // Hide warning also as it makes no sense since
            // the filesetmanifest attribute itself has been
            // hidden

            //int logLevel = filesetManifestConfig == null ?
            //    Project.MSG_WARN : Project.MSG_VERBOSE;
            //log("File " + file
            //    + " includes a META-INF/MANIFEST.MF which will be ignored. "
            //    + "To include this file, set filesetManifest to a value other "
            //    + "than 'skip'.", logLevel);
        }
    }

    /**
     * Collect the resources that are newer than the corresponding
     * entries (or missing) in the original archive.
     *
     * <p>If we are going to recreate the archive instead of updating
     * it, all resources should be considered as new, if a single one
     * is.  Because of this, subclasses overriding this method must
     * call <code>super.getResourcesToAdd</code> and indicate with the
     * third arg if they already know that the archive is
     * out-of-date.</p>
     *
     * @param rcs The resource collections to grab resources from
     * @param zipFile intended archive file (may or may not exist)
     * @param needsUpdate whether we already know that the archive is
     * out-of-date.  Subclasses overriding this method are supposed to
     * set this value correctly in their call to
     * super.getResourcesToAdd.
     * @return an array of resources to add for each fileset passed in as well
     *         as a flag that indicates whether the archive is uptodate.
     *
     * @exception BuildException if it likes
     */
    protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs,
                                             File zipFile,
                                             boolean needsUpdate)
        throws BuildException {

        if (skipWriting) {
            // this pass is only there to construct the merged
            // manifest this means we claim an update was needed and
            // only include the manifests, skipping any uptodate
            // checks here deferring them for the second run
            Resource[][] manifests = grabManifests(rcs);
            int count = 0;
            for (int i = 0; i < manifests.length; i++) {
                count += manifests[i].length;
            }
            log("found a total of " + count + " manifests in "
                + manifests.length + " resource collections",
                Project.MSG_VERBOSE);
            return new ArchiveState(true, manifests);
        }

        // need to handle manifest as a special check
        if (zipFile.exists()) {
            // if it doesn't exist, it will get created anyway, don't
            // bother with any up-to-date checks.

            try {
                originalManifest = getManifestFromJar(zipFile);
                if (originalManifest == null) {
                    log("Updating jar since the current jar has"
                                   + " no manifest", Project.MSG_VERBOSE);
                    needsUpdate = true;
                } else {
                    Manifest mf = createManifest();
                    if (!mf.equals(originalManifest)) {
                        log("Updating jar since jar manifest has"
                                       + " changed", Project.MSG_VERBOSE);
                        needsUpdate = true;
                    }
                }
            } catch (Throwable t) {
                log("error while reading original manifest in file: "
                    + zipFile.toString() + " due to " + t.getMessage(),
                    Project.MSG_WARN);
                needsUpdate = true;
            }

        } else {
            // no existing archive
            needsUpdate = true;
        }

        createEmpty = needsUpdate;
        if (!needsUpdate && index) {
            try {
                needsUpdate = !jarHasIndex(zipFile);
            } catch (IOException e) {
                //if we couldn't read it, we might as well recreate it?
                needsUpdate = true;
            }
        }
        return super.getResourcesToAdd(rcs, zipFile, needsUpdate);
    }

    /**
     * Create an empty jar file.
     * @param zipFile the file to create
     * @return true for historic reasons
     * @throws BuildException on error
     */
    protected boolean createEmptyZip(File zipFile) throws BuildException {
        if (!createEmpty) {
            return true;
        }

        if (emptyBehavior.equals("skip")) {
            if (!skipWriting) {
                log("Warning: skipping " + archiveType + " archive "
                    + zipFile + " because no files were included.",
                    Project.MSG_WARN);
            }
            return true;
        } else if (emptyBehavior.equals("fail")) {
            throw new BuildException("Cannot create " + archiveType
                                     + " archive " + zipFile
                                     + ": no files were included.",
                                     getLocation());
        }

        ZipOutputStream zOut = null;
        try {
            if (!skipWriting) {
                log("Building MANIFEST-only jar: "
                    + getDestFile().getAbsolutePath());
            }
            zOut = new ZipOutputStream(getDestFile());

            zOut.setEncoding(getEncoding());
            zOut.setUseZip64(getZip64Mode().getMode());
            if (isCompress()) {
                zOut.setMethod(ZipOutputStream.DEFLATED);
            } else {
                zOut.setMethod(ZipOutputStream.STORED);
            }
            initZipOutputStream(zOut);
            finalizeZipOutputStream(zOut);
        } catch (IOException ioe) {
            throw new BuildException("Could not create almost empty JAR archive"
                                     + " (" + ioe.getMessage() + ")", ioe,
                                     getLocation());
        } finally {
            // Close the output stream.
            FileUtils.close(zOut);
            createEmpty = false;
        }
        return true;
    }

    /**
     * Make sure we don't think we already have a MANIFEST next time this task
     * gets executed.
     *
     * @see Zip#cleanUp
     */
    protected void cleanUp() {
        super.cleanUp();
        checkJarSpec();

        // we want to save this info if we are going to make another pass
        if (!doubleFilePass || !skipWriting) {
            manifest = null;
            configuredManifest = savedConfiguredManifest;
            filesetManifest = null;
            originalManifest = null;
        }
        rootEntries.removeAllElements();
    }

    // CheckStyle:LineLength OFF - Link is too long.
    /**
     * Check against packaging spec
     * @see "http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning"
     */
    // CheckStyle:LineLength ON
    private void checkJarSpec() {
        String br = System.getProperty("line.separator");
        StringBuffer message = new StringBuffer();
        Section mainSection = (configuredManifest == null)
                            ? null
                            : configuredManifest.getMainSection();

        if (mainSection == null) {
            message.append("No Implementation-Title set.");
            message.append("No Implementation-Version set.");
            message.append("No Implementation-Vendor set.");
        } else {
            if (mainSection.getAttribute("Implementation-Title") == null) {
                message.append("No Implementation-Title set.");
            }
            if (mainSection.getAttribute("Implementation-Version") == null) {
                message.append("No Implementation-Version set.");
            }
            if (mainSection.getAttribute("Implementation-Vendor") == null) {
                message.append("No Implementation-Vendor set.");
            }
        }

        if (message.length() > 0) {
            message.append(br);
            message.append("Location: ").append(getLocation());
            message.append(br);
            if (strict.getValue().equalsIgnoreCase("fail")) {
                throw new BuildException(message.toString(), getLocation());
            } else {
                logWhenWriting(message.toString(), strict.getLogLevel());
            }
        }
    }

    /**
     * reset to default values.
     *
     * @see Zip#reset
     *
     * @since 1.44, Ant 1.5
     */
    public void reset() {
        super.reset();
        emptyBehavior = "create";
        configuredManifest = null;
        filesetManifestConfig = null;
        mergeManifestsMain = false;
        manifestFile = null;
        index = false;
    }

    /**
     * The manifest config enumerated type.
     */
    public static class FilesetManifestConfig extends EnumeratedAttribute {
        /**
         * Get the list of valid strings.
         * @return the list of values - "skip", "merge" and "mergewithoutmain"
         */
        public String[] getValues() {
            return new String[] {"skip", "merge", "mergewithoutmain"};
        }
    }

    /**
     * Writes the directory entries from the first and the filenames
     * from the second list to the given writer, one entry per line.
     *
     * @param dirs a list of directories
     * @param files a list of files
     * @param writer the writer to write to
     * @throws IOException on error
     * @since Ant 1.6.2
     */
    protected final void writeIndexLikeList(List<String> dirs, List<String> files,
                                            PrintWriter writer) {
        // JarIndex is sorting the directories by ascending order.
        // it has no value but cosmetic since it will be read into a
        // hashtable by the classloader, but we'll do so anyway.
        Collections.sort(dirs);
        Collections.sort(files);
        for (String dir : dirs) {
            // try to be smart, not to be fooled by a weird directory name
            dir = dir.replace('\\', '/');
            if (dir.startsWith("./")) {
                dir = dir.substring(2);
            }
            while (dir.startsWith("/")) {
                dir = dir.substring(1);
            }
            int pos = dir.lastIndexOf('/');
            if (pos != -1) {
                dir = dir.substring(0, pos);
            }

            // looks like nothing from META-INF should be added
            // and the check is not case insensitive.
            // see sun.misc.JarIndex
            // see also
            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526
            if (!indexMetaInf && dir.startsWith("META-INF")) {
                continue;
            }
            // name newline
            writer.println(dir);
        }

        for (String file : files) {
            writer.println(file);
        }
    }

    /**
     * try to guess the name of the given file.
     *
     * <p>If this jar has a classpath attribute in its manifest, we
     * can assume that it will only require an index of jars listed
     * there.  try to find which classpath entry is most likely the
     * one the given file name points to.</p>
     *
     * <p>In the absence of a classpath attribute, assume the other
     * files will be placed inside the same directory as this jar and
     * use their basename.</p>
     *
     * <p>if there is a classpath and the given file doesn't match any
     * of its entries, return null.</p>
     *
     * @param fileName the name to look for
     * @param classpath the classpath to look in (may be null)
     * @return the matching entry, or null if the file is not found
     * @since Ant 1.6.2
     */
    protected static String findJarName(String fileName,
                                              String[] classpath) {
        if (classpath == null) {
            return (new File(fileName)).getName();
        }
        fileName = fileName.replace(File.separatorChar, '/');
        TreeMap<String, String> matches = new TreeMap<String, String>(new Comparator<Object>() {
                // longest match comes first
                public int compare(Object o1, Object o2) {
                    if (o1 instanceof String && o2 instanceof String) {
                        return ((String) o2).length()
                            - ((String) o1).length();
                    }
                    return 0;
                }
            });

        for (int i = 0; i < classpath.length; i++) {
            if (fileName.endsWith(classpath[i])) {
                matches.put(classpath[i], classpath[i]);
            } else {
                int slash = classpath[i].indexOf("/");
                String candidate = classpath[i];
                while (slash > -1) {
                    candidate = candidate.substring(slash + 1);
                    if (fileName.endsWith(candidate)) {
                        matches.put(candidate, classpath[i]);
                        break;
                    }
                    slash = candidate.indexOf("/");
                }
            }
        }

        return matches.size() == 0
            ? null : (String) matches.get(matches.firstKey());
    }

    /**
     * Grab lists of all root-level files and all directories
     * contained in the given archive.
     * @param file the zip file to examine
     * @param dirs where to place the directories found
     * @param files where to place the files found
     * @since Ant 1.7
     * @throws IOException on error
     */
    protected static void grabFilesAndDirs(String file, List<String> dirs,
                                                 List<String> files)
        throws IOException {
        org.apache.tools.zip.ZipFile zf = null;
        try {
            zf = new org.apache.tools.zip.ZipFile(file, "utf-8");
            Enumeration<org.apache.tools.zip.ZipEntry> entries = zf.getEntries();
            HashSet<String> dirSet = new HashSet<String>();
            while (entries.hasMoreElements()) {
                org.apache.tools.zip.ZipEntry ze =
                    entries.nextElement();
                String name = ze.getName();
                if (ze.isDirectory()) {
                    dirSet.add(name);
                } else if (name.indexOf("/") == -1) {
                    files.add(name);
                } else {
                    // a file, not in the root
                    // since the jar may be one without directory
                    // entries, add the parent dir of this file as
                    // well.
                    dirSet.add(name.substring(0, name.lastIndexOf("/") + 1));
                }
            }
            dirs.addAll(dirSet);
        } finally {
            if (zf != null) {
                zf.close();
            }
        }
    }

    private Resource[][] grabManifests(ResourceCollection[] rcs) {
        Resource[][] manifests = new Resource[rcs.length][];
        for (int i = 0; i < rcs.length; i++) {
            Resource[][] resources = null;
            if (rcs[i] instanceof FileSet) {
                resources = grabResources(new FileSet[] {(FileSet) rcs[i]});
            } else {
                resources = grabNonFileSetResources(new ResourceCollection[] {
                        rcs[i]
                    });
            }
            for (int j = 0; j < resources[0].length; j++) {
                String name = resources[0][j].getName().replace('\\', '/');
                if (rcs[i] instanceof ArchiveFileSet) {
                    ArchiveFileSet afs = (ArchiveFileSet) rcs[i];
                    if (!"".equals(afs.getFullpath(getProject()))) {
                        name = afs.getFullpath(getProject());
                    } else if (!"".equals(afs.getPrefix(getProject()))) {
                        String prefix = afs.getPrefix(getProject());
                        if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
                            prefix += "/";
                        }
                        name = prefix + name;
                    }
                }
                if (name.equalsIgnoreCase(MANIFEST_NAME)) {
                    manifests[i] = new Resource[] {resources[0][j]};
                    break;
                }
            }
            if (manifests[i] == null) {
                manifests[i] = new Resource[0];
            }
        }
        return manifests;
    }

    /** The strict enumerated type. */
    public static class StrictMode extends EnumeratedAttribute {
        /** Public no arg constructor. */
        public StrictMode() {
        }
        /**
         * Constructor with an arg.
         * @param value the enumerated value as a string.
         */
        public StrictMode(String value) {
            setValue(value);
        }
        /**
         * Get List of valid strings.
         * @return the list of values.
         */
        public String[] getValues() {
            return new String[]{"fail", "warn", "ignore"};
        }
        /**
         * @return The log level according to the strict mode.
         */
        public int getLogLevel() {
            return (getValue().equals("ignore")) ? Project.MSG_VERBOSE : Project.MSG_WARN;
        }
    }
}
