Skip to content

Commit

Permalink
Qute: fix NativeImageResourceBuildItem registration on Windows
Browse files Browse the repository at this point in the history
- previously, a NativeImageResourceBuildItem with a wrong path was
produced for a template located in a nested directory
  • Loading branch information
mkouba committed Apr 15, 2024
1 parent 9929c7d commit 986ad73
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.toMap;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
Expand Down Expand Up @@ -2149,15 +2148,17 @@ public boolean test(String path) {
}
for (Path resolvedPath : artifact.getResolvedPaths()) {
if (Files.isDirectory(resolvedPath)) {
scanPath(resolvedPath, resolvedPath, config, templateRoots, watchedPaths, templatePaths,
scanRootPath(resolvedPath, config, templateRoots, watchedPaths, templatePaths,
nativeImageResources);
} else {
try (FileSystem artifactFs = ZipUtils.newFileSystem(resolvedPath)) {
// Iterate over template roots, such as "templates", and collect the included templates
for (String templateRoot : templateRoots) {
Path artifactBasePath = artifactFs.getPath(templateRoot);
if (Files.exists(artifactBasePath)) {
LOGGER.debugf("Found extension templates in: %s", resolvedPath);
scan(artifactBasePath, artifactBasePath, templateRoot + "/", watchedPaths, templatePaths,
LOGGER.debugf("Found template root in extension artifact: %s", resolvedPath);
scanDirectory(artifactBasePath, artifactBasePath, templateRoot + "/", watchedPaths,
templatePaths,
nativeImageResources,
config);
}
Expand All @@ -2173,13 +2174,20 @@ public boolean test(String path) {
for (Path root : tree.getRoots()) {
// Note that we cannot use ApplicationArchive.getChildPath(String) here because we would not be able to detect
// a wrong directory name on case-insensitive file systems
scanPath(root, root, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
scanRootPath(root, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
}
});
}
}

private void scanPath(Path rootPath, Path path, QuteConfig config, TemplateRootsBuildItem templateRoots,
private void scanRootPath(Path rootPath, QuteConfig config, TemplateRootsBuildItem templateRoots,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
BuildProducer<TemplatePathBuildItem> templatePaths,
BuildProducer<NativeImageResourceBuildItem> nativeImageResources) {
scanRootPath(rootPath, rootPath, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
}

private void scanRootPath(Path rootPath, Path path, QuteConfig config, TemplateRootsBuildItem templateRoots,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
BuildProducer<TemplatePathBuildItem> templatePaths,
BuildProducer<NativeImageResourceBuildItem> nativeImageResources) {
Expand All @@ -2193,15 +2201,15 @@ private void scanPath(Path rootPath, Path path, QuteConfig config, TemplateRoots
// "/io", "/META-INF", "/templates", "/web", etc.
Path relativePath = rootPath.relativize(file);
if (templateRoots.isRoot(relativePath)) {
LOGGER.debugf("Found templates dir: %s", file);
// The base path is an OS-specific path relative to the template root
String basePath = relativePath.toString() + File.separatorChar;
scan(file, file, basePath, watchedPaths, templatePaths,
LOGGER.debugf("Found templates root dir: %s", file);
// The base path is an OS-specific template root path relative to the scanned root path
String basePath = relativePath.toString() + relativePath.getFileSystem().getSeparator();
scanDirectory(file, file, basePath, watchedPaths, templatePaths,
nativeImageResources,
config);
} else if (templateRoots.maybeRoot(relativePath)) {
// Scan the path recursively because the template root may be nested, for example "/web/public"
scanPath(rootPath, file, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
scanRootPath(rootPath, file, config, templateRoots, watchedPaths, templatePaths, nativeImageResources);
}
}
}
Expand Down Expand Up @@ -3384,33 +3392,54 @@ public static String getName(InjectionPointInfo injectionPoint) {
throw new IllegalArgumentException();
}

/**
*
* @param templatePaths
* @param watchedPaths
* @param nativeImageResources
* @param osSpecificResourcePath The OS-specific resource path, i.e. templates\nested\foo.html
* @param templatePath The path relative to the template root; using the {@code /} path separator
* @param originalPath
* @param config
*/
private static void produceTemplateBuildItems(BuildProducer<TemplatePathBuildItem> templatePaths,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
BuildProducer<NativeImageResourceBuildItem> nativeImageResources, String basePath, String filePath,
BuildProducer<NativeImageResourceBuildItem> nativeImageResources, String osSpecificResourcePath,
String templatePath,
Path originalPath, QuteConfig config) {
if (filePath.isEmpty()) {
if (templatePath.isEmpty()) {
return;
}
// OS-specific full path, i.e. templates\foo.html
String osSpecificPath = basePath + filePath;
// OS-agnostic full path, i.e. templates/foo.html
String osAgnosticPath = osSpecificPath;
if (File.separatorChar != '/') {
osAgnosticPath = osAgnosticPath.replace(File.separatorChar, '/');
}
LOGGER.debugf("Produce template build items [filePath: %s, fullPath: %s, originalPath: %s", filePath, osSpecificPath,
String osAgnosticResourcePath = toOsAgnosticPath(osSpecificResourcePath, originalPath.getFileSystem());
LOGGER.debugf("Produce template build items [templatePath: %s, osSpecificResourcePath: %s, originalPath: %s",
templatePath,
osSpecificResourcePath,
originalPath);
boolean restartNeeded = true;
if (config.devMode.noRestartTemplates.isPresent()) {
restartNeeded = !config.devMode.noRestartTemplates.get().matcher(osAgnosticPath).matches();
restartNeeded = !config.devMode.noRestartTemplates.get().matcher(osAgnosticResourcePath).matches();
}
watchedPaths.produce(new HotDeploymentWatchedFileBuildItem(osAgnosticPath, restartNeeded));
nativeImageResources.produce(new NativeImageResourceBuildItem(osSpecificPath));
watchedPaths.produce(new HotDeploymentWatchedFileBuildItem(osAgnosticResourcePath, restartNeeded));
nativeImageResources.produce(new NativeImageResourceBuildItem(osSpecificResourcePath));
templatePaths.produce(
new TemplatePathBuildItem(filePath, originalPath, readTemplateContent(originalPath, config.defaultCharset)));
new TemplatePathBuildItem(templatePath, originalPath,
readTemplateContent(originalPath, config.defaultCharset)));
}

private void scan(Path root, Path directory, String basePath, BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
/**
*
* @param root
* @param directory
* @param basePath OS-specific template root path relative to the scanned root path, e.g. {@code templates/}
* @param watchedPaths
* @param templatePaths
* @param nativeImageResources
* @param config
* @throws IOException
*/
private void scanDirectory(Path root, Path directory, String basePath,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedPaths,
BuildProducer<TemplatePathBuildItem> templatePaths,
BuildProducer<NativeImageResourceBuildItem> nativeImageResources,
QuteConfig config)
Expand All @@ -3431,24 +3460,36 @@ private void scan(Path root, Path directory, String basePath, BuildProducer<HotD
}
if (Files.isRegularFile(filePath)) {
LOGGER.debugf("Found template: %s", filePath);
String templatePath = root.relativize(filePath).toString();
if (File.separatorChar != '/') {
templatePath = templatePath.replace(File.separatorChar, '/');
}
Path relativePath = root.relativize(filePath);
String templatePath = toOsAgnosticPath(relativePath);
if (config.templatePathExclude.matcher(templatePath).matches()) {
LOGGER.debugf("Template file excluded: %s", filePath);
continue;
}
produceTemplateBuildItems(templatePaths, watchedPaths, nativeImageResources, basePath, templatePath,
produceTemplateBuildItems(templatePaths, watchedPaths, nativeImageResources,
basePath + relativePath.toString(),
templatePath,
filePath, config);
} else if (Files.isDirectory(filePath)) {
LOGGER.debugf("Scan directory: %s", filePath);
scan(root, filePath, basePath, watchedPaths, templatePaths, nativeImageResources, config);
scanDirectory(root, filePath, basePath, watchedPaths, templatePaths, nativeImageResources, config);
}
}
}
}

private static String toOsAgnosticPath(String path, FileSystem fs) {
String separator = fs.getSeparator();
if (!separator.equals("/")) {
path = path.replace(separator, "/");
}
return path;
}

private static String toOsAgnosticPath(Path path) {
return toOsAgnosticPath(path.toString(), path.getFileSystem());
}

private static boolean isExcluded(TypeCheck check, Iterable<Predicate<TypeCheck>> excludes) {
for (Predicate<TypeCheck> exclude : excludes) {
if (exclude.test(check)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class AdditionalTemplateRootTest {
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot(root -> root
.addAsResource(new StringAsset("Hi {name}!"), "templates/hi.txt")
.addAsResource(new StringAsset("Hoho {name}!"), "templates/nested/hoho.txt")
.addAsResource(new StringAsset("Hello {name}!"), "web/public/hello.txt"))
.addBuildChainCustomizer(buildCustomizer());

Expand All @@ -52,11 +53,13 @@ public void execute(BuildContext context) {
if (item.getResources().contains("web/public/hello.txt")
|| item.getResources().contains("web\\public\\hello.txt")
|| item.getResources().contains("templates/hi.txt")
|| item.getResources().contains("templates\\hi.txt")) {
|| item.getResources().contains("templates\\hi.txt")
|| item.getResources().contains("templates/nested/hoho.txt")
|| item.getResources().contains("templates\\nested\\hoho.txt")) {
found++;
}
}
if (found != 2) {
if (found != 3) {
throw new IllegalStateException(items.stream().flatMap(i -> i.getResources().stream())
.collect(Collectors.toList()).toString());
}
Expand All @@ -79,6 +82,7 @@ public void execute(BuildContext context) {
public void testTemplate() {
assertEquals("Hi M!", engine.getTemplate("hi").data("name", "M").render());
assertEquals("Hello M!", hello.data("name", "M").render());
assertEquals("Hoho M!", engine.getTemplate("nested/hoho").data("name", "M").render());
}

}

0 comments on commit 986ad73

Please sign in to comment.