Archive.java

/*
 * Copyright © 2024-2025 The CTAN Team and individual authors
 *
 * This file is distributed under the 3-clause BSD license.
 * See file LICENSE for details.
 */

package org.ctan.site.services.upload.util.archive;

import java.io.IOException;
import java.io.InputStream;

/**
 * The interface <code>Archive</code> contains the common description for a ZIP
 * and tar.gz archive.
 *
 * @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
 */
public interface Archive {

    /**
     * The interface <code>Entry</code> contains the wrapper definition for an
     * archive entry.
     */
    public interface Entry {

        /**
         * The method <code>getName</code> provides means to get the name.
         *
         * @return the name
         */
        String getName();

        /**
         * The method <code>isDirectory</code> provides means to determine the
         * type.
         *
         * @return true iff the entry is a directory
         */
        boolean isDirectory();
    }

    /**
     * The method <code>of</code> provides means to create a wrapper for an
     * archive file.
     *
     * @param name the file name
     * @param in the file to wrap
     * @return the new archive wrapper for the file or <code>null</code> if the
     *     file type is not supported
     */
    static Archive of(String name, InputStream in) {

        if (name == null || in == null) {
            return null;
        }
        var it = name.toLowerCase();
        if (it.endsWith(".zip")) {
            return new ZipArchiveWrapper(name, in);
        } else if (it.endsWith(".tgz") || it.endsWith(".tar.gz")) {
            try {
                return new TgzArchiveWrapper(name, in);
            } catch (IOException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * The method <code>close</code> provides means to close the stream.
     *
     * @throws IOException in case of an I/O error
     */
    void close() throws IOException;

    /**
     * The method <code>closeEntry</code> provides means to close the current
     * entry.
     *
     * @throws IOException in case of an I/O error
     */
    void closeEntry() throws IOException;

    /**
     * The method <code>getName</code> provides means to retrieve the file name.
     *
     * @return the file name or null
     */
    String getName();

    /**
     * The method <code>getNextEntry</code> provides means to move to the next
     * entry.
     *
     * @return the next entry
     * @throws IOException in case of an I/O error
     */
    Entry getNextEntry() throws IOException;

    /**
     * The method <code>getStream</code> provides means to get the InputStream
     * for the current entry.
     *
     * @return the InputStream for the current entry
     */
    InputStream getStream();
}