public void testImplicitPermissions() throws IOException {
    File zipFile = getTestFile("target/output/zip-with-implicit-dirmode.zip");

    ZipArchiver archiver = getZipArchiver(zipFile);

    archiver.setDefaultDirectoryMode(0777);
    archiver.setDirectoryMode(0641);
    archiver.setFileMode(0222);
    archiver.addFile(new File("pom.xml"), "fizz/buzz/pom.xml");
    archiver.setDefaultDirectoryMode(0530);
    archiver.setDirectoryMode(-1); // Not forced mode
    archiver.setFileMode(0111);
    archiver.addFile(new File("pom.xml"), "fazz/bazz/pam.xml");
    archiver.createArchive();

    assertTrue(zipFile.exists());
    ZipFile zf = new ZipFile(zipFile);
    ZipArchiveEntry fizz = zf.getEntry("fizz/");
    assertEquals(040641, fizz.getUnixMode());
    ZipArchiveEntry pom = zf.getEntry("fizz/buzz/pom.xml");
    assertEquals(0100222, pom.getUnixMode());

    ZipArchiveEntry fazz = zf.getEntry("fazz/");
    assertEquals(040530, fazz.getUnixMode());
    ZipArchiveEntry pam = zf.getEntry("fazz/bazz/pam.xml");
    assertEquals(0100111, pam.getUnixMode());
  }
Ejemplo n.º 2
0
  @Test
  public void testThatExternalAttributesFieldIsFunctional() throws IOException {

    // Prepare some sample modes to write into the zip file.
    final ImmutableList<String> samples =
        ImmutableList.of("rwxrwxrwx", "rw-r--r--", "--x--x--x", "---------");

    for (String stringMode : samples) {
      long mode = MorePosixFilePermissions.toMode(PosixFilePermissions.fromString(stringMode));

      // Write a tiny sample zip file, which sets the external attributes per the
      // permission sample above.
      try (CustomZipOutputStream out =
          ZipOutputStreams.newOutputStream(output, OVERWRITE_EXISTING)) {
        CustomZipEntry entry = new CustomZipEntry("test");
        entry.setTime(System.currentTimeMillis());
        entry.setExternalAttributes(mode << 16);
        out.putNextEntry(entry);
        out.write(new byte[0]);
      }

      // Now re-read the zip file using apache's commons-compress, which supports parsing
      // the external attributes field.
      try (ZipFile in = new ZipFile(output.toFile())) {
        Enumeration<ZipArchiveEntry> entries = in.getEntries();
        ZipArchiveEntry entry = entries.nextElement();
        assertEquals(mode, entry.getExternalAttributes() >> 16);
        assertFalse(entries.hasMoreElements());
      }
    }
  }
  private void createArchive(ZipArchiver archiver) throws ArchiverException, IOException {
    archiver.createArchive();

    ZipFile zf = new ZipFile(archiver.getDestFile());

    Enumeration e = zf.getEntries();

    while (e.hasMoreElements()) {
      ZipArchiveEntry ze = (ZipArchiveEntry) e.nextElement();
      if (ze.isDirectory()) {
        if (ze.getName().startsWith("worldwritable")) {
          fileModeAssert(0777, UnixStat.PERM_MASK & ze.getUnixMode());
        } else if (ze.getName().startsWith("groupwritable")) {
          fileModeAssert(0070, UnixStat.PERM_MASK & ze.getUnixMode());
        } else {
          fileModeAssert(0500, UnixStat.PERM_MASK & ze.getUnixMode());
        }
      } else {
        if (ze.getName().equals("one.txt")) {
          fileModeAssert(0640, UnixStat.PERM_MASK & ze.getUnixMode());
        } else if (ze.getName().equals("two.txt")) {
          fileModeAssert(0664, UnixStat.PERM_MASK & ze.getUnixMode());
        } else if (ze.isUnixSymlink()) {
          //         assertEquals( ze.getName(), 0500, UnixStat.PERM_MASK & ze.getUnixMode() );
        } else {
          fileModeAssert(0400, UnixStat.PERM_MASK & ze.getUnixMode());
        }
      }
    }
  }
