    001/*
    002 *  Licensed to the Apache Software Foundation (ASF) under one or more
    003 *  contributor license agreements.  See the NOTICE file distributed with
    004 *  this work for additional information regarding copyright ownership.
    005 *  The ASF licenses this file to You under the Apache License, Version 2.0
    006 *  (the "License"); you may not use this file except in compliance with
    007 *  the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 */
    017
    018package org.apache.commons.compress.archivers;
    019
    020import java.io.BufferedInputStream;
    021import java.io.File;
    022import java.io.IOException;
    023import java.io.InputStream;
    024import java.nio.file.Files;
    025import java.util.Enumeration;
    026import java.util.Objects;
    027
    028import org.apache.commons.compress.archivers.sevenz.SevenZFile;
    029import org.apache.commons.compress.archivers.tar.TarFile;
    030import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
    031import org.apache.commons.compress.archivers.zip.ZipFile;
    032
    033/**
    034 * Simple command line application that lists the contents of an archive.
    035 *
    036 * <p>
    037 * The name of the archive must be given as a command line argument.
    038 * </p>
    039 * <p>
    040 * The optional second argument defines the archive type, in case the format is not recognized.
    041 * </p>
    042 *
    043 * @since 1.1
    044 */
    045public final class Lister {
    046
    047    private static final ArchiveStreamFactory FACTORY = ArchiveStreamFactory.DEFAULT;
    048
    049    private static <T extends ArchiveInputStream<? extends E>, E extends ArchiveEntry> T createArchiveInputStream(final String[] args,
    050            final InputStream inputStream) throws ArchiveException {
    051        if (args.length > 1) {
    052            return FACTORY.createArchiveInputStream(args[1], inputStream);
    053        }
    054        return FACTORY.createArchiveInputStream(inputStream);
    055    }
    056
    057    private static String detectFormat(final File file) throws ArchiveException, IOException {
    058        try (final InputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
    059            return ArchiveStreamFactory.detect(inputStream);
    060        }
    061    }
    062
    063    private static void list7z(final File file) throws IOException {
    064        try (SevenZFile sevenZFile = new SevenZFile(file)) {
    065            System.out.println("Created " + sevenZFile);
    066            ArchiveEntry entry;
    067            while ((entry = sevenZFile.getNextEntry()) != null) {
    068                final String name = entry.getName() == null ? sevenZFile.getDefaultName() + " (entry name was null)" : entry.getName();
    069                System.out.println(name);
    070            }
    071        }
    072    }
    073
    074    private static void listStream(final File file, final String[] args) throws ArchiveException, IOException {
    075        try (final InputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()));
    076                final ArchiveInputStream<?> archiveInputStream = createArchiveInputStream(args, inputStream)) {
    077            System.out.println("Created " + archiveInputStream.toString());
    078            ArchiveEntry entry;
    079            while ((entry = archiveInputStream.getNextEntry()) != null) {
    080                System.out.println(entry.getName());
    081            }
    082        }
    083    }
    084
    085    private static void listZipUsingTarFile(final File file) throws IOException {
    086        try (TarFile tarFile = new TarFile(file)) {
    087            System.out.println("Created " + tarFile);
    088            tarFile.getEntries().forEach(en -> System.out.println(en.getName()));
    089        }
    090    }
    091
    092    private static void listZipUsingZipFile(final File file) throws IOException {
    093        try (ZipFile zipFile = new ZipFile(file)) {
    094            System.out.println("Created " + zipFile);
    095            for (final Enumeration<ZipArchiveEntry> en = zipFile.getEntries(); en.hasMoreElements();) {
    096                System.out.println(en.nextElement().getName());
    097            }
    098        }
    099    }
    100
    101    /**
    102     * Runs this class from the command line.
    103     * <p>
    104     * The name of the archive must be given as a command line argument.
    105     * </p>
    106     * <p>
    107     * The optional second argument defines the archive type, in case the format is not recognized.
    108     * </p>
    109     *
    110     * @param args name of the archive and optional argument archive type.
    111     * @throws ArchiveException Archiver related Exception.
    112     * @throws IOException      an I/O exception.
    113     */
    114    public static void main(final String[] args) throws ArchiveException, IOException {
    115        if (args == null || args.length == 0) {
    116            usage();
    117            return;
    118        }
    119        Objects.requireNonNull(args[0], "args[0]");
    120        System.out.println("Analysing " + args[0]);
    121        final File file = new File(args[0]);
    122        if (!file.isFile()) {
    123            System.err.println(file + " doesn't exist or is a directory");
    124        }
    125        final String format = args.length > 1 ? args[1] : detectFormat(file);
    126        if (ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(format)) {
    127            list7z(file);
    128        } else if ("zipfile".equals(format)) {
    129            listZipUsingZipFile(file);
    130        } else if ("tarfile".equals(format)) {
    131            listZipUsingTarFile(file);
    132        } else {
    133            listStream(file, args);
    134        }
    135    }
    136
    137    private static void usage() {
    138        System.out.println("Parameters: archive-name [archive-type]\n");
    139        System.out.println("The magic archive-type 'zipfile' prefers ZipFile over ZipArchiveInputStream");
    140        System.out.println("The magic archive-type 'tarfile' prefers TarFile over TarArchiveInputStream");
    141    }
    142
    143}