From e25af73f5c7aa8e2afb7af262f071f8e57cd2c99 Mon Sep 17 00:00:00 2001 From: essobedo Date: Wed, 12 May 2021 18:42:39 +0200 Subject: [PATCH 1/2] Add support of several resource and test resource folders in dev mode --- .../deployment/dev/DevModeContext.java | 28 +-- .../deployment/dev/IDEDevModeMain.java | 16 +- .../dev/RuntimeUpdatesProcessor.java | 202 ++++++++++-------- .../gradle/builder/QuarkusModelBuilder.java | 5 +- .../io/quarkus/gradle/tasks/QuarkusDev.java | 16 +- .../main/java/io/quarkus/maven/DevMojo.java | 47 ++-- .../bootstrap/model/gradle/SourceSet.java | 2 +- .../model/gradle/impl/SourceSetImpl.java | 16 +- .../io/quarkus/bootstrap/IDELauncherImpl.java | 3 +- .../bootstrap/util/QuarkusModelHelper.java | 7 +- .../maven/workspace/LocalProject.java | 30 ++- .../maven/workspace/LocalWorkspace.java | 2 +- .../builder/QuarkusModelBuilderTest.java | 4 +- .../java/io/quarkus/maven/it/DevMojoIT.java | 45 ++++ .../pom.xml | 88 ++++++++ .../src/main/java/org/acme/HelloResource.java | 31 +++ .../src/main/java/org/acme/MyApplication.java | 9 + .../META-INF/resources/index.html | 156 ++++++++++++++ .../resources-primary/application.properties | 2 + .../dev-mode-multiple-resource-dirs/pom.xml | 76 +++++++ .../src/main/java/org/acme/HelloResource.java | 31 +++ .../src/main/java/org/acme/MyApplication.java | 9 + .../META-INF/resources/index.html | 156 ++++++++++++++ .../resources-primary/application.properties | 2 + .../src/main/resources-secondary/.keep | 1 + .../io/quarkus/test/QuarkusDevModeTest.java | 4 +- 26 files changed, 830 insertions(+), 158 deletions(-) create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/pom.xml create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/MyApplication.java create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/META-INF/resources/index.html create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/application.properties create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/pom.xml create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/MyApplication.java create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/META-INF/resources/index.html create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/application.properties create mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java index 4d7815910fac7..0ebb11ce4f6ba 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java @@ -242,11 +242,12 @@ public static class ModuleInfo implements Serializable { this.appArtifactKey = builder.appArtifactKey; this.name = builder.name; this.projectDirectory = builder.projectDirectory; - this.main = new CompilationUnit(new LinkedHashSet<>(builder.sourcePaths), builder.classesPath, builder.resourcePath, + this.main = new CompilationUnit(new LinkedHashSet<>(builder.sourcePaths), builder.classesPath, + builder.resourcePaths, builder.resourcesOutputPath); if (builder.testClassesPath != null) { this.test = new CompilationUnit(new LinkedHashSet<>(builder.testSourcePaths), - builder.testClassesPath, builder.testResourcePath, builder.testResourcesOutputPath); + builder.testClassesPath, builder.testResourcePaths, builder.testResourcesOutputPath); } else { this.test = null; } @@ -301,7 +302,7 @@ public static class Builder { private String projectDirectory; private Set sourcePaths = Collections.emptySet(); private String classesPath; - private String resourcePath; + private Set resourcePaths = Collections.emptySet(); private String resourcesOutputPath; private String preBuildOutputDir; @@ -310,7 +311,7 @@ public static class Builder { private Set testSourcePaths = Collections.emptySet(); private String testClassesPath; - private String testResourcePath; + private Set testResourcePaths = Collections.emptySet(); private String testResourcesOutputPath; public Builder setAppArtifactKey(AppArtifactKey appArtifactKey) { @@ -338,8 +339,8 @@ public Builder setClassesPath(String classesPath) { return this; } - public Builder setResourcePath(String resourcePath) { - this.resourcePath = resourcePath; + public Builder setResourcePaths(Set resourcePaths) { + this.resourcePaths = resourcePaths; return this; } @@ -373,8 +374,8 @@ public Builder setTestClassesPath(String testClassesPath) { return this; } - public Builder setTestResourcePath(String testResourcePath) { - this.testResourcePath = testResourcePath; + public Builder setTestResourcePaths(Set testResourcePaths) { + this.testResourcePaths = testResourcePaths; return this; } @@ -392,13 +393,14 @@ public ModuleInfo build() { public static class CompilationUnit implements Serializable { private final Set sourcePaths; private final String classesPath; - private final String resourcePath; + private final Set resourcePaths; private final String resourcesOutputPath; - public CompilationUnit(Set sourcePaths, String classesPath, String resourcePath, String resourcesOutputPath) { + public CompilationUnit(Set sourcePaths, String classesPath, Set resourcePaths, + String resourcesOutputPath) { this.sourcePaths = sourcePaths; this.classesPath = classesPath; - this.resourcePath = resourcePath; + this.resourcePaths = resourcePaths; this.resourcesOutputPath = resourcesOutputPath; } @@ -410,8 +412,8 @@ public String getClassesPath() { return classesPath; } - public String getResourcePath() { - return resourcePath; + public Set getResourcePaths() { + return resourcePaths; } public String getResourcesOutputPath() { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java index c4ba1c0778c19..cb454445c36df 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; +import java.util.stream.Collectors; import org.jboss.logging.Logger; @@ -102,8 +103,9 @@ private DevModeContext.ModuleInfo toModule(WorkspaceModule module) throws Bootst sourceParents.add(srcDir.getParent()); } String resourceDirectory = null; - if (module.getSourceSet().getResourceDirectory() != null) { - resourceDirectory = module.getSourceSet().getResourceDirectory().getPath(); + if (!module.getSourceSet().getResourceDirectories().isEmpty()) { + // Peek the first one as we assume that it is the primary + resourceDirectory = module.getSourceSet().getResourceDirectories().iterator().next().getPath(); } return new DevModeContext.ModuleInfo.Builder() .setAppArtifactKey(key) @@ -111,7 +113,8 @@ private DevModeContext.ModuleInfo toModule(WorkspaceModule module) throws Bootst .setProjectDirectory(module.getProjectRoot().getPath()) .setSourcePaths(sourceDirectories) .setClassesPath(QuarkusModelHelper.getClassPath(module).toAbsolutePath().toString()) - .setResourcePath(module.getSourceSourceSet().getResourceDirectory().toString()) + .setResourcePaths(module.getSourceSourceSet().getResourceDirectories().stream().map(Object::toString) + .collect(Collectors.toSet())) .setResourcesOutputPath(resourceDirectory) .setSourceParents(sourceParents) .setPreBuildOutputDir(module.getBuildDir().toPath().resolve("generated-sources").toAbsolutePath().toString()) @@ -127,9 +130,12 @@ private DevModeContext.ModuleInfo toModule(LocalProject project) { .setSourcePaths(Collections.singleton(project.getSourcesSourcesDir().toAbsolutePath().toString())) .setClassesPath(project.getClassesDir().toAbsolutePath().toString()) .setResourcesOutputPath(project.getClassesDir().toAbsolutePath().toString()) - .setResourcePath(project.getResourcesSourcesDir().toAbsolutePath().toString()) + .setResourcePaths( + project.getResourcesSourcesDirs().stream() + .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .collect(Collectors.toSet())) .setSourceParents(Collections.singleton(project.getSourcesDir().toString())) .setPreBuildOutputDir(project.getCodeGenOutputDir().toString()) .setTargetDir(project.getOutputDir().toString()).build(); } -} \ No newline at end of file +} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java index 953fcb669f058..baa23121b420b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java @@ -216,16 +216,15 @@ public void handleChanges(Collection changes) { for (String path : module.getMain().getSourcePaths()) { testClassChangeWatcher.watchPath(new File(path), callback); } - if (module.getMain().getResourcePath() != null) { - testClassChangeWatcher.watchPath(new File(module.getMain().getResourcePath()), callback); + for (String path : module.getMain().getResourcePaths()) { + testClassChangeWatcher.watchPath(new File(path), callback); } } for (String path : context.getApplicationRoot().getTest().get().getSourcePaths()) { testClassChangeWatcher.watchPath(new File(path), callback); } - if (context.getApplicationRoot().getTest().get().getResourcePath() != null) { - testClassChangeWatcher - .watchPath(new File(context.getApplicationRoot().getTest().get().getResourcePath()), callback); + for (String path : context.getApplicationRoot().getTest().get().getResourcePaths()) { + testClassChangeWatcher.watchPath(new File(path), callback); } periodicTestCompile(); } else { @@ -295,8 +294,10 @@ private ClassScanResult compileTestClasses() { public List getResourcesDir() { List ret = new ArrayList<>(); for (DevModeContext.ModuleInfo i : context.getAllModules()) { - if (i.getMain().getResourcePath() != null) { - ret.add(Paths.get(i.getMain().getResourcePath())); + if (!i.getMain().getResourcePaths().isEmpty()) { + for (String path : i.getMain().getResourcePaths()) { + ret.add(Paths.get(path)); + } } else if (i.getMain().getResourcesOutputPath() != null) { ret.add(Paths.get(i.getMain().getResourcesOutputPath())); } @@ -700,55 +701,61 @@ Set checkForFileChange(Function moduleResources = correspondingResources.computeIfAbsent(cuf.apply(module), m -> Collections.newSetFromMap(new ConcurrentHashMap<>())); boolean doCopy = true; - String rootPath = cuf.apply(module).getResourcePath(); + Set rootPaths = cuf.apply(module).getResourcePaths(); String outputPath = cuf.apply(module).getResourcesOutputPath(); - if (rootPath == null) { - rootPath = cuf.apply(module).getClassesPath(); + if (rootPaths.isEmpty()) { + String rootPath = cuf.apply(module).getClassesPath(); + if (rootPath != null) { + rootPaths = Collections.singleton(rootPath); + } outputPath = rootPath; doCopy = false; } - if (rootPath == null || outputPath == null) { + if (rootPaths.isEmpty() || outputPath == null) { continue; } - Path root = Paths.get(rootPath); - if (!Files.exists(root) || !Files.isReadable(root)) { - continue; - } - Path outputDir = Paths.get(outputPath); + final List roots = rootPaths.stream() + .map(Paths::get) + .filter(Files::exists) + .filter(Files::isReadable) + .collect(Collectors.toList()); //copy all modified non hot deployment files over if (doCopy) { + final Set seen = new HashSet<>(moduleResources); try { - final Set seen = new HashSet<>(moduleResources); - //since the stream is Closeable, use a try with resources so the underlying iterator is closed - try (final Stream walk = Files.walk(root)) { - walk.forEach(path -> { - try { - Path relative = root.relativize(path); - Path target = outputDir.resolve(relative); - seen.remove(target); - if (!timestampSet.watchedFileTimestamps.containsKey(path)) { - moduleResources.add(target); - if (!Files.exists(target) || Files.getLastModifiedTime(target).toMillis() < Files - .getLastModifiedTime(path).toMillis()) { - if (Files.isDirectory(path)) { - Files.createDirectories(target); - } else { - Files.createDirectories(target.getParent()); - ret.add(relative.toString()); - byte[] data = Files.readAllBytes(path); - try (FileOutputStream out = new FileOutputStream(target.toFile())) { - out.write(data); - } - if (copyResourceNotification != null) { - copyResourceNotification.accept(module, relative.toString()); + for (Path root : roots) { + Path outputDir = Paths.get(outputPath); + //since the stream is Closeable, use a try with resources so the underlying iterator is closed + try (final Stream walk = Files.walk(root)) { + walk.forEach(path -> { + try { + Path relative = root.relativize(path); + Path target = outputDir.resolve(relative); + seen.remove(target); + if (!timestampSet.watchedFileTimestamps.containsKey(path)) { + moduleResources.add(target); + if (!Files.exists(target) || Files.getLastModifiedTime(target).toMillis() < Files + .getLastModifiedTime(path).toMillis()) { + if (Files.isDirectory(path)) { + Files.createDirectories(target); + } else { + Files.createDirectories(target.getParent()); + ret.add(relative.toString()); + byte[] data = Files.readAllBytes(path); + try (FileOutputStream out = new FileOutputStream(target.toFile())) { + out.write(data); + } + if (copyResourceNotification != null) { + copyResourceNotification.accept(module, relative.toString()); + } } } } + } catch (Exception e) { + log.error("Failed to copy resources", e); } - } catch (Exception e) { - log.error("Failed to copy resources", e); - } - }); + }); + } } for (Path i : seen) { moduleResources.remove(i); @@ -761,36 +768,39 @@ Set checkForFileChange(Function existing) { - ret.add(path); - log.infof("File change detected: %s", file); - if (doCopy && !Files.isDirectory(file)) { - Path target = outputDir.resolve(path); - byte[] data = Files.readAllBytes(file); - try (FileOutputStream out = new FileOutputStream(target.toFile())) { - out.write(data); + for (Path root : roots) { + Path outputDir = Paths.get(outputPath); + for (String path : timestampSet.watchedFilePaths.keySet()) { + Path file = root.resolve(path); + if (file.toFile().exists()) { + try { + long value = Files.getLastModifiedTime(file).toMillis(); + Long existing = timestampSet.watchedFileTimestamps.get(file); + //existing can be null when running tests + //as there is both normal and test resources, but only one set of watched timestampts + if (existing != null && value > existing) { + ret.add(path); + log.infof("File change detected: %s", file); + if (doCopy && !Files.isDirectory(file)) { + Path target = outputDir.resolve(path); + byte[] data = Files.readAllBytes(file); + try (FileOutputStream out = new FileOutputStream(target.toFile())) { + out.write(data); + } } + timestampSet.watchedFileTimestamps.put(file, value); } - timestampSet.watchedFileTimestamps.put(file, value); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } else { + timestampSet.watchedFileTimestamps.put(file, 0L); + Path target = outputDir.resolve(path); + try { + FileUtil.deleteDirectory(target); + } catch (IOException e) { + throw new UncheckedIOException(e); } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } else { - timestampSet.watchedFileTimestamps.put(file, 0L); - Path target = outputDir.resolve(path); - try { - FileUtil.deleteDirectory(target); - } catch (IOException e) { - throw new UncheckedIOException(e); } } } @@ -870,33 +880,35 @@ private RuntimeUpdatesProcessor setWatchedFilePathsInternal(Map for (DevModeContext.ModuleInfo module : context.getAllModules()) { List compilationUnits = cuf.apply(module); for (DevModeContext.CompilationUnit unit : compilationUnits) { - String rootPath = unit.getResourcePath(); - - if (rootPath == null) { - rootPath = unit.getClassesPath(); - } - if (rootPath == null) { - continue; + Set rootPaths = unit.getResourcePaths(); + if (rootPaths.isEmpty()) { + String rootPath = unit.getClassesPath(); + if (rootPath == null) { + continue; + } + rootPaths = Collections.singleton(rootPath); } - Path root = Paths.get(rootPath); - for (String path : watchedFilePaths.keySet()) { - Path config = root.resolve(path); - if (config.toFile().exists()) { - try { - FileTime lastModifiedTime = Files.getLastModifiedTime(config); - timestamps.watchedFileTimestamps.put(config, lastModifiedTime.toMillis()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } else { - timestamps.watchedFileTimestamps.put(config, 0L); - Map extraWatchedFileTimestamps = expandGlobPattern(root, config); - timestamps.watchedFileTimestamps.putAll(extraWatchedFileTimestamps); - for (Path extraPath : extraWatchedFileTimestamps.keySet()) { - extraWatchedFilePaths.put(root.relativize(extraPath).toString(), - timestamps.watchedFilePaths.get(path)); + for (String rootPath : rootPaths) { + Path root = Paths.get(rootPath); + for (String path : watchedFilePaths.keySet()) { + Path config = root.resolve(path); + if (config.toFile().exists()) { + try { + FileTime lastModifiedTime = Files.getLastModifiedTime(config); + timestamps.watchedFileTimestamps.put(config, lastModifiedTime.toMillis()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } else { + timestamps.watchedFileTimestamps.put(config, 0L); + Map extraWatchedFileTimestamps = expandGlobPattern(root, config); + timestamps.watchedFileTimestamps.putAll(extraWatchedFileTimestamps); + for (Path extraPath : extraWatchedFileTimestamps.keySet()) { + extraWatchedFilePaths.put(root.relativize(extraPath).toString(), + timestamps.watchedFilePaths.get(path)); + } + timestamps.watchedFileTimestamps.putAll(extraWatchedFileTimestamps); } - timestamps.watchedFileTimestamps.putAll(extraWatchedFileTimestamps); } } } diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java index 8b56fd4336427..8b2411e0a4ff4 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java @@ -8,6 +8,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -449,14 +450,14 @@ private SourceSetImpl convert(SourceSet sourceSet) { if (sourceSet.getOutput().getResourcesDir().exists()) { return new SourceSetImpl( existingSrcDirs, - sourceSet.getOutput().getResourcesDir()); + Collections.singleton(sourceSet.getOutput().getResourcesDir())); } return new SourceSetImpl(existingSrcDirs); } private io.quarkus.bootstrap.model.gradle.SourceSet getSourceSourceSet(SourceSet sourceSet) { return new SourceSetImpl(sourceSet.getAllJava().getSrcDirs(), - sourceSet.getResources().getSourceDirectories().getSingleFile()); + sourceSet.getResources().getSourceDirectories().getFiles()); } private static boolean isDependency(ResolvedArtifact a) { diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java index 61193bc33db3b..b353d0ce36b92 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java @@ -369,8 +369,10 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil sourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath().toString()); } } - //TODO: multiple resource directories - final File resourcesSrcDir = mainSourceSet.getResources().getSourceDirectories().getSingleFile(); + final Set resourcesSrcDirs = new HashSet<>(); + for (File resourcesSrcDir : mainSourceSet.getResources().getSourceDirectories().getFiles()) { + resourcesSrcDirs.add(resourcesSrcDir.getAbsolutePath()); + } // resourcesSrcDir may exist but if it's empty the resources output dir won't be created final File resourcesOutputDir = mainSourceSet.getOutput().getResourcesDir(); @@ -405,7 +407,7 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil .setProjectDirectory(project.getProjectDir().getAbsolutePath()) .setSourcePaths(sourcePaths) .setClassesPath(classesDir) - .setResourcePath(resourcesSrcDir.getAbsolutePath()) + .setResourcePaths(resourcesSrcDirs) .setResourcesOutputPath(resourcesOutputPath) .setSourceParents(sourceParentPaths) .setPreBuildOutputDir(project.getBuildDir().toPath().resolve("generated-sources").toAbsolutePath().toString()) @@ -423,8 +425,10 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil testSourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath().toString()); } } - //TODO: multiple resource directories - final File testResourcesSrcDir = testSourceSet.getResources().getSourceDirectories().getSingleFile(); + final Set testResourcesSrcDirs = new HashSet<>(); + for (File testResourcesSrcDir : testSourceSet.getResources().getSourceDirectories().getFiles()) { + testResourcesSrcDirs.add(testResourcesSrcDir.getAbsolutePath()); + } // resourcesSrcDir may exist but if it's empty the resources output dir won't be created final File testResourcesOutputDir = testSourceSet.getOutput().getResourcesDir(); @@ -446,7 +450,7 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil } moduleBuilder.setTestSourcePaths(testSourcePaths) .setTestClassesPath(testClassesDir) - .setTestResourcePath(testResourcesSrcDir.getAbsolutePath()) + .setTestResourcePaths(testResourcesSrcDirs) .setTestResourcesOutputPath(testResourcesOutputPath); } } diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java index 12eec63882f5a..b92a6cf0b9ce8 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java @@ -37,9 +37,11 @@ import org.aesh.terminal.utils.ANSI; import org.apache.maven.artifact.Artifact; import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.BuildBase; import org.apache.maven.model.Dependency; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; +import org.apache.maven.model.Profile; import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.BuildPluginManager; @@ -578,10 +580,11 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local String projectDirectory = null; Set sourcePaths = null; String classesPath = null; - String resourcePath = null; + Set resourcePaths; Set testSourcePaths = null; String testClassesPath = null; - String testResourcePath = null; + Set testResourcePaths; + List activeProfiles = Collections.emptyList(); final MavenProject mavenProject = session.getProjectMap().get( String.format("%s:%s:%s", localProject.getGroupId(), localProject.getArtifactId(), localProject.getVersion())); @@ -613,6 +616,7 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local .filter(Files::isDirectory) .map(src -> src.toAbsolutePath().toString()) .collect(Collectors.toSet()); + activeProfiles = mavenProject.getActiveProfiles(); } Path sourceParent = localProject.getSourcesDir().toAbsolutePath(); @@ -624,16 +628,34 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local if (Files.isDirectory(testClassesDir)) { testClassesPath = testClassesDir.toAbsolutePath().toString(); } - Path resourcesSourcesDir = localProject.getResourcesSourcesDir(); - if (Files.isDirectory(resourcesSourcesDir)) { - resourcePath = resourcesSourcesDir.toAbsolutePath().toString(); - } - Path testResourcesSourcesDir = localProject.getTestResourcesSourcesDir(); - if (Files.isDirectory(testResourcesSourcesDir)) { - testResourcePath = testResourcesSourcesDir.toAbsolutePath().toString(); + resourcePaths = localProject.getResourcesSourcesDirs().stream() + .filter(Files::isDirectory) + .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .collect(Collectors.toSet()); + testResourcePaths = localProject.getTestResourcesSourcesDirs().stream() + .filter(Files::isDirectory) + .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .collect(Collectors.toSet()); + // Add the resources and test resources from the profiles + for (Profile profile : activeProfiles) { + final BuildBase build = profile.getBuild(); + if (build != null) { + resourcePaths.addAll( + build.getResources().stream() + .map(Resource::getDirectory) + .map(localProject::resolveRelativeToBaseDir) + .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .collect(Collectors.toList())); + testResourcePaths.addAll( + build.getTestResources().stream() + .map(Resource::getDirectory) + .map(localProject::resolveRelativeToBaseDir) + .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .collect(Collectors.toList())); + } } - if (classesPath == null && (!sourcePaths.isEmpty() || resourcePath != null)) { + if (classesPath == null && (!sourcePaths.isEmpty() || !resourcePaths.isEmpty())) { throw new MojoExecutionException("Hot reloadable dependency " + localProject.getAppArtifact() + " has not been compiled yet (the classes directory " + classesDir + " does not exist)"); } @@ -646,14 +668,15 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local .setSourcePaths(sourcePaths) .setClassesPath(classesPath) .setResourcesOutputPath(classesPath) - .setResourcePath(resourcePath) + .setResourcePaths(resourcePaths) .setSourceParents(Collections.singleton(sourceParent.toAbsolutePath().toString())) .setPreBuildOutputDir(targetDir.resolve("generated-sources").toAbsolutePath().toString()) .setTargetDir(targetDir.toAbsolutePath().toString()) .setTestSourcePaths(testSourcePaths) .setTestClassesPath(testClassesPath) - .setTestResourcePath(testResourcePath) + .setTestResourcePaths(testResourcePaths) .setTestResourcesOutputPath(testClassesPath) + .setTestResourcePaths(testResourcePaths) .build(); if (root) { diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java index 840f4d86f7937..ddb6cb24965de 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java @@ -7,5 +7,5 @@ public interface SourceSet { Set getSourceDirectories(); - File getResourceDirectory(); + Set getResourceDirectories(); } diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java index 040d03b46a14d..450968fb38a6a 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java @@ -4,17 +4,19 @@ import java.io.File; import java.io.Serializable; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; public class SourceSetImpl implements SourceSet, Serializable { - private Set sourceDirectories = new HashSet<>(); - private File resourceDirectory; + private final Set sourceDirectories = new HashSet<>(); + // Use a LinkedHashSet to keep the original order + private final Set resourceDirectories = new LinkedHashSet<>(); - public SourceSetImpl(Set sourceDirectories, File resourceDirectory) { + public SourceSetImpl(Set sourceDirectories, Set resourceDirectories) { this.sourceDirectories.addAll(sourceDirectories); - this.resourceDirectory = resourceDirectory; + this.resourceDirectories.addAll(resourceDirectories); } public SourceSetImpl(Set sourceDirectories) { @@ -31,15 +33,15 @@ public Set getSourceDirectories() { } @Override - public File getResourceDirectory() { - return resourceDirectory; + public Set getResourceDirectories() { + return resourceDirectories; } @Override public String toString() { return "SourceSetImpl{" + "sourceDirectories=" + sourceDirectories.stream().map(File::getPath).collect(Collectors.joining(":")) + - ", resourceDirectory=" + resourceDirectory + + ", resourceDirectories=" + resourceDirectories.stream().map(File::getPath).collect(Collectors.joining(":")) + '}'; } } diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java index 460b2ae317037..ece8773b62877 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java @@ -55,7 +55,8 @@ public static Closeable launch(Path classesDir, Map context) { QuarkusModelHelper.toPathsCollection(additionalModule.getSourceSet().getSourceDirectories()), true, false)); builder.addAdditionalApplicationArchive(new AdditionalDependency( - additionalModule.getSourceSet().getResourceDirectory().toPath(), true, false)); + QuarkusModelHelper.toPathsCollection(additionalModule.getSourceSet().getResourceDirectories()), + true, false)); } } } else { diff --git a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java index 9d5ed81c2c98c..65cd15085e4d1 100644 --- a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java +++ b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java @@ -145,9 +145,10 @@ public static AppModel convert(QuarkusModel model, AppArtifact appArtifact) thro WorkspaceModule module = model.getWorkspace().getMainModule(); module.getSourceSet().getSourceDirectories().stream().filter(File::exists).map(File::toPath) .forEach(paths::add); - File resourceDirectory = module.getSourceSet().getResourceDirectory(); - if (resourceDirectory != null && resourceDirectory.exists()) { - paths.add(resourceDirectory.toPath()); + for (File resourceDirectory : module.getSourceSet().getResourceDirectories()) { + if (resourceDirectory.exists()) { + paths.add(resourceDirectory.toPath()); + } } appArtifact.setPaths(paths.build()); } diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java index e98875ef5d8c8..82cf271df6798 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java @@ -11,7 +11,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.function.Function; +import java.util.stream.Collectors; import org.apache.maven.model.Build; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; @@ -228,20 +230,28 @@ public Path getSourcesDir() { return getSourcesSourcesDir().getParent(); } - public Path getResourcesSourcesDir() { + public Set getResourcesSourcesDirs() { final List resources = rawModel.getBuild() == null ? Collections.emptyList() : rawModel.getBuild().getResources(); - //todo: support multiple resources dirs for config hot deployment - final String resourcesDir = resources.isEmpty() ? null : resources.get(0).getDirectory(); - return resolveRelativeToBaseDir(resourcesDir, "src/main/resources"); + if (resources.isEmpty()) { + return Collections.singleton(resolveRelativeToBaseDir(null, "src/main/resources")); + } + return resources.stream() + .map(Resource::getDirectory) + .map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/main/resources")) + .collect(Collectors.toSet()); } - public Path getTestResourcesSourcesDir() { + public Set getTestResourcesSourcesDirs() { final List resources = rawModel.getBuild() == null ? Collections.emptyList() : rawModel.getBuild().getTestResources(); - //todo: support multiple resources dirs for config hot deployment - final String resourcesDir = resources.isEmpty() ? null : resources.get(0).getDirectory(); - return resolveRelativeToBaseDir(resourcesDir, "src/test/resources"); + if (resources.isEmpty()) { + return Collections.singleton(resolveRelativeToBaseDir(null, "src/test/resources")); + } + return resources.stream() + .map(Resource::getDirectory) + .map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/test/resources")) + .collect(Collectors.toSet()); } public ModelBuildingResult getModelBuildingResult() { @@ -269,6 +279,10 @@ public AppArtifact getAppArtifact(String extension) { return new AppArtifact(groupId, artifactId, "", extension, getVersion()); } + public Path resolveRelativeToBaseDir(String path) { + return resolveRelativeToBaseDir(path, null); + } + private Path resolveRelativeToBaseDir(String path, String defaultPath) { return dir.resolve(path == null ? defaultPath : stripProjectBasedirPrefix(path, PROJECT_BASEDIR)); } diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java index 9f0b853297e0b..b9ddb97b814ae 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java @@ -161,7 +161,7 @@ private Path emptyJarOutput(LocalProject lp, Artifact artifact) { // so the Maven resolver will succeed resolving it from the repo. // If the artifact does not exist in the local repo, we are creating an empty classes directory in the target directory. if (!Files.exists(lp.getSourcesSourcesDir()) - && !Files.exists(lp.getResourcesSourcesDir()) + && lp.getResourcesSourcesDirs().stream().noneMatch(Files::exists) && !isFoundInLocalRepo(artifact)) { try { final Path classesDir = lp.getClassesDir(); diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java index b897bc4e3fcc9..c24fefc09813e 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java @@ -72,11 +72,11 @@ private void assertWorkspace(WorkspaceModule workspaceModule, File projectDir) { assertEquals(new File(projectDir, "build"), workspaceModule.getBuildDir()); final SourceSet sourceSet = workspaceModule.getSourceSet(); assertNotNull(sourceSet); - assertNull(sourceSet.getResourceDirectory()); + assertTrue(sourceSet.getResourceDirectories().isEmpty()); assertThat(sourceSet.getSourceDirectories()).containsAnyOf(new File(projectDir, "build/classes/java/main"), new File(projectDir, "build/classes/java/test")); final SourceSet sourceSourceSet = workspaceModule.getSourceSourceSet(); - assertEquals(new File(projectDir, "src/main/resources"), sourceSourceSet.getResourceDirectory()); + assertThat(sourceSourceSet.getResourceDirectories()).containsAnyOf(new File(projectDir, "src/main/resources")); assertEquals(5, sourceSourceSet.getSourceDirectories().size()); assertThat(sourceSourceSet.getSourceDirectories()).contains(new File(projectDir, "src/main/java")); } diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java index 82ce10529fc4d..5ab9ce39f2585 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java @@ -848,6 +848,51 @@ public void testThatNewResourcesAreServed() throws MavenInvocationException, IOE .until(() -> DevModeTestUtils.getHttpResponse("/lorem.txt", 404)); } + @Test + public void testThatMultipleResourceDirectoriesAreSupported() throws MavenInvocationException, IOException { + testDir = initProject("projects/dev-mode-multiple-resource-dirs"); + testMultipleResourceDirectories(); + } + + @Test + public void testThatMultipleResourceDirectoriesAreSupportedWithProfile() throws MavenInvocationException, IOException { + testDir = initProject("projects/dev-mode-multiple-resource-dirs-with-profile"); + testMultipleResourceDirectories(); + } + + private void testMultipleResourceDirectories() throws MavenInvocationException, IOException { + runAndCheck(); + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello/greetings").contains("Bonjour/Other")); + + // Update the application.properties + File source = new File(testDir, "src/main/resources-primary/application.properties"); + FileUtils.write(source, "greeting=Salut", "UTF-8"); + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello/greetings").contains("Salut/Other")); + + // Add the application.yaml + source = new File(testDir, "src/main/resources-secondary/application.yaml"); + FileUtils.write(source, "other:\n" + + " greeting: Buenos dias", "UTF-8"); + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello/greetings").contains("Salut/Buenos dias")); + + // Update the application.yaml + FileUtils.write(source, "other:\n" + + " greeting: Hola", "UTF-8"); + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES) + .until(() -> DevModeTestUtils.getHttpResponse("/app/hello/greetings").contains("Salut/Hola")); + } + @Test public void testThatApplicationRecoversCompilationIssue() throws MavenInvocationException, IOException { testDir = initProject("projects/classic", "projects/project-classic-run-compilation-issue"); diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/pom.xml b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/pom.xml new file mode 100644 index 0000000000000..2cea4535deb14 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + org.acme + acme + 1.0-SNAPSHOT + + io.quarkus + quarkus-bom + @project.version@ + @project.version@ + 11 + UTF-8 + 11 + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-config-yaml + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + src/main/resources-primary + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + generate-code + generate-code-tests + build + + + + + + + + + add-secondary + + true + + + + + src/main/resources-secondary + + + + + + diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/HelloResource.java b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..3dc7e048691f4 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,31 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @ConfigProperty(name = "greeting") + String greeting; + + @ConfigProperty(name = "other.greeting", defaultValue = "Other") + String otherGreeting; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } + + @GET + @Path("/greetings") + @Produces(MediaType.TEXT_PLAIN) + public String greetings() { + return greeting + "/" + otherGreeting; + } +} diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/MyApplication.java b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/MyApplication.java new file mode 100644 index 0000000000000..2b41cd0385afb --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/java/org/acme/MyApplication.java @@ -0,0 +1,9 @@ +package org.acme; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/app") +public class MyApplication extends Application { + +} diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/META-INF/resources/index.html b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/META-INF/resources/index.html new file mode 100644 index 0000000000000..c09bb5c96b869 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/META-INF/resources/index.html @@ -0,0 +1,156 @@ + + + + + acme - 1.0-SNAPSHOT + + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

Do you like Quarkus?

+

Go give it a star on GitHub.

+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: acme
  • +
  • Version: 1.0-SNAPSHOT
  • +
  • Quarkus Version: 999-SNAPSHOT
  • +
+
+
+

Next steps

+ +
+
+
+ + + + \ No newline at end of file diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/application.properties b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/application.properties new file mode 100644 index 0000000000000..acb0268bff21d --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs-with-profile/src/main/resources-primary/application.properties @@ -0,0 +1,2 @@ +# Configuration file +greeting=Bonjour diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/pom.xml b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/pom.xml new file mode 100644 index 0000000000000..b30df964c899b --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + org.acme + acme + 1.0-SNAPSHOT + + io.quarkus + quarkus-bom + @project.version@ + @project.version@ + 11 + UTF-8 + 11 + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-config-yaml + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + src/main/resources-primary + + + src/main/resources-secondary + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + generate-code + generate-code-tests + build + + + + + + + diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/HelloResource.java b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..3dc7e048691f4 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,31 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @ConfigProperty(name = "greeting") + String greeting; + + @ConfigProperty(name = "other.greeting", defaultValue = "Other") + String otherGreeting; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } + + @GET + @Path("/greetings") + @Produces(MediaType.TEXT_PLAIN) + public String greetings() { + return greeting + "/" + otherGreeting; + } +} diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/MyApplication.java b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/MyApplication.java new file mode 100644 index 0000000000000..2b41cd0385afb --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/java/org/acme/MyApplication.java @@ -0,0 +1,9 @@ +package org.acme; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/app") +public class MyApplication extends Application { + +} diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/META-INF/resources/index.html b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/META-INF/resources/index.html new file mode 100644 index 0000000000000..c09bb5c96b869 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/META-INF/resources/index.html @@ -0,0 +1,156 @@ + + + + + acme - 1.0-SNAPSHOT + + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

Do you like Quarkus?

+

Go give it a star on GitHub.

+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: acme
  • +
  • Version: 1.0-SNAPSHOT
  • +
  • Quarkus Version: 999-SNAPSHOT
  • +
+
+
+

Next steps

+ +
+
+
+ + + + \ No newline at end of file diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/application.properties b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/application.properties new file mode 100644 index 0000000000000..acb0268bff21d --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-primary/application.properties @@ -0,0 +1,2 @@ +# Configuration file +greeting=Bonjour diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep new file mode 100644 index 0000000000000..8a0a8385da974 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep @@ -0,0 +1 @@ +# Just to be able to commit this empty folder needed for the test diff --git a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java index cf1237660f5e3..47ce1c26d7a8d 100644 --- a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java +++ b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java @@ -337,7 +337,7 @@ private DevModeContext exportArchive(Path deploymentDir, Path testSourceDir, Pat .setProjectDirectory(deploymentDir.toAbsolutePath().toString()) .setSourcePaths(Collections.singleton(deploymentSourcePath.toAbsolutePath().toString())) .setClassesPath(classes.toAbsolutePath().toString()) - .setResourcePath(deploymentResourcePath.toAbsolutePath().toString()) + .setResourcePaths(Collections.singleton(deploymentResourcePath.toAbsolutePath().toString())) .setResourcesOutputPath(classes.toAbsolutePath().toString()) .setSourceParents(Collections.singleton(deploymentSourceParentPath.toAbsolutePath().toString())) .setPreBuildOutputDir(targetDir.resolve("generated-sources").toAbsolutePath().toString()) @@ -386,7 +386,7 @@ private DevModeContext exportArchive(Path deploymentDir, Path testSourceDir, Pat moduleBuilder .setTestSourcePaths(Collections.singleton(deploymentTestSourcePath.toAbsolutePath().toString())) .setTestClassesPath(testClasses.toAbsolutePath().toString()) - .setTestResourcePath(deploymentTestResourcePath.toAbsolutePath().toString()) + .setTestResourcePaths(Collections.singleton(deploymentTestResourcePath.toAbsolutePath().toString())) .setTestResourcesOutputPath(testClasses.toAbsolutePath().toString()); } From 15145b763f741d51940ae0ce0a07360d6aea8b80 Mon Sep 17 00:00:00 2001 From: essobedo Date: Mon, 17 May 2021 21:28:12 +0200 Subject: [PATCH 2/2] Replace Set of paths to PathsCollection --- .../io/quarkus/deployment/CodeGenerator.java | 6 +- .../deployment/dev/CompilationProvider.java | 4 +- .../deployment/dev/DevModeContext.java | 52 ++-- .../deployment/dev/IDEDevModeMain.java | 29 +-- .../deployment/dev/IsolatedDevModeMain.java | 3 +- .../dev/JavaCompilationProvider.java | 12 +- .../deployment/dev/QuarkusCompiler.java | 7 +- .../dev/RuntimeUpdatesProcessor.java | 43 ++-- .../gradle/builder/QuarkusModelBuilder.java | 19 +- .../io/quarkus/gradle/tasks/QuarkusDev.java | 36 +-- .../gradle/tasks/QuarkusGenerateCode.java | 3 +- .../main/java/io/quarkus/maven/DevMojo.java | 55 ++-- .../io/quarkus/maven/GenerateCodeMojo.java | 8 +- .../ConfigPropertiesBuildStep.java | 1 - .../deployment/KotlinCompilationProvider.java | 3 +- .../deployment/ScalaCompilationProvider.java | 3 +- .../bootstrap/model/PathsCollection.java | 242 ++++++++++++------ .../bootstrap/model/gradle/SourceSet.java | 7 +- .../model/gradle/impl/SourceSetImpl.java | 31 +-- .../io/quarkus/bootstrap/IDELauncherImpl.java | 4 +- .../bootstrap/util/QuarkusModelHelper.java | 16 +- .../maven/workspace/LocalProject.java | 19 +- .../maven/workspace/LocalWorkspace.java | 2 +- .../builder/QuarkusModelBuilderTest.java | 10 +- .../src/main/resources-secondary/.keep | 1 - .../jacoco/deployment/JacocoProcessor.java | 11 +- .../io/quarkus/test/QuarkusDevModeTest.java | 15 +- .../test/junit/IntegrationTestUtil.java | 8 +- .../test/junit/QuarkusTestExtension.java | 9 +- 29 files changed, 371 insertions(+), 288 deletions(-) delete mode 100644 integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep diff --git a/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java index a530e31c84267..c42d1524fc7f7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java @@ -7,10 +7,10 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; -import java.util.Set; import java.util.function.Consumer; import io.quarkus.bootstrap.model.AppModel; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.prebuild.CodeGenException; import io.quarkus.deployment.codegen.CodeGenData; @@ -22,7 +22,7 @@ public class CodeGenerator { // used by Gradle @SuppressWarnings("unused") public static void initAndRun(ClassLoader classLoader, - Set sourceParentDirs, Path generatedSourcesDir, Path buildDir, + PathsCollection sourceParentDirs, Path generatedSourcesDir, Path buildDir, Consumer sourceRegistrar, AppModel appModel, Map properties) throws CodeGenException { List generators = init(classLoader, sourceParentDirs, generatedSourcesDir, buildDir, sourceRegistrar); @@ -33,7 +33,7 @@ public static void initAndRun(ClassLoader classLoader, } public static List init(ClassLoader deploymentClassLoader, - Set sourceParentDirs, + PathsCollection sourceParentDirs, Path generatedSourcesDir, Path buildDir, Consumer sourceRegistrar) throws CodeGenException { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/CompilationProvider.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/CompilationProvider.java index d1829ea2c7947..898cd7b033af6 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/CompilationProvider.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/CompilationProvider.java @@ -11,6 +11,8 @@ import java.util.List; import java.util.Set; +import io.quarkus.bootstrap.model.PathsCollection; + public interface CompilationProvider extends Closeable { Set handledExtensions(); @@ -21,7 +23,7 @@ default Set handledSourcePaths() { void compile(Set files, Context context); - Path getSourcePath(Path classFilePath, Set sourcePaths, String classesPath); + Path getSourcePath(Path classFilePath, PathsCollection sourcePaths, String classesPath); @Override default void close() throws IOException { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java index 0ebb11ce4f6ba..b52164b6a8136 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/DevModeContext.java @@ -3,13 +3,12 @@ import java.io.File; import java.io.Serializable; import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -17,6 +16,7 @@ import io.quarkus.bootstrap.app.QuarkusBootstrap; import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.bootstrap.model.PathsCollection; /** * Object that is used to pass context data from the plugin doing the invocation @@ -26,7 +26,7 @@ */ public class DevModeContext implements Serializable { - public static final CompilationUnit EMPTY_COMPILATION_UNIT = new CompilationUnit(Collections.emptySet(), null, null, null); + public static final CompilationUnit EMPTY_COMPILATION_UNIT = new CompilationUnit(PathsCollection.of(), null, null, null); public static final String ENABLE_PREVIEW_FLAG = "--enable-preview"; @@ -235,18 +235,18 @@ public static class ModuleInfo implements Serializable { private final CompilationUnit test; private final String preBuildOutputDir; - private final Set sourceParents; + private final PathsCollection sourceParents; private final String targetDir; ModuleInfo(Builder builder) { this.appArtifactKey = builder.appArtifactKey; this.name = builder.name; this.projectDirectory = builder.projectDirectory; - this.main = new CompilationUnit(new LinkedHashSet<>(builder.sourcePaths), builder.classesPath, + this.main = new CompilationUnit(builder.sourcePaths, builder.classesPath, builder.resourcePaths, builder.resourcesOutputPath); if (builder.testClassesPath != null) { - this.test = new CompilationUnit(new LinkedHashSet<>(builder.testSourcePaths), + this.test = new CompilationUnit(builder.testSourcePaths, builder.testClassesPath, builder.testResourcePaths, builder.testResourcesOutputPath); } else { this.test = null; @@ -264,15 +264,17 @@ public String getProjectDirectory() { return projectDirectory; } - public Set getSourceParents() { + public PathsCollection getSourceParents() { return sourceParents; } //TODO: why isn't this immutable? public void addSourcePaths(Collection additionalPaths) { - additionalPaths.stream() - .map(p -> Paths.get(p).isAbsolute() ? p : (projectDirectory + File.separator + p)) - .forEach(main.sourcePaths::add); + this.main.sourcePaths = this.main.sourcePaths.add( + additionalPaths.stream() + .map(p -> Paths.get(p).isAbsolute() ? p : (projectDirectory + File.separator + p)) + .map(Paths::get) + .toArray(Path[]::new)); } public String getPreBuildOutputDir() { @@ -300,18 +302,18 @@ public static class Builder { private AppArtifactKey appArtifactKey; private String name; private String projectDirectory; - private Set sourcePaths = Collections.emptySet(); + private PathsCollection sourcePaths = PathsCollection.of(); private String classesPath; - private Set resourcePaths = Collections.emptySet(); + private PathsCollection resourcePaths = PathsCollection.of(); private String resourcesOutputPath; private String preBuildOutputDir; - private Set sourceParents = Collections.emptySet(); + private PathsCollection sourceParents = PathsCollection.of(); private String targetDir; - private Set testSourcePaths = Collections.emptySet(); + private PathsCollection testSourcePaths = PathsCollection.of(); private String testClassesPath; - private Set testResourcePaths = Collections.emptySet(); + private PathsCollection testResourcePaths = PathsCollection.of(); private String testResourcesOutputPath; public Builder setAppArtifactKey(AppArtifactKey appArtifactKey) { @@ -329,7 +331,7 @@ public Builder setProjectDirectory(String projectDirectory) { return this; } - public Builder setSourcePaths(Set sourcePaths) { + public Builder setSourcePaths(PathsCollection sourcePaths) { this.sourcePaths = sourcePaths; return this; } @@ -339,7 +341,7 @@ public Builder setClassesPath(String classesPath) { return this; } - public Builder setResourcePaths(Set resourcePaths) { + public Builder setResourcePaths(PathsCollection resourcePaths) { this.resourcePaths = resourcePaths; return this; } @@ -354,7 +356,7 @@ public Builder setPreBuildOutputDir(String preBuildOutputDir) { return this; } - public Builder setSourceParents(Set sourceParents) { + public Builder setSourceParents(PathsCollection sourceParents) { this.sourceParents = sourceParents; return this; } @@ -364,7 +366,7 @@ public Builder setTargetDir(String targetDir) { return this; } - public Builder setTestSourcePaths(Set testSourcePaths) { + public Builder setTestSourcePaths(PathsCollection testSourcePaths) { this.testSourcePaths = testSourcePaths; return this; } @@ -374,7 +376,7 @@ public Builder setTestClassesPath(String testClassesPath) { return this; } - public Builder setTestResourcePaths(Set testResourcePaths) { + public Builder setTestResourcePaths(PathsCollection testResourcePaths) { this.testResourcePaths = testResourcePaths; return this; } @@ -391,12 +393,12 @@ public ModuleInfo build() { } public static class CompilationUnit implements Serializable { - private final Set sourcePaths; + private PathsCollection sourcePaths; private final String classesPath; - private final Set resourcePaths; + private final PathsCollection resourcePaths; private final String resourcesOutputPath; - public CompilationUnit(Set sourcePaths, String classesPath, Set resourcePaths, + public CompilationUnit(PathsCollection sourcePaths, String classesPath, PathsCollection resourcePaths, String resourcesOutputPath) { this.sourcePaths = sourcePaths; this.classesPath = classesPath; @@ -404,7 +406,7 @@ public CompilationUnit(Set sourcePaths, String classesPath, Set this.resourcesOutputPath = resourcesOutputPath; } - public Set getSourcePaths() { + public PathsCollection getSourcePaths() { return sourcePaths; } @@ -412,7 +414,7 @@ public String getClassesPath() { return classesPath; } - public Set getResourcePaths() { + public PathsCollection getResourcePaths() { return resourcePaths; } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java index cb454445c36df..0c7bae528ccc0 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IDEDevModeMain.java @@ -1,10 +1,9 @@ package io.quarkus.deployment.dev; import java.io.Closeable; -import java.io.File; import java.nio.file.Path; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; @@ -15,6 +14,7 @@ import io.quarkus.bootstrap.BootstrapGradleException; import io.quarkus.bootstrap.app.CuratedApplication; import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.model.gradle.QuarkusModel; import io.quarkus.bootstrap.model.gradle.WorkspaceModule; import io.quarkus.bootstrap.resolver.AppModelResolverException; @@ -96,27 +96,24 @@ private DevModeContext.ModuleInfo toModule(WorkspaceModule module) throws Bootst AppArtifactKey key = new AppArtifactKey(module.getArtifactCoords().getGroupId(), module.getArtifactCoords().getArtifactId(), module.getArtifactCoords().getClassifier()); - Set sourceDirectories = new HashSet<>(); - Set sourceParents = new HashSet<>(); - for (File srcDir : module.getSourceSourceSet().getSourceDirectories()) { - sourceDirectories.add(srcDir.getPath()); + final Set sourceParents = new LinkedHashSet<>(); + for (Path srcDir : module.getSourceSourceSet().getSourceDirectories()) { sourceParents.add(srcDir.getParent()); } String resourceDirectory = null; if (!module.getSourceSet().getResourceDirectories().isEmpty()) { // Peek the first one as we assume that it is the primary - resourceDirectory = module.getSourceSet().getResourceDirectories().iterator().next().getPath(); + resourceDirectory = module.getSourceSet().getResourceDirectories().iterator().next().toString(); } return new DevModeContext.ModuleInfo.Builder() .setAppArtifactKey(key) .setName(module.getArtifactCoords().getArtifactId()) .setProjectDirectory(module.getProjectRoot().getPath()) - .setSourcePaths(sourceDirectories) + .setSourcePaths(module.getSourceSourceSet().getSourceDirectories()) .setClassesPath(QuarkusModelHelper.getClassPath(module).toAbsolutePath().toString()) - .setResourcePaths(module.getSourceSourceSet().getResourceDirectories().stream().map(Object::toString) - .collect(Collectors.toSet())) + .setResourcePaths(module.getSourceSourceSet().getResourceDirectories()) .setResourcesOutputPath(resourceDirectory) - .setSourceParents(sourceParents) + .setSourceParents(PathsCollection.from(sourceParents)) .setPreBuildOutputDir(module.getBuildDir().toPath().resolve("generated-sources").toAbsolutePath().toString()) .setTargetDir(module.getBuildDir().toString()).build(); } @@ -127,14 +124,14 @@ private DevModeContext.ModuleInfo toModule(LocalProject project) { .setAppArtifactKey(project.getKey()) .setName(project.getArtifactId()) .setProjectDirectory(project.getDir().toAbsolutePath().toString()) - .setSourcePaths(Collections.singleton(project.getSourcesSourcesDir().toAbsolutePath().toString())) + .setSourcePaths(PathsCollection.of(project.getSourcesSourcesDir().toAbsolutePath())) .setClassesPath(project.getClassesDir().toAbsolutePath().toString()) .setResourcesOutputPath(project.getClassesDir().toAbsolutePath().toString()) .setResourcePaths( - project.getResourcesSourcesDirs().stream() - .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) - .collect(Collectors.toSet())) - .setSourceParents(Collections.singleton(project.getSourcesDir().toString())) + PathsCollection.from(project.getResourcesSourcesDirs().toList().stream() + .map(Path::toAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)))) + .setSourceParents(PathsCollection.of(project.getSourcesDir())) .setPreBuildOutputDir(project.getCodeGenOutputDir().toString()) .setTargetDir(project.getOutputDir().toString()).build(); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java index cca7f17f59ab7..50389cf2cdb2d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java @@ -23,7 +23,6 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.jboss.logging.Logger; @@ -395,7 +394,7 @@ public boolean test(String s) { codeGens.addAll( CodeGenerator.init( deploymentClassLoader, - module.getSourceParents().stream().map(Paths::get).collect(Collectors.toSet()), + module.getSourceParents(), Paths.get(module.getPreBuildOutputDir()), Paths.get(module.getTargetDir()), sourcePath -> module.addSourcePaths(singleton(sourcePath.toAbsolutePath().toString())))); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/JavaCompilationProvider.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/JavaCompilationProvider.java index 47decbc6dbc70..2346fba5cbfb7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/JavaCompilationProvider.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/JavaCompilationProvider.java @@ -23,6 +23,7 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.gizmo.Gizmo; public class JavaCompilationProvider implements CompilationProvider { @@ -94,7 +95,7 @@ public void compile(Set filesToCompile, Context context) { } @Override - public Path getSourcePath(Path classFilePath, Set sourcePaths, String classesPath) { + public Path getSourcePath(Path classFilePath, PathsCollection sourcePaths, String classesPath) { Path sourceFilePath = null; final RuntimeUpdatesClassVisitor visitor = new RuntimeUpdatesClassVisitor(sourcePaths, classesPath); try (final InputStream inputStream = Files.newInputStream(classFilePath)) { @@ -117,11 +118,11 @@ public void close() throws IOException { } static class RuntimeUpdatesClassVisitor extends ClassVisitor { - private Set sourcePaths; - private String classesPath; + private final PathsCollection sourcePaths; + private final String classesPath; private String sourceFile; - public RuntimeUpdatesClassVisitor(Set sourcePaths, String classesPath) { + public RuntimeUpdatesClassVisitor(PathsCollection sourcePaths, String classesPath) { super(Gizmo.ASM_API_VERSION); this.sourcePaths = sourcePaths; this.classesPath = classesPath; @@ -133,8 +134,7 @@ public void visitSource(String source, String debug) { } public Path getSourceFileForClass(final Path classFilePath) { - for (String moduleSourcePath : sourcePaths) { - final Path sourcesDir = Paths.get(moduleSourcePath); + for (Path sourcesDir : sourcePaths) { final Path classesDir = Paths.get(classesPath); final StringBuilder sourceRelativeDir = new StringBuilder(); sourceRelativeDir.append(classesDir.relativize(classFilePath.getParent())); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusCompiler.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusCompiler.java index 208bc783f9176..20b1285ad214d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusCompiler.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/QuarkusCompiler.java @@ -27,6 +27,7 @@ import io.quarkus.bootstrap.app.CuratedApplication; import io.quarkus.bootstrap.app.QuarkusBootstrap; import io.quarkus.bootstrap.model.AppDependency; +import io.quarkus.bootstrap.model.PathsCollection; /** * Class that handles compilation of source files @@ -161,12 +162,12 @@ public void setupSourceCompilationContext(DevModeContext context, Set clas return; } compilationUnit.getSourcePaths().forEach(sourcePath -> { - this.compilationContexts.put(sourcePath, + this.compilationContexts.put(sourcePath.toString(), new CompilationProvider.Context( i.getName(), classPathElements, i.getProjectDirectory() == null ? null : new File(i.getProjectDirectory()), - new File(sourcePath), + sourcePath.toFile(), new File(compilationUnit.getClassesPath()), context.getSourceEncoding(), context.getCompilerOptions(), @@ -194,7 +195,7 @@ public void compile(String sourceDir, Map> extensionToChangedF } } - public Path findSourcePath(Path classFilePath, Set sourcePaths, String classesPath) { + public Path findSourcePath(Path classFilePath, PathsCollection sourcePaths, String classesPath) { for (CompilationProvider compilationProvider : compilationProviders) { Path sourcePath = compilationProvider.getSourcePath(classFilePath, sourcePaths, classesPath); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java index baa23121b420b..92bb6239f0dfc 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java @@ -53,6 +53,7 @@ import org.jboss.jandex.Indexer; import org.jboss.logging.Logger; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.runner.Timing; import io.quarkus.changeagent.ClassChangeAgent; import io.quarkus.deployment.dev.filewatch.FileChangeCallback; @@ -182,7 +183,7 @@ public Path getClassesDir() { @Override public List getSourcesDir() { - return context.getAllModules().stream().flatMap(m -> m.getMain().getSourcePaths().stream()).map(Paths::get) + return context.getAllModules().stream().flatMap(m -> m.getMain().getSourcePaths().toList().stream()) .collect(toList()); } @@ -213,18 +214,18 @@ public void handleChanges(Collection changes) { } }; for (DevModeContext.ModuleInfo module : context.getAllModules()) { - for (String path : module.getMain().getSourcePaths()) { - testClassChangeWatcher.watchPath(new File(path), callback); + for (Path path : module.getMain().getSourcePaths()) { + testClassChangeWatcher.watchPath(path.toFile(), callback); } - for (String path : module.getMain().getResourcePaths()) { - testClassChangeWatcher.watchPath(new File(path), callback); + for (Path path : module.getMain().getResourcePaths()) { + testClassChangeWatcher.watchPath(path.toFile(), callback); } } - for (String path : context.getApplicationRoot().getTest().get().getSourcePaths()) { - testClassChangeWatcher.watchPath(new File(path), callback); + for (Path path : context.getApplicationRoot().getTest().get().getSourcePaths()) { + testClassChangeWatcher.watchPath(path.toFile(), callback); } - for (String path : context.getApplicationRoot().getTest().get().getResourcePaths()) { - testClassChangeWatcher.watchPath(new File(path), callback); + for (Path path : context.getApplicationRoot().getTest().get().getResourcePaths()) { + testClassChangeWatcher.watchPath(path.toFile(), callback); } periodicTestCompile(); } else { @@ -295,8 +296,8 @@ public List getResourcesDir() { List ret = new ArrayList<>(); for (DevModeContext.ModuleInfo i : context.getAllModules()) { if (!i.getMain().getResourcePaths().isEmpty()) { - for (String path : i.getMain().getResourcePaths()) { - ret.add(Paths.get(path)); + for (Path path : i.getMain().getResourcePaths()) { + ret.add(path); } } else if (i.getMain().getResourcesOutputPath() != null) { ret.add(Paths.get(i.getMain().getResourcesOutputPath())); @@ -554,9 +555,9 @@ ClassScanResult checkForChangedClasses(QuarkusCompiler compiler, for (DevModeContext.ModuleInfo module : context.getAllModules()) { final List moduleChangedSourceFilePaths = new ArrayList<>(); - for (String sourcePath : cuf.apply(module).getSourcePaths()) { + for (Path sourcePath : cuf.apply(module).getSourcePaths()) { final Set changedSourceFiles; - Path start = Paths.get(sourcePath); + Path start = sourcePath; if (!Files.exists(start)) { continue; } @@ -580,7 +581,7 @@ && sourceFileWasRecentModified(p, ignoreFirstScanChanges)) .map(File::toPath) .collect(Collectors.toSet()); moduleChangedSourceFilePaths.addAll(changedPaths); - compiler.compile(sourcePath, changedSourceFiles.stream() + compiler.compile(sourcePath.toString(), changedSourceFiles.stream() .collect(groupingBy(this::getFileExtension, Collectors.toSet()))); compileProblem = null; } catch (Exception e) { @@ -701,12 +702,12 @@ Set checkForFileChange(Function moduleResources = correspondingResources.computeIfAbsent(cuf.apply(module), m -> Collections.newSetFromMap(new ConcurrentHashMap<>())); boolean doCopy = true; - Set rootPaths = cuf.apply(module).getResourcePaths(); + PathsCollection rootPaths = cuf.apply(module).getResourcePaths(); String outputPath = cuf.apply(module).getResourcesOutputPath(); if (rootPaths.isEmpty()) { String rootPath = cuf.apply(module).getClassesPath(); if (rootPath != null) { - rootPaths = Collections.singleton(rootPath); + rootPaths = PathsCollection.of(Paths.get(rootPath)); } outputPath = rootPath; doCopy = false; @@ -714,8 +715,7 @@ Set checkForFileChange(Function roots = rootPaths.stream() - .map(Paths::get) + final List roots = rootPaths.toList().stream() .filter(Files::exists) .filter(Files::isReadable) .collect(Collectors.toList()); @@ -880,16 +880,15 @@ private RuntimeUpdatesProcessor setWatchedFilePathsInternal(Map for (DevModeContext.ModuleInfo module : context.getAllModules()) { List compilationUnits = cuf.apply(module); for (DevModeContext.CompilationUnit unit : compilationUnits) { - Set rootPaths = unit.getResourcePaths(); + PathsCollection rootPaths = unit.getResourcePaths(); if (rootPaths.isEmpty()) { String rootPath = unit.getClassesPath(); if (rootPath == null) { continue; } - rootPaths = Collections.singleton(rootPath); + rootPaths = PathsCollection.of(Paths.get(rootPath)); } - for (String rootPath : rootPaths) { - Path root = Paths.get(rootPath); + for (Path root : rootPaths) { for (String path : watchedFilePaths.keySet()) { Path config = root.resolve(path); if (config.toFile().exists()) { diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java index 8b2411e0a4ff4..04647a0a38f85 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java @@ -11,6 +11,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -188,15 +189,16 @@ private WorkspaceModule getWorkspaceModule(Project project, LaunchMode mode, boo ArtifactCoords appArtifactCoords = new ArtifactCoordsImpl(project.getGroup().toString(), project.getName(), project.getVersion().toString()); final SourceSet mainSourceSet = QuarkusGradleUtils.getSourceSet(project, SourceSet.MAIN_SOURCE_SET_NAME); - final SourceSetImpl modelSourceSet = convert(mainSourceSet); - WorkspaceModuleImpl workspaceModule = new WorkspaceModuleImpl(appArtifactCoords, - project.getProjectDir().getAbsoluteFile(), - project.getBuildDir().getAbsoluteFile(), getSourceSourceSet(mainSourceSet), modelSourceSet); + final SourceSetImpl modelSourceSet; if (isMainModule && mode == LaunchMode.TEST) { final SourceSet testSourceSet = QuarkusGradleUtils.getSourceSet(project, SourceSet.TEST_SOURCE_SET_NAME); - workspaceModule.getSourceSet().getSourceDirectories().addAll(testSourceSet.getOutput().getClassesDirs().getFiles()); + modelSourceSet = convert(mainSourceSet, testSourceSet.getOutput().getClassesDirs().getFiles()); + } else { + modelSourceSet = convert(mainSourceSet, Collections.emptySet()); } - return workspaceModule; + return new WorkspaceModuleImpl(appArtifactCoords, + project.getProjectDir().getAbsoluteFile(), + project.getBuildDir().getAbsoluteFile(), getSourceSourceSet(mainSourceSet), modelSourceSet); } private List getEnforcedPlatforms(Project project) { @@ -440,13 +442,14 @@ private IncludedBuild includedBuild(final Project project, final String projectN } } - private SourceSetImpl convert(SourceSet sourceSet) { - Set existingSrcDirs = new HashSet<>(); + private SourceSetImpl convert(SourceSet sourceSet, Set additionalSourceDirs) { + final Set existingSrcDirs = new LinkedHashSet<>(); for (File srcDir : sourceSet.getOutput().getClassesDirs().getFiles()) { if (srcDir.exists()) { existingSrcDirs.add(srcDir); } } + existingSrcDirs.addAll(additionalSourceDirs); if (sourceSet.getOutput().getResourcesDir().exists()) { return new SourceSetImpl( existingSrcDirs, diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java index b353d0ce36b92..680e37fd3e7fb 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java @@ -8,6 +8,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -45,6 +46,7 @@ import io.quarkus.bootstrap.model.AppArtifactKey; import io.quarkus.bootstrap.model.AppDependency; import io.quarkus.bootstrap.model.AppModel; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.resolver.AppModelResolver; import io.quarkus.bootstrap.resolver.AppModelResolverException; import io.quarkus.deployment.dev.DevModeContext; @@ -360,18 +362,18 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil if (mainSourceSet == null) { return; } - Set sourcePaths = new HashSet<>(); - Set sourceParentPaths = new HashSet<>(); + Set sourcePaths = new LinkedHashSet<>(); + Set sourceParentPaths = new LinkedHashSet<>(); for (File sourceDir : mainSourceSet.getAllJava().getSrcDirs()) { if (sourceDir.exists()) { - sourcePaths.add(sourceDir.getAbsolutePath()); - sourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath().toString()); + sourcePaths.add(sourceDir.toPath().toAbsolutePath()); + sourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath()); } } - final Set resourcesSrcDirs = new HashSet<>(); + final Set resourcesSrcDirs = new LinkedHashSet<>(); for (File resourcesSrcDir : mainSourceSet.getResources().getSourceDirectories().getFiles()) { - resourcesSrcDirs.add(resourcesSrcDir.getAbsolutePath()); + resourcesSrcDirs.add(resourcesSrcDir.toPath().toAbsolutePath()); } // resourcesSrcDir may exist but if it's empty the resources output dir won't be created final File resourcesOutputDir = mainSourceSet.getOutput().getResourcesDir(); @@ -405,29 +407,29 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil DevModeContext.ModuleInfo.Builder moduleBuilder = new DevModeContext.ModuleInfo.Builder().setAppArtifactKey(key) .setName(project.getName()) .setProjectDirectory(project.getProjectDir().getAbsolutePath()) - .setSourcePaths(sourcePaths) + .setSourcePaths(PathsCollection.from(sourcePaths)) .setClassesPath(classesDir) - .setResourcePaths(resourcesSrcDirs) + .setResourcePaths(PathsCollection.from(resourcesSrcDirs)) .setResourcesOutputPath(resourcesOutputPath) - .setSourceParents(sourceParentPaths) + .setSourceParents(PathsCollection.from(sourceParentPaths)) .setPreBuildOutputDir(project.getBuildDir().toPath().resolve("generated-sources").toAbsolutePath().toString()) .setTargetDir(project.getBuildDir().toString()); SourceSet testSourceSet = sourceSets.findByName(SourceSet.TEST_SOURCE_SET_NAME); if (testSourceSet != null) { - Set testSourcePaths = new HashSet<>(); - Set testSourceParentPaths = new HashSet<>(); + Set testSourcePaths = new LinkedHashSet<>(); + Set testSourceParentPaths = new LinkedHashSet<>(); for (File sourceDir : testSourceSet.getAllJava().getSrcDirs()) { if (sourceDir.exists()) { - testSourcePaths.add(sourceDir.getAbsolutePath()); - testSourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath().toString()); + testSourcePaths.add(sourceDir.toPath().toAbsolutePath()); + testSourceParentPaths.add(sourceDir.toPath().getParent().toAbsolutePath()); } } - final Set testResourcesSrcDirs = new HashSet<>(); + final Set testResourcesSrcDirs = new LinkedHashSet<>(); for (File testResourcesSrcDir : testSourceSet.getResources().getSourceDirectories().getFiles()) { - testResourcesSrcDirs.add(testResourcesSrcDir.getAbsolutePath()); + testResourcesSrcDirs.add(testResourcesSrcDir.toPath().toAbsolutePath()); } // resourcesSrcDir may exist but if it's empty the resources output dir won't be created final File testResourcesOutputDir = testSourceSet.getOutput().getResourcesDir(); @@ -448,9 +450,9 @@ private void addLocalProject(Project project, GradleDevModeLauncher.Builder buil // currently resources dir should exist testResourcesOutputPath = testClassesDir; } - moduleBuilder.setTestSourcePaths(testSourcePaths) + moduleBuilder.setTestSourcePaths(PathsCollection.from(testSourcePaths)) .setTestClassesPath(testClassesDir) - .setTestResourcePaths(testResourcesSrcDirs) + .setTestResourcePaths(PathsCollection.from(testResourcesSrcDirs)) .setTestResourcesOutputPath(testResourcesOutputPath); } } diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java index 6ec53119ea683..e34da5d08d799 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java @@ -29,6 +29,7 @@ import io.quarkus.bootstrap.app.QuarkusBootstrap; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.bootstrap.model.AppArtifact; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.resolver.AppModelResolver; import io.quarkus.deployment.CodeGenerator; @@ -131,7 +132,7 @@ public void prepareQuarkus() { throw new GradleException("Failed to find " + INIT_AND_RUN + " method in " + CodeGenerator.class.getName()); } initAndRun.get().invoke(null, deploymentClassLoader, - sourcesDirectories, + PathsCollection.from(sourcesDirectories), paths.iterator().next(), buildDir, sourceRegistrar, diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java index b92a6cf0b9ce8..4282f489031f9 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -76,6 +77,7 @@ import io.quarkus.bootstrap.devmode.DependenciesFilter; import io.quarkus.bootstrap.model.AppArtifactKey; import io.quarkus.bootstrap.model.AppModel; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions; import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject; import io.quarkus.deployment.dev.DevModeContext; @@ -577,13 +579,13 @@ private String getSourceEncoding() { private void addProject(MavenDevModeLauncher.Builder builder, LocalProject localProject, boolean root) throws Exception { - String projectDirectory = null; - Set sourcePaths = null; + String projectDirectory; + Set sourcePaths; String classesPath = null; - Set resourcePaths; - Set testSourcePaths = null; + Set resourcePaths; + Set testSourcePaths; String testClassesPath = null; - Set testResourcePaths; + Set testResourcePaths; List activeProfiles = Collections.emptyList(); final MavenProject mavenProject = session.getProjectMap().get( @@ -592,15 +594,13 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local projectDirectory = localProject.getDir().toAbsolutePath().toString(); Path sourcePath = localProject.getSourcesSourcesDir().toAbsolutePath(); if (Files.isDirectory(sourcePath)) { - sourcePaths = Collections.singleton( - sourcePath.toString()); + sourcePaths = Collections.singleton(sourcePath); } else { sourcePaths = Collections.emptySet(); } Path testSourcePath = localProject.getTestSourcesSourcesDir().toAbsolutePath(); if (Files.isDirectory(testSourcePath)) { - testSourcePaths = Collections.singleton( - testSourcePath.toString()); + testSourcePaths = Collections.singleton(testSourcePath); } else { testSourcePaths = Collections.emptySet(); } @@ -609,13 +609,13 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local sourcePaths = mavenProject.getCompileSourceRoots().stream() .map(Paths::get) .filter(Files::isDirectory) - .map(src -> src.toAbsolutePath().toString()) - .collect(Collectors.toSet()); + .map(Path::toAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)); testSourcePaths = mavenProject.getTestCompileSourceRoots().stream() .map(Paths::get) .filter(Files::isDirectory) - .map(src -> src.toAbsolutePath().toString()) - .collect(Collectors.toSet()); + .map(Path::toAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)); activeProfiles = mavenProject.getActiveProfiles(); } Path sourceParent = localProject.getSourcesDir().toAbsolutePath(); @@ -628,14 +628,12 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local if (Files.isDirectory(testClassesDir)) { testClassesPath = testClassesDir.toAbsolutePath().toString(); } - resourcePaths = localProject.getResourcesSourcesDirs().stream() - .filter(Files::isDirectory) - .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) - .collect(Collectors.toSet()); - testResourcePaths = localProject.getTestResourcesSourcesDirs().stream() - .filter(Files::isDirectory) - .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) - .collect(Collectors.toSet()); + resourcePaths = localProject.getResourcesSourcesDirs().toList().stream() + .map(Path::toAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)); + testResourcePaths = localProject.getTestResourcesSourcesDirs().toList().stream() + .map(Path::toAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)); // Add the resources and test resources from the profiles for (Profile profile : activeProfiles) { final BuildBase build = profile.getBuild(); @@ -644,13 +642,13 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local build.getResources().stream() .map(Resource::getDirectory) .map(localProject::resolveRelativeToBaseDir) - .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .map(Path::toAbsolutePath) .collect(Collectors.toList())); testResourcePaths.addAll( build.getTestResources().stream() .map(Resource::getDirectory) .map(localProject::resolveRelativeToBaseDir) - .map(resourcesSourcesDir -> resourcesSourcesDir.toAbsolutePath().toString()) + .map(Path::toAbsolutePath) .collect(Collectors.toList())); } } @@ -665,18 +663,17 @@ private void addProject(MavenDevModeLauncher.Builder builder, LocalProject local DevModeContext.ModuleInfo moduleInfo = new DevModeContext.ModuleInfo.Builder().setAppArtifactKey(localProject.getKey()) .setName(localProject.getArtifactId()) .setProjectDirectory(projectDirectory) - .setSourcePaths(sourcePaths) + .setSourcePaths(PathsCollection.from(sourcePaths)) .setClassesPath(classesPath) .setResourcesOutputPath(classesPath) - .setResourcePaths(resourcePaths) - .setSourceParents(Collections.singleton(sourceParent.toAbsolutePath().toString())) + .setResourcePaths(PathsCollection.from(resourcePaths)) + .setSourceParents(PathsCollection.of(sourceParent.toAbsolutePath())) .setPreBuildOutputDir(targetDir.resolve("generated-sources").toAbsolutePath().toString()) .setTargetDir(targetDir.toAbsolutePath().toString()) - .setTestSourcePaths(testSourcePaths) + .setTestSourcePaths(PathsCollection.from(testSourcePaths)) .setTestClassesPath(testClassesPath) - .setTestResourcePaths(testResourcePaths) .setTestResourcesOutputPath(testClassesPath) - .setTestResourcePaths(testResourcePaths) + .setTestResourcePaths(PathsCollection.from(testResourcePaths)) .build(); if (root) { diff --git a/devtools/maven/src/main/java/io/quarkus/maven/GenerateCodeMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/GenerateCodeMojo.java index cb7bd5159d0da..cd72420cce4eb 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/GenerateCodeMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/GenerateCodeMojo.java @@ -3,9 +3,7 @@ import java.lang.reflect.Method; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collections; import java.util.Map; -import java.util.Set; import java.util.function.Consumer; import org.apache.maven.plugin.MojoExecutionException; @@ -18,6 +16,7 @@ import io.quarkus.bootstrap.app.CuratedApplication; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.bootstrap.model.AppModel; +import io.quarkus.bootstrap.model.PathsCollection; @Mojo(name = "generate-code", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true) public class GenerateCodeMojo extends QuarkusBootstrapMojo { @@ -61,11 +60,12 @@ void generateCode(Path sourcesDir, Thread.currentThread().setContextClassLoader(deploymentClassLoader); final Class codeGenerator = deploymentClassLoader.loadClass("io.quarkus.deployment.CodeGenerator"); - final Method initAndRun = codeGenerator.getMethod("initAndRun", ClassLoader.class, Set.class, Path.class, + final Method initAndRun = codeGenerator.getMethod("initAndRun", ClassLoader.class, PathsCollection.class, + Path.class, Path.class, Consumer.class, AppModel.class, Map.class); initAndRun.invoke(null, deploymentClassLoader, - Collections.singleton(sourcesDir), + PathsCollection.of(sourcesDir), generatedSourcesDir(test), buildDir().toPath(), sourceRegistrar, diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/configproperties/ConfigPropertiesBuildStep.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/configproperties/ConfigPropertiesBuildStep.java index 7f2245e2e822a..0130f1f64b01c 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/configproperties/ConfigPropertiesBuildStep.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/configproperties/ConfigPropertiesBuildStep.java @@ -49,7 +49,6 @@ void produceConfigPropertiesMetadata(CombinedIndexBuildItem combinedIndex, ArcCo Map failOnMismatchingMembers = new HashMap<>(); // handle @ConfigProperties - final Set excludedDeclaringClasses = exclusionsBuildItem.getExcludedDeclaringClasses(); for (AnnotationInstance instance : index.getAnnotations(DotNames.CONFIG_PROPERTIES)) { final AnnotationTarget target = instance.target(); if (exclusionsBuildItem.isExcluded(target)) { diff --git a/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinCompilationProvider.java b/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinCompilationProvider.java index ea7340edf98de..18633f295c9e1 100644 --- a/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinCompilationProvider.java +++ b/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinCompilationProvider.java @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import org.jetbrains.kotlin.config.Services; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.deployment.dev.CompilationProvider; public class KotlinCompilationProvider implements CompilationProvider { @@ -87,7 +88,7 @@ public void compile(Set filesToCompile, Context context) { } @Override - public Path getSourcePath(Path classFilePath, Set sourcePaths, String classesPath) { + public Path getSourcePath(Path classFilePath, PathsCollection sourcePaths, String classesPath) { // return same class so it is not removed return classFilePath; } diff --git a/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaCompilationProvider.java b/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaCompilationProvider.java index f5edd1faf09e4..0e4f32e03d3ef 100644 --- a/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaCompilationProvider.java +++ b/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaCompilationProvider.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.stream.Collectors; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.deployment.dev.CompilationProvider; import scala.collection.JavaConverters; import scala.tools.nsc.Global; @@ -35,7 +36,7 @@ public void compile(Set files, Context context) { } @Override - public Path getSourcePath(Path classFilePath, Set sourcePaths, String classesPath) { + public Path getSourcePath(Path classFilePath, PathsCollection sourcePaths, String classesPath) { return classFilePath; } } diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/PathsCollection.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/PathsCollection.java index 0304215f60362..3278df65e263c 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/PathsCollection.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/PathsCollection.java @@ -12,20 +12,87 @@ import java.util.Iterator; import java.util.List; -public class PathsCollection implements Iterable, Serializable { - - public static PathsCollection from(Iterable paths) { +/** + * A specific collection meant to be used to manipulate {@code Path}s. + */ +public interface PathsCollection extends Iterable { + + /** + * @return {@code true} if the collection is empty, {@code false} otherwise. + */ + boolean isEmpty(); + + /** + * @return the size of the collection id paths. + */ + int size(); + + /** + * @return {@code true} if the collection contains one path. {@code false} otherwise. + */ + boolean isSinglePath(); + + /** + * @return the only path that could be found into the collection. + * @throws IllegalStateException if there is no path or there are more than one paths into the collection. + */ + Path getSinglePath(); + + /** + * @param path the path to check. + * @return {@code true} if the collection contains the given path, {@code false} otherwise. + */ + boolean contains(Path path); + + /** + * Appends the given paths to the collection. + * + * @param paths the paths to append. + * @return a new collection with the appended paths. + */ + PathsCollection add(Path... paths); + + /** + * Adds the given paths at the beginning of the collection + * + * @param paths the paths to add. + * @return a new collection with the added paths. + */ + PathsCollection addFirst(Path... paths); + + /** + * Adds the given paths at the beginning of the collection + * + * @param paths the paths to add. + * @return a new collection with the added paths. + */ + PathsCollection addAllFirst(Iterable paths); + + /** + * Gives a path of the collection for which a file could found at the given relative location. + * + * @param path the relative location for which we want to find a matching root path. + * @return the root path of the collection that could match with the given location, {@code null} otherwise. + */ + Path resolveExistingOrNull(String path); + + /** + * @return the content of the collection as a {@link List}. + */ + Collection toList(); + + static PathsCollection from(Iterable paths) { final List list = new ArrayList<>(); paths.forEach(list::add); - return new PathsCollection(list); + return new Default(list); } - public static PathsCollection of(Path... paths) { - return new PathsCollection(Arrays.asList(paths)); + static PathsCollection of(Path... paths) { + return new Default(Arrays.asList(paths)); } - public static class Builder { - private List paths = new ArrayList<>(); + class Builder { + private final List paths = new ArrayList<>(); private Builder() { } @@ -40,108 +107,117 @@ public boolean contains(Path p) { } public PathsCollection build() { - return new PathsCollection(paths); + return new Default(paths); } } - public static Builder builder() { + static Builder builder() { return new Builder(); } - private List paths; + class Default implements PathsCollection, Serializable { + private List paths; - private PathsCollection(List paths) { - this.paths = Collections.unmodifiableList(paths); - } + private Default(List paths) { + this.paths = Collections.unmodifiableList(paths); + } - public boolean isEmpty() { - return paths.isEmpty(); - } + @Override + public boolean isEmpty() { + return paths.isEmpty(); + } - public int size() { - return paths.size(); - } + @Override + public int size() { + return paths.size(); + } - public boolean isSinglePath() { - return paths.size() == 1; - } + @Override + public boolean isSinglePath() { + return paths.size() == 1; + } - public Path getSinglePath() { - if (paths.size() != 1) { - throw new IllegalStateException("Paths collection expected to contain a single path but contains " + paths.size()); + @Override + public Path getSinglePath() { + if (paths.size() != 1) { + throw new IllegalStateException( + "Paths collection expected to contain a single path but contains " + paths.size()); + } + return paths.get(0); } - return paths.get(0); - } - @Override - public Iterator iterator() { - return paths.iterator(); - } + @Override + public Iterator iterator() { + return paths.iterator(); + } - public boolean contains(Path path) { - return paths.contains(path); - } + @Override + public boolean contains(Path path) { + return paths.contains(path); + } - public PathsCollection add(Path... paths) { - final List list = new ArrayList<>(this.paths.size() + paths.length); - list.addAll(this.paths); - for (int i = 0; i < paths.length; ++i) { - list.add(paths[i]); + @Override + public PathsCollection add(Path... paths) { + final List list = new ArrayList<>(this.paths.size() + paths.length); + list.addAll(this.paths); + list.addAll(Arrays.asList(paths)); + return new Default(list); } - return new PathsCollection(list); - } - public PathsCollection addFirst(Path... paths) { - final List list = new ArrayList<>(this.paths.size() + paths.length); - for (int i = 0; i < paths.length; ++i) { - list.add(paths[i]); + @Override + public PathsCollection addFirst(Path... paths) { + final List list = new ArrayList<>(this.paths.size() + paths.length); + list.addAll(Arrays.asList(paths)); + list.addAll(this.paths); + return new Default(list); } - list.addAll(this.paths); - return new PathsCollection(list); - } - public PathsCollection addAllFirst(Iterable i) { - final List list = new ArrayList<>(); - i.forEach(list::add); - paths.forEach(list::add); - return new PathsCollection(list); - } + @Override + public PathsCollection addAllFirst(Iterable i) { + final List list = new ArrayList<>(); + i.forEach(list::add); + list.addAll(paths); + return new Default(list); + } - public Path resolveExistingOrNull(String path) { - for (Path p : paths) { - final Path resolved = p.resolve(path); - if (Files.exists(resolved)) { - return resolved; + @Override + public Path resolveExistingOrNull(String path) { + for (Path p : paths) { + final Path resolved = p.resolve(path); + if (Files.exists(resolved)) { + return resolved; + } } + return null; } - return null; - } - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - buf.append("[paths: "); - forEach(p -> buf.append(p).append(';')); - return buf.append(']').toString(); - } + @Override + public Collection toList() { + return new ArrayList<>(paths); + } - private void writeObject(java.io.ObjectOutputStream out) throws IOException { - out.writeInt(paths.size()); - for (Path p : paths) { - out.writeUTF(p.toAbsolutePath().toString()); + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("[paths: "); + forEach(p -> buf.append(p).append(';')); + return buf.append(']').toString(); } - } - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { - final int pathsTotal = in.readInt(); - List paths = new ArrayList<>(pathsTotal); - for (int i = 0; i < pathsTotal; ++i) { - paths.add(Paths.get(in.readUTF())); + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.writeInt(paths.size()); + for (Path p : paths) { + out.writeUTF(p.toAbsolutePath().toString()); + } } - this.paths = Collections.unmodifiableList(paths); - } - public Collection toList() { - return new ArrayList<>(paths); + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + final int pathsTotal = in.readInt(); + List paths = new ArrayList<>(pathsTotal); + for (int i = 0; i < pathsTotal; ++i) { + paths.add(Paths.get(in.readUTF())); + } + this.paths = Collections.unmodifiableList(paths); + } } } diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java index ddb6cb24965de..a8d6670f5a81f 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/SourceSet.java @@ -1,11 +1,10 @@ package io.quarkus.bootstrap.model.gradle; -import java.io.File; -import java.util.Set; +import io.quarkus.bootstrap.model.PathsCollection; public interface SourceSet { - Set getSourceDirectories(); + PathsCollection getSourceDirectories(); - Set getResourceDirectories(); + PathsCollection getResourceDirectories(); } diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java index 450968fb38a6a..b562e2cbe9b58 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/gradle/impl/SourceSetImpl.java @@ -1,47 +1,48 @@ package io.quarkus.bootstrap.model.gradle.impl; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.model.gradle.SourceSet; import java.io.File; import java.io.Serializable; -import java.util.HashSet; +import java.nio.file.Path; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; public class SourceSetImpl implements SourceSet, Serializable { - private final Set sourceDirectories = new HashSet<>(); - // Use a LinkedHashSet to keep the original order - private final Set resourceDirectories = new LinkedHashSet<>(); + private final PathsCollection sourceDirectories; + private final PathsCollection resourceDirectories; public SourceSetImpl(Set sourceDirectories, Set resourceDirectories) { - this.sourceDirectories.addAll(sourceDirectories); - this.resourceDirectories.addAll(resourceDirectories); + this.sourceDirectories = PathsCollection + .from(sourceDirectories.stream().map(File::toPath).collect(Collectors.toCollection(LinkedHashSet::new))); + this.resourceDirectories = PathsCollection + .from(resourceDirectories.stream().map(File::toPath).collect(Collectors.toCollection(LinkedHashSet::new))); } public SourceSetImpl(Set sourceDirectories) { - this.sourceDirectories.addAll(sourceDirectories); - } - - public void addSourceDirectories(Set files) { - sourceDirectories.addAll(files); + this(sourceDirectories, Collections.emptySet()); } @Override - public Set getSourceDirectories() { + public PathsCollection getSourceDirectories() { return sourceDirectories; } @Override - public Set getResourceDirectories() { + public PathsCollection getResourceDirectories() { return resourceDirectories; } @Override public String toString() { return "SourceSetImpl{" + - "sourceDirectories=" + sourceDirectories.stream().map(File::getPath).collect(Collectors.joining(":")) + - ", resourceDirectories=" + resourceDirectories.stream().map(File::getPath).collect(Collectors.joining(":")) + + "sourceDirectories=" + sourceDirectories.toList().stream().map(Path::toString).collect(Collectors.joining(":")) + + + ", resourceDirectories=" + + resourceDirectories.toList().stream().map(Path::toString).collect(Collectors.joining(":")) + '}'; } } diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java index ece8773b62877..fda5b2bfe47e4 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/IDELauncherImpl.java @@ -52,10 +52,10 @@ public static Closeable launch(Path classesDir, Map context) { for (WorkspaceModule additionalModule : quarkusModel.getWorkspace().getAllModules()) { if (!additionalModule.getArtifactCoords().equals(launchingModule.getArtifactCoords())) { builder.addAdditionalApplicationArchive(new AdditionalDependency( - QuarkusModelHelper.toPathsCollection(additionalModule.getSourceSet().getSourceDirectories()), + additionalModule.getSourceSet().getSourceDirectories(), true, false)); builder.addAdditionalApplicationArchive(new AdditionalDependency( - QuarkusModelHelper.toPathsCollection(additionalModule.getSourceSet().getResourceDirectories()), + additionalModule.getSourceSet().getResourceDirectories(), true, false)); } } diff --git a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java index 65cd15085e4d1..91ab2c0e9befe 100644 --- a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java +++ b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/util/QuarkusModelHelper.java @@ -88,8 +88,9 @@ public static QuarkusModel deserializeQuarkusModel(Path modelPath) throws Bootst public static Path getClassPath(WorkspaceModule model) throws BootstrapGradleException { // TODO handle multiple class directory - final Optional classDir = model.getSourceSet().getSourceDirectories().stream().filter(File::exists) - .map(File::toPath).findFirst(); + final Optional classDir = model.getSourceSet().getSourceDirectories().toList().stream() + .filter(Files::exists) + .findFirst(); if (!classDir.isPresent()) { throw new BootstrapGradleException("Failed to locate class directory"); } @@ -143,13 +144,12 @@ public static AppModel convert(QuarkusModel model, AppArtifact appArtifact) thro if (!appArtifact.isResolved()) { PathsCollection.Builder paths = PathsCollection.builder(); WorkspaceModule module = model.getWorkspace().getMainModule(); - module.getSourceSet().getSourceDirectories().stream().filter(File::exists).map(File::toPath) + module.getSourceSet().getSourceDirectories().toList().stream() + .filter(Files::exists) + .forEach(paths::add); + module.getSourceSet().getResourceDirectories().toList().stream() + .filter(Files::exists) .forEach(paths::add); - for (File resourceDirectory : module.getSourceSet().getResourceDirectories()) { - if (resourceDirectory.exists()) { - paths.add(resourceDirectory.toPath()); - } - } appArtifact.setPaths(paths.build()); } diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java index 82cf271df6798..30b2048e3856b 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java @@ -2,6 +2,7 @@ import io.quarkus.bootstrap.model.AppArtifact; import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext; import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException; import java.io.IOException; @@ -10,8 +11,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import org.apache.maven.model.Build; @@ -230,28 +231,28 @@ public Path getSourcesDir() { return getSourcesSourcesDir().getParent(); } - public Set getResourcesSourcesDirs() { + public PathsCollection getResourcesSourcesDirs() { final List resources = rawModel.getBuild() == null ? Collections.emptyList() : rawModel.getBuild().getResources(); if (resources.isEmpty()) { - return Collections.singleton(resolveRelativeToBaseDir(null, "src/main/resources")); + return PathsCollection.of(resolveRelativeToBaseDir(null, "src/main/resources")); } - return resources.stream() + return PathsCollection.from(resources.stream() .map(Resource::getDirectory) .map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/main/resources")) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new))); } - public Set getTestResourcesSourcesDirs() { + public PathsCollection getTestResourcesSourcesDirs() { final List resources = rawModel.getBuild() == null ? Collections.emptyList() : rawModel.getBuild().getTestResources(); if (resources.isEmpty()) { - return Collections.singleton(resolveRelativeToBaseDir(null, "src/test/resources")); + return PathsCollection.of(resolveRelativeToBaseDir(null, "src/test/resources")); } - return resources.stream() + return PathsCollection.from(resources.stream() .map(Resource::getDirectory) .map(resourcesDir -> resolveRelativeToBaseDir(resourcesDir, "src/test/resources")) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new))); } public ModelBuildingResult getModelBuildingResult() { diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java index b9ddb97b814ae..34b1e417b1904 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalWorkspace.java @@ -161,7 +161,7 @@ private Path emptyJarOutput(LocalProject lp, Artifact artifact) { // so the Maven resolver will succeed resolving it from the repo. // If the artifact does not exist in the local repo, we are creating an empty classes directory in the target directory. if (!Files.exists(lp.getSourcesSourcesDir()) - && lp.getResourcesSourcesDirs().stream().noneMatch(Files::exists) + && lp.getResourcesSourcesDirs().toList().stream().noneMatch(Files::exists) && !isFoundInLocalRepo(artifact)) { try { final Path classesDir = lp.getClassesDir(); diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java index c24fefc09813e..ca01a9a7eaf78 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java @@ -73,12 +73,14 @@ private void assertWorkspace(WorkspaceModule workspaceModule, File projectDir) { final SourceSet sourceSet = workspaceModule.getSourceSet(); assertNotNull(sourceSet); assertTrue(sourceSet.getResourceDirectories().isEmpty()); - assertThat(sourceSet.getSourceDirectories()).containsAnyOf(new File(projectDir, "build/classes/java/main"), - new File(projectDir, "build/classes/java/test")); + assertThat(sourceSet.getSourceDirectories().toList()).containsAnyOf( + new File(projectDir, "build/classes/java/main").toPath(), + new File(projectDir, "build/classes/java/test").toPath()); final SourceSet sourceSourceSet = workspaceModule.getSourceSourceSet(); - assertThat(sourceSourceSet.getResourceDirectories()).containsAnyOf(new File(projectDir, "src/main/resources")); + assertThat(sourceSourceSet.getResourceDirectories().toList()) + .containsAnyOf(new File(projectDir, "src/main/resources").toPath()); assertEquals(5, sourceSourceSet.getSourceDirectories().size()); - assertThat(sourceSourceSet.getSourceDirectories()).contains(new File(projectDir, "src/main/java")); + assertThat(sourceSourceSet.getSourceDirectories().toList()).contains(new File(projectDir, "src/main/java").toPath()); } private File getResourcesProject(String projectName) throws URISyntaxException, IOException { diff --git a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep b/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep deleted file mode 100644 index 8a0a8385da974..0000000000000 --- a/integration-tests/maven/src/test/resources/projects/dev-mode-multiple-resource-dirs/src/main/resources-secondary/.keep +++ /dev/null @@ -1 +0,0 @@ -# Just to be able to commit this empty folder needed for the test diff --git a/test-framework/jacoco/deployment/src/main/java/io/quarkus/jacoco/deployment/JacocoProcessor.java b/test-framework/jacoco/deployment/src/main/java/io/quarkus/jacoco/deployment/JacocoProcessor.java index 542bd12ef094e..32d51e5b67033 100644 --- a/test-framework/jacoco/deployment/src/main/java/io/quarkus/jacoco/deployment/JacocoProcessor.java +++ b/test-framework/jacoco/deployment/src/main/java/io/quarkus/jacoco/deployment/JacocoProcessor.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import java.util.HashSet; @@ -130,12 +131,12 @@ public byte[] apply(String className, byte[] bytes) { QuarkusModel model = BuildToolHelper.enableGradleAppModelForDevMode(targetdir.toPath()); for (WorkspaceModule i : model.getWorkspace().getAllModules()) { info.savedData.add(new File(i.getBuildDir(), config.dataFile).getAbsolutePath()); - for (File src : i.getSourceSourceSet().getSourceDirectories()) { - sources.add(src.getAbsolutePath()); + for (Path src : i.getSourceSourceSet().getSourceDirectories()) { + sources.add(src.toAbsolutePath().toString()); } - for (File classesDir : i.getSourceSet().getSourceDirectories()) { - if (classesDir.isDirectory()) { - for (final File file : FileUtils.getFiles(classesDir, includes, excludes, + for (Path classesDir : i.getSourceSet().getSourceDirectories()) { + if (Files.isDirectory(classesDir)) { + for (final File file : FileUtils.getFiles(classesDir.toFile(), includes, excludes, true)) { if (file.getName().endsWith(".class")) { classes.add(file.getAbsolutePath()); diff --git a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java index 47ce1c26d7a8d..2a71daa94ac94 100644 --- a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java +++ b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java @@ -46,6 +46,7 @@ import org.junit.jupiter.api.extension.TestInstantiationException; import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.bootstrap.model.PathsCollection; import io.quarkus.bootstrap.util.ZipUtils; import io.quarkus.deployment.dev.CompilationProvider; import io.quarkus.deployment.dev.DevModeContext; @@ -335,11 +336,11 @@ private DevModeContext exportArchive(Path deploymentDir, Path testSourceDir, Pat .setAppArtifactKey(AppArtifactKey.fromString("io.quarkus.test:app-under-test")) .setName("default") .setProjectDirectory(deploymentDir.toAbsolutePath().toString()) - .setSourcePaths(Collections.singleton(deploymentSourcePath.toAbsolutePath().toString())) + .setSourcePaths(PathsCollection.of(deploymentSourcePath.toAbsolutePath())) .setClassesPath(classes.toAbsolutePath().toString()) - .setResourcePaths(Collections.singleton(deploymentResourcePath.toAbsolutePath().toString())) + .setResourcePaths(PathsCollection.of(deploymentResourcePath.toAbsolutePath())) .setResourcesOutputPath(classes.toAbsolutePath().toString()) - .setSourceParents(Collections.singleton(deploymentSourceParentPath.toAbsolutePath().toString())) + .setSourceParents(PathsCollection.of(deploymentSourceParentPath.toAbsolutePath())) .setPreBuildOutputDir(targetDir.resolve("generated-sources").toAbsolutePath().toString()) .setTargetDir(targetDir.toAbsolutePath().toString()); @@ -384,9 +385,9 @@ private DevModeContext exportArchive(Path deploymentDir, Path testSourceDir, Pat }); } moduleBuilder - .setTestSourcePaths(Collections.singleton(deploymentTestSourcePath.toAbsolutePath().toString())) + .setTestSourcePaths(PathsCollection.of(deploymentTestSourcePath.toAbsolutePath())) .setTestClassesPath(testClasses.toAbsolutePath().toString()) - .setTestResourcePaths(Collections.singleton(deploymentTestResourcePath.toAbsolutePath().toString())) + .setTestResourcePaths(PathsCollection.of(deploymentTestResourcePath.toAbsolutePath())) .setTestResourcesOutputPath(testClasses.toAbsolutePath().toString()); } @@ -775,7 +776,7 @@ private void copyFromSource(Path projectSourcesDir, Path deploymentSourcesDir, P private Path copySourceFilesForClass(Path projectSourcesDir, Path deploymentSourcesDir, Path classesDir, Path classFile) { for (CompilationProvider provider : compilationProviders) { Path source = provider.getSourcePath(classFile, - Collections.singleton(projectSourcesDir.toAbsolutePath().toString()), + PathsCollection.of(projectSourcesDir.toAbsolutePath()), classesDir.toAbsolutePath().toString()); if (source != null) { String relative = projectSourcesDir.relativize(source).toString(); @@ -797,7 +798,7 @@ private Path findTargetSourceFilesForPath(Path projectSourcesDir, Path deploymen Path classFile) { for (CompilationProvider provider : compilationProviders) { Path source = provider.getSourcePath(classFile, - Collections.singleton(projectSourcesDir.toAbsolutePath().toString()), + PathsCollection.of(projectSourcesDir.toAbsolutePath()), classesDir.toAbsolutePath().toString()); if (source != null) { String relative = projectSourcesDir.relativize(source).toString(); diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java index b66ec31a131b7..c01bb57fea312 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java @@ -184,11 +184,11 @@ static Map handleDevDb(ExtensionContext context) throws Exceptio if (System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null) { QuarkusModel model = BuildToolHelper.enableGradleAppModelForTest(projectRoot); if (model != null) { - final Set classDirectories = model.getWorkspace().getMainModule().getSourceSet() + final PathsCollection classDirectories = model.getWorkspace().getMainModule().getSourceSet() .getSourceDirectories(); - for (File classes : classDirectories) { - if (classes.exists() && !rootBuilder.contains(classes.toPath())) { - rootBuilder.add(classes.toPath()); + for (Path classes : classDirectories) { + if (Files.exists(classes) && !rootBuilder.contains(classes)) { + rootBuilder.add(classes); } } } diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java index a1ec93a87d9d6..44851fdda0b46 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java @@ -4,7 +4,6 @@ import static io.quarkus.test.common.PathTestHelper.getTestClassesLocation; import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.management.ManagementFactory; @@ -276,11 +275,11 @@ private ExtensionState doJavaStart(ExtensionContext context, Class classDirectories = model.getWorkspace().getMainModule().getSourceSet() + final PathsCollection classDirectories = model.getWorkspace().getMainModule().getSourceSet() .getSourceDirectories(); - for (File classes : classDirectories) { - if (classes.exists() && !rootBuilder.contains(classes.toPath())) { - rootBuilder.add(classes.toPath()); + for (Path classes : classDirectories) { + if (Files.exists(classes) && !rootBuilder.contains(classes)) { + rootBuilder.add(classes); } } }