Skip to content

Commit 6014d51

Browse files
aloubyanskymkouba
authored andcommitted
Refactor Qute template scanning
1 parent cb39e07 commit 6014d51

File tree

1 file changed

+43
-129
lines changed

1 file changed

+43
-129
lines changed

extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java

Lines changed: 43 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.function.Predicate;
3939
import java.util.regex.Pattern;
4040
import java.util.stream.Collectors;
41-
import java.util.stream.Stream;
4241

4342
import jakarta.inject.Singleton;
4443

@@ -93,12 +92,15 @@
9392
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
9493
import io.quarkus.deployment.pkg.NativeConfig;
9594
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
96-
import io.quarkus.fs.util.ZipUtils;
9795
import io.quarkus.gizmo.ClassOutput;
9896
import io.quarkus.gizmo.MethodDescriptor;
99-
import io.quarkus.maven.dependency.Dependency;
97+
import io.quarkus.maven.dependency.ArtifactKey;
98+
import io.quarkus.maven.dependency.DependencyFlags;
10099
import io.quarkus.maven.dependency.ResolvedDependency;
101100
import io.quarkus.panache.common.deployment.PanacheEntityClassesBuildItem;
101+
import io.quarkus.paths.FilteredPathTree;
102+
import io.quarkus.paths.PathFilter;
103+
import io.quarkus.paths.PathTree;
102104
import io.quarkus.qute.CheckedTemplate;
103105
import io.quarkus.qute.Engine;
104106
import io.quarkus.qute.EngineBuilder;
@@ -2124,9 +2126,6 @@ void collectTemplates(ApplicationArchivesBuildItem applicationArchives,
21242126
QuteConfig config,
21252127
TemplateRootsBuildItem templateRoots)
21262128
throws IOException {
2127-
Set<ApplicationArchive> allApplicationArchives = applicationArchives.getAllApplicationArchives();
2128-
List<ResolvedDependency> extensionArtifacts = curateOutcome.getApplicationModel().getDependencies().stream()
2129-
.filter(Dependency::isRuntimeExtensionArtifact).collect(Collectors.toList());
21302129

21312130
// Make sure the new templates are watched as well
21322131
watchedPaths.produce(HotDeploymentWatchedFileBuildItem.builder().setLocationPredicate(new Predicate<String>() {
@@ -2141,80 +2140,39 @@ public boolean test(String path) {
21412140
}
21422141
}).build());
21432142

2144-
for (ResolvedDependency artifact : extensionArtifacts) {
2145-
if (isApplicationArchive(artifact, allApplicationArchives)) {
2146-
// Skip extension archives that are also application archives
2147-
continue;
2148-
}
2149-
for (Path resolvedPath : artifact.getResolvedPaths()) {
2150-
if (Files.isDirectory(resolvedPath)) {
2151-
scanRootPath(resolvedPath, config, templateRoots, watchedPaths, templatePaths,
2152-
nativeImageResources);
2153-
} else {
2154-
try (FileSystem artifactFs = ZipUtils.newFileSystem(resolvedPath)) {
2155-
// Iterate over template roots, such as "templates", and collect the included templates
2156-
for (String templateRoot : templateRoots) {
2157-
Path artifactBasePath = artifactFs.getPath(templateRoot);
2158-
if (Files.exists(artifactBasePath)) {
2159-
LOGGER.debugf("Found template root in extension artifact: %s", resolvedPath);
2160-
scanDirectory(artifactBasePath, artifactBasePath, templateRoot + "/", watchedPaths,
2161-
templatePaths,
2162-
nativeImageResources,
2163-
config);
2164-
}
2165-
}
2166-
} catch (IOException e) {
2167-
LOGGER.warnf(e, "Unable to create the file system from the path: %s", resolvedPath);
2168-
}
2169-
}
2143+
final Set<ApplicationArchive> allApplicationArchives = applicationArchives.getAllApplicationArchives();
2144+
final Set<ArtifactKey> appArtifactKeys = new HashSet<>(allApplicationArchives.size());
2145+
for (var archive : allApplicationArchives) {
2146+
appArtifactKeys.add(archive.getKey());
2147+
}
2148+
for (ResolvedDependency artifact : curateOutcome.getApplicationModel()
2149+
.getDependencies(DependencyFlags.RUNTIME_EXTENSION_ARTIFACT)) {
2150+
// Skip extension archives that are also application archives
2151+
if (!appArtifactKeys.contains(artifact.getKey())) {
2152+
scanPathTree(artifact.getContentTree(), templateRoots, watchedPaths, templatePaths, nativeImageResources,
2153+
config);
21702154
}
21712155
}
21722156
for (ApplicationArchive archive : allApplicationArchives) {
2173-
archive.accept(tree -> {
2174-
for (Path root : tree.getRoots()) {
2175-
// Note that we cannot use ApplicationArchive.getChildPath(String) here because we would not be able to detect
2176-
// a wrong directory name on case-insensitive file systems
2177-
scanRootPath(root, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
2178-
}
2179-
});
2157+
archive.accept(
2158+
tree -> scanPathTree(tree, templateRoots, watchedPaths, templatePaths, nativeImageResources, config));
21802159
}
21812160
}
21822161

2183-
private void scanRootPath(Path rootPath, QuteConfig config, TemplateRootsBuildItem templateRoots,
2162+
private void scanPathTree(PathTree pathTree, TemplateRootsBuildItem templateRoots,
21842163
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
21852164
BuildProducer<TemplatePathBuildItem> templatePaths,
2186-
BuildProducer<NativeImageResourceBuildItem> nativeImageResources) {
2187-
scanRootPath(rootPath, rootPath, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
2188-
}
2189-
2190-
private void scanRootPath(Path rootPath, Path path, QuteConfig config, TemplateRootsBuildItem templateRoots,
2191-
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
2192-
BuildProducer<TemplatePathBuildItem> templatePaths,
2193-
BuildProducer<NativeImageResourceBuildItem> nativeImageResources) {
2194-
if (!Files.isDirectory(path)) {
2195-
return;
2196-
}
2197-
try (Stream<Path> paths = Files.list(path)) {
2198-
for (Path file : paths.collect(Collectors.toList())) {
2199-
if (Files.isDirectory(file)) {
2200-
// Iterate over the directories in the root
2201-
// "/io", "/META-INF", "/templates", "/web", etc.
2202-
Path relativePath = rootPath.relativize(file);
2203-
if (templateRoots.isRoot(relativePath)) {
2204-
LOGGER.debugf("Found templates root dir: %s", file);
2205-
// The base path is an OS-specific template root path relative to the scanned root path
2206-
String basePath = relativePath.toString() + relativePath.getFileSystem().getSeparator();
2207-
scanDirectory(file, file, basePath, watchedPaths, templatePaths,
2208-
nativeImageResources,
2209-
config);
2210-
} else if (templateRoots.maybeRoot(relativePath)) {
2211-
// Scan the path recursively because the template root may be nested, for example "/web/public"
2212-
scanRootPath(rootPath, file, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
2213-
}
2165+
BuildProducer<NativeImageResourceBuildItem> nativeImageResources,
2166+
QuteConfig config) {
2167+
for (String templateRoot : templateRoots) {
2168+
pathTree.accept(templateRoot, visit -> {
2169+
if (visit != null) {
2170+
// if template root is found in this tree then walk over its subtree
2171+
scanTemplateRootSubtree(
2172+
new FilteredPathTree(pathTree, PathFilter.forIncludes(List.of(templateRoot + "/**"))),
2173+
visit.getPath(), watchedPaths, templatePaths, nativeImageResources, config);
22142174
}
2215-
}
2216-
} catch (IOException e) {
2217-
throw new UncheckedIOException(e);
2175+
});
22182176
}
22192177
}
22202178

@@ -3427,55 +3385,24 @@ private static void produceTemplateBuildItems(BuildProducer<TemplatePathBuildIte
34273385
readTemplateContent(originalPath, config.defaultCharset)));
34283386
}
34293387

3430-
/**
3431-
*
3432-
* @param root
3433-
* @param directory
3434-
* @param basePath OS-specific template root path relative to the scanned root path, e.g. {@code templates/}
3435-
* @param watchedPaths
3436-
* @param templatePaths
3437-
* @param nativeImageResources
3438-
* @param config
3439-
* @throws IOException
3440-
*/
3441-
private void scanDirectory(Path root, Path directory, String basePath,
3388+
private void scanTemplateRootSubtree(PathTree pathTree, Path templateRoot,
34423389
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
34433390
BuildProducer<TemplatePathBuildItem> templatePaths,
34443391
BuildProducer<NativeImageResourceBuildItem> nativeImageResources,
3445-
QuteConfig config)
3446-
throws IOException {
3447-
try (Stream<Path> files = Files.list(directory)) {
3448-
Iterator<Path> iter = files.iterator();
3449-
while (iter.hasNext()) {
3450-
Path filePath = iter.next();
3451-
/*
3452-
* Fix for https://github.com/quarkusio/quarkus/issues/25751 where running tests in Eclipse
3453-
* sometimes produces `/templates/tags` (absolute) files listed for `templates` (relative)
3454-
* directories, so we work around this
3455-
*/
3456-
if (!directory.isAbsolute()
3457-
&& filePath.isAbsolute()
3458-
&& filePath.getRoot() != null) {
3459-
filePath = filePath.getRoot().relativize(filePath);
3460-
}
3461-
if (Files.isRegularFile(filePath)) {
3462-
LOGGER.debugf("Found template: %s", filePath);
3463-
Path relativePath = root.relativize(filePath);
3464-
String templatePath = toOsAgnosticPath(relativePath);
3465-
if (config.templatePathExclude.matcher(templatePath).matches()) {
3466-
LOGGER.debugf("Template file excluded: %s", filePath);
3467-
continue;
3468-
}
3469-
produceTemplateBuildItems(templatePaths, watchedPaths, nativeImageResources,
3470-
basePath + relativePath.toString(),
3471-
templatePath,
3472-
filePath, config);
3473-
} else if (Files.isDirectory(filePath)) {
3474-
LOGGER.debugf("Scan directory: %s", filePath);
3475-
scanDirectory(root, filePath, basePath, watchedPaths, templatePaths, nativeImageResources, config);
3476-
}
3392+
QuteConfig config) {
3393+
pathTree.walk(visit -> {
3394+
if (Files.isRegularFile(visit.getPath())) {
3395+
LOGGER.debugf("Found template: %s", visit.getPath());
3396+
String templatePath = toOsAgnosticPath(templateRoot.relativize(visit.getPath()));
3397+
if (config.templatePathExclude.matcher(templatePath).matches()) {
3398+
LOGGER.debugf("Template file excluded: %s", visit.getPath());
3399+
return;
3400+
}
3401+
produceTemplateBuildItems(templatePaths, watchedPaths, nativeImageResources,
3402+
visit.getRelativePath(visit.getPath().getFileSystem().getSeparator()),
3403+
templatePath, visit.getPath(), config);
34773404
}
3478-
}
3405+
});
34793406
}
34803407

34813408
private static String toOsAgnosticPath(String path, FileSystem fs) {
@@ -3518,19 +3445,6 @@ private void checkDuplicatePaths(List<TemplatePathBuildItem> templatePaths) {
35183445
}
35193446
}
35203447

3521-
private boolean isApplicationArchive(ResolvedDependency dependency, Set<ApplicationArchive> applicationArchives) {
3522-
for (ApplicationArchive archive : applicationArchives) {
3523-
if (archive.getKey() == null) {
3524-
continue;
3525-
}
3526-
if (dependency.getGroupId().equals(archive.getKey().getGroupId())
3527-
&& dependency.getArtifactId().equals(archive.getKey().getArtifactId())) {
3528-
return true;
3529-
}
3530-
}
3531-
return false;
3532-
}
3533-
35343448
static String readTemplateContent(Path path, Charset defaultCharset) {
35353449
try {
35363450
return Files.readString(path, defaultCharset);

0 commit comments

Comments
 (0)