Skip to content

Commit

Permalink
IDE dev mode: add only reloadable local dependencies to the devmode c…
Browse files Browse the repository at this point in the history
…ontext
  • Loading branch information
aloubyansky committed Dec 10, 2020
1 parent d27abb4 commit 88cc785
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.quarkus.bootstrap.model.AppArtifactKey;
import io.quarkus.bootstrap.resolver.AppModelResolverException;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalWorkspace;
import io.quarkus.bootstrap.resolver.model.QuarkusModel;
import io.quarkus.bootstrap.resolver.model.WorkspaceModule;
import io.quarkus.bootstrap.util.QuarkusModelHelper;
Expand All @@ -24,6 +25,7 @@
public class IDEDevModeMain implements BiConsumer<CuratedApplication, Map<String, Object>>, Closeable {

private static final Logger log = Logger.getLogger(IDEDevModeMain.class.getName());
private static final String APP_PROJECT = "app-project";

private IsolatedDevModeMain delegate;

Expand All @@ -34,14 +36,26 @@ public void accept(CuratedApplication curatedApplication, Map<String, Object> st
devModeContext.setArgs((String[]) stringObjectMap.get("args"));
try {
if (BuildToolHelper.isMavenProject(appClasses)) {
LocalProject project = LocalProject.loadWorkspace(appClasses);
LocalProject project = (LocalProject) stringObjectMap.get(APP_PROJECT);
if (project == null) {
project = LocalProject.loadWorkspace(appClasses);
}

DevModeContext.ModuleInfo root = toModule(project);
devModeContext.setApplicationRoot(root);
for (Map.Entry<AppArtifactKey, LocalProject> module : project.getWorkspace().getProjects().entrySet()) {
if (module.getKey().equals(project.getKey())) {

final LocalWorkspace workspace = project.getWorkspace();
for (AppArtifactKey localKey : curatedApplication.getAppModel().getLocalProjectArtifacts()) {
final LocalProject depProject = workspace.getProject(localKey.getGroupId(), localKey.getArtifactId());
if (project == depProject) {
continue;
}
devModeContext.getAdditionalModules().add(toModule(module.getValue()));
if (depProject == null) {
throw new IllegalStateException(
"Failed to locate project dependency " + localKey + " in the workspace");
}
devModeContext.getAdditionalModules().add(toModule(depProject));
devModeContext.getLocalArtifacts().add(localKey);
}
} else {
final QuarkusModel model = QuarkusModelHelper
Expand Down
1 change: 1 addition & 0 deletions core/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
<parentFirstArtifact>io.quarkus:quarkus-bootstrap-core</parentFirstArtifact>
<parentFirstArtifact>io.quarkus:quarkus-development-mode-spi</parentFirstArtifact>
<parentFirstArtifact>io.quarkus:quarkus-bootstrap-app-model</parentFirstArtifact>
<parentFirstArtifact>io.quarkus:quarkus-bootstrap-maven-resolver</parentFirstArtifact>
<parentFirstArtifact>org.slf4j:slf4j-api</parentFirstArtifact>
<parentFirstArtifact>org.jboss.slf4j:slf4j-jboss-logmanager</parentFirstArtifact>
<parentFirstArtifact>org.jboss.logmanager:jboss-logmanager-embedded</parentFirstArtifact>
Expand Down
94 changes: 10 additions & 84 deletions devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand All @@ -42,6 +41,7 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
Expand All @@ -56,9 +56,6 @@
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.DependencyVisitor;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactRequest;
Expand All @@ -69,11 +66,11 @@
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.util.artifact.JavaScopes;

import io.quarkus.bootstrap.devmode.DependenciesFilter;
import io.quarkus.bootstrap.model.AppArtifactKey;
import io.quarkus.bootstrap.model.AppModel;
import io.quarkus.bootstrap.resolver.maven.options.BootstrapMavenOptions;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalWorkspace;
import io.quarkus.deployment.dev.DevModeContext;
import io.quarkus.deployment.dev.DevModeMain;
import io.quarkus.deployment.dev.QuarkusDevModeLauncher;
Expand Down Expand Up @@ -278,6 +275,12 @@ public class DevMojo extends AbstractMojo {
@Component
private ToolchainManager toolchainManager;

@Override
public void setLog(Log log) {
super.setLog(log);
MojoLogger.delegate = log;
}

@Override
public void execute() throws MojoFailureException, MojoExecutionException {

Expand Down Expand Up @@ -682,7 +685,8 @@ private QuarkusDevModeLauncher newLauncher() throws Exception {
builder.localArtifact(new AppArtifactKey(localProject.getGroupId(), localProject.getArtifactId(), null, "jar"));
} else {
final LocalProject localProject = LocalProject.loadWorkspace(project.getModel().getPomFile().toPath());
for (LocalProject project : filterExtensionDependencies(localProject)) {
for (LocalProject project : DependenciesFilter.filterNotReloadableDependencies(localProject,
this.project.getArtifacts(), repoSystem, repoSession, repos)) {
addProject(builder, project, project == localProject);
builder.watchedBuildFile(project.getRawModel().getPomFile().toPath());
builder.localArtifact(new AppArtifactKey(project.getGroupId(), project.getArtifactId(), null, "jar"));
Expand Down Expand Up @@ -856,84 +860,6 @@ protected void modifyDevModeContext(MavenDevModeLauncher.Builder builder) {

}

private List<LocalProject> filterExtensionDependencies(LocalProject localProject) {
final LocalWorkspace workspace = localProject.getWorkspace();
if (workspace == null) {
return Collections.singletonList(localProject);
}

List<LocalProject> ret = new ArrayList<>();
Set<AppArtifactKey> extensionsAndDeps = new HashSet<>();

ret.add(localProject);
for (Artifact a : project.getArtifacts()) {
final AppArtifactKey depKey = new AppArtifactKey(a.getGroupId(), a.getArtifactId());
final LocalProject project = workspace.getProject(depKey);
if (project == null) {
continue;
}
if (!project.getVersion().equals(a.getVersion())) {
getLog().warn(depKey + " is excluded from live coding since the application depends on version "
+ a.getVersion() + " while the version present in the workspace is " + project.getVersion());
continue;
}
if (project.getClassesDir() != null &&
//if this project also contains Quarkus extensions we do no want to include these in the discovery
//a bit of an edge case, but if you try and include a sample project with your extension you will
//run into problems without this
(Files.exists(project.getClassesDir().resolve("META-INF/quarkus-extension.properties")) ||
Files.exists(project.getClassesDir().resolve("META-INF/quarkus-build-steps.list")))) {
// TODO add the deployment deps
extensionDepWarning(depKey);
try {
final DependencyNode depRoot = repoSystem.collectDependencies(repoSession, new CollectRequest()
.setRoot(new org.eclipse.aether.graph.Dependency(
new DefaultArtifact(a.getGroupId(), a.getArtifactId(),
a.getClassifier(), a.getArtifactHandler().getExtension(), a.getVersion()),
JavaScopes.RUNTIME))
.setRepositories(repos)).getRoot();
depRoot.accept(new DependencyVisitor() {
@Override
public boolean visitEnter(DependencyNode node) {
final org.eclipse.aether.artifact.Artifact artifact = node.getArtifact();
if ("jar".equals(artifact.getExtension())) {
extensionsAndDeps.add(new AppArtifactKey(artifact.getGroupId(), artifact.getArtifactId()));
}
return true;
}

@Override
public boolean visitLeave(DependencyNode node) {
return true;
}
});
} catch (DependencyCollectionException e) {
throw new RuntimeException("Failed to collect dependencies for " + a, e);
}
} else {
ret.add(project);
}
}

if (extensionsAndDeps.isEmpty()) {
return ret;
}

Iterator<LocalProject> iterator = ret.iterator();
while (iterator.hasNext()) {
final LocalProject localDep = iterator.next();
if (extensionsAndDeps.contains(localDep.getKey())) {
extensionDepWarning(localDep.getKey());
iterator.remove();
}
}
return ret;
}

private void extensionDepWarning(AppArtifactKey key) {
getLog().warn("Local Quarkus extension dependency " + key + " will not be hot-reloadable");
}

private Optional<Xpp3Dom> findCompilerPluginConfiguration() {
for (final Plugin plugin : project.getBuildPlugins()) {
if (!plugin.getKey().equals("org.apache.maven.plugins:maven-compiler-plugin")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ private BootstrapMavenContext createBootstrapMavenContext() throws AppModelResol
if (mvnContext != null) {
return mvnContext;
}
if (mavenArtifactResolver != null) {
mvnContext = mavenArtifactResolver.getMavenContext();
if (mvnContext != null) {
return mvnContext;
}
}
final BootstrapMavenContextConfig<?> config = BootstrapMavenContext.config();
if (offline != null) {
config.setOffline(offline);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
import io.quarkus.bootstrap.app.AdditionalDependency;
import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.devmode.DependenciesFilter;
import io.quarkus.bootstrap.model.AppArtifactKey;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject;
import io.quarkus.bootstrap.resolver.model.QuarkusModel;
import io.quarkus.bootstrap.resolver.model.WorkspaceModule;
import io.quarkus.bootstrap.util.QuarkusModelHelper;
Expand All @@ -24,9 +29,7 @@ public static Closeable launch(Path projectRoot, Map<String, Object> context) {
try {
//todo : proper support for everything
final QuarkusBootstrap.Builder builder = QuarkusBootstrap.builder()
.setApplicationRoot(projectRoot)
.setBaseClassLoader(IDELauncherImpl.class.getClassLoader())
.setProjectRoot(projectRoot)
.setIsolateDeployment(true)
.setMode(QuarkusBootstrap.Mode.DEV);

Expand All @@ -50,6 +53,21 @@ public static Closeable launch(Path projectRoot, Map<String, Object> context) {
additionalModule.getSourceSet().getResourceDirectory().toPath(), true, false));
}
}
} else {
builder.setApplicationRoot(projectRoot)
.setProjectRoot(projectRoot);

final LocalProject currentProject = LocalProject.loadWorkspace(projectRoot);
context.put("app-project", currentProject);

final BootstrapMavenContext mvnCtx = new BootstrapMavenContext(
BootstrapMavenContext.config().setCurrentProject(currentProject));
final MavenArtifactResolver mvnResolver = new MavenArtifactResolver(mvnCtx);
builder.setMavenArtifactResolver(mvnResolver);

DependenciesFilter.filterNotReloadableDependencies(currentProject, mvnResolver)
.forEach(p -> builder
.addLocalArtifact(new AppArtifactKey(p.getGroupId(), p.getArtifactId(), null, "jar")));
}

final CuratedApplication curatedApp = builder.build().bootstrap();
Expand Down
Loading

0 comments on commit 88cc785

Please sign in to comment.