use of io.quarkus.paths.PathCollection in project quarkus by quarkusio.
the class RuntimeUpdatesProcessor method checkForFileChange.
Set<String> checkForFileChange(Function<DevModeContext.ModuleInfo, DevModeContext.CompilationUnit> cuf, TimestampSet timestampSet) {
Set<String> ret = new HashSet<>();
for (DevModeContext.ModuleInfo module : context.getAllModules()) {
DevModeContext.CompilationUnit compilationUnit = cuf.apply(module);
if (compilationUnit == null) {
continue;
}
final Set<Path> moduleResources = correspondingResources.computeIfAbsent(compilationUnit, m -> Collections.newSetFromMap(new ConcurrentHashMap<>()));
boolean doCopy = true;
PathCollection rootPaths = compilationUnit.getResourcePaths();
String outputPath = compilationUnit.getResourcesOutputPath();
if (rootPaths.isEmpty()) {
String rootPath = compilationUnit.getClassesPath();
if (rootPath != null) {
rootPaths = PathList.of(Paths.get(rootPath));
}
outputPath = rootPath;
doCopy = false;
}
if (rootPaths.isEmpty() || outputPath == null) {
continue;
}
Path outputDir = Paths.get(outputPath);
final List<Path> roots = rootPaths.stream().filter(Files::exists).filter(Files::isReadable).collect(Collectors.toList());
// copy all modified non hot deployment files over
if (doCopy) {
final Set<Path> seen = new HashSet<>(moduleResources);
try {
for (Path root : roots) {
// since the stream is Closeable, use a try with resources so the underlying iterator is closed
try (final Stream<Path> 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);
}
});
}
}
for (Path i : seen) {
moduleResources.remove(i);
if (!Files.isDirectory(i)) {
Files.delete(i);
}
}
} catch (IOException e) {
log.error("Failed to copy resources", e);
}
}
for (String path : timestampSet.watchedFilePaths.keySet()) {
boolean pathCurrentlyExisting = false;
boolean pathPreviouslyExisting = false;
for (Path root : roots) {
Path file = root.resolve(path);
if (file.toFile().exists()) {
pathCurrentlyExisting = true;
try {
long value = Files.getLastModifiedTime(file).toMillis();
Long existing = timestampSet.watchedFileTimestamps.get(file);
// as there is both normal and test resources, but only one set of watched timestampts
if (existing != null && value > existing) {
ret.add(path);
// if the file is empty we may be seeing the middle of a write
if (Files.size(file) == 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// ignore
}
}
// re-read, as we may have read the original TS if the middle of
// a truncate+write, even if the write had completed by the time
// we read the size
value = Files.getLastModifiedTime(file).toMillis();
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);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} else {
Long prevValue = timestampSet.watchedFileTimestamps.put(file, 0L);
pathPreviouslyExisting = pathPreviouslyExisting || (prevValue != null && prevValue > 0);
}
}
if (!pathCurrentlyExisting) {
if (pathPreviouslyExisting) {
ret.add(path);
}
Path target = outputDir.resolve(path);
try {
FileUtil.deleteIfExists(target);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
// Mostly a copy of the code above but to handle watched files that are set with absolute path (not in the app resources)
for (String watchedFilePath : timestampSet.watchedFilePaths.keySet()) {
Path watchedFile = Paths.get(watchedFilePath);
if (watchedFile.isAbsolute()) {
if (watchedFile.toFile().exists()) {
try {
long value = Files.getLastModifiedTime(watchedFile).toMillis();
Long existing = timestampSet.watchedFileTimestamps.get(watchedFile);
// as there is both normal and test resources, but only one set of watched timestampts
if (existing != null && value > existing) {
ret.add(watchedFilePath);
// if the file is empty we may be seeing the middle of a write
if (Files.size(watchedFile) == 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// ignore
}
}
// re-read, as we may have read the original TS if the middle of
// a truncate+write, even if the write had completed by the time
// we read the size
value = Files.getLastModifiedTime(watchedFile).toMillis();
log.infof("File change detected: %s", watchedFile);
timestampSet.watchedFileTimestamps.put(watchedFile, value);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} else {
Long prevValue = timestampSet.watchedFileTimestamps.put(watchedFile, 0L);
if (prevValue != null && prevValue > 0) {
ret.add(watchedFilePath);
}
}
}
}
}
return ret;
}
use of io.quarkus.paths.PathCollection in project quarkus by quarkusio.
the class RuntimeUpdatesProcessor method setWatchedFilePathsInternal.
private RuntimeUpdatesProcessor setWatchedFilePathsInternal(Map<String, Boolean> watchedFilePaths, TimestampSet timestamps, Function<DevModeContext.ModuleInfo, List<DevModeContext.CompilationUnit>> cuf) {
timestamps.watchedFilePaths = watchedFilePaths;
Map<String, Boolean> extraWatchedFilePaths = new HashMap<>();
for (DevModeContext.ModuleInfo module : context.getAllModules()) {
List<DevModeContext.CompilationUnit> compilationUnits = cuf.apply(module);
for (DevModeContext.CompilationUnit unit : compilationUnits) {
PathCollection rootPaths = unit.getResourcePaths();
if (rootPaths.isEmpty()) {
String rootPath = unit.getClassesPath();
if (rootPath == null) {
continue;
}
rootPaths = PathList.of(Path.of(rootPath));
}
for (Path root : rootPaths) {
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<Path, Long> 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.watchedFilePaths.putAll(extraWatchedFilePaths);
return this;
}
use of io.quarkus.paths.PathCollection in project quarkus by quarkusio.
the class QuarkusAugmentor method run.
public BuildResult run() throws Exception {
if (!JavaVersionUtil.isJava11OrHigher()) {
throw new IllegalStateException("Quarkus applications require Java 11 or higher to build");
}
long time = System.currentTimeMillis();
log.debug("Beginning Quarkus augmentation");
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
QuarkusBuildCloseablesBuildItem buildCloseables = new QuarkusBuildCloseablesBuildItem();
try {
Thread.currentThread().setContextClassLoader(deploymentClassLoader);
final BuildChainBuilder chainBuilder = BuildChain.builder();
chainBuilder.setClassLoader(deploymentClassLoader);
// provideCapabilities(chainBuilder);
// TODO: we load everything from the deployment class loader
// this allows the deployment config (application.properties) to be loaded, but in theory could result
// in additional stuff from the deployment leaking in, this is unlikely but has a bit of a smell.
ExtensionLoader.loadStepsFrom(deploymentClassLoader, buildSystemProperties == null ? new Properties() : buildSystemProperties, effectiveModel, launchMode, devModeType).accept(chainBuilder);
Thread.currentThread().setContextClassLoader(classLoader);
chainBuilder.loadProviders(classLoader);
chainBuilder.addInitial(QuarkusBuildCloseablesBuildItem.class).addInitial(ArchiveRootBuildItem.class).addInitial(ShutdownContextBuildItem.class).addInitial(RawCommandLineArgumentsBuildItem.class).addInitial(LaunchModeBuildItem.class).addInitial(LiveReloadBuildItem.class).addInitial(AdditionalApplicationArchiveBuildItem.class).addInitial(CuratedApplicationShutdownBuildItem.class).addInitial(BuildSystemTargetBuildItem.class).addInitial(AppModelProviderBuildItem.class);
for (Class<? extends BuildItem> i : finalResults) {
chainBuilder.addFinal(i);
}
for (Consumer<BuildChainBuilder> i : buildChainCustomizers) {
i.accept(chainBuilder);
}
if (launchMode.isDevOrTest()) {
chainBuilder.addFinal(RuntimeApplicationShutdownBuildItem.class);
}
final ArchiveRootBuildItem.Builder rootBuilder = ArchiveRootBuildItem.builder();
if (root != null) {
rootBuilder.addArchiveRoots(root);
}
rootBuilder.setExcludedFromIndexing(excludedFromIndexing);
BuildChain chain = chainBuilder.build();
BuildExecutionBuilder execBuilder = chain.createExecutionBuilder("main").produce(buildCloseables).produce(liveReloadBuildItem).produce(rootBuilder.build(buildCloseables)).produce(new ShutdownContextBuildItem()).produce(new RawCommandLineArgumentsBuildItem()).produce(new CuratedApplicationShutdownBuildItem((QuarkusClassLoader) deploymentClassLoader.getParent(), !liveReloadBuildItem.isLiveReload())).produce(new LaunchModeBuildItem(launchMode, devModeType == null ? Optional.empty() : Optional.of(devModeType), auxiliaryApplication, auxiliaryDevModeType, test)).produce(new BuildSystemTargetBuildItem(targetDir, baseName, rebuild, buildSystemProperties == null ? new Properties() : buildSystemProperties)).produce(new AppModelProviderBuildItem(effectiveModel));
for (PathCollection i : additionalApplicationArchives) {
execBuilder.produce(new AdditionalApplicationArchiveBuildItem(i));
}
BuildResult buildResult = execBuilder.execute();
String message = "Quarkus augmentation completed in " + (System.currentTimeMillis() - time) + "ms";
if (launchMode == LaunchMode.NORMAL) {
log.info(message);
} else {
// test and dev mode already report the total startup time, no need to add noise to the logs
log.debug(message);
}
return buildResult;
} finally {
try {
ConfigProviderResolver.instance().releaseConfig(ConfigProviderResolver.instance().getConfig(deploymentClassLoader));
} catch (Exception ignore) {
}
if (deploymentClassLoader instanceof Closeable) {
((Closeable) deploymentClassLoader).close();
}
Thread.currentThread().setContextClassLoader(originalClassLoader);
buildCloseables.close();
}
}
use of io.quarkus.paths.PathCollection in project quarkus by quarkusio.
the class GradleApplicationModelBuilder method collectDependencies.
private void collectDependencies(org.gradle.api.artifacts.ResolvedDependency resolvedDep, LaunchMode mode, Project project, Map<ArtifactKey, ResolvedDependencyBuilder> appDependencies, Set<File> artifactFiles, Set<ArtifactKey> processedModules, ApplicationModelBuilder modelBuilder, WorkspaceModule.Mutable parentModule, byte flags) {
WorkspaceModule.Mutable projectModule = null;
for (ResolvedArtifact a : resolvedDep.getModuleArtifacts()) {
final ArtifactKey artifactKey = toAppDependenciesKey(a.getModuleVersion().getId().getGroup(), a.getName(), a.getClassifier());
if (!isDependency(a) || appDependencies.containsKey(artifactKey)) {
continue;
}
final ArtifactCoords depCoords = toArtifactCoords(a);
final ResolvedDependencyBuilder depBuilder = ResolvedDependencyBuilder.newInstance().setCoords(depCoords).setRuntimeCp();
if (isFlagOn(flags, COLLECT_DIRECT_DEPS)) {
depBuilder.setDirect(true);
flags = clearFlag(flags, COLLECT_DIRECT_DEPS);
}
if (parentModule != null) {
parentModule.addDependency(new ArtifactDependency(depCoords));
}
PathCollection paths = null;
if ((LaunchMode.DEVELOPMENT.equals(mode) || LaunchMode.TEST.equals(mode)) && a.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier) {
final Project projectDep = project.getRootProject().findProject(((ProjectComponentIdentifier) a.getId().getComponentIdentifier()).getProjectPath());
final JavaPluginConvention javaExtension = projectDep == null ? null : projectDep.getConvention().findPlugin(JavaPluginConvention.class);
final String classifier = a.getClassifier();
if (classifier == null || classifier.isEmpty()) {
final IncludedBuild includedBuild = ToolingUtils.includedBuild(project.getRootProject(), a.getName());
if (includedBuild != null) {
final PathList.Builder pathBuilder = PathList.builder();
addSubstitutedProject(pathBuilder, includedBuild.getProjectDir());
paths = pathBuilder.build();
} else if (javaExtension != null) {
final PathList.Builder pathBuilder = PathList.builder();
projectModule = initProjectModuleAndBuildPaths(projectDep, a, modelBuilder, depBuilder, javaExtension, pathBuilder, SourceSet.MAIN_SOURCE_SET_NAME, false);
paths = pathBuilder.build();
}
} else if (javaExtension != null) {
if ("test".equals(classifier)) {
final PathList.Builder pathBuilder = PathList.builder();
projectModule = initProjectModuleAndBuildPaths(projectDep, a, modelBuilder, depBuilder, javaExtension, pathBuilder, SourceSet.TEST_SOURCE_SET_NAME, true);
paths = pathBuilder.build();
} else if ("test-fixtures".equals(classifier)) {
final PathList.Builder pathBuilder = PathList.builder();
projectModule = initProjectModuleAndBuildPaths(projectDep, a, modelBuilder, depBuilder, javaExtension, pathBuilder, "testFixtures", true);
paths = pathBuilder.build();
}
}
}
depBuilder.setResolvedPaths(paths == null ? PathList.of(a.getFile().toPath()) : paths).setWorkspaceModule(projectModule);
if (processQuarkusDependency(depBuilder, modelBuilder)) {
if (isFlagOn(flags, COLLECT_TOP_EXTENSION_RUNTIME_NODES)) {
depBuilder.setFlags(DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT);
flags = clearFlag(flags, COLLECT_TOP_EXTENSION_RUNTIME_NODES);
}
flags = clearFlag(flags, COLLECT_RELOADABLE_MODULES);
}
if (!isFlagOn(flags, COLLECT_RELOADABLE_MODULES)) {
depBuilder.clearFlag(DependencyFlags.RELOADABLE);
}
appDependencies.put(depBuilder.getKey(), depBuilder);
if (artifactFiles != null) {
artifactFiles.add(a.getFile());
}
}
processedModules.add(new GACT(resolvedDep.getModuleGroup(), resolvedDep.getModuleName()));
for (org.gradle.api.artifacts.ResolvedDependency child : resolvedDep.getChildren()) {
if (!processedModules.contains(new GACT(child.getModuleGroup(), child.getModuleName()))) {
collectDependencies(child, mode, project, appDependencies, artifactFiles, processedModules, modelBuilder, projectModule, flags);
}
}
}
use of io.quarkus.paths.PathCollection in project quarkus by quarkusio.
the class ResolvedDependency method getContentTree.
default PathTree getContentTree() {
final WorkspaceModule module = getWorkspaceModule();
final PathTree workspaceTree = module == null ? EmptyPathTree.getInstance() : module.getContentTree(getClassifier());
if (!workspaceTree.isEmpty()) {
return workspaceTree;
}
final PathCollection paths = getResolvedPaths();
if (paths == null || paths.isEmpty()) {
return EmptyPathTree.getInstance();
}
if (paths.isSinglePath()) {
final Path p = paths.getSinglePath();
return PathTree.ofDirectoryOrArchive(p);
}
final PathTree[] trees = new PathTree[paths.size()];
int i = 0;
for (Path p : paths) {
trees[i++] = PathTree.ofDirectoryOrArchive(p);
}
return new MultiRootPathTree(trees);
}
Aggregations