package org.jfrog.bamboo.util.deployment; import com.atlassian.bamboo.task.TaskDefinition; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.FileFilter; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Finds artifacts we want to upload to Artifactory when using Bamboo deployment task * * @author Aviad Shikloshi */ public class FilesCollector { private static final String PATH_KEY = "localPath"; private String projectRoot; private List<String> subDirectories; // This map holds a set of files with the sub directory path as a key so we could upload it correctly to Artifactory private Map<String, Set<File>> collectedFiles; public FilesCollector(String projectRoot, TaskDefinition taskDefinition) { this.projectRoot = projectRoot; this.subDirectories = Lists.newArrayList(); collectSubDirectories(taskDefinition); } public Map<String, Set<File>> getCollectedFiles() { if (collectedFiles == null) { collectFiles(); } return this.collectedFiles; } /** * Collect all artifacts from the root directory of the deployment project */ private void collectFiles() { this.collectedFiles = Maps.newHashMap(); File dir = new File(projectRoot); File[] preConfiguredDirectories = dir.listFiles(new PreConfiguredDirectoriesFilter(this.subDirectories)); // Collecting artifacts from the directories that were pre configured in the "Artifacts Download" task that occurred before the deployment task for (File subDir : preConfiguredDirectories) { Iterator<File> files = FileUtils.iterateFiles(subDir, null, true); Set<File> currentPathFiles = Sets.newHashSet(); this.collectedFiles.put(subDir.getAbsolutePath().substring(this.projectRoot.length() + 1), currentPathFiles); // For each sub directory we are iterating over all of its files and collecting them while (files.hasNext()) { File current = files.next(); if (current.isFile()) { currentPathFiles.add(current); } } } // Iterating over all files in the root directory of our project which will include artifacts in case of no sub directory was configured File[] otherFiles = dir.listFiles(new RootDirFilesFilter(this.projectRoot, this.subDirectories)); Set<File> rootDirFiles = Sets.newHashSet(); this.collectedFiles.put(StringUtils.EMPTY, rootDirFiles); for (File otherFile : otherFiles) { if (otherFile.isFile()) { rootDirFiles.add(otherFile); } } } /** * Get all sub directories that were specified in the ArtifactDownload task * * @param artifactsDownloadRtd configuration for the ArtifactDownload task */ private void collectSubDirectories(TaskDefinition artifactsDownloadRtd) { if (artifactsDownloadRtd != null) { Map<String, String> downloadTaskConfiguration = artifactsDownloadRtd.getConfiguration(); for (String s : downloadTaskConfiguration.keySet()) { // Each PATH_KEY_{number} in ArtifactoryDownload configuration map holds the directory path as the value, // we want to collect all of the sub directories. if (s.startsWith(PATH_KEY)) { subDirectories.add(downloadTaskConfiguration.get(s)); } } } } /** * Accepts only the folders that was downloaded directly to the projects root directory */ private class RootDirFilesFilter implements FileFilter { private String rootDirectory; private List<String> subDirs; public RootDirFilesFilter(String rootDirectory, List<String> subDirs) { this.rootDirectory = rootDirectory; this.subDirs = subDirs; } @Override public boolean accept(File pathname) { String substring = pathname.getAbsolutePath().substring(rootDirectory.length() + 1); return !subDirs.contains(substring); } } /** * Accepts directories that were specified in the Artifact Download configuration task */ private class PreConfiguredDirectoriesFilter implements FileFilter { private List<String> subDirs; public PreConfiguredDirectoriesFilter(List<String> subDirs) { this.subDirs = subDirs; } @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { for (String subDir : subDirs) { if (StringUtils.endsWith(pathname.getAbsolutePath(), subDir)) { return true; } } } return false; } } }