All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.heroku.sdk.deploy.utils.Tar Maven / Gradle / Ivy

There is a newer version: 3.0.7
Show newest version
package com.heroku.sdk.deploy.utils;

import org.apache.commons.compress.archivers.*;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.tar.TarConstants;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.FileSystems;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;


public class Tar {
  public static File create(String filename, String directory, File workingDir, File outputDir) throws IOException, ArchiveException, InterruptedException {
    return new Pack(workingDir, directory).apply(filename, outputDir);
  }

  public static void extract(File tarFile, File outputDir) throws IOException, InterruptedException, ArchiveException {
    new Unpack(tarFile, outputDir).apply();
  }

  public static class Pack {
    private File workingDir;
    private String directory;

    public Pack(File workingDir, String directory) {
      this.workingDir = workingDir;
      this.directory = directory;
    }

    private List recursiveListFiles(File f) {
      List allFiles = new ArrayList();

      for (File subFile : f.listFiles()) {
        if (subFile.isDirectory()) {
          allFiles.addAll(recursiveListFiles(subFile));
        }
        allFiles.add(subFile);
      }
      return allFiles;
    }

    private void addFilesToTar(ArchiveOutputStream tarBall, File dir) throws IOException {
      for (File file : recursiveListFiles(dir)) {
        if (!file.isDirectory()) {
          Path path = FileSystems.getDefault().getPath(file.getAbsolutePath());
          String pathInTar = relativize(file);
          if (Files.isSymbolicLink(path)) {
            TarArchiveEntry tarFile = new TarArchiveEntry(pathInTar, TarConstants.LF_SYMLINK);
            String symbolicLink = Files.readSymbolicLink(path).toString();
            tarFile.setLinkName(symbolicLink);
            tarBall.putArchiveEntry(tarFile);
            tarBall.closeArchiveEntry();
          } else {
            TarArchiveEntry tarFile = new TarArchiveEntry(file, pathInTar);
            tarFile.setSize(file.length());
            if (Files.isExecutable(path)) {
              tarFile.setMode(493);
            }
            tarBall.putArchiveEntry(tarFile);
            IOUtils.copy(new FileInputStream(file), tarBall);
            tarBall.closeArchiveEntry();
          }
        }
      }
    }

    private void compress(File sourceFile, File targetFile) throws IOException {
      try (FileOutputStream fos = new FileOutputStream(targetFile);
           GZIPOutputStream gzs = new GZIPOutputStream(fos);
           FileInputStream fis = new FileInputStream(sourceFile)) {
        IOUtils.copy(fis, gzs);
      }
    }

    private File apply(String archiveFilename, File outputDir) throws ArchiveException, IOException {
      File archive = new File(outputDir, (archiveFilename + ".tar"));
      FileOutputStream tarOutput = new FileOutputStream(archive);

      TarArchiveOutputStream tarBall = (TarArchiveOutputStream)new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.TAR, tarOutput);
      tarBall.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
      try {
        addFilesToTar(tarBall, new File(workingDir, directory));
      } finally {
        tarBall.close();
      }

      File outputFile = new File(outputDir, (archiveFilename));
      compress(archive, outputFile);
      FileUtils.deleteQuietly(archive);
      return outputFile;
    }

    private String relativize(File path) {
      String relativePath = new File(this.workingDir, this.directory).toURI().relativize(path.toURI()).getPath();

      // don't use File.separator because it will be wrong on Windows
      return this.directory + "/" + relativePath;
    }
  }

  public static class Unpack {

    private File tarFile;
    private File outputDir;

    public Unpack(File tarFile, File outputDir) {
      this.tarFile = tarFile;
      this.outputDir = outputDir;
    }

    private ArchiveInputStream extract(InputStream input) throws ArchiveException {
      return new ArchiveStreamFactory().createArchiveInputStream(input);
    }

    public void apply() throws IOException, ArchiveException {
      try (FileInputStream fis = new FileInputStream(tarFile);
           GZIPInputStream gzs = new GZIPInputStream(fis)) {
        ArchiveInputStream archiveInputStream = extract(new BufferedInputStream(gzs));

        ArchiveEntry entry = archiveInputStream.getNextEntry();
        while (entry != null) {
          if (entry.isDirectory()) {
            FileUtils.forceMkdir(new File(outputDir, entry.getName()));
          } else {
            File destPath = new File(outputDir, entry.getName());

            IOUtils.copy(archiveInputStream, new FileOutputStream(destPath));

            if (((TarArchiveEntry) entry).getMode() == 493) {
              destPath.setExecutable(true);
            }
          }
          entry = archiveInputStream.getNextEntry();
        }
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy