1- group = " org.mongodb"
2- description = " This Bill of Materials POM simplifies dependency management when referencing multiple" +
3- " MongoDB Java Driver artifacts in projects using Gradle or Maven."
1+ /*
2+ * Copyright 2008-present MongoDB, Inc.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+ import ProjectExtensions.configureMavenPublication
17+ import groovy.util.Node
18+ import groovy.util.NodeList
19+
20+ plugins {
21+ id(" java-platform" )
22+ id(" project.base" )
23+ id(" conventions.publishing" )
24+ id(" conventions.spotless" )
25+ }
26+
27+ base.archivesName.set(" mongodb-driver-bom" )
428
529dependencies {
630 constraints {
@@ -21,3 +45,109 @@ dependencies {
2145 api(project(" :driver-scala" ))
2246 }
2347}
48+
49+ /*
50+ * Handle the multiple versions of Scala we support as defined in `gradle.properties`
51+ */
52+ val defaultScalaVersion: String = project.findProperty(" defaultScalaVersion" )!! .toString()
53+ val scalaVersions: List <String >? = project.findProperty(" supportedScalaVersions" )?.toString()?.split(" ," )
54+
55+ assert (! scalaVersions.isNullOrEmpty()) {
56+ " Scala versions must be provided as a comma-separated list in the 'supportedScalaVersions' project property"
57+ }
58+
59+ /*
60+ * Apply the Java Platform plugin to create the BOM
61+ * Modify the generated POM to include all supported versions of Scala for driver-scala or bson-scala.
62+ */
63+ configureMavenPublication {
64+ components.findByName(" javaPlatform" )?.let { from(it) }
65+
66+ pom {
67+ name.set(" bom" )
68+ description.set(
69+ " This Bill of Materials POM simplifies dependency management when referencing multiple MongoDB Java Driver artifacts in projects using Gradle or Maven." )
70+
71+ withXml {
72+ val pomXml: Node = asNode()
73+
74+ val dependencyManagementNode = pomXml.getNode(" dependencyManagement" )
75+ assert (dependencyManagementNode != null ) {
76+ " <dependencyManagement> node not found in the generated BOM POM"
77+ }
78+ val dependenciesNode = dependencyManagementNode.getNode(" dependencies" )
79+ assert (dependenciesNode != null ) { " <dependencies> node not found in the generated BOM POM" }
80+
81+ val existingScalaDeps =
82+ dependenciesNode!!
83+ .children()
84+ .map { it as Node }
85+ .filter { it.getNode(" artifactId" )?.text()?.contains(" scala" ) ? : false }
86+
87+ existingScalaDeps.forEach {
88+ val groupId: String = it.getNode(" groupId" )!! .text()
89+ val originalArtifactId: String = it.getNode(" artifactId" )!! .text()
90+ val artifactVersion: String = it.getNode(" version" )!! .text()
91+
92+ // Add multiple versions with Scala suffixes for each Scala-related dependency.
93+ scalaVersions!! .forEach { scalaVersion ->
94+ if (scalaVersion != defaultScalaVersion) {
95+ // Replace scala version suffix
96+ val newArtifactId: String = originalArtifactId.replace(defaultScalaVersion, scalaVersion)
97+ val dependencyNode = dependenciesNode.appendNode(" dependency" )
98+ dependencyNode.appendNode(" groupId" , groupId)
99+ dependencyNode.appendNode(" artifactId" , newArtifactId)
100+ dependencyNode.appendNode(" version" , artifactVersion)
101+ }
102+ }
103+ }
104+ }
105+ }
106+ }
107+
108+ /*
109+ * Validate the BOM file.
110+ */
111+ tasks.withType<GenerateMavenPom > {
112+ doLast {
113+ pom.withXml {
114+ val pomXml: Node = asNode()
115+ val dependenciesNode = pomXml.getNode(" dependencyManagement" ).getNode(" dependencies" )
116+ assert (dependenciesNode!! .children().isNotEmpty()) {
117+ " BOM must contain more then one <dependency> element:\n $destination "
118+ }
119+
120+ dependenciesNode
121+ .children()
122+ .map { it as Node }
123+ .forEach {
124+ val groupId: String = it.getNode(" groupId" )!! .text()
125+ assert (groupId.startsWith(" org.mongodb" )) {
126+ " BOM must contain only 'org.mongodb' dependencies, but found '$groupId ':\n $destination "
127+ }
128+
129+ /*
130+ * The <scope> and <optional> tags should be omitted in BOM dependencies.
131+ * This ensures that consuming projects have the flexibility to decide whether a dependency is optional in their context.
132+ *
133+ * The BOM's role is to provide version information, not to dictate inclusion or exclusion of dependencies.
134+ */
135+ assert (it.getNode(" scope" ) == null ) {
136+ " BOM must not contain <scope> elements in dependency:\n $destination "
137+ }
138+ assert (it.getNode(" optional" ) == null ) {
139+ " BOM must not contain <optional> elements in dependency:\n $destination "
140+ }
141+ }
142+ }
143+ }
144+ }
145+
146+ /* * A node lookup helper. */
147+ private fun Node?.getNode (nodeName : String ): Node ? {
148+ val found = this ?.get(nodeName)
149+ if (found is NodeList && found.isNotEmpty()) {
150+ return found[0 ] as Node
151+ }
152+ return null
153+ }
0 commit comments