package org.jfrog.bamboo.util.generic; import com.atlassian.core.util.FileUtils; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.Dependency; import org.jfrog.build.api.dependency.DownloadableArtifact; import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; import org.jfrog.build.extractor.clientConfiguration.util.DependenciesDownloader; import org.jfrog.build.extractor.clientConfiguration.util.DependenciesDownloaderHelper; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Map; import java.util.Set; /** * @author Lior Hasson */ public class DependenciesDownloaderImpl implements DependenciesDownloader { private ArtifactoryDependenciesClient client; private Log log; private File workingDirectory; private boolean flatDownload = false; public DependenciesDownloaderImpl(ArtifactoryDependenciesClient client, File workingDirectory, Log log) { this.client = client; this.workingDirectory = workingDirectory; this.log = log; } @Override public ArtifactoryDependenciesClient getClient() { return client; } @Override public List<Dependency> download(Set<DownloadableArtifact> downloadableArtifacts) throws IOException { DependenciesDownloaderHelper helper = new DependenciesDownloaderHelper(this, log); return helper.downloadDependencies(downloadableArtifacts); } @Override public String getTargetDir(String targetDir, String relativeDir) throws IOException { return FilenameUtils.concat(workingDirectory.getPath(), FilenameUtils.concat(targetDir, relativeDir)); } @Override public Map<String, String> saveDownloadedFile(InputStream is, String filePath) throws IOException { try { File newFile = new File(filePath); FileUtils.copyFile(is, newFile, true); return FileChecksumCalculator.calculateChecksums(newFile, "md5", "sha1"); } catch (Exception e) { log.warn("Caught exception while saving dependency file" + e.getLocalizedMessage()); } finally { IOUtils.closeQuietly(is); } return null; } @Override public boolean isFileExistsLocally(String filePath, String md5, String sha1) throws IOException { File localFile = new File(filePath); if (!localFile.exists()) { return false; } // If it's a folder return true since we don't care about it, not going to download a folder anyway if (localFile.isDirectory()) { return true; } try { Map<String, String> checksumsMap = FileChecksumCalculator.calculateChecksums(localFile, "md5", "sha1"); return checksumsMap != null && StringUtils.isNotBlank(md5) && StringUtils.equals(md5, checksumsMap.get("md5")) && StringUtils.isNotBlank(sha1) && StringUtils.equals(sha1, checksumsMap.get("sha1")); } catch (NoSuchAlgorithmException e) { log.warn("Could not find checksum algorithm: " + e.getLocalizedMessage()); } return false; } @Override public void removeUnusedArtifactsFromLocal(Set<String> allResolvesFiles, Set<String> forDeletionFiles) throws IOException { try { for (String resolvedFile : forDeletionFiles) { File resolvedFileParent = org.apache.commons.io.FileUtils.getFile(resolvedFile).getParentFile(); File[] fileSiblings = resolvedFileParent.listFiles(); if (!(fileSiblings == null || fileSiblings.length == 0)) { for (File sibling : fileSiblings) { if (!isResolvedOrParentOfResolvedFile(allResolvesFiles, sibling.getPath())) { log.info("Deleted unresolved file '" + sibling.getPath() + "'"); sibling.delete(); } } } } } catch (Exception e) { log.warn("Caught interrupted exception: " + e.getLocalizedMessage()); } } private boolean isResolvedOrParentOfResolvedFile(Set<String> resolvedFiles, final String path) { return Iterables.any(resolvedFiles, new Predicate<String>() { public boolean apply(String filePath) { return StringUtils.equals(filePath, path) || StringUtils.startsWith(filePath, path); } }); } //TODO - as part of buildInfo V-2.6.x we need to do some changes to support the json spec public boolean getFlatDownload(){ return this.flatDownload; } //TODO - as part of buildInfo V-2.6.x we need to do some changes to support the json spec public void setFlatDownload(boolean flat){ this.flatDownload = flat; } }