Skip to content

Commit 5cec962

Browse files
Merge pull request #48663 from aloubyansky/dev-ui-extension-processing
Fix Dev UI extension metadata loading
2 parents d6dd8a9 + 5c10bb2 commit 5cec962

File tree

1 file changed

+81
-61
lines changed

1 file changed

+81
-61
lines changed

extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIProcessor.java

Lines changed: 81 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.devui.deployment;
22

3+
import java.io.BufferedReader;
34
import java.io.ByteArrayInputStream;
45
import java.io.IOException;
56
import java.io.InputStream;
@@ -19,6 +20,7 @@
1920
import java.util.LinkedHashMap;
2021
import java.util.List;
2122
import java.util.Map;
23+
import java.util.Properties;
2224
import java.util.Scanner;
2325
import java.util.regex.Matcher;
2426
import java.util.regex.Pattern;
@@ -36,6 +38,7 @@
3638
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
3739
import io.quarkus.arc.deployment.BeanContainerBuildItem;
3840
import io.quarkus.arc.processor.BuiltinScope;
41+
import io.quarkus.bootstrap.BootstrapConstants;
3942
import io.quarkus.deployment.Capabilities;
4043
import io.quarkus.deployment.Capability;
4144
import io.quarkus.deployment.IsLocalDevelopment;
@@ -72,6 +75,8 @@
7275
import io.quarkus.devui.spi.page.PageBuilder;
7376
import io.quarkus.devui.spi.page.QuteDataPageBuilder;
7477
import io.quarkus.devui.spi.page.WebComponentPageBuilder;
78+
import io.quarkus.maven.dependency.ArtifactKey;
79+
import io.quarkus.maven.dependency.DependencyFlags;
7580
import io.quarkus.maven.dependency.GACT;
7681
import io.quarkus.maven.dependency.GACTV;
7782
import io.quarkus.maven.dependency.ResolvedDependency;
@@ -101,8 +106,6 @@ public class DevUIProcessor {
101106
private static final String DEVUI = "dev-ui";
102107
private static final String SLASH = "/";
103108
private static final String DOT = ".";
104-
private static final String DOUBLE_POINT = ":";
105-
private static final String DASH_DEPLOYMENT = "-deployment";
106109
private static final String SLASH_ALL = SLASH + "*";
107110
private static final String JSONRPC = "json-rpc-ws";
108111

@@ -112,7 +115,6 @@ public class DevUIProcessor {
112115

113116
private static final String JAR = "jar";
114117
private static final GACT UI_JAR = new GACT("io.quarkus", "quarkus-vertx-http-dev-ui-resources", null, JAR);
115-
private static final String YAML_FILE = "/META-INF/quarkus-extension.yaml";
116118
private static final String NAME = "name";
117119
private static final String DESCRIPTION = "description";
118120
private static final String ARTIFACT = "artifact";
@@ -519,17 +521,27 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
519521
Map<String, CardPageBuildItem> cardPagesMap = getCardPagesMap(curateOutcomeBuildItem, cardPageBuildItems);
520522
Map<String, MenuPageBuildItem> menuPagesMap = getMenuPagesMap(curateOutcomeBuildItem, menuPageBuildItems);
521523
Map<String, List<FooterPageBuildItem>> footerPagesMap = getFooterPagesMap(curateOutcomeBuildItem, footerPageBuildItems);
522-
try {
523-
final Yaml yaml = new Yaml();
524-
List<Extension> activeExtensions = new ArrayList<>();
525-
List<Extension> inactiveExtensions = new ArrayList<>();
526-
List<Extension> sectionMenuExtensions = new ArrayList<>();
527-
List<Extension> footerTabExtensions = new ArrayList<>();
528-
ClassPathUtils.consumeAsPaths(YAML_FILE, (var p) -> {
524+
525+
final Yaml yaml = new Yaml();
526+
List<Extension> activeExtensions = new ArrayList<>();
527+
List<Extension> inactiveExtensions = new ArrayList<>();
528+
List<Extension> sectionMenuExtensions = new ArrayList<>();
529+
List<Extension> footerTabExtensions = new ArrayList<>();
530+
531+
for (ResolvedDependency runtimeExt : curateOutcomeBuildItem.getApplicationModel()
532+
.getDependencies(DependencyFlags.RUNTIME_EXTENSION_ARTIFACT)) {
533+
runtimeExt.getContentTree().accept(BootstrapConstants.EXTENSION_METADATA_PATH, extYamlVisit -> {
534+
if (extYamlVisit == null) {
535+
// this could be an exception but previously the code was simply looking for this resource on the classpath
536+
log.error("Failed to locate " + BootstrapConstants.EXTENSION_METADATA_PATH + " in "
537+
+ runtimeExt.toCompactCoords());
538+
return;
539+
}
540+
final Path extYaml = extYamlVisit.getPath();
529541
try {
530542
Extension extension = new Extension();
531543
final String extensionYaml;
532-
try (Scanner scanner = new Scanner(Files.newBufferedReader(p, StandardCharsets.UTF_8))) {
544+
try (Scanner scanner = new Scanner(Files.newBufferedReader(extYaml, StandardCharsets.UTF_8))) {
533545
scanner.useDelimiter("\\A");
534546
extensionYaml = scanner.hasNext() ? scanner.next() : null;
535547
}
@@ -551,8 +563,7 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
551563
extension.setNamespace(namespace);
552564
extension.setName((String) extensionMap.get(NAME));
553565
extension.setDescription((String) extensionMap.getOrDefault(DESCRIPTION, null));
554-
String artifactId = (String) extensionMap.getOrDefault(ARTIFACT, null);
555-
extension.setArtifact(artifactId);
566+
extension.setArtifact((String) extensionMap.getOrDefault(ARTIFACT, null));
556567

557568
extension.setKeywords((List<String>) metaData.getOrDefault(KEYWORDS, null));
558569
extension.setShortName((String) metaData.getOrDefault(SHORT_NAME, null));
@@ -614,14 +625,12 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
614625
addLibraryLinks(extension, cardPageBuildItem, curateOutcomeBuildItem, metaData);
615626

616627
// Also make sure the static resources for that static resource is available
617-
produceResources(artifactId, webJarBuildProducer,
618-
devUIWebJarProducer);
628+
produceResources(runtimeExt, webJarBuildProducer, devUIWebJarProducer);
619629
activeExtensions.add(extension);
620630
} else { // Inactive
621631
if (addLogo(extension, cardPagesMap.get(namespace), metaData)) {
622632
// Also make sure the static resources for that static resource is available
623-
produceResources(artifactId, webJarBuildProducer,
624-
devUIWebJarProducer);
633+
produceResources(runtimeExt, webJarBuildProducer, devUIWebJarProducer);
625634
}
626635

627636
addLibraryLinks(extension, cardPagesMap.get(namespace), curateOutcomeBuildItem,
@@ -643,8 +652,7 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
643652
}
644653
}
645654
// Also make sure the static resources for that static resource is available
646-
produceResources(artifactId, webJarBuildProducer,
647-
devUIWebJarProducer);
655+
produceResources(runtimeExt, webJarBuildProducer, devUIWebJarProducer);
648656
sectionMenuExtensions.add(extension);
649657
}
650658

@@ -663,8 +671,7 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
663671
}
664672
}
665673
// Also make sure the static resources for that static resource is available
666-
produceResources(artifactId, webJarBuildProducer,
667-
devUIWebJarProducer);
674+
produceResources(runtimeExt, webJarBuildProducer, devUIWebJarProducer);
668675
footerTabExtensions.add(extension);
669676
}
670677
}
@@ -676,41 +683,39 @@ void getAllExtensions(List<CardPageBuildItem> cardPageBuildItems,
676683
}
677684
} catch (IOException | RuntimeException e) {
678685
// don't abort, just log, to prevent a single extension from breaking entire dev ui
679-
log.error("Failed to process extension descriptor " + p.toUri(), e);
686+
log.error("Failed to process extension descriptor " + extYaml.toUri(), e);
680687
}
681688
});
689+
}
682690

