package com.prezi.spaghetti.gradle.internal; import com.google.common.base.Joiner; import com.google.common.base.Throwables; import com.google.common.collect.Sets; import com.prezi.spaghetti.bundle.ModuleBundleSet; import com.prezi.spaghetti.bundle.internal.ModuleBundleLoader; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.lang.reflect.Array; import java.util.Collection; import java.util.Set; import java.util.concurrent.Callable; public class ModuleBundleLookup { private static final Logger logger = LoggerFactory.getLogger(ModuleBundleLookup.class); public static ModuleBundleSet lookup(Project project, Object dependencies) throws IOException { Set<File> directFiles = Sets.newLinkedHashSet(); Set<File> transitiveFiles = Sets.newLinkedHashSet(); addFiles(project, dependencies, directFiles, transitiveFiles); if (logger.isDebugEnabled()) { logger.debug("Loading modules from:"); logger.debug("\tDirect dependencies:\n\t\t{}", Joiner.on("\n\t\t").join(directFiles)); logger.debug("\tTransitive dependencies:\n\t\t{}", Joiner.on("\n\t\t").join(transitiveFiles)); } return ModuleBundleLoader.loadBundles(directFiles, transitiveFiles); } private static void addFiles(Project project, Object from, Set<File> directFiles, Set<File> transitiveFiles) throws IOException { if (from == null) { return; } if (from instanceof Configuration) { Configuration config = (Configuration) from; Set<ResolvedDependency> firstLevelDependencies = config.getResolvedConfiguration().getFirstLevelModuleDependencies(); addAllFilesFrom(firstLevelDependencies, directFiles); addAllFilesFromChildren(firstLevelDependencies, transitiveFiles); } else if (from instanceof ConfigurableFileCollection) { for (Object child : ((ConfigurableFileCollection) from).getFrom()) { addFiles(project, child, directFiles, transitiveFiles); } } else if (from instanceof FileCollection) { directFiles.addAll(((FileCollection) from).getFiles()); } else if (from instanceof Collection) { for (Object child : ((Collection<?>) from)) { addFiles(project, child, directFiles, transitiveFiles); } } else if (from.getClass().isArray()) { for (int i = 0; i < Array.getLength(from); i++) { addFiles(project, Array.get(from, i), directFiles, transitiveFiles); } } else if (from instanceof Callable) { try { addFiles(project, ((Callable) from).call(), directFiles, transitiveFiles); } catch (Exception e) { throw Throwables.propagate(e); } } else if (from instanceof File) { directFiles.add((File) from); } else { for (File file : project.files(from)) { directFiles.add(file); } } } private static void addAllFilesFromChildren(Set<ResolvedDependency> dependencies, Set<File> files) throws IOException { for (ResolvedDependency dependency : dependencies) { addAllFilesFrom(dependency.getChildren(), files); addAllFilesFromChildren(dependency.getChildren(), files); } } private static void addAllFilesFrom(Set<ResolvedDependency> dependencies, Set<File> files) throws IOException { for (ResolvedDependency dependency : dependencies) { for (ResolvedArtifact artifact : dependency.getModuleArtifacts()) { files.add(artifact.getFile()); } } } }