NpmBundleDownloader.java
package org.entando.kubernetes.model.bundle.downloader;
import static java.nio.file.Files.newInputStream;
import static java.nio.file.StandardOpenOption.READ;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.io.IOUtils;
import org.entando.kubernetes.exception.job.JobPackageException;
import org.entando.kubernetes.model.debundle.EntandoDeBundleTag;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class NpmBundleDownloader extends BundleDownloader {
@Override
protected Path saveBundleStrategy(EntandoDeBundleTag tag, Path targetPath) {
try {
InputStream is = downloadComponentPackage(tag);
Path tarPath = savePackageStreamLocally(is);
unpackTar(tarPath, targetPath);
return targetPath;
} catch (IOException e) {
throw new BundleDownloaderException(e);
}
}
private TarArchiveInputStream getGzipTarInputStream(Path p) {
try {
return new TarArchiveInputStream(new GzipCompressorInputStream(newInputStream(p, READ)));
} catch (IOException e) {
throw new UncheckedIOException("An error occurred while reading file " + p.getFileName().toString(), e);
}
}
private Path unpackTar(Path tarPath, Path destination) throws IOException {
TarArchiveInputStream tarInputStream = getGzipTarInputStream(tarPath);
TarArchiveEntry tae;
Map<String, File> tes = new HashMap<>();
while ((tae = tarInputStream.getNextTarEntry()) != null) {
if (!tarInputStream.canReadEntryData(tae)) {
// log something?
continue;
}
String rebasedName = tae.getName().replaceFirst("package/", "");
Path filePath = destination.resolve(rebasedName);
File tmpf = filePath.toFile();
tmpf.deleteOnExit();
if (tae.isDirectory()) {
if (!tmpf.isDirectory() && !tmpf.mkdirs()) {
throw new IOException("failed to create directory " + tmpf);
}
} else {
File parent = tmpf.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("failed to create directory " + parent);
}
try (OutputStream o = Files.newOutputStream(tmpf.toPath())) {
IOUtils.copy(tarInputStream, o);
}
}
tes.put(tae.getName(), tmpf);
}
return destination;
}
private InputStream downloadComponentPackage(EntandoDeBundleTag tag) {
String tarballUrl = tag.getTarball();
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("user-agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
headers.add("Accept", "*/*");
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
ResponseEntity<Resource> responseEntity = restTemplate.exchange(
tarballUrl, HttpMethod.GET, entity, Resource.class);
if (responseEntity.getBody() == null) {
throw new BundleDownloaderException("Requested package returned an empty body");
}
try {
return responseEntity.getBody().getInputStream();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private Path savePackageStreamLocally(InputStream is) {
Path tempPath = null;
try {
tempPath = Files.createTempFile(null, null);
Files.copy(is, tempPath, StandardCopyOption.REPLACE_EXISTING);
return tempPath;
} catch (IOException e) {
throw new JobPackageException(tempPath,
"An error occurred while copying the package stream locally", e);
}
}
}