forked from quarkusio/quarkus
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
maven plugin goal generating extensions.json for a BOM
- Loading branch information
1 parent
bd3e6d7
commit c80e58e
Showing
5 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
245 changes: 245 additions & 0 deletions
245
devtools/maven/src/main/java/io/quarkus/maven/GenerateExtensionsJsonMojo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
package io.quarkus.maven; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.nio.file.FileSystem; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Properties; | ||
|
||
import javax.json.Json; | ||
import javax.json.JsonArrayBuilder; | ||
import javax.json.JsonObjectBuilder; | ||
import javax.json.JsonWriter; | ||
import javax.json.JsonWriterFactory; | ||
import javax.json.stream.JsonGenerator; | ||
|
||
import org.apache.maven.plugin.AbstractMojo; | ||
import org.apache.maven.plugin.MojoExecutionException; | ||
import org.apache.maven.plugin.MojoFailureException; | ||
import org.apache.maven.plugins.annotations.Component; | ||
import org.apache.maven.plugins.annotations.Mojo; | ||
import org.apache.maven.plugins.annotations.Parameter; | ||
import org.apache.maven.project.MavenProject; | ||
import org.eclipse.aether.RepositorySystem; | ||
import org.eclipse.aether.RepositorySystemSession; | ||
import org.eclipse.aether.artifact.Artifact; | ||
import org.eclipse.aether.artifact.DefaultArtifact; | ||
import org.eclipse.aether.graph.Dependency; | ||
import org.eclipse.aether.repository.RemoteRepository; | ||
import org.eclipse.aether.resolution.ArtifactDescriptorException; | ||
import org.eclipse.aether.resolution.ArtifactDescriptorRequest; | ||
import org.eclipse.aether.resolution.ArtifactRequest; | ||
import org.eclipse.aether.resolution.ArtifactResolutionException; | ||
import org.eclipse.aether.resolution.ArtifactResult; | ||
|
||
import io.quarkus.bootstrap.BootstrapConstants; | ||
import io.quarkus.bootstrap.BootstrapDependencyProcessingException; | ||
import io.quarkus.bootstrap.resolver.maven.DeploymentInjectionException; | ||
import io.quarkus.bootstrap.util.ZipUtils; | ||
|
||
/** | ||
* This goal generates a list of extensions for a given BOM | ||
* and stores it in a JSON format file that is later used by the tools | ||
* as the catalog of available extensions. | ||
*/ | ||
@Mojo(name = "generate-extensions-json") | ||
public class GenerateExtensionsJsonMojo extends AbstractMojo { | ||
|
||
private static final String PROP_ARTIFACT_ID = "artifactId"; | ||
private static final String PROP_GROUP_ID = "groupId"; | ||
private static final String PROP_GUIDE = "guide"; | ||
private static final String PROP_LABELS = "labels"; | ||
private static final String PROP_NAME = "name"; | ||
private static final String PROP_SHORT_NAME = "shortName"; | ||
|
||
@Parameter(property = "bomGroupId", defaultValue = "io.quarkus") | ||
private String bomGroupId; | ||
|
||
@Parameter(property = "bomArtifactId", defaultValue = "quarkus-bom") | ||
private String bomArtifactId; | ||
|
||
@Parameter(property = "bomVersion", defaultValue = "${project.version}") | ||
private String bomVersion; | ||
|
||
@Parameter(property = "outputFile", defaultValue = "${project.build.directory}/extensions.json") | ||
private File outputFile; | ||
|
||
@Component | ||
private RepositorySystem repoSystem; | ||
|
||
@Parameter(defaultValue = "${repositorySystemSession}", readonly = true) | ||
private RepositorySystemSession repoSession; | ||
|
||
@Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true) | ||
private List<RemoteRepository> repos; | ||
|
||
@Component | ||
private MavenProject project; | ||
|
||
public GenerateExtensionsJsonMojo() { | ||
MojoLogger.logSupplier = this::getLog; | ||
} | ||
|
||
@Override | ||
public void execute() throws MojoExecutionException, MojoFailureException { | ||
|
||
final DefaultArtifact bomArtifact = new DefaultArtifact(bomGroupId, bomArtifactId, "", "pom", bomVersion); | ||
debug("Generating catalog of extensions for %s", bomArtifact); | ||
|
||
final List<Dependency> deps; | ||
try { | ||
deps = repoSystem | ||
.readArtifactDescriptor(repoSession, | ||
new ArtifactDescriptorRequest().setRepositories(repos).setArtifact(bomArtifact)) | ||
.getManagedDependencies(); | ||
} catch (ArtifactDescriptorException e) { | ||
throw new MojoExecutionException("Failed to read descriptor of " + bomArtifact, e); | ||
} | ||
if (deps.isEmpty()) { | ||
getLog().warn("BOM " + bomArtifact + " does not include any dependency"); | ||
return; | ||
} | ||
|
||
/* | ||
* final List<ArtifactRequest> requests = deps.stream() | ||
* .map(d -> new ArtifactRequest() | ||
* .setArtifact(d.getArtifact()) | ||
* .setRepositories(repos)) | ||
* .collect(Collectors.toList()); | ||
* final List<ArtifactResult> resolvedDeps; | ||
* try { | ||
* resolvedDeps = repoSystem.resolveArtifacts(repoSession, requests); | ||
* } catch (ArtifactResolutionException e) { | ||
* throw new MojoExecutionException("Failed to resolve dependencies defined in " + bomArtifact, e); | ||
* } | ||
* | ||
* for (ArtifactResult resolved : resolvedDeps) { | ||
* if (!resolved.getArtifact().getExtension().equals("jar")) { | ||
* continue; | ||
* } | ||
* processDependency(resolved.getArtifact().getFile().toPath()); | ||
* } | ||
*/ | ||
|
||
final JsonArrayBuilder extJsonBuilder = Json.createArrayBuilder(); | ||
for (Dependency dep : deps) { | ||
if (!dep.getArtifact().getExtension().equals("jar")) { | ||
continue; | ||
} | ||
ArtifactResult resolved = null; | ||
try { | ||
resolved = repoSystem.resolveArtifact(repoSession, | ||
new ArtifactRequest().setRepositories(repos).setArtifact(dep.getArtifact())); | ||
} catch (ArtifactResolutionException e) { | ||
getLog().error("Failed to resolve dependency " + dep.getArtifact() + " defined in " + bomArtifact); | ||
//throw new MojoExecutionException("Failed to resolve dependency " + dep.getArtifact() + " defined in " + bomArtifact, e); | ||
} | ||
if (resolved != null) { | ||
processDependency(resolved.getArtifact(), extJsonBuilder); | ||
} | ||
} | ||
|
||
final JsonWriterFactory jsonWriterFactory = Json | ||
.createWriterFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true)); | ||
try (JsonWriter jsonWriter = jsonWriterFactory.createWriter(new FileOutputStream(outputFile))) { | ||
jsonWriter.writeArray(extJsonBuilder.build()); | ||
} catch (IOException e) { | ||
throw new MojoExecutionException("Failed to persist " + outputFile, e); | ||
} | ||
} | ||
|
||
private void processDependency(Artifact artifact, JsonArrayBuilder extJsonBuilder) { | ||
final Path path = artifact.getFile().toPath(); | ||
try { | ||
if (Files.isDirectory(path)) { | ||
processMetaInfDir(artifact, path.resolve(BootstrapConstants.META_INF), extJsonBuilder); | ||
} else { | ||
try (FileSystem artifactFs = ZipUtils.newFileSystem(path)) { | ||
processMetaInfDir(artifact, artifactFs.getPath(BootstrapConstants.META_INF), extJsonBuilder); | ||
} | ||
} | ||
} catch (Throwable t) { | ||
throw new DeploymentInjectionException("Failed to inject extension deplpyment dependencies", t); | ||
} | ||
} | ||
|
||
private boolean processMetaInfDir(Artifact artifact, Path metaInfDir, JsonArrayBuilder extJsonBuilder) | ||
throws BootstrapDependencyProcessingException { | ||
if (!Files.exists(metaInfDir)) { | ||
return false; | ||
} | ||
final Path p = metaInfDir.resolve(BootstrapConstants.DESCRIPTOR_FILE_NAME); | ||
if (!Files.exists(p)) { | ||
return false; | ||
} | ||
processPlatformArtifact(artifact, p, extJsonBuilder); | ||
return true; | ||
} | ||
|
||
private void processPlatformArtifact(Artifact artifact, Path descriptor, JsonArrayBuilder extJsonBuilder) | ||
throws BootstrapDependencyProcessingException { | ||
final Properties extProps = resolveDescriptor(descriptor); | ||
if (extProps == null) { | ||
return; | ||
} | ||
debug("Adding Quarkus extension %s", artifact); | ||
|
||
final JsonObjectBuilder jsonExtBuilder = Json.createObjectBuilder() | ||
.add(PROP_GROUP_ID, artifact.getGroupId()) | ||
.add(PROP_ARTIFACT_ID, artifact.getArtifactId()); | ||
|
||
addJsonProp(PROP_NAME, extProps, jsonExtBuilder); | ||
addJsonProp(PROP_SHORT_NAME, extProps, jsonExtBuilder); | ||
addJsonProp(PROP_GUIDE, extProps, jsonExtBuilder); | ||
|
||
final String labelsStr = extProps.getProperty(PROP_LABELS); | ||
if (labelsStr != null) { | ||
final JsonArrayBuilder jsonArr = Json.createArrayBuilder(); | ||
for (String label : labelsStr.split("\\s*,\\s*")) { | ||
jsonArr.add(label); | ||
} | ||
jsonExtBuilder.add(PROP_LABELS, jsonArr.build()); | ||
} | ||
|
||
extJsonBuilder.add(jsonExtBuilder.build()); | ||
} | ||
|
||
private static void addJsonProp(String name, Properties props, JsonObjectBuilder builder) { | ||
final String value = props.getProperty(name); | ||
if (value == null) { | ||
return; | ||
} | ||
builder.add(name, value); | ||
} | ||
|
||
private Properties resolveDescriptor(final Path path) throws BootstrapDependencyProcessingException { | ||
final Properties rtProps; | ||
if (!Files.exists(path)) { | ||
// not a platform artifact | ||
return null; | ||
} | ||
rtProps = new Properties(); | ||
try (BufferedReader reader = Files.newBufferedReader(path)) { | ||
rtProps.load(reader); | ||
} catch (IOException e) { | ||
throw new BootstrapDependencyProcessingException("Failed to load " + path, e); | ||
} | ||
return rtProps; | ||
} | ||
|
||
private void debug(String msg, Object... args) { | ||
if (!getLog().isDebugEnabled()) { | ||
return; | ||
} | ||
if (args.length == 0) { | ||
getLog().debug(msg); | ||
return; | ||
} | ||
getLog().debug(String.format(msg, args)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters