com.heroku.sdk.deploy.utils.Tar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of heroku-deploy Show documentation
Show all versions of heroku-deploy Show documentation
Library for deploying Java applications to Heroku
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();
}
}
}
}
}