diff --git a/compiler/ballerina-lang/spotbugs-exclude.xml b/compiler/ballerina-lang/spotbugs-exclude.xml index 8796d15f9e2d..c27500b6116e 100644 --- a/compiler/ballerina-lang/spotbugs-exclude.xml +++ b/compiler/ballerina-lang/spotbugs-exclude.xml @@ -354,6 +354,11 @@ + + + + + diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/model/BalToolDescriptor.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/model/BalToolDescriptor.java index 04fb3487ec38..3de5441e5bc8 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/model/BalToolDescriptor.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/model/BalToolDescriptor.java @@ -27,9 +27,18 @@ import io.ballerina.toml.semantic.ast.TomlValueNode; import io.ballerina.toml.semantic.ast.TopLevelNode; +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * {@code BalToolDescriptor} Model for `BalTool.toml` file. @@ -130,7 +139,15 @@ private static List getDependencies(TomlTableNode for (TomlTableNode dependencyNode : dependencyTableArray.children()) { TopLevelNode pathNode = dependencyNode.entries().get(PATH); - dependencies.add(new BalToolDescriptor.Dependency(getStringFromTomlTableNode(pathNode))); + String path = getStringFromTomlTableNode(pathNode); + if (path == null) { + continue; + } + if (new File(path).isFile()) { + dependencies.add(new BalToolDescriptor.Dependency(path)); + } else { + dependencies.addAll(getDependenciesInDir(path)); + } } } return dependencies; @@ -158,4 +175,41 @@ private static String getStringFromTomlTableNode(TopLevelNode topLevelNode) { } return null; } + + private static List getDependenciesInDir(String path) { + // in the path provided, only the last part can be a pattern. the rest should be an existing directory path + + List dependencies = new ArrayList<>(); + Path dependencyPath = Path.of(path); + Optional patternPath = Optional.ofNullable(dependencyPath.getFileName()); + if (patternPath.isEmpty()) { + return dependencies; + } + String pattern = patternPath.get().toString(); + Optional parentPath = Optional.ofNullable(dependencyPath.getParent()); + if (parentPath.isEmpty() || !parentPath.get().toFile().exists()) { + return dependencies; + } + + return getToolJarsMatchingPattern(pattern, parentPath.get()).stream() + .map(path1 -> new BalToolDescriptor.Dependency(path1.toString())) + .collect(Collectors.toList()); + } + + private static List getToolJarsMatchingPattern(String pattern, Path parentPath) { + PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern); + List matchingPaths = new ArrayList<>(); + try (Stream paths = Files.list(parentPath)) { + paths.filter(Files::isRegularFile) + .filter(path -> { + Path fileName = path.getFileName(); + return fileName != null && fileName.toString().endsWith(".jar"); + }) + .filter(path -> pathMatcher.matches(path.getFileName())) + .forEach(matchingPaths::add); + } catch (IOException e) { + // ignore + } + return matchingPaths; + } }