Ejemplo n.º 4
0
  /** extract zip file */
  public void extract(String outputDir) throws IOException {
    org.apache.commons.compress.archivers.zip.ZipFile file = null;
    InputStream in = null;
    OutputStream out = null;

    try {
      file = new org.apache.commons.compress.archivers.zip.ZipFile(fileName, fileEncoding);
      Enumeration<ZipArchiveEntry> entries = file.getEntries();
      while (entries.hasMoreElements()) {
        ZipArchiveEntry entry = entries.nextElement();
        String entryName = entry.getName();
        if (entry.isDirectory()) {
          forceMkdir(new File(outputDir + File.separator + entryName));
          continue;
        }
        out = openOutputStream(new File(outputDir + File.separator + entryName));
        in = file.getInputStream(entry);
        copy(in, out);
        closeQuietly(in);
        closeQuietly(out);
      }
    } finally {
      closeQuietly(in);
      closeQuietly(out);
      org.apache.commons.compress.archivers.zip.ZipFile.closeQuietly(file);
    }
  }
Ejemplo n.º 5
0
  /**
   * Test of compressPathToZip method, of class ZipManager.
   *
   * @throws Exception
   */
  @Test
  public void testCompressPathToZip() throws Exception {
    File path = new File(mavenTargetDirectoryRule.getResourceTestDirFile(), "ZipSample");
    File outfile = new File(tempDir, "testCompressPathToZip.zip");
    ZipUtil.compressPathToZip(path, outfile);
    ZipFile zipFile = new ZipFile(outfile, CharEncoding.UTF_8);
    try {
      Enumeration<? extends ZipEntry> entries = zipFile.getEntries();
      assertThat(zipFile.getEncoding(), is(CharEncoding.UTF_8));
      int nbEntries = 0;
      while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        nbEntries++;
      }
      assertThat(nbEntries, is(5));
      assertThat(zipFile.getEntry("ZipSample/simple.txt"), is(notNullValue()));
      assertThat(zipFile.getEntry("ZipSample/level1/simple.txt"), is(notNullValue()));
      assertThat(zipFile.getEntry("ZipSample/level1/level2b/simple.txt"), is(notNullValue()));
      assertThat(zipFile.getEntry("ZipSample/level1/level2a/simple.txt"), is(notNullValue()));

      ZipEntry accentuatedEntry =
          zipFile.getEntry("ZipSample/level1/level2a/s\u00efmplifi\u00e9.txt");
      if (accentuatedEntry == null) {
        accentuatedEntry =
            zipFile.getEntry(
                "ZipSample/level1/level2a/"
                    + new String("sïmplifié.txt".getBytes("UTF-8"), Charset.defaultCharset()));
      }
      assertThat(accentuatedEntry, is(notNullValue()));
      assertThat(zipFile.getEntry("ZipSample/level1/level2c/"), is(nullValue()));
    } finally {
      zipFile.close();
    }
  }
  public void testZipNonConcurrentResourceCollection() throws Exception {
    final File tarFile = getTestFile("target/output/zip-non-concurrent.tar");
    TarArchiver tarArchiver = (TarArchiver) lookup(Archiver.ROLE, "tar");
    tarArchiver.setDestFile(tarFile);
    // We're testing concurrency issue so we need large amount of files
    for (int i = 0; i < 100; i++) {
      tarArchiver.addFile(
          getTestFile("src/test/resources/manifests/manifest1.mf"), "manifest1.mf" + i);
      // Directories are added separately so let's test them too
      tarArchiver.addFile(
          getTestFile("src/test/resources/manifests/manifest2.mf"), "subdir" + i + "/manifest2.mf");
    }
    tarArchiver.createArchive();

    final File zipFile = new File("target/output/zip-non-concurrent.zip");
    ZipArchiver zipArchive = getZipArchiver(zipFile);
    zipArchive.addArchivedFileSet(tarFile, "prfx/");
    zipArchive.setEncoding("UTF-8");
    zipArchive.createArchive();

    final TarFile cmp1 = new TarFile(tarFile);
    final ZipFile cmp2 = new ZipFile(zipFile);
    ArchiveFileComparator.assertEquals(cmp1, cmp2, "prfx/");
    cmp1.close();
    cmp2.close();
  }
