|
| 1 | +/* |
| 2 | + * Licensed to Elasticsearch B.V. under one or more contributor |
| 3 | + * license agreements. See the NOTICE file distributed with |
| 4 | + * this work for additional information regarding copyright |
| 5 | + * ownership. Elasticsearch B.V. licenses this file to you under |
| 6 | + * the Apache License, Version 2.0 (the "License"); you may |
| 7 | + * not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, |
| 13 | + * software distributed under the License is distributed on an |
| 14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | + * KIND, either express or implied. See the License for the |
| 16 | + * specific language governing permissions and limitations |
| 17 | + * under the License. |
| 18 | + */ |
| 19 | + |
| 20 | +import com.github.jk1.license.ProjectData |
| 21 | +import com.github.jk1.license.render.LicenseDataCollector |
| 22 | +import com.github.jk1.license.render.ReportRenderer |
| 23 | +import java.io.File |
| 24 | +import java.io.FileWriter |
| 25 | + |
| 26 | +plugins { |
| 27 | + java |
| 28 | + `java-library` |
| 29 | + checkstyle |
| 30 | + `maven-publish` |
| 31 | + id("com.github.jk1.dependency-license-report") version "2.2" |
| 32 | + id("de.thetaphi.forbiddenapis") version "3.4" |
| 33 | +} |
| 34 | + |
| 35 | +// GitHub Maven repo doesn't like 1.0.0+20231031-SNAPSHOT |
| 36 | +version = "1.0.0-20231031-SNAPSHOT" |
| 37 | + |
| 38 | +java { |
| 39 | + targetCompatibility = JavaVersion.VERSION_1_8 |
| 40 | + sourceCompatibility = JavaVersion.VERSION_1_8 |
| 41 | + |
| 42 | + withJavadocJar() |
| 43 | + withSourcesJar() |
| 44 | +} |
| 45 | + |
| 46 | +sourceSets { |
| 47 | + main { |
| 48 | + java.srcDir("src/main-flavored/java") |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +forbiddenApis { |
| 53 | + signaturesFiles = files(File(rootProject.projectDir, "config/forbidden-apis.txt")) |
| 54 | + suppressAnnotations = setOf("co.elastic.clients.util.AllowForbiddenApis") |
| 55 | +} |
| 56 | + |
| 57 | +tasks.forbiddenApisMain { |
| 58 | + bundledSignatures = setOf("jdk-system-out") |
| 59 | +} |
| 60 | + |
| 61 | +tasks.getByName<ProcessResources>("processResources") { |
| 62 | + eachFile { |
| 63 | + if (name != "apis.json") { |
| 64 | + // Only process main source-set resources (test files are large) |
| 65 | + expand( |
| 66 | + "version" to version, |
| 67 | + "git_revision" to (if (rootProject.extra.has("gitHashFull")) rootProject.extra["gitHashFull"] else "unknown") |
| 68 | + ) |
| 69 | + } |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +tasks.withType<Test> { |
| 74 | + useJUnitPlatform() |
| 75 | +} |
| 76 | + |
| 77 | +tasks.withType<Jar> { |
| 78 | + doFirst { |
| 79 | + if (rootProject.extra.has("gitHashFull")) { |
| 80 | + val jar = this as Jar |
| 81 | + jar.manifest.attributes["X-Git-Revision"] = rootProject.extra["gitHashFull"] |
| 82 | + jar.manifest.attributes["X-Git-Commit-Time"] = rootProject.extra["gitCommitTime"] |
| 83 | + } else { |
| 84 | + throw GradleException("No git information available") |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + manifest { |
| 89 | + attributes["Implementation-Title"] = "Elasticsearch Java client (Serverless edition)" |
| 90 | + attributes["Implementation-Vendor"] = "Elastic" |
| 91 | + attributes["Implementation-URL"] = "https://github.com/elastic/elasticsearch-java/" |
| 92 | + attributes["Build-Date"] = rootProject.extra["buildTime"] |
| 93 | + } |
| 94 | + |
| 95 | + metaInf { |
| 96 | + from("../LICENSE.txt") |
| 97 | + from("../NOTICE.txt") |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +tasks.withType<Javadoc> { |
| 102 | + val opt = options as StandardJavadocDocletOptions |
| 103 | + // Gradle calls javadoc with a list of file and not a path. This prevents doc-files from being copied. |
| 104 | + opt.addStringOption("sourcepath", project.projectDir.path + "/src/main/java") |
| 105 | + opt.docFilesSubDirs(true) |
| 106 | + opt.addBooleanOption("Xdoclint:-missing", true) |
| 107 | + |
| 108 | + doLast { |
| 109 | + // Javadoc adds its decoration to html doc files, including quite some JS. This slows down the api spec |
| 110 | + // redirector that doesn't need it. So overwrite the target file with the original one. |
| 111 | + val specFile = "co/elastic/clients/elasticsearch/doc-files/api-spec.html" |
| 112 | + val source = File(project.projectDir, "src/main/java/" + specFile) |
| 113 | + val target = File(project.projectDir, "build/docs/javadoc/" + specFile) |
| 114 | + source.copyTo(target, overwrite = true) |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +publishing { |
| 119 | + repositories { |
| 120 | + maven { |
| 121 | + // See https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry |
| 122 | + // and https://docs.gradle.org/current/samples/sample_publishing_credentials.html |
| 123 | + name = "ESJavaGithubPackages" |
| 124 | + url = uri("https://maven.pkg.github.com/elastic/elasticsearch-java") |
| 125 | + credentials(PasswordCredentials::class) |
| 126 | + } |
| 127 | + |
| 128 | + maven { |
| 129 | + name = "Build" |
| 130 | + url = uri("${rootProject.buildDir}/repository") |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + publications { |
| 135 | + register<MavenPublication>("maven") { |
| 136 | + from(components["java"]) |
| 137 | + pom { |
| 138 | + name.set("Elasticsearch Java API Client (Serverless edition)") |
| 139 | + artifactId = "elasticsearch-java-serverless" |
| 140 | + description.set("Java API Client for Elasticsearch Serverless") |
| 141 | + url.set("https://github.com/elastic/elasticsearch-java/") |
| 142 | + licenses { |
| 143 | + license { |
| 144 | + name.set("The Apache Software License, Version 2.0") |
| 145 | + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") |
| 146 | + } |
| 147 | + } |
| 148 | + developers { |
| 149 | + developer { |
| 150 | + name.set("Elastic") |
| 151 | + url.set("https://www.elastic.co") |
| 152 | + inceptionYear.set("2020") |
| 153 | + } |
| 154 | + } |
| 155 | + scm { |
| 156 | + connection.set("scm:git:https://github.com/elastic/elasticsearch-java.git") |
| 157 | + developerConnection.set( "scm:git:ssh://[email protected]:elastic/elasticsearch-java.git") |
| 158 | + url.set("https://github.com/elastic/elasticsearch-java/") |
| 159 | + } |
| 160 | + |
| 161 | +// Fixed version in Serverless. |
| 162 | +// withXml { |
| 163 | +// // Set the version of dependencies of the org.elasticsearch.client group to the one that we are building. |
| 164 | +// // Since the unified release process releases everything at once, this ensures all published artifacts depend |
| 165 | +// // on the exact same version. This assumes of course that the binary API and the behavior of these dependencies |
| 166 | +// // are the same as the one used in the dependency section below. |
| 167 | +// val xPathFactory = javax.xml.xpath.XPathFactory.newInstance() |
| 168 | +// val depSelector = xPathFactory.newXPath() |
| 169 | +// .compile("/project/dependencies/dependency[groupId/text() = 'org.elasticsearch.client']") |
| 170 | +// val versionSelector = xPathFactory.newXPath().compile("version") |
| 171 | +// |
| 172 | +// var foundVersion = false; |
| 173 | +// |
| 174 | +// val deps = depSelector.evaluate(asElement().ownerDocument, javax.xml.xpath.XPathConstants.NODESET) |
| 175 | +// as org.w3c.dom.NodeList |
| 176 | +// |
| 177 | +// for (i in 0 until deps.length) { |
| 178 | +// val dep = deps.item(i) |
| 179 | +// val version = versionSelector.evaluate(dep, javax.xml.xpath.XPathConstants.NODE) as org.w3c.dom.Element |
| 180 | +// foundVersion = true; |
| 181 | +// version.textContent = project.version.toString() |
| 182 | +// } |
| 183 | +// |
| 184 | +// if (!foundVersion) { |
| 185 | +// throw GradleException("Could not find a 'org.elasticsearch.client' to update dependency version in the POM.") |
| 186 | +// } |
| 187 | +// } |
| 188 | + } |
| 189 | + } |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +dependencies { |
| 194 | + val elasticsearchVersion = "8.9.0" |
| 195 | + val jacksonVersion = "2.13.3" |
| 196 | + val openTelemetryVersion = "1.29.0" |
| 197 | + |
| 198 | + // Apache 2.0 |
| 199 | + // https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html |
| 200 | + api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion) |
| 201 | + |
| 202 | + // Apache 2.0 |
| 203 | + // https://search.maven.org/artifact/com.google.code.findbugs/jsr305 |
| 204 | + api("com.google.code.findbugs:jsr305:3.0.2") |
| 205 | + |
| 206 | + // EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| 207 | + // https://github.com/eclipse-ee4j/jsonp |
| 208 | + api("jakarta.json:jakarta.json-api:2.0.1") |
| 209 | + |
| 210 | + // Needed even if using Jackson to have an implementation of the Jsonp object model |
| 211 | + // EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| 212 | + // https://github.com/eclipse-ee4j/parsson |
| 213 | + api("org.eclipse.parsson:parsson:1.0.0") |
| 214 | + |
| 215 | + // OpenTelemetry API for native instrumentation of the client. |
| 216 | + // Apache 2.0 |
| 217 | + // https://github.com/open-telemetry/opentelemetry-java |
| 218 | + implementation("io.opentelemetry", "opentelemetry-api", openTelemetryVersion) |
| 219 | + // Use it once it's stable (see Instrumentation.java). Limited to tests for now. |
| 220 | + testImplementation("io.opentelemetry", "opentelemetry-semconv", "$openTelemetryVersion-alpha") |
| 221 | + |
| 222 | + // EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| 223 | + // https://github.com/eclipse-ee4j/jsonb-api |
| 224 | + compileOnly("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0") |
| 225 | + testImplementation("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0") |
| 226 | + |
| 227 | + // Apache 2.0 |
| 228 | + // https://github.com/FasterXML/jackson |
| 229 | + compileOnly("com.fasterxml.jackson.core", "jackson-core", jacksonVersion) |
| 230 | + compileOnly("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion) |
| 231 | + testImplementation("com.fasterxml.jackson.core", "jackson-core", jacksonVersion) |
| 232 | + testImplementation("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion) |
| 233 | + |
| 234 | + // EPL-2.0 OR BSD-3-Clause |
| 235 | + // https://eclipse-ee4j.github.io/yasson/ |
| 236 | + testImplementation("org.eclipse", "yasson", "2.0.4") { |
| 237 | + // Exclude Glassfish as we use Parsson (basically Glassfish renamed in the Jakarta namespace). |
| 238 | + exclude(group = "org.glassfish", module = "jakarta.json") |
| 239 | + } |
| 240 | + |
| 241 | + // Apache-2.0 |
| 242 | + testImplementation("commons-io:commons-io:2.11.0") |
| 243 | + |
| 244 | + // EPL-2.0 |
| 245 | + // https://junit.org/junit5/ |
| 246 | + testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") |
| 247 | + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") |
| 248 | + |
| 249 | + // MIT |
| 250 | + // https://github.com/classgraph/classgraph |
| 251 | + testImplementation("io.github.classgraph:classgraph:4.8.147") |
| 252 | + |
| 253 | + // MIT |
| 254 | + // https://www.testcontainers.org/ |
| 255 | + testImplementation("org.testcontainers", "testcontainers", "1.17.3") |
| 256 | + testImplementation("org.testcontainers", "elasticsearch", "1.17.3") |
| 257 | + |
| 258 | + |
| 259 | + testImplementation("io.opentelemetry", "opentelemetry-sdk", openTelemetryVersion) |
| 260 | +} |
| 261 | + |
| 262 | + |
| 263 | +licenseReport { |
| 264 | + renderers = arrayOf(SpdxReporter(File(rootProject.buildDir, "release/dependencies.csv"))) |
| 265 | + excludeGroups = arrayOf("org.elasticsearch.client") |
| 266 | +} |
| 267 | + |
| 268 | +class SpdxReporter(val dest: File) : ReportRenderer { |
| 269 | + // License names to their SPDX identifier |
| 270 | + val spdxIds = mapOf( |
| 271 | + "The Apache License, Version 2.0" to "Apache-2.0", |
| 272 | + "Apache License, Version 2.0" to "Apache-2.0", |
| 273 | + "The Apache Software License, Version 2.0" to "Apache-2.0", |
| 274 | + "BSD Zero Clause License" to "0BSD", |
| 275 | + "Eclipse Public License 2.0" to "EPL-2.0", |
| 276 | + "Eclipse Public License v. 2.0" to "EPL-2.0", |
| 277 | + "Eclipse Public License - v 2.0" to "EPL-2.0", |
| 278 | + "GNU General Public License, version 2 with the GNU Classpath Exception" to "GPL-2.0 WITH Classpath-exception-2.0", |
| 279 | + "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0" to "CDDL-1.0" |
| 280 | + ) |
| 281 | + |
| 282 | + private fun quote(str: String): String { |
| 283 | + return if (str.contains(',') || str.contains("\"")) { |
| 284 | + "\"" + str.replace("\"", "\"\"") + "\"" |
| 285 | + } else { |
| 286 | + str |
| 287 | + } |
| 288 | + } |
| 289 | + |
| 290 | + override fun render(data: ProjectData?) { |
| 291 | + dest.parentFile.mkdirs() |
| 292 | + FileWriter(dest).use { out -> |
| 293 | + out.append("name,url,version,revision,license\n") |
| 294 | + data?.allDependencies?.forEach { dep -> |
| 295 | + |
| 296 | + val depVersion = dep.version |
| 297 | + val depName = dep.group + ":" + dep.name |
| 298 | + |
| 299 | + val info = LicenseDataCollector.multiModuleLicenseInfo(dep) |
| 300 | + val depUrl = info.moduleUrls.first() |
| 301 | + |
| 302 | + val licenseIds = info.licenses.mapNotNull { license -> |
| 303 | + license.name?.let { |
| 304 | + checkNotNull(spdxIds[it]) { "No SPDX identifier for $license" } |
| 305 | + } |
| 306 | + }.toSet() |
| 307 | + |
| 308 | + // Combine multiple licenses. |
| 309 | + // See https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/#composite-license-expressions |
| 310 | + val licenseId = licenseIds.joinToString(" OR ") |
| 311 | + |
| 312 | + out.append("${quote(depName)},${quote(depUrl)},${quote(depVersion)},,${quote(licenseId)}\n") |
| 313 | + } |
| 314 | + } |
| 315 | + } |
| 316 | +} |
0 commit comments