683-
// Also add footers for extensions that might not have a runtime
684-
if (!footerPagesMap.isEmpty()) {
685-
for (Map.Entry<String, List<FooterPageBuildItem>> footer : footerPagesMap.entrySet()) {
686-
List<FooterPageBuildItem> fbis = footer.getValue();
687-
for (FooterPageBuildItem footerPageBuildItem : fbis) {
688-
if (footerPageBuildItem.isInternal()) {
689-
Extension deploymentOnlyExtension = new Extension();
690-
deploymentOnlyExtension.setName(footer.getKey());
691-
deploymentOnlyExtension.setNamespace(FOOTER_LOG_NAMESPACE);
692-
693-
List<PageBuilder> footerPageBuilders = footerPageBuildItem.getPages();
694-
695-
for (PageBuilder pageBuilder : footerPageBuilders) {
696-
pageBuilder.namespace(deploymentOnlyExtension.getNamespace());
697-
pageBuilder.extension(deploymentOnlyExtension.getName());
698-
pageBuilder.internal();
699-
Page page = pageBuilder.build();
700-
deploymentOnlyExtension.addFooterPage(page);
701-
}
702-
703-
footerTabExtensions.add(deploymentOnlyExtension);
691+
// Also add footers for extensions that might not have a runtime
692+
if (!footerPagesMap.isEmpty()) {
693+
for (Map.Entry<String, List<FooterPageBuildItem>> footer : footerPagesMap.entrySet()) {
694+
List<FooterPageBuildItem> fbis = footer.getValue();
695+
for (FooterPageBuildItem footerPageBuildItem : fbis) {
696+
if (footerPageBuildItem.isInternal()) {
697+
Extension deploymentOnlyExtension = new Extension();
698+
deploymentOnlyExtension.setName(footer.getKey());
699+
deploymentOnlyExtension.setNamespace(FOOTER_LOG_NAMESPACE);
700+
701+
List<PageBuilder> footerPageBuilders = footerPageBuildItem.getPages();
702+
703+
for (PageBuilder pageBuilder : footerPageBuilders) {
704+
pageBuilder.namespace(deploymentOnlyExtension.getNamespace());
705+
pageBuilder.extension(deploymentOnlyExtension.getName());
706+
pageBuilder.internal();
707+
Page page = pageBuilder.build();
708+
deploymentOnlyExtension.addFooterPage(page);
704709
}
710+
711+
footerTabExtensions.add(deploymentOnlyExtension);
705712
}
706713
}
707714
}
708-
709-
extensionsProducer.produce(
710-
new ExtensionsBuildItem(activeExtensions, inactiveExtensions, sectionMenuExtensions, footerTabExtensions));
711-
} catch (IOException ex) {
712-
throw new RuntimeException(ex);
713715
}
716+
717+
extensionsProducer.produce(
718+
new ExtensionsBuildItem(activeExtensions, inactiveExtensions, sectionMenuExtensions, footerTabExtensions));
714719
}
715720

716721
private void addLibraryLinks(Extension extension, CardPageBuildItem cardPageBuildItem,
@@ -805,19 +810,19 @@ private List<String> listOrString(Map<String, Object> metaData, String key) {
805810
return List.of(String.valueOf(value));
806811
}
807812

808-
private void produceResources(String artifactId,
813+
private void produceResources(ResolvedDependency runtimeExt,
809814
BuildProducer<WebJarBuildItem> webJarBuildProducer,
810815
BuildProducer<DevUIWebJarBuildItem> devUIWebJarProducer) {
811816

812-
GACT gact = getGACT(artifactId);
813-
String namespace = getNamespace(gact);
817+
String namespace = getNamespace(runtimeExt.getKey());
814818
if (namespace.isEmpty()) {
815819
namespace = "devui";
816820
}
817821
String buildTimeDataImport = namespace + "-data";
818822

823+
final GACT deploymentKey = getDeploymentKey(runtimeExt);
819824
webJarBuildProducer.produce(WebJarBuildItem.builder()
820-
.artifactKey(gact)
825+
.artifactKey(deploymentKey)
821826
.root(DEVUI + SLASH)
822827
.filter(new WebJarResourcesFilter() {
823828
@Override
@@ -834,9 +839,29 @@ public WebJarResourcesFilter.FilterResult apply(String fileName, InputStream fil
834839
})
835840
.build());
836841

837-
devUIWebJarProducer.produce(
838-
new DevUIWebJarBuildItem(gact,
839-
DEVUI));
842+
devUIWebJarProducer.produce(new DevUIWebJarBuildItem(deploymentKey, DEVUI));
843+
}
844+
845+
private static GACT getDeploymentKey(ResolvedDependency runtimeExt) {
846+
return runtimeExt.getContentTree().apply(BootstrapConstants.DESCRIPTOR_PATH, extPropsVisit -> {
847+
if (extPropsVisit == null) {
848+
throw new RuntimeException("Failed to locate " + BootstrapConstants.DESCRIPTOR_PATH
849+
+ " in " + runtimeExt.toCompactCoords());
850+
}
851+
final Properties props = new Properties();
852+
try (BufferedReader reader = Files.newBufferedReader(extPropsVisit.getPath())) {
853+
props.load(reader);
854+
} catch (IOException e) {
855+
throw new RuntimeException("Failed to read " + extPropsVisit.getUrl(), e);
856+
}
857+
final String deploymentCoords = props.getProperty(BootstrapConstants.PROP_DEPLOYMENT_ARTIFACT);
858+
if (deploymentCoords == null) {
859+
throw new RuntimeException(
860+
"Failed to locate " + BootstrapConstants.PROP_DEPLOYMENT_ARTIFACT + " in " + extPropsVisit.getUrl());
861+
}
862+
var coords = GACTV.fromString(deploymentCoords);
863+
return new GACT(coords.getGroupId(), coords.getArtifactId(), coords.getClassifier(), coords.getType());
864+
});
840865
}
841866

842867
@BuildStep(onlyIf = IsLocalDevelopment.class)
@@ -860,7 +885,7 @@ void createAllRoutes(WebJarResultsBuildItem webJarResultsBuildItem,
860885
}
861886
}
862887

863-
private String getNamespace(GACT artifactKey) {
888+
private String getNamespace(ArtifactKey artifactKey) {
864889
String namespace = artifactKey.getGroupId() + "." + artifactKey.getArtifactId();
865890

866891
if (namespace.equals("io.quarkus.quarkus-vertx-http-dev-ui-resources")) {
@@ -905,11 +930,6 @@ private Page buildQutePage(PageBuilder pageBuilder, Extension extension, Map<Str
905930
return pageBuilder.build();
906931
}
907932

908-
private GACT getGACT(String artifactKey) {
909-
String[] split = artifactKey.split(DOUBLE_POINT);
910-
return new GACT(split[0], split[1] + DASH_DEPLOYMENT, null, JAR);
911-
}
912-
913933
private Class toClass(Type type) {
914934
if (type.kind().equals(Type.Kind.PRIMITIVE)) {
915935
return JandexReflection.loadRawType(type);

0 commit comments

Comments
 (0)