Ejemplo n.º 7
0
  @SuppressWarnings("unchecked")
  private static void unzipFolder(File uncompressFile, File descPathFile, boolean override) {

    ZipFile zipFile = null;
    try {
      zipFile = new ZipFile(uncompressFile, "GBK");

      Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
      while (entries.hasMoreElements()) {
        ZipArchiveEntry zipEntry = entries.nextElement();
        String name = zipEntry.getName();
        name = name.replace("\\", "/");

        File currentFile = new File(descPathFile, name);

        // 非覆盖 跳过
        if (currentFile.isFile() && currentFile.exists() && !override) {
          continue;
        }

        if (name.endsWith("/")) {
          currentFile.mkdirs();
          continue;
        } else {
          currentFile.getParentFile().mkdirs();
        }

        FileOutputStream fos = null;
        try {
          fos = new FileOutputStream(currentFile);
          InputStream is = zipFile.getInputStream(zipEntry);
          IOUtils.copy(is, fos);
        } finally {
          IOUtils.closeQuietly(fos);
        }
      }
    } catch (IOException e) {
      throw new RuntimeException("解压缩失败", e);
    } finally {
      if (zipFile != null) {
        try {
          zipFile.close();
        } catch (IOException e) {
        }
      }
    }
  }
  public void testOverddidenPermissions() throws IOException {
    File zipFile = getTestFile("target/output/zip-with-overriden-modes.zip");

    ZipArchiver archiver = getZipArchiver(zipFile);
    archiver.setDefaultDirectoryMode(0777);
    archiver.setDirectoryMode(0641);
    archiver.setFileMode(0777);
    archiver.addDirectory(new File("src/test/resources/symlinks/src"));
    archiver.createArchive();

    assertTrue(zipFile.exists());
    ZipFile zf = new ZipFile(zipFile);
    ZipArchiveEntry fizz = zf.getEntry("symDir");
    assertTrue(fizz.isUnixSymlink());
    ZipArchiveEntry symR = zf.getEntry("symR");
    assertTrue(symR.isUnixSymlink());
  }
Ejemplo n.º 9
0
 /**
  * Test of compressStreamToZip method, of class ZipManager.
  *
  * @throws Exception
  */
 @Test
 public void testCompressStreamToZip() throws Exception {
   InputStream inputStream =
       this.getClass().getClassLoader().getResourceAsStream("FrenchScrum.odp");
   String filePathNameToCreate =
       separatorChar + "dir1" + separatorChar + "dir2" + separatorChar + "FrenchScrum.odp";
   File outfile = new File(tempDir, "testCompressStreamToZip.zip");
   ZipUtil.compressStreamToZip(inputStream, filePathNameToCreate, outfile.getPath());
   inputStream.close();
   assertThat(outfile, is(notNullValue()));
   assertThat(outfile.exists(), is(true));
   assertThat(outfile.isFile(), is(true));
   int result = ZipUtil.getNbFiles(outfile);
   assertThat(result, is(1));
   ZipFile zipFile = new ZipFile(outfile);
   assertThat(zipFile.getEntry("/dir1/dir2/FrenchScrum.odp"), is(notNullValue()));
   zipFile.close();
 }
