package org.echocat.gradle.plugins.golang.utils; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Request.Builder; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import static java.nio.file.Files.*; import static org.apache.commons.io.FilenameUtils.getExtension; import static org.apache.commons.io.IOUtils.copy; import static org.echocat.gradle.plugins.golang.utils.FileUtils.createDirectoriesIfRequired; import static org.echocat.gradle.plugins.golang.utils.FileUtils.deleteQuietly; import static org.echocat.gradle.plugins.golang.utils.FileUtils.ensureParentOf; public class ArchiveUtils { private static final Pattern REMOVE_LEADING_GO_PATH_PATTERN = Pattern.compile("^(|\\./)go/"); public static void download(URI uri, Path to) throws IOException { if (exists(to)) { deleteQuietly(to); } createDirectoriesIfRequired(to); final OkHttpClient client = new OkHttpClient(); final Request request = new Builder() .url(uri.toURL()) .build(); final Path tempFile = createTempFile("golang-maven-plugin", "." + getExtension(uri.toString())); try { try (final InputStream is = client.newCall(request).execute().body().byteStream()) { try (final OutputStream os = newOutputStream(tempFile)) { copy(is, os); } } if (uri.toString().endsWith(".tar.gz")) { unTarGz(tempFile, to); } else if (uri.toString().endsWith(".zip")) { unZip(tempFile, to); } else { throw new IllegalStateException("Does not support download archive of type " + uri + "."); } } finally { deleteQuietly(tempFile); } } public static void unTarGz(Path file, Path target) throws IOException { try (final InputStream is = newInputStream(file)) { final InputStream gzip = new GZIPInputStream(is); final TarArchiveInputStream archive = new TarArchiveInputStream(gzip); TarArchiveEntry entry = archive.getNextTarEntry(); while (entry != null) { final Path entryFile = target.resolve(REMOVE_LEADING_GO_PATH_PATTERN.matcher(entry.getName()).replaceFirst("")).toAbsolutePath(); if (entry.isDirectory()) { createDirectoriesIfRequired(entryFile); } else { ensureParentOf(entryFile); try (final OutputStream os = newOutputStream(entryFile)) { copy(archive, os); } final PosixFileAttributeView view = getFileAttributeView(entryFile, PosixFileAttributeView.class); if (view != null) { final int mode = entry.getMode(); final Set<PosixFilePermission> perms = new HashSet<>(); perms.add(PosixFilePermission.OWNER_READ); perms.add(PosixFilePermission.GROUP_READ); perms.add(PosixFilePermission.OTHERS_READ); //noinspection OctalInteger,ResultOfMethodCallIgnored,IncompatibleBitwiseMaskOperation if ((mode | 0001) > 0) { perms.add(PosixFilePermission.OWNER_EXECUTE); } //noinspection OctalInteger,ResultOfMethodCallIgnored,IncompatibleBitwiseMaskOperation if ((mode | 0100) > 0) { perms.add(PosixFilePermission.GROUP_EXECUTE); perms.add(PosixFilePermission.OTHERS_EXECUTE); } view.setPermissions(perms); } } entry = archive.getNextTarEntry(); } } } public static void unZip(Path file, Path target) throws IOException { try (final ZipFile zipFile = new ZipFile(file.toFile())) { final Enumeration<ZipArchiveEntry> files = zipFile.getEntriesInPhysicalOrder(); while (files.hasMoreElements()) { final ZipArchiveEntry entry = files.nextElement(); final Path entryFile = target.resolve(REMOVE_LEADING_GO_PATH_PATTERN.matcher(entry.getName()).replaceFirst("")).toAbsolutePath(); if (entry.isDirectory()) { createDirectoriesIfRequired(entryFile); } else { ensureParentOf(entryFile); try (final InputStream is = zipFile.getInputStream(entry)) { try (final OutputStream os = newOutputStream(entryFile)) { copy(is, os); } } } } } } }