Skip to content

Commit

Permalink
Make sure pathFilter is applied to workspace module content tree
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Mar 30, 2024
1 parent eb56608 commit d746e82
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.quarkus.bootstrap.workspace.ArtifactSources;
import io.quarkus.bootstrap.workspace.WorkspaceModule;
import io.quarkus.paths.EmptyPathTree;
import io.quarkus.paths.FilteredPathTree;
import io.quarkus.paths.MultiRootPathTree;
import io.quarkus.paths.PathCollection;
import io.quarkus.paths.PathFilter;
Expand Down Expand Up @@ -36,7 +37,7 @@ default PathTree getContentTree(PathFilter pathFilter) {
final WorkspaceModule module = getWorkspaceModule();
final PathTree workspaceTree = module == null ? EmptyPathTree.getInstance() : module.getContentTree(getClassifier());
if (!workspaceTree.isEmpty()) {
return workspaceTree;
return pathFilter == null ? workspaceTree : new FilteredPathTree(workspaceTree, pathFilter);
}
final PathCollection paths = getResolvedPaths();
if (paths == null || paths.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.quarkus.paths;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.jar.Manifest;

public class FilteredPathTree implements PathTree {

private final PathTree original;
protected final PathFilter filter;

public FilteredPathTree(PathTree tree, PathFilter filter) {
this.original = Objects.requireNonNull(tree, "tree is null");
this.filter = Objects.requireNonNull(filter, "filter is null");
}

@Override
public Collection<Path> getRoots() {
return original.getRoots();
}

@Override
public Manifest getManifest() {
return original.getManifest();
}

@Override
public void walk(PathVisitor visitor) {
original.walk(visit -> {
if (visit != null && filter.isVisible(visit.getRelativePath("/"))) {
visitor.visitPath(visit);
}
});
}

@Override
public <T> T apply(String relativePath, Function<PathVisit, T> func) {
if (!PathFilter.isVisible(filter, relativePath)) {
return func.apply(null);
}
return original.apply(relativePath, func);
}

@Override
public void accept(String relativePath, Consumer<PathVisit> consumer) {
if (!PathFilter.isVisible(filter, relativePath)) {
consumer.accept(null);
} else {
original.accept(relativePath, consumer);
}
}

@Override
public boolean contains(String relativePath) {
return PathFilter.isVisible(filter, relativePath) && original.contains(relativePath);
}

@Override
public OpenPathTree open() {
return new OpenFilteredPathTree(original.open(), filter);
}

private static class OpenFilteredPathTree extends FilteredPathTree implements OpenPathTree {

private final OpenPathTree original;

private OpenFilteredPathTree(OpenPathTree original, PathFilter filter) {
super(original, filter);
this.original = original;
}

@Override
public PathTree getOriginalTree() {
return original.getOriginalTree();
}

@Override
public boolean isOpen() {
return original.isOpen();
}

@Override
public Path getPath(String relativePath) {
if (!PathFilter.isVisible(filter, relativePath)) {
return null;
}
return original.getPath(relativePath);
}

@Override
public void close() throws IOException {
original.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package io.quarkus.paths;

import static org.assertj.core.api.Assertions.assertThat;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import io.quarkus.fs.util.ZipUtils;

public class FilteredPathTreeTest {

@TempDir
static Path testDir;
static Path testJar;

private static void createFile(String path) throws Exception {
var file = testDir.resolve(path);
Files.createDirectories(file.getParent());
Files.createFile(file);
}

@BeforeAll
public static void beforeAll() throws Exception {
createFile("META-INF/jandex.idx");
createFile("org/toolbox/Axe.class");
createFile("org/toolbox/Hammer.class");
createFile("org/toolbox/Saw.class");
createFile("README.md");
testJar = testDir.resolve("test.jar");
ZipUtils.zip(testDir, testJar);
}

@Test
public void unfilteredTestDir() {
var pathTree = PathTree.ofDirectoryOrArchive(testDir);
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"",
"META-INF",
"META-INF/jandex.idx",
"org",
"org/toolbox",
"org/toolbox/Axe.class",
"org/toolbox/Hammer.class",
"org/toolbox/Saw.class",
"README.md",
"test.jar");
}

@Test
public void unfilteredTestJar() {
var pathTree = PathTree.ofDirectoryOrArchive(testJar);
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"",
"META-INF",
"META-INF/jandex.idx",
"org",
"org/toolbox",
"org/toolbox/Axe.class",
"org/toolbox/Hammer.class",
"org/toolbox/Saw.class",
"README.md",
"test.jar");
}

@Test
public void dirIncludeToolbox() {
var pathTree = PathTree.ofDirectoryOrArchive(testDir, PathFilter.forIncludes(List.of("*/toolbox/**")));
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"org/toolbox/Axe.class",
"org/toolbox/Hammer.class",
"org/toolbox/Saw.class");
}

@Test
public void jarIncludeToolbox() {
var pathTree = PathTree.ofDirectoryOrArchive(testJar, PathFilter.forIncludes(List.of("*/toolbox/**")));
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"org/toolbox/Axe.class",
"org/toolbox/Hammer.class",
"org/toolbox/Saw.class");
}

@Test
public void dirIncludeToolboxExcludeHammer() {
var pathTree = PathTree.ofDirectoryOrArchive(testDir, new PathFilter(
List.of("*/toolbox/**"),
List.of("**/Hammer.class")));
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"org/toolbox/Axe.class",
"org/toolbox/Saw.class");
}

@Test
public void jarIncludeToolboxExcludeHammer() {
var pathTree = PathTree.ofDirectoryOrArchive(testJar, new PathFilter(
List.of("*/toolbox/**"),
List.of("**/Hammer.class")));
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"org/toolbox/Axe.class",
"org/toolbox/Saw.class");
}

@Test
public void filteredPathTree() throws Exception {
var originalFilter = new PathFilter(
List.of("*/toolbox/**"),
List.of("**/Hammer.class"));
var outerFilter = new PathFilter(
List.of("**/Axe.class"),
List.of("**/Saw.class"));

var pathTree = PathTree.ofDirectoryOrArchive(testDir, originalFilter);
pathTree = new FilteredPathTree(pathTree, outerFilter);
assertFilteredPathTree(pathTree);
try (var openTree = pathTree.open()) {
assertFilteredPathTree(openTree);
}

pathTree = PathTree.ofDirectoryOrArchive(testJar, originalFilter);
pathTree = new FilteredPathTree(pathTree, outerFilter);
assertFilteredPathTree(pathTree);
try (var openTree = pathTree.open()) {
assertFilteredPathTree(openTree);
}
}

private static void assertFilteredPathTree(PathTree pathTree) {
assertThat(getAllPaths(pathTree)).containsExactlyInAnyOrder(
"org/toolbox/Axe.class");

assertThat(pathTree.isEmpty()).isFalse();
assertThat(pathTree.contains("org/toolbox/Axe.class")).isTrue();
assertThat(pathTree.apply("org/toolbox/Axe.class", Objects::nonNull)).isTrue();
assertThat(pathTree.apply("org/toolbox/Saw.class", Objects::nonNull)).isFalse();
pathTree.accept("org/toolbox/Axe.class", visit -> assertThat(visit).isNotNull());
pathTree.accept("org/toolbox/Saw.class", visit -> assertThat(visit).isNull());
}

private static Set<String> getAllPaths(PathTree pathTree) {
final Set<String> paths = new HashSet<>();
pathTree.walk(visit -> paths.add(visit.getRelativePath("/")));
return paths;
}
}

0 comments on commit d746e82

Please sign in to comment.