Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Oct 28, 2024
1 parent fcc7889 commit 3e954e2
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ public interface BootstrapConstants {
String PLATFORM_PROPERTY_PREFIX = "platform.";

String QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY = "quarkus.bootstrap.workspace-discovery";

String EXTENSION_DEV_MODE_JVM_ARGS_PREFIX = "dev-mode.jvm-args.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import org.jboss.logging.Logger;

import io.quarkus.bootstrap.BootstrapConstants;
import io.quarkus.bootstrap.workspace.WorkspaceModule;
import io.quarkus.bootstrap.workspace.WorkspaceModuleId;
import io.quarkus.maven.dependency.ArtifactCoords;
Expand All @@ -35,6 +36,8 @@ public class ApplicationModelBuilder {

private static final Logger log = Logger.getLogger(ApplicationModelBuilder.class);

private static final String COMMA = ",";

ResolvedDependencyBuilder appArtifact;

final Map<ArtifactKey, ResolvedDependencyBuilder> dependencies = new LinkedHashMap<>();
Expand All @@ -47,6 +50,7 @@ public class ApplicationModelBuilder {
final Collection<ExtensionCapabilities> extensionCapabilities = new ConcurrentLinkedDeque<>();
PlatformImports platformImports;
final Map<WorkspaceModuleId, WorkspaceModule.Mutable> projectModules = new HashMap<>();
final Collection<ExtensionDevModeConfig> extensionDevConfig = new ConcurrentLinkedDeque<>();

public ApplicationModelBuilder() {
// we never include the ide launcher in the final app model
Expand Down Expand Up @@ -166,81 +170,115 @@ public WorkspaceModule.Mutable getOrCreateProjectModule(WorkspaceModuleId id, Fi
}

/**
* Sets the parent first and excluded artifacts from a descriptor properties file
* Collects extension properties from the {@code META-INF/quarkus-extension.properties}
*
* @param props The quarkus-extension.properties file
* @param props extension properties
* @param extensionKey extension dependency key
*/
public void handleExtensionProperties(Properties props, String extension) {
public void handleExtensionProperties(Properties props, ArtifactKey extensionKey) {
Map<String, List<String>> devJvmArgs = null;
for (Map.Entry<Object, Object> prop : props.entrySet()) {
if (prop.getValue() == null) {
continue;
}
final String name = prop.getKey().toString();
final String value = prop.getValue().toString();

if (name.startsWith(BootstrapConstants.EXTENSION_DEV_MODE_JVM_ARGS_PREFIX)) {
log.debugf("Extension %s configures JVM argument %s=%s in dev mode", extensionKey, name, value);
if (devJvmArgs == null) {
devJvmArgs = new HashMap<>(4);
}
devJvmArgs.computeIfAbsent(name, k -> new ArrayList<>(1)).add(value);
continue;
}

if (value.isBlank()) {
continue;
}
final String name = prop.getKey().toString();
switch (name) {
case PARENT_FIRST_ARTIFACTS:
for (String artifact : value.split(",")) {
parentFirstArtifacts.add(new GACT(artifact.split(":")));
}
addParentFirstArtifacts(value);
break;
case RUNNER_PARENT_FIRST_ARTIFACTS:
for (String artifact : value.split(",")) {
runnerParentFirstArtifacts.add(new GACT(artifact.split(":")));
}
addRunnerParentFirstArtifacts(value);
break;
case EXCLUDED_ARTIFACTS:
for (String artifact : value.split(",")) {
excludedArtifacts.add(ArtifactCoordsPattern.of(artifact));
log.debugf("Extension %s is excluding %s", extension, artifact);
}
addExcludedArtifacts(extensionKey, value);
break;
case LESSER_PRIORITY_ARTIFACTS:
String[] artifacts = value.split(",");
for (String artifact : artifacts) {
lesserPriorityArtifacts.add(new GACT(artifact.split(":")));
log.debugf("Extension %s is making %s a lesser priority artifact", extension, artifact);
}
addLesserPriorityArtifacts(extensionKey, value);
break;
default:
if (name.startsWith(REMOVED_RESOURCES_DOT)) {
final String keyStr = name.substring(REMOVED_RESOURCES_DOT.length());
if (!keyStr.isBlank()) {
ArtifactKey key = null;
try {
key = ArtifactKey.fromString(keyStr);
} catch (IllegalArgumentException e) {
log.warnf("Failed to parse artifact key %s in %s from descriptor of extension %s", keyStr, name,
extension);
}
if (key != null) {
final Set<String> resources;
Collection<String> existingResources = excludedResources.get(key);
if (existingResources == null || existingResources.isEmpty()) {
resources = Set.of(value.split(","));
} else {
final String[] split = value.split(",");
resources = new HashSet<>(existingResources.size() + split.length);
resources.addAll(existingResources);
for (String s : split) {
resources.add(s);
}
}
log.debugf("Extension %s is excluding resources %s from artifact %s", extension, resources,
key);
excludedResources.put(key, resources);
}
}
addRemovedResources(extensionKey, name, value);
}
}
}
if (devJvmArgs != null) {
extensionDevConfig.add(new ExtensionDevModeConfig(extensionKey, devJvmArgs));
}
}

private void addRemovedResources(ArtifactKey extension, String name, String value) {
final String keyStr = name.substring(REMOVED_RESOURCES_DOT.length());
if (keyStr.isBlank()) {
return;
}
final ArtifactKey key;
try {
key = ArtifactKey.fromString(keyStr);
} catch (IllegalArgumentException e) {
log.warnf("Failed to parse artifact key %s in %s from descriptor of extension %s", keyStr, name, extension);
return;
}
final Set<String> resources;
final Collection<String> existingResources = excludedResources.get(key);
if (existingResources == null || existingResources.isEmpty()) {
resources = Set.of(value.split(COMMA));
} else {
final String[] split = value.split(COMMA);
resources = new HashSet<>(existingResources.size() + split.length);
resources.addAll(existingResources);
resources.addAll(List.of(split));
}
log.debugf("Extension %s is excluding resources %s from artifact %s", extension, resources, key);
excludedResources.put(key, resources);
}

private void addLesserPriorityArtifacts(ArtifactKey extension, String value) {
for (String artifact : value.split(COMMA)) {
lesserPriorityArtifacts.add(toArtifactKey(artifact));
log.debugf("Extension %s is making %s a lesser priority artifact", extension, artifact);
}
}

private void addExcludedArtifacts(ArtifactKey extension, String value) {
for (String artifact : value.split(COMMA)) {
excludedArtifacts.add(ArtifactCoordsPattern.of(artifact));
log.debugf("Extension %s is excluding %s", extension, artifact);
}
}

private void addRunnerParentFirstArtifacts(String value) {
for (String artifact : value.split(COMMA)) {
runnerParentFirstArtifacts.add(toArtifactKey(artifact));
}
}

private void addParentFirstArtifacts(String value) {
for (String artifact : value.split(COMMA)) {
parentFirstArtifacts.add(toArtifactKey(artifact));
}
}

private static GACT toArtifactKey(String artifact) {
return new GACT(artifact.split(":"));
}

private boolean isExcluded(ArtifactCoords coords) {
for (var pattern : excludedArtifacts) {
if (pattern.matches(coords)) {
private static boolean matches(ArtifactCoordsPattern[] patterns, ArtifactCoords coords) {
for (int i = 0; i < patterns.length; ++i) {
if (patterns[i].matches(coords)) {
return true;
}
}
Expand Down Expand Up @@ -268,8 +306,9 @@ List<ResolvedDependency> buildDependencies() {
}

final List<ResolvedDependency> result = new ArrayList<>(dependencies.size());
final ArtifactCoordsPattern[] excludePatterns = excludedArtifacts.toArray(new ArtifactCoordsPattern[0]);
for (ResolvedDependencyBuilder db : this.dependencies.values()) {
if (!isExcluded(db.getArtifactCoords())) {
if (!matches(excludePatterns, db.getArtifactCoords())) {
result.add(db.build());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@

public class DefaultApplicationModel implements ApplicationModel, Serializable {

private static final long serialVersionUID = -3878782344578748234L;
private static final long serialVersionUID = -5247678201356725379L;

private final ResolvedDependency appArtifact;
private final List<ResolvedDependency> dependencies;
private final PlatformImports platformImports;
private final List<ExtensionCapabilities> capabilityContracts;
private final Set<ArtifactKey> localProjectArtifacts;
private final Map<ArtifactKey, Set<String>> excludedResources;
private final List<ExtensionDevModeConfig> extDevModeJvmArgs;

public DefaultApplicationModel(ApplicationModelBuilder builder) {
this.appArtifact = builder.appArtifact.build();
this.dependencies = builder.buildDependencies();
this.platformImports = builder.platformImports;
this.capabilityContracts = List.copyOf(builder.extensionCapabilities);
this.localProjectArtifacts = Set.copyOf(builder.reloadableWorkspaceModules);
this.excludedResources = builder.excludedResources;
this.excludedResources = Map.copyOf(builder.excludedResources);
this.extDevModeJvmArgs = List.copyOf(builder.extensionDevConfig);
}

@Override
Expand Down Expand Up @@ -121,7 +123,7 @@ private FlagDependencyIterator(int[] flags) {
public Iterator<ResolvedDependency> iterator() {
return new Iterator<>() {

final Iterator<ResolvedDependency> i = dependencies.iterator();
int index = 0;
ResolvedDependency next;

{
Expand All @@ -145,8 +147,8 @@ public ResolvedDependency next() {

private void moveOn() {
next = null;
while (i.hasNext()) {
var d = i.next();
while (index < dependencies.size()) {
var d = dependencies.get(index++);
if (d.hasAnyFlag(flags)) {
next = d;
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.bootstrap.model;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import io.quarkus.maven.dependency.ArtifactKey;

public class ExtensionDevModeConfig implements Serializable {

private final ArtifactKey extensionKey;
private final Map<String, List<String>> jvmArgs;

public ExtensionDevModeConfig(ArtifactKey extensionKey, Map<String, List<String>> jvmArgs) {
this.extensionKey = extensionKey;
this.jvmArgs = jvmArgs;
}

public ArtifactKey getExtensionKey() {
return extensionKey;
}

public Map<String, List<String>> getJvmArgs() {
return jvmArgs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ void ensureActivated() {
return;
}
activated = true;
appBuilder.handleExtensionProperties(props, runtimeArtifact.toString());
appBuilder.handleExtensionProperties(props, getKey(runtimeArtifact));

final String providesCapabilities = props.getProperty(BootstrapConstants.PROP_PROVIDES_CAPABILITIES);
final String requiresCapabilities = props.getProperty(BootstrapConstants.PROP_REQUIRES_CAPABILITIES);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,9 @@ public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolver

DependencyNode root = resolveRuntimeDeps(collectRtDepsRequest);
processRuntimeDeps(root);
final List<ConditionalDependency> activatedConditionalDeps = activateConditionalDeps();

// resolve and inject deployment dependency branches for the top (first met) runtime extension nodes
injectDeployment(activatedConditionalDeps);
injectDeployment(activateConditionalDeps());
root = normalize(resolver.getSession(), root);
processDeploymentDeps(root);

Expand Down Expand Up @@ -516,9 +515,8 @@ void scheduleRuntimeVisit(ModelResolutionTaskRunner taskRunner) {

void visitRuntimeDependency() {
Artifact artifact = node.getArtifact();
final ArtifactKey key = getKey(artifact);
if (resolvedDep == null) {
resolvedDep = appBuilder.getDependency(key);
resolvedDep = appBuilder.getDependency(getKey(artifact));
}

// in case it was relocated it might not survive conflict resolution in the deployment graph
Expand Down Expand Up @@ -562,8 +560,7 @@ void scheduleChildVisits(ModelResolutionTaskRunner taskRunner,
var winner = getWinner(childNode);
if (winner == null) {
allDeps.add(getCoords(childNode.getArtifact()));
var child = new AppDep(this, childNode);
children.add(child);
children.add(new AppDep(this, childNode));
if (filtered != null) {
filtered.add(childNode);
}
Expand Down Expand Up @@ -871,7 +868,7 @@ void ensureActivated() {
return;
}
activated = true;
appBuilder.handleExtensionProperties(props, runtimeArtifact.toString());
appBuilder.handleExtensionProperties(props, getKey(runtimeArtifact));

final String providesCapabilities = props.getProperty(BootstrapConstants.PROP_PROVIDES_CAPABILITIES);
final String requiresCapabilities = props.getProperty(BootstrapConstants.PROP_REQUIRES_CAPABILITIES);
Expand Down
Loading

0 comments on commit 3e954e2

Please sign in to comment.