Ejemplo n.º 10
0
 /**
  * Grab lists of all root-level files and all directories contained in the given archive.
  *
  * @param file .
  * @param files .
  * @param dirs .
  * @throws java.io.IOException .
  */
 protected static void grabFilesAndDirs(String file, List<String> dirs, List<String> files)
     throws IOException {
   File zipFile = new File(file);
   if (!zipFile.exists()) {
     Logger logger = new ConsoleLogger(Logger.LEVEL_INFO, "console");
     logger.error("JarArchive skipping non-existing file: " + zipFile.getAbsolutePath());
   } else if (zipFile.isDirectory()) {
     Logger logger = new ConsoleLogger(Logger.LEVEL_INFO, "console");
     logger.info("JarArchiver skipping indexJar " + zipFile + " because it is not a jar");
   } else {
     org.apache.commons.compress.archivers.zip.ZipFile zf = null;
     try {
       zf = new org.apache.commons.compress.archivers.zip.ZipFile(file, "utf-8");
       Enumeration<ZipArchiveEntry> entries = zf.getEntries();
       HashSet<String> dirSet = new HashSet<String>();
       while (entries.hasMoreElements()) {
         ZipArchiveEntry ze = entries.nextElement();
         String name = ze.getName();
         // avoid index for manifest-only jars.
         if (!name.equals(META_INF_NAME)
             && !name.equals(META_INF_NAME + '/')
             && !name.equals(INDEX_NAME)
             && !name.equals(MANIFEST_NAME)) {
           if (ze.isDirectory()) {
             dirSet.add(name);
           } else if (!name.contains("/")) {
             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();
       }
     }
   }
 }
Ejemplo n.º 11
0
  public ZipDirResource(File file) throws IOException {
    this.zipFile = new ZipFile(file);

    initialize();

    Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
    while (entries.hasMoreElements()) {
      ZipArchiveEntry zipArchiveEntry = entries.nextElement();
      String entryPath = zipArchiveEntry.getName();

      createResource(entryPath, zipArchiveEntry);
    }
  }
  public void testCreateResourceCollection() throws Exception {
    final File srcDir = new File("src");
    final File zipFile = new File("target/output/src.zip");
    ZipArchiver zipArchiver = getZipArchiver(zipFile);
    zipArchiver.addDirectory(srcDir, null, FileUtils.getDefaultExcludes());
    zipArchiver.setEncoding("UTF-8");
    FileUtils.removePath(zipFile.getPath());
    zipArchiver.createArchive();

    final File zipFile2 = new File("target/output/src2.zip");
    ZipArchiver zipArchiver2 = getZipArchiver(zipFile2);
    zipArchiver2.addArchivedFileSet(zipFile, "prfx/");
    zipArchiver2.setEncoding("UTF-8");
    FileUtils.removePath(zipFile2.getPath());
    zipArchiver2.createArchive();

    final ZipFile cmp1 = new ZipFile(zipFile);
    final ZipFile cmp2 = new ZipFile(zipFile2);
    ArchiveFileComparator.assertEquals(cmp1, cmp2, "prfx/");
    cmp1.close();
    cmp2.close();
  }
  /* package */ File createAndAddCustomizedAndroidManifestToSelendroidServer()
      throws IOException, ShellCommandException, AndroidSdkException {
    String targetPackageName = applicationUnderTest.getBasePackage();
    File tempdir =
        new File(
            FileUtils.getTempDirectoryPath()
                + File.separatorChar
                + targetPackageName
                + System.currentTimeMillis());

    if (!tempdir.exists()) {
      tempdir.mkdirs();
    }

    File customizedManifest = new File(tempdir, "AndroidManifest.xml");
    log.info(
        "Adding target package '"
            + targetPackageName
            + "' to "
            + customizedManifest.getAbsolutePath());

    // add target package
    InputStream inputStream = getResourceAsStream(selendroidApplicationXmlTemplate);
    if (inputStream == null) {
      throw new SelendroidException("AndroidApplication.xml template file was not found.");
    }
    String content = IOUtils.toString(inputStream, Charset.defaultCharset().displayName());

    // find the first occurance of "package" and appending the targetpackagename to begining
    int i = content.toLowerCase().indexOf("package");
    int cnt = 0;
    for (; i < content.length(); i++) {
      if (content.charAt(i) == '\"') {
        cnt++;
      }
      if (cnt == 2) {
        break;
      }
    }
    content = content.substring(0, i) + "." + targetPackageName + content.substring(i);
    log.info("Final Manifest File:\n" + content);
    content = content.replaceAll(SELENDROID_TEST_APP_PACKAGE, targetPackageName);
    // Seems like this needs to be done
    if (content.contains(ICON)) {
      content = content.replaceAll(ICON, "");
    }

    OutputStream outputStream = new FileOutputStream(customizedManifest);
    IOUtils.write(content, outputStream, Charset.defaultCharset().displayName());
    IOUtils.closeQuietly(inputStream);
    IOUtils.closeQuietly(outputStream);

    // adding the xml to an empty apk
    CommandLine createManifestApk = new CommandLine(AndroidSdk.aapt());

    createManifestApk.addArgument("package", false);
    createManifestApk.addArgument("-M", false);
    createManifestApk.addArgument(customizedManifest.getAbsolutePath(), false);
    createManifestApk.addArgument("-I", false);
    createManifestApk.addArgument(AndroidSdk.androidJar(), false);
    createManifestApk.addArgument("-F", false);
    createManifestApk.addArgument(
        tempdir.getAbsolutePath() + File.separatorChar + "manifest.apk", false);
    createManifestApk.addArgument("-f", false);
    log.info(ShellCommand.exec(createManifestApk, 20000L));

    ZipFile manifestApk =
        new ZipFile(new File(tempdir.getAbsolutePath() + File.separatorChar + "manifest.apk"));
    ZipArchiveEntry binaryManifestXml = manifestApk.getEntry("AndroidManifest.xml");

    File finalSelendroidServerFile = new File(tempdir.getAbsolutePath() + "selendroid-server.apk");
    ZipArchiveOutputStream finalSelendroidServer =
        new ZipArchiveOutputStream(finalSelendroidServerFile);
    finalSelendroidServer.putArchiveEntry(binaryManifestXml);
    IOUtils.copy(manifestApk.getInputStream(binaryManifestXml), finalSelendroidServer);

    ZipFile selendroidPrebuildApk = new ZipFile(selendroidServer.getAbsolutePath());
    Enumeration<ZipArchiveEntry> entries = selendroidPrebuildApk.getEntries();
    for (; entries.hasMoreElements(); ) {
      ZipArchiveEntry dd = entries.nextElement();
      finalSelendroidServer.putArchiveEntry(dd);

      IOUtils.copy(selendroidPrebuildApk.getInputStream(dd), finalSelendroidServer);
    }

    finalSelendroidServer.closeArchiveEntry();
    finalSelendroidServer.close();
    manifestApk.close();
    log.info("file: " + finalSelendroidServerFile.getAbsolutePath());
    return finalSelendroidServerFile;
  }
  public void testCreateArchiveWithDetectedModes() throws Exception {

    String[] executablePaths = {"path/to/executable", "path/to/executable.bat"};

    String[] confPaths = {"path/to/etc/file", "path/to/etc/file2"};

    String[] logPaths = {"path/to/logs/log.txt"};

    int exeMode = 0777;
    int confMode = 0600;
    int logMode = 0640;

    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
      StackTraceElement e = new Throwable().getStackTrace()[0];
      System.out.println(
          "Cannot execute test: " + e.getMethodName() + " on " + System.getProperty("os.name"));
      return;
    }

    File tmpDir = null;
    try {
      tmpDir = File.createTempFile("zip-with-chmod.", ".dir");
      tmpDir.delete();

      tmpDir.mkdirs();

      for (String executablePath : executablePaths) {
        writeFile(tmpDir, executablePath, exeMode);
      }

      for (String confPath : confPaths) {
        writeFile(tmpDir, confPath, confMode);
      }

      for (String logPath : logPaths) {
        writeFile(tmpDir, logPath, logMode);
      }

      {
        Map<String, PlexusIoResourceAttributes> attributesByPath =
            PlexusIoResourceAttributeUtils.getFileAttributesByPath(tmpDir);
        for (String path : executablePaths) {
          PlexusIoResourceAttributes attrs = attributesByPath.get(path);
          if (attrs == null) {
            attrs = attributesByPath.get(new File(tmpDir, path).getAbsolutePath());
          }

          assertNotNull(attrs);
          assertEquals(
              "Wrong mode for: " + path + "; expected: " + exeMode, exeMode, attrs.getOctalMode());
        }

        for (String path : confPaths) {
          PlexusIoResourceAttributes attrs = attributesByPath.get(path);
          if (attrs == null) {
            attrs = attributesByPath.get(new File(tmpDir, path).getAbsolutePath());
          }

          assertNotNull(attrs);
          assertEquals(
              "Wrong mode for: " + path + "; expected: " + confMode,
              confMode,
              attrs.getOctalMode());
        }

        for (String path : logPaths) {
          PlexusIoResourceAttributes attrs = attributesByPath.get(path);
          if (attrs == null) {
            attrs = attributesByPath.get(new File(tmpDir, path).getAbsolutePath());
          }

          assertNotNull(attrs);
          assertEquals(
              "Wrong mode for: " + path + "; expected: " + logMode, logMode, attrs.getOctalMode());
        }
      }

      File zipFile = getTestFile("target/output/zip-with-modes.zip");

      ZipArchiver archiver = getZipArchiver(zipFile);

      archiver.addDirectory(tmpDir);
      archiver.createArchive();

      assertTrue(zipFile.exists());

      File zipFile2 = getTestFile("target/output/zip-with-modes-L2.zip");

      archiver = getZipArchiver();
      archiver.setDestFile(zipFile2);

      archiver.addArchivedFileSet(zipFile);
      archiver.createArchive();

      ZipFile zf = new ZipFile(zipFile2);

      for (String path : executablePaths) {
        ZipArchiveEntry ze = zf.getEntry(path);

        int mode = ze.getUnixMode() & UnixStat.PERM_MASK;

        assertEquals("Wrong mode for: " + path + "; expected: " + exeMode, exeMode, mode);
      }

      for (String path : confPaths) {
        ZipArchiveEntry ze = zf.getEntry(path);

        int mode = ze.getUnixMode() & UnixStat.PERM_MASK;

        assertEquals("Wrong mode for: " + path + "; expected: " + confMode, confMode, mode);
      }

      for (String path : logPaths) {
        ZipArchiveEntry ze = zf.getEntry(path);

        int mode = ze.getUnixMode() & UnixStat.PERM_MASK;

        assertEquals("Wrong mode for: " + path + "; expected: " + logMode, logMode, mode);
      }
    } finally {
      if (tmpDir != null && tmpDir.exists()) {
        try {
          FileUtils.forceDelete(tmpDir);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
Ejemplo n.º 15
0
  private cfQueryResultData performZiplist(cfSession session, File zipfile, String charset)
      throws IOException {
    ZipFile zFile = null;
    try {
      cfQueryResultData filesQuery =
          new cfQueryResultData(
              new String[] {
                "name",
                "type",
                "compressedsize",
                "size",
                "compressedpercent",
                "datelastmodified",
                "comment"
              },
              "CFZIP");
      zFile = new ZipFile(zipfile, charset);

      List<Map<String, cfData>> allResultRows = new ArrayList<Map<String, cfData>>();
      Map<String, cfData> resultRow;
      Enumeration<? extends ZipArchiveEntry> files = zFile.getEntries();
      ZipArchiveEntry nextEntry = null;
      long size;
      double compressed;

      while (files.hasMoreElements()) {
        nextEntry = (ZipArchiveEntry) files.nextElement();
        resultRow = new FastMap<String, cfData>(8);
        resultRow.put("name", new cfStringData(nextEntry.getName()));
        resultRow.put("comment", new cfStringData(nextEntry.getComment()));
        resultRow.put("datelastmodified", new cfDateData(nextEntry.getTime()));

        if (nextEntry.isDirectory()) {
          resultRow.put("compressedsize", new cfNumberData(0));
          resultRow.put("size", new cfNumberData(0));
          resultRow.put("type", new cfStringData("Dir"));
          resultRow.put("compressedpercent", new cfNumberData(0));

        } else {
          size = nextEntry.getSize();
          resultRow.put(
              "compressedsize", new cfStringData(String.valueOf(nextEntry.getCompressedSize())));
          resultRow.put("size", new cfStringData(String.valueOf(size)));
          resultRow.put("type", new cfStringData("File"));
          if (size != 0) {
            compressed = ((float) nextEntry.getCompressedSize() / (float) size);
            resultRow.put(
                "compressedpercent",
                new cfStringData(String.valueOf(100 - (int) (compressed * 100))));
          } else {
            resultRow.put("compressedpercent", new cfStringData("0"));
          }
        }

        allResultRows.add(resultRow);
      }
      filesQuery.populateQuery(allResultRows);
      return filesQuery;
    } finally {
      try {
        zFile.close();
      } catch (IOException ignored) {
      }
    }
  }
Ejemplo n.º 16
0
  public static int unpackFileToFolder(
      @Nonnull final Log logger,
      @Nullable final String folder,
      @Nonnull final File archiveFile,
      @Nonnull final File destinationFolder,
      final boolean makeAllExecutable)
      throws IOException {
    final String normalizedName = archiveFile.getName().toLowerCase(Locale.ENGLISH);

    final ArchEntryGetter entryGetter;

    boolean modeZipFile = false;

    final ZipFile theZipFile;
    final ArchiveInputStream archInputStream;
    if (normalizedName.endsWith(".zip")) {
      logger.debug("Detected ZIP archive");

      modeZipFile = true;

      theZipFile = new ZipFile(archiveFile);
      archInputStream = null;
      entryGetter =
          new ArchEntryGetter() {
            private final Enumeration<ZipArchiveEntry> iterator = theZipFile.getEntries();

            @Override
            @Nullable
            public ArchiveEntry getNextEntry() throws IOException {
              ArchiveEntry result = null;
              if (this.iterator.hasMoreElements()) {
                result = this.iterator.nextElement();
              }
              return result;
            }
          };
    } else {
      theZipFile = null;
      final InputStream in = new BufferedInputStream(new FileInputStream(archiveFile));
      try {
        if (normalizedName.endsWith(".tar.gz")) {
          logger.debug("Detected TAR.GZ archive");
          archInputStream = new TarArchiveInputStream(new GZIPInputStream(in));

          entryGetter =
              new ArchEntryGetter() {
                @Override
                @Nullable
                public ArchiveEntry getNextEntry() throws IOException {
                  return ((TarArchiveInputStream) archInputStream).getNextTarEntry();
                }
              };

        } else {
          logger.debug("Detected OTHER archive");
          archInputStream = ARCHIVE_STREAM_FACTORY.createArchiveInputStream(in);
          logger.debug("Created archive stream : " + archInputStream.getClass().getName());

          entryGetter =
              new ArchEntryGetter() {
                @Override
                @Nullable
                public ArchiveEntry getNextEntry() throws IOException {
                  return archInputStream.getNextEntry();
                }
              };
        }

      } catch (ArchiveException ex) {
        IOUtils.closeQuietly(in);
        throw new IOException("Can't recognize or read archive file : " + archiveFile, ex);
      } catch (CantReadArchiveEntryException ex) {
        IOUtils.closeQuietly(in);
        throw new IOException("Can't read entry from archive file : " + archiveFile, ex);
      }
    }

    try {

      final String normalizedFolder =
          folder == null ? null : FilenameUtils.normalize(folder, true) + '/';

      int unpackedFilesCounter = 0;
      while (true) {
        final ArchiveEntry entry = entryGetter.getNextEntry();
        if (entry == null) {
          break;
        }
        final String normalizedPath = FilenameUtils.normalize(entry.getName(), true);

        logger.debug("Detected archive entry : " + normalizedPath);

        if (normalizedFolder == null || normalizedPath.startsWith(normalizedFolder)) {
          final File targetFile =
              new File(
                  destinationFolder,
                  normalizedFolder == null
                      ? normalizedPath
                      : normalizedPath.substring(normalizedFolder.length()));
          if (entry.isDirectory()) {
            logger.debug("Folder : " + normalizedPath);
            if (!targetFile.exists() && !targetFile.mkdirs()) {
              throw new IOException("Can't create folder " + targetFile);
            }
          } else {
            final File parent = targetFile.getParentFile();

            if (parent != null && !parent.isDirectory() && !parent.mkdirs()) {
              throw new IOException("Can't create folder : " + parent);
            }

            final FileOutputStream fos = new FileOutputStream(targetFile);

            try {
              if (modeZipFile) {
                logger.debug("Unpacking ZIP entry : " + normalizedPath);

                final InputStream zipEntryInStream =
                    theZipFile.getInputStream((ZipArchiveEntry) entry);
                try {
                  if (IOUtils.copy(zipEntryInStream, fos) != entry.getSize()) {
                    throw new IOException(
                        "Can't unpack file, illegal unpacked length : " + entry.getName());
                  }
                } finally {
                  IOUtils.closeQuietly(zipEntryInStream);
                }
              } else {
                logger.debug("Unpacking archive entry : " + normalizedPath);

                if (!archInputStream.canReadEntryData(entry)) {
                  throw new IOException("Can't read archive entry data : " + normalizedPath);
                }
                if (IOUtils.copy(archInputStream, fos) != entry.getSize()) {
                  throw new IOException(
                      "Can't unpack file, illegal unpacked length : " + entry.getName());
                }
              }
            } finally {
              fos.close();
            }

            if (makeAllExecutable) {
              try {
                targetFile.setExecutable(true, true);
              } catch (SecurityException ex) {
                throw new IOException("Can't make file executable : " + targetFile, ex);
              }
            }
            unpackedFilesCounter++;
          }
        } else {
          logger.debug("Archive entry " + normalizedPath + " ignored");
        }
      }
      return unpackedFilesCounter;
    } finally {
      IOUtils.closeQuietly(theZipFile);
      IOUtils.closeQuietly(archInputStream);
    }
  }
  public void testForcedFileModes() throws IOException {
    File step1file = new File("target/output/forced-file-mode.zip");
    {
      final ZipArchiver zipArchiver = getZipArchiver(step1file);
      zipArchiver.setFileMode(0077);
      zipArchiver.setDirectoryMode(0007);
      PlexusIoResourceAttributes attrs =
          new SimpleResourceAttributes(123, "fred", 22, "filntstones", 0111);
      PlexusIoResource resource =
          ResourceFactory.createResource(
              new File("src/test/resources/folders/File.txt"), "Test.txt", null, attrs);
      zipArchiver.addResource(resource, "Test2.txt", 0707);
      PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
      files.setBaseDir(new File("src/test/resources/folders"));
      files.setPrefix("sixsixsix/");
      zipArchiver.addResources(files);

      zipArchiver.createArchive();

      ZipFile zf = new ZipFile(step1file);
      fileModeAssert(040007, zf.getEntry("sixsixsix/a/").getUnixMode());
      fileModeAssert(0100077, zf.getEntry("sixsixsix/b/FileInB.txt").getUnixMode());
      fileModeAssert(0100707, zf.getEntry("Test2.txt").getUnixMode());
      zf.close();
    }

    File Step2file = new File("target/output/forced-file-mode-from-zip.zip");
    {
      final ZipArchiver za2 = getZipArchiver(Step2file);
      za2.setFileMode(0666);
      za2.setDirectoryMode(0676);

      PlexusIoZipFileResourceCollection zipSrc = new PlexusIoZipFileResourceCollection();
      zipSrc.setFile(step1file);
      zipSrc.setPrefix("zz/");
      za2.addResources(zipSrc);
      za2.createArchive();
      ZipFile zf = new ZipFile(Step2file);
      fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
      fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
      zf.close();
    }

    File step3file = new File("target/output/forced-file-mode-from-zip2.zip");
    {
      final ZipArchiver za2 = getZipArchiver(step3file);
      za2.setFileMode(0666);
      za2.setDirectoryMode(0676);

      PlexusArchiverZipFileResourceCollection zipSrc =
          new PlexusArchiverZipFileResourceCollection();
      zipSrc.setFile(step1file);
      zipSrc.setPrefix("zz/");
      za2.addResources(zipSrc);
      za2.createArchive();
      ZipFile zf = new ZipFile(Step2file);
      fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
      fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
      zf.close();
    }
  }