Skip to content

Commit

Permalink
feat: support for BOM POM's i.e. maven dependencyManagement (#673)
Browse files Browse the repository at this point in the history
jbang will now if and only if the very first dependency has a `@pom`
classifier, download it and load it as pom file in shrinkwrap.

Example:

```java
//DEPS io.quarkus:quarkus-bom:1.11.0.Final@pom
//DEPS io.quarkus:quarkus-resteasy
//DEPS io.quarkus:quarkus-smallrye-openapi
//DEPS io.quarkus:quarkus-swagger-ui
```

Then that pom file dependency management (and dependencies) gets listened to.

Fixes #63
  • Loading branch information
maxandersen authored Jan 17, 2021
1 parent 6da988e commit 2d81c74
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 21 deletions.
15 changes: 11 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ dependencies {
implementation 'org.codehaus.plexus:plexus-java:1.0.5'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'org.jsoup:jsoup:1.13.1'
implementation 'org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-api:3.1.4'
implementation 'org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven:3.1.4'

implementation 'com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-api:3.1.5-allowpom'
implementation 'com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-impl-maven:3.1.5-allowpom'

//implementation 'org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-api:3.1.4'
//implementation 'org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven:3.1.4'
implementation "org.slf4j:slf4j-nop:1.7.30"
implementation "org.jboss:jandex:2.2.2.Final"
//implementation 'org.apache.maven:maven-aether-provider:3.0.5'
Expand Down Expand Up @@ -145,8 +149,11 @@ compileTestJava {

shadowJar {
minimize() {
exclude(dependency('org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-spi:.*'))
exclude(dependency('org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven:.*'))
//exclude(dependency('org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-spi:.*'))
//exclude(dependency('org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven:.*'))
exclude(dependency('com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-spi:.*'))
exclude(dependency('com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-impl-maven:.*'))

//exclude(dependency('org.slf4j:slf4j-api:.*'))
exclude(dependency('org.slf4j:slf4j-nop:.*'))
exclude(dependency('org.jboss.logging:jboss-logging:.*'))
Expand Down
22 changes: 22 additions & 0 deletions readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,28 @@ $ ./classpath_example.java
1 [main] INFO classpath_example - Hello from Java!
----

=== Managed dependencies ("BOM POM"'s) [Experimental]

When using libraries and frameworks it can get tedious to mange and update multiple versions.
For that jbang started since 0.62 to support so called "BOM POM"'s which are commonly used for managing versions.

You use it by having as the very first dependency a `@pom` reference. This first reference will be used
to define your managed dependences. Below is an example how that could look like when using Quarkus:

```java
//DEPS io.quarkus:quarkus-bom:1.11.0.Final@pom
//DEPS io.quarkus:quarkus-resteasy
//DEPS io.quarkus:quarkus-smallrye-openapi
//DEPS io.quarkus:quarkus-swagger-ui
```

Notice the `@pom` at first line and then following dependencies are not required to use explicit versions.

[NOTE]
At the moment jbang support only one bom pom; in future it should be expanded to multiple.
For now you can workaround this by reusing a published pom that includes all the dependency management
sections you need.

=== Using links to Git sources

Instead of gradle-style locators you can also use URLs to projects on GitHub, GitLab or BitBucket.
Expand Down
50 changes: 46 additions & 4 deletions src/main/java/dev/jbang/DependencyUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
import org.jboss.shrinkwrap.resolver.api.maven.MavenFormatStage;
import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact;
import org.jboss.shrinkwrap.resolver.api.maven.MavenStrategyStage;
import org.jboss.shrinkwrap.resolver.api.maven.MavenWorkingSession;
import org.jboss.shrinkwrap.resolver.api.maven.PackagingType;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinate;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinates;
import org.jboss.shrinkwrap.resolver.impl.maven.MavenWorkingSessionContainer;

public class DependencyUtil {

Expand All @@ -42,9 +45,12 @@ public class DependencyUtil {
aliasToRepos.put("sponge", "https://repo.spongepowered.org/maven");
}

public static final Pattern gavPattern = Pattern.compile(
public static final Pattern fullGavPattern = Pattern.compile(
"^(?<groupid>[^:]*):(?<artifactid>[^:]*):(?<version>[^:@]*)(:(?<classifier>[^@]*))?(@(?<type>.*))?$");

public static final Pattern gavPattern = Pattern.compile(
"^(?<groupid>[^:]*):(?<artifactid>[^:]*)(:(?<version>[^:@]*))?(:(?<classifier>[^@]*))?(@(?<type>.*))?$");

public ModularClassPath resolveDependencies(List<String> deps, List<MavenRepo> repos,
boolean offline, boolean loggingEnabled) {
return resolveDependencies(deps, repos, offline, loggingEnabled, true);
Expand Down Expand Up @@ -131,26 +137,62 @@ public List<ArtifactInfo> resolveDependenciesViaAether(List<String> depIds, List
mavenRepo.apply(resolver);
});

MavenWorkingSession xyz = ((MavenWorkingSessionContainer) resolver).getMavenWorkingSession();
System.setProperty("maven.repo.local", Settings.getLocalMavenRepo().toPath().toAbsolutePath().toString());

List<MavenCoordinate> deps = depIds.stream().map(it -> depIdToArtifact(it)).collect(Collectors.toList());

PomEquippedResolveStage pomResolve = null;

if (!depIds.isEmpty()) {
MavenCoordinate mc = depIdToArtifact(depIds.get(0));
if (PackagingType.POM.equals(mc.getType())) {
if (loggingEnabled) {
infoMsg("Loading " + mc);
}
System.setProperty("jbang-allowpom", "true"); // big hack to trick shrinkwrap in actually get pom
// location
MavenStrategyStage resolve = resolver.resolve(mc.toCanonicalForm());
pomResolve = resolver.loadPomFromFile(resolve.withoutTransitivity().asSingleFile());
System.getProperties().remove("jbang-allowpom");
depIds.remove(0);
}
}

final PomEquippedResolveStage ps = pomResolve;

return depIds.stream().flatMap(it -> {

MavenCoordinate artifact = depIdToArtifact(it);

if (PackagingType.POM.equals(artifact.getType())) {
// proactively avoiding that we break users in future
// when we support more than one BOM POM
throw new ExitException(1, "POM imports as found in " + it + " is only supported as the first import.");
}

if (loggingEnabled) {
infoHeader();
infoMsgFmt(" Resolving %s...", it);
}

List<MavenResolvedArtifact> artifacts;
try {
MavenStrategyStage resolve = resolver.resolve(depIdToArtifact(it).toCanonicalForm());
MavenStrategyStage resolve;
MavenFormatStage stage = null;
if (ps != null) {
resolve = ps.resolve(artifact.toCanonicalForm());
} else {
resolve = resolver.resolve(artifact.toCanonicalForm());
}

if (transitively) {
stage = resolve.withTransitivity();
} else {
stage = resolve.withoutTransitivity();
}
artifacts = stage.asList(MavenResolvedArtifact.class); // , RUNTIME);

} catch (RuntimeException e) {
throw new ExitException(1, "Could not resolve dependency", e);
}
Expand All @@ -177,7 +219,7 @@ public String decodeEnv(String value) {
}

public static boolean looksLikeAGav(String candidate) {
Matcher gav = gavPattern.matcher(candidate);
Matcher gav = fullGavPattern.matcher(candidate);
gav.find();
return (gav.matches());
}
Expand Down Expand Up @@ -211,7 +253,7 @@ public MavenCoordinate depIdToArtifact(String depId) {

public String formatVersion(String version) {
// replace + with open version range for maven
if (version.endsWith("+")) {
if (version != null && version.endsWith("+")) {
return "[" + removeLastCharOptional(version) + ",)";
} else {
return version;
Expand Down
26 changes: 13 additions & 13 deletions src/test/java/dev/jbang/DependencyResolverTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,18 +213,18 @@ protected boolean supportsModules(String requestedVersion) {

/*
* @Ignore("BOM import not yet figured out with shrinkwrap")
*
* @Test void testImportPOM() {
*
* List<String> deps =
* Arrays.asList("com.microsoft.azure:azure-bom:1.0.0.M1@pom",
* "com.microsoft.azure:azure");
*
* String classpath = new DependencyUtil().resolveDependencies(deps,
* Collections.emptyList(), false, true);
*
* assertEquals(46, classpath.split(Settings.CP_SEPARATOR).length);
*
* }
*/
@Test
void testImportPOM() {

List<String> deps = Arrays.asList("com.microsoft.azure:azure-bom:1.0.0.M1@pom",
"com.microsoft.azure:azure");

ModularClassPath classpath = new DependencyUtil().resolveDependencies(deps,
Collections.emptyList(), false, true);

assertEquals(62, classpath.getArtifacts().size());

}

}

0 comments on commit 2d81c74

Please sign in to comment.