Lister.java

  1. /*
  2.  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3.  *  contributor license agreements.  See the NOTICE file distributed with
  4.  *  this work for additional information regarding copyright ownership.
  5.  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6.  *  (the "License"); you may not use this file except in compliance with
  7.  *  the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */

  17. package org.apache.commons.compress.archivers;

  18. import java.io.BufferedInputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.nio.file.Files;
  22. import java.nio.file.Path;
  23. import java.nio.file.Paths;
  24. import java.util.Enumeration;
  25. import java.util.Locale;
  26. import java.util.Objects;

  27. import org.apache.commons.compress.archivers.sevenz.SevenZFile;
  28. import org.apache.commons.compress.archivers.tar.TarFile;
  29. import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
  30. import org.apache.commons.compress.archivers.zip.ZipFile;

  31. /**
  32.  * Simple command line application that lists the contents of an archive.
  33.  *
  34.  * <p>
  35.  * The name of the archive must be given as a command line argument.
  36.  * </p>
  37.  * <p>
  38.  * The optional second argument defines the archive type, in case the format is not recognized.
  39.  * </p>
  40.  *
  41.  * @since 1.1
  42.  */
  43. public final class Lister {

  44.     private static final ArchiveStreamFactory FACTORY = ArchiveStreamFactory.DEFAULT;

  45.     private static <T extends ArchiveInputStream<? extends E>, E extends ArchiveEntry> T createArchiveInputStream(final String[] args,
  46.             final InputStream inputStream) throws ArchiveException {
  47.         if (args.length > 1) {
  48.             return FACTORY.createArchiveInputStream(args[1], inputStream);
  49.         }
  50.         return FACTORY.createArchiveInputStream(inputStream);
  51.     }

  52.     private static String detectFormat(final Path file) throws ArchiveException, IOException {
  53.         try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(file))) {
  54.             return ArchiveStreamFactory.detect(inputStream);
  55.         }
  56.     }

  57.     /**
  58.      * Runs this class from the command line.
  59.      * <p>
  60.      * The name of the archive must be given as a command line argument.
  61.      * </p>
  62.      * <p>
  63.      * The optional second argument defines the archive type, in case the format is not recognized.
  64.      * </p>
  65.      *
  66.      * @param args name of the archive and optional argument archive type.
  67.      * @throws ArchiveException Archiver related Exception.
  68.      * @throws IOException      an I/O exception.
  69.      */
  70.     public static void main(final String... args) throws ArchiveException, IOException {
  71.         if (args == null || args.length == 0) {
  72.             usage();
  73.             return;
  74.         }
  75.         new Lister(false, args).go();
  76.     }

  77.     private static void usage() {
  78.         System.err.println("Parameters: archive-name [archive-type]\n");
  79.         System.err.println("The magic archive-type 'zipfile' prefers ZipFile over ZipArchiveInputStream");
  80.         System.err.println("The magic archive-type 'tarfile' prefers TarFile over TarArchiveInputStream");
  81.     }

  82.     private final boolean quiet;

  83.     private final String[] args;

  84.     /**
  85.      * Constructs a new instance.
  86.      *
  87.      * @deprecated No replacement.
  88.      */
  89.     @Deprecated
  90.     public Lister() {
  91.         this(false, "");
  92.     }

  93.     Lister(final boolean quiet, final String... args) {
  94.         this.quiet = quiet;
  95.         this.args = args.clone();
  96.         Objects.requireNonNull(args[0], "args[0]");
  97.     }

  98.     void go() throws ArchiveException, IOException {
  99.         list(Paths.get(args[0]), args);
  100.     }

  101.     private void list(final Path file, final String... args) throws ArchiveException, IOException {
  102.         println("Analyzing " + file);
  103.         if (!Files.isRegularFile(file)) {
  104.             System.err.println(file + " doesn't exist or is a directory");
  105.         }
  106.         final String format = (args.length > 1 ? args[1] : detectFormat(file)).toLowerCase(Locale.ROOT);
  107.         println("Detected format " + format);
  108.         switch (format) {
  109.         case ArchiveStreamFactory.SEVEN_Z:
  110.             list7z(file);
  111.             break;
  112.         case ArchiveStreamFactory.ZIP:
  113.             listZipUsingZipFile(file);
  114.             break;
  115.         case ArchiveStreamFactory.TAR:
  116.             listZipUsingTarFile(file);
  117.             break;
  118.         default:
  119.             listStream(file, args);
  120.         }
  121.     }

  122.     private  void list7z(final Path file) throws IOException {
  123.         try (SevenZFile sevenZFile = SevenZFile.builder().setPath(file).get()) {
  124.             println("Created " + sevenZFile);
  125.             ArchiveEntry entry;
  126.             while ((entry = sevenZFile.getNextEntry()) != null) {
  127.                 println(entry.getName() == null ? sevenZFile.getDefaultName() + " (entry name was null)" : entry.getName());
  128.             }
  129.         }
  130.     }

  131.     private  void listStream(final Path file, final String[] args) throws ArchiveException, IOException {
  132.         try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(file));
  133.                 ArchiveInputStream<?> archiveInputStream = createArchiveInputStream(args, inputStream)) {
  134.             println("Created " + archiveInputStream.toString());
  135.             archiveInputStream.forEach(this::println);
  136.         }
  137.     }

  138.     private  void listZipUsingTarFile(final Path file) throws IOException {
  139.         try (TarFile tarFile = new TarFile(file)) {
  140.             println("Created " + tarFile);
  141.             tarFile.getEntries().forEach(this::println);
  142.         }
  143.     }

  144.     private  void listZipUsingZipFile(final Path file) throws IOException {
  145.         try (ZipFile zipFile = ZipFile.builder().setPath(file).get()) {
  146.             println("Created " + zipFile);
  147.             for (final Enumeration<ZipArchiveEntry> en = zipFile.getEntries(); en.hasMoreElements();) {
  148.                 println(en.nextElement());
  149.             }
  150.         }
  151.     }

  152.     private void println(final ArchiveEntry entry) {
  153.         println(entry.getName());
  154.     }

  155.     private void println(final String line) {
  156.         if (!quiet) {
  157.             System.out.println(line);
  158.         }
  159.     }

  160. }