com.redhat.ceylon.common.tools.SourceDependencyResolver Maven / Gradle / Ivy
/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.redhat.ceylon.common.tools;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import com.redhat.ceylon.cmr.api.ModuleDependencyInfo;
import com.redhat.ceylon.cmr.api.ModuleVersionDetails;
import com.redhat.ceylon.common.Backends;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.ModuleUtil;
import com.redhat.ceylon.model.typechecker.model.ModelUtil;
/**
* This class takes a list of source files and determines which modules
* are referenced as dependencies by them that were not mentioned in the
* original list.
*
* @author Tako Schotanus ([email protected])
*/
public class SourceDependencyResolver {
private final ModuleVersionReader moduleVersionReader;
private final Iterable sourceDirs;
private final Backends forBackends;
private Set originalModules;
private Set allModules;
private Set additionalModules;
public SourceDependencyResolver(ModuleVersionReader moduleVersionReader, Iterable sourceDirs, Backends forBackends) {
this.moduleVersionReader = moduleVersionReader;
this.sourceDirs = sourceDirs;
this.forBackends = forBackends;
}
/**
* Returns the list of modules as found in the list of sources
* passed to traverseDependencies()
* @return A list of ModuleVersionDetails
*/
public Set getOriginalModules() {
return originalModules;
}
/**
* Returns the list of modules as found in the list of sources
* passed to traverseDependencies()
and the ones
* that were found while traversing their dependencies
* @return A list of ModuleVersionDetails
*/
public Set getAllModules() {
return allModules;
}
/**
* Returns the list of dependent modules that were found while
* traversing the list of sources passed to
* traverseDependencies()
that were not mentioned
* in the original list of sources
* @return A list of ModuleVersionDetails
*/
public Set getAdditionalModules() {
return additionalModules;
}
/**
* Traverses the given sources finding all dependencies that have
* their sources available in the source directories
* @param sourceFiles Iterable of pointing to sources
* @return A boolean indicating if any additional modules were found
*/
public boolean traverseDependencies(Iterable sourceFiles) {
originalModules = collectModulesFromSources(sourceFiles);
allModules = new HashSet(originalModules);
for (ModuleVersionDetails module : originalModules) {
collectModulesFromDependencies(allModules, module);
}
additionalModules = new HashSet(allModules);
additionalModules.removeAll(originalModules);
return !additionalModules.isEmpty();
}
// Recursively traverses and collects all dependencies from the
// given module and adds their dependencies to the given set, but
// only those that have locally available sources
private void collectModulesFromDependencies(Set modules, String moduleName) {
ModuleVersionDetails mvd = moduleVersionReader.fromSource(moduleName);
if (mvd != null) {
modules.add(mvd);
collectModulesFromDependencies(modules, mvd);
}
}
// Recursively traverses and collects all dependencies from the
// given module and adds their dependencies to the given set, but
// only those that have locally available sources
private void collectModulesFromDependencies(Set modules, ModuleVersionDetails mvd) {
for (ModuleDependencyInfo dep : mvd.getDependencies()) {
if (dep.getNamespace() == null
&& !modules.contains(dep)
&& hasSources(dep.getName())
&& ModelUtil.isForBackend(dep.getNativeBackends(), forBackends)) {
collectModulesFromDependencies(modules, dep.getName());
}
}
}
// Determines if the given module has locally available sources
private boolean hasSources(String moduleName) {
for (File srcDir : sourceDirs) {
File moduleDir = ModuleUtil.moduleToPath(srcDir, moduleName);
if (moduleDir.isDirectory() && moduleDir.canRead()) {
File descriptor = new File(moduleDir, Constants.MODULE_DESCRIPTOR);
if (descriptor.isFile() && descriptor.canRead()) {
return true;
}
}
}
return false;
}
// Given the list of _all_ source files we return the list of module details
private Set collectModulesFromSources(Iterable sourceFiles) {
Set modules = new HashSet();
Set descriptors = collectModuleDescriptorsFromSources(sourceFiles);
for (File d : descriptors) {
String moduleName = moduleNameFromDescriptorFile(d);
ModuleVersionDetails mvd = moduleVersionReader.fromSource(moduleName);
if (mvd != null) {
modules.add(mvd);
}
}
return modules;
}
// Given a descriptor File we return its module name
private String moduleNameFromDescriptorFile(File descriptor) {
String rel = FileUtil.relativeFile(sourceDirs, descriptor.getParentFile().getPath());
return ModuleUtil.pathToModule(new File(rel));
}
// Given a list of source files returns only the module descriptors
private Set collectModuleDescriptorsFromSources(Iterable sourceFiles) {
Set files = new HashSet();
for (File f : sourceFiles) {
if (Constants.MODULE_DESCRIPTOR.equals(f.getName())) {
files.add(f);
}
}
return files;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy