Skip to content

Commit

Permalink
feat: Generation of extension.json should allow for overrides
Browse files Browse the repository at this point in the history
Fixes #4320
  • Loading branch information
quintesse committed Oct 25, 2019
1 parent eb50076 commit 0e6f1f1
Showing 1 changed file with 100 additions and 14 deletions.
@@ -1,20 +1,25 @@
package io.quarkus.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.json.JsonWriter;
import javax.json.JsonWriterFactory;
import javax.json.stream.JsonGenerator;
Expand Down Expand Up @@ -59,6 +64,9 @@ public class GenerateExtensionsJsonMojo extends AbstractMojo {
@Parameter(property = "bomVersion", defaultValue = "${project.version}")
private String bomVersion;

@Parameter(property = "overridesFile", defaultValue = "${project.basedir}/src/main/resources/extensions-overrides.json")
private File overridesFile;

@Parameter(property = "outputFile", defaultValue = "${project.build.directory}/extensions.json")
private File outputFile;

Expand All @@ -83,9 +91,11 @@ public GenerateExtensionsJsonMojo() {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {

// Get the BOM artifact
final DefaultArtifact bomArtifact = new DefaultArtifact(bomGroupId, bomArtifactId, "", "pom", bomVersion);
debug("Generating catalog of extensions for %s", bomArtifact);
info("Generating catalog of extensions for %s", bomArtifact);

// And get all its dependencies (which are extensions)
final List<Dependency> deps;
try {
deps = repoSystem
Expand All @@ -100,6 +110,27 @@ public void execute() throws MojoExecutionException, MojoFailureException {
return;
}

// Read the overrides file for the extensions (if it exists)
Map<String, JsonObject> extOverrides = new HashMap<>();
if (overridesFile.isFile()) {
info("Found overrides file %s", overridesFile);
try (JsonReader jsonReader = Json.createReader(new FileInputStream(overridesFile))) {
JsonObject overridesObject = jsonReader.readObject();
JsonArray extOverrideObjects = overridesObject.getJsonArray("extensions");
if (extOverrideObjects != null) {
// Put the extension overrides into a map keyed to their GAV
for (JsonValue val : extOverrideObjects) {
JsonObject extOverrideObject = val.asJsonObject();
String key = extensionId(extOverrideObject);
extOverrides.put(key, extOverrideObject);
}
}
} catch (IOException e) {
throw new MojoExecutionException("Failed to read " + overridesFile, e);
}
}

// Create a JSON array of extension descriptors
final JsonArrayBuilder extListJson = Json.createArrayBuilder();
for (Dependency dep : deps) {
final Artifact artifact = dep.getArtifact();
Expand All @@ -113,7 +144,15 @@ public void execute() throws MojoExecutionException, MojoFailureException {
try {
resolved = repoSystem.resolveArtifact(repoSession,
new ArtifactRequest().setRepositories(repos).setArtifact(artifact));
processDependency(resolved.getArtifact(), extListJson);
JsonObject extObject = processDependency(resolved.getArtifact());
if (extObject != null) {
String key = extensionId(extObject);
JsonObject extOverride = extOverrides.get(key);
if (extOverride != null) {
extObject = mergeObject(extObject, extOverride);
}
extListJson.add(extObject);
}
} catch (ArtifactResolutionException e) {
// there are some parent poms that appear as jars for some reason
debug("Failed to resolve dependency %s defined in %s", artifact, bomArtifact);
Expand All @@ -122,14 +161,18 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}

// Create the toplevel JSON
final JsonObjectBuilder platformJson = Json.createObjectBuilder();
// Add information about the BOM to it
final JsonObjectBuilder bomJson = Json.createObjectBuilder();
bomJson.add("groupId", bomGroupId);
bomJson.add("artifactId", bomArtifactId);
bomJson.add("version", bomVersion);
platformJson.add("bom", bomJson.build());
// And add the list of extensions
platformJson.add("extensions", extListJson.build());

// Write the JSON to the output file
final File outputDir = outputFile.getParentFile();
if (!outputDir.exists()) {
if (!outputDir.mkdirs()) {
Expand All @@ -143,56 +186,99 @@ public void execute() throws MojoExecutionException, MojoFailureException {
} catch (IOException e) {
throw new MojoExecutionException("Failed to persist " + outputFile, e);
}
info("Extensions file written to %s", outputFile);

projectHelper.attachArtifact(project, "json", null, outputFile);
}

private void processDependency(Artifact artifact, JsonArrayBuilder extJsonBuilder) throws IOException {
private JsonObject processDependency(Artifact artifact) throws IOException {
final Path path = artifact.getFile().toPath();
if (Files.isDirectory(path)) {
processMetaInfDir(artifact, path.resolve(BootstrapConstants.META_INF), extJsonBuilder);
return processMetaInfDir(artifact, path.resolve(BootstrapConstants.META_INF));
} else {
try (FileSystem artifactFs = ZipUtils.newFileSystem(path)) {
processMetaInfDir(artifact, artifactFs.getPath(BootstrapConstants.META_INF), extJsonBuilder);
return processMetaInfDir(artifact, artifactFs.getPath(BootstrapConstants.META_INF));
}
}
}

private boolean processMetaInfDir(Artifact artifact, Path metaInfDir, JsonArrayBuilder extJsonBuilder)
private JsonObject processMetaInfDir(Artifact artifact, Path metaInfDir)
throws IOException {
if (!Files.exists(metaInfDir)) {
return false;
return null;
}
final Path p = metaInfDir.resolve(BootstrapConstants.EXTENSION_PROPS_JSON_FILE_NAME);
if (!Files.exists(p)) {
final Path props = metaInfDir.resolve(BootstrapConstants.DESCRIPTOR_FILE_NAME);
if (Files.exists(props)) {
extJsonBuilder.add(Json.createObjectBuilder()
return Json.createObjectBuilder()
.add("artifactId", artifact.getArtifactId())
.add("groupId", artifact.getGroupId())
.add("version", artifact.getVersion())
.add("name", artifact.getArtifactId())
.build());
.build();
}
return false;
return null;
}
processPlatformArtifact(artifact, p, extJsonBuilder);
return true;
return processPlatformArtifact(artifact, p);
}

private void processPlatformArtifact(Artifact artifact, Path descriptor, JsonArrayBuilder extJsonBuilder)
private JsonObject processPlatformArtifact(Artifact artifact, Path descriptor)
throws IOException {
try (InputStream is = Files.newInputStream(descriptor)) {
try (JsonReader reader = Json.createReader(is)) {
final JsonObject object = reader.readObject();
debug("Adding Quarkus extension %s:%s", object.get("groupId"), object.get("artifactId"));
extJsonBuilder.add(object);
return object;
}
} catch (IOException e) {
throw new IOException("Failed to parse " + descriptor, e);
}
}

private String extensionId(JsonObject extObject) {
String artId = extObject.getString("artifactId", "");
if (artId.isEmpty()) {
getLog().warn("Missing artifactId in extension overrides");
}
String groupId = extObject.getString("artifactId", "");
if (groupId.isEmpty()) {
return artId;
} else {
return extObject.getString("groupId", "") + ":" + artId;
}
}

private JsonObject mergeObject(JsonObject extObject, JsonObject extOverride) {
final JsonObjectBuilder mergedObject = Json.createObjectBuilder();
for (Map.Entry<String, JsonValue> e : extOverride.entrySet()) {
JsonValue.ValueType tp = e.getValue().getValueType();
if (tp == JsonValue.ValueType.OBJECT
&& extObject.containsKey(e.getKey())
&& extObject.get(e.getKey()).getValueType() == JsonValue.ValueType.OBJECT) {
mergedObject.add(e.getKey(),
mergeObject(extObject.get(e.getKey()).asJsonObject(), e.getValue().asJsonObject()));
} else if (tp == JsonValue.ValueType.ARRAY) {
final JsonArrayBuilder newArray = Json.createArrayBuilder(e.getValue().asJsonArray());
mergedObject.add(e.getKey(), newArray.build());
} else {
mergedObject.add(e.getKey(), e.getValue());
}
}
return mergedObject.build();
}

private void info(String msg, Object... args) {
if (!getLog().isInfoEnabled()) {
return;
}
if (args.length == 0) {
getLog().info(msg);
return;
}
getLog().info(String.format(msg, args));
}

private void debug(String msg, Object... args) {
if (!getLog().isDebugEnabled()) {
return;
Expand Down

0 comments on commit 0e6f1f1

Please sign in to comment.