Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate mongodb-crypt module #1487

Merged
merged 27 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ceb18e5
Integrate mongodb-crypt module into mongo-java-driver as a new Gradle…
vbabanin Aug 27, 2024
fb7c733
Integrate mongocrypt tests.
vbabanin Aug 27, 2024
0750e20
Prevent downloading binaries on each local run.
vbabanin Aug 27, 2024
578a0a8
Merge branch 'master' into JAVA-5582
vbabanin Aug 28, 2024
4d967e3
Update manifest.
vbabanin Aug 28, 2024
ed15a21
Merge branch 'master' into JAVA-5582
vbabanin Aug 30, 2024
b71f621
Add slf4j to manifest.
vbabanin Aug 30, 2024
1233c1b
Remove gitignore due to having one in root directory.
vbabanin Aug 30, 2024
cc32a17
- Fix checkstyle issues.
vbabanin Sep 9, 2024
b8bad4e
Remove redundant benchmark.
vbabanin Sep 9, 2024
ee7d96c
Fix checkstyle issues.
vbabanin Sep 10, 2024
1e38914
Ensure incremental builds for unzip and downloadJava tasks.
vbabanin Sep 10, 2024
a99def1
Remove redundant configs.
vbabanin Sep 11, 2024
d390438
Format code.
vbabanin Sep 11, 2024
fb6f31f
Merge branch 'master' into JAVA-5582
vbabanin Sep 11, 2024
070fba8
Move mongocrypt benchmark.
vbabanin Sep 11, 2024
5495133
Delete whole resources dir instead of individual files.
vbabanin Sep 12, 2024
b0438fd
Add runtimeElemens to GraalVM script, as this configuration is meant …
vbabanin Sep 17, 2024
10f3cf5
PR nits
rozza Sep 17, 2024
7b5738b
Spotbugs naming convention fix
rozza Sep 17, 2024
204330b
Remove logback from dependencies.
vbabanin Sep 19, 2024
a8cee8d
Fix driver-core pom optional.
rozza Sep 19, 2024
acf2205
Merge branch 'master' into JAVA-5582
rozza Sep 19, 2024
6699721
Merge branch 'master' into JAVA-5582
rozza Sep 19, 2024
28c5b83
Add mongocrypt support to driver-sync and reactive streams driver
rozza Sep 19, 2024
6e3e706
Changed the project name in the configuration to align with the artif…
vbabanin Sep 19, 2024
a8699de
Move mongocrypt to mongodb-crypt to work around optional project name…
rozza Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ ext {
zstdVersion = '1.5.5-3'
awsSdkV2Version = '2.18.9'
awsSdkV1Version = '1.12.337'
mongoCryptVersion = '1.11.0'
projectReactorVersion = '2022.0.0'
junitBomVersion = '5.10.2'
logbackVersion = '1.3.14'
Expand Down
2 changes: 1 addition & 1 deletion driver-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ dependencies {
implementation project(path: ':bson-record-codec', configuration: 'default')
implementation project(path: ':bson-kotlin', configuration: 'default'), optional
implementation project(path: ':bson-kotlinx', configuration: 'default'), optional
implementation project(path: ':mongocrypt', configuration: 'default'), optional

implementation "com.github.jnr:jnr-unixsocket:$jnrUnixsocketVersion", optional
api platform("io.netty:netty-bom:$nettyVersion")
Expand All @@ -55,7 +56,6 @@ dependencies {

implementation "org.xerial.snappy:snappy-java:$snappyVersion", optional
implementation "com.github.luben:zstd-jni:$zstdVersion", optional
implementation "org.mongodb:mongodb-crypt:$mongoCryptVersion", optional

testImplementation project(':bson').sourceSets.test.output
testImplementation('org.junit.jupiter:junit-jupiter-api')
Expand Down
2 changes: 1 addition & 1 deletion graalvm-native-image-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ dependencies {
implementation project(path:':driver-sync', configuration:'archives')
implementation project(path:':driver-reactive-streams', configuration:'archives')
implementation project(path:':driver-legacy', configuration:'archives')
implementation project(path: ':mongocrypt', configuration: 'archives')
// note that as a result of these `sourceSets` dependencies, `driver-sync/src/test/resources/logback-test.xml` is used
implementation project(':driver-core').sourceSets.test.output
implementation project(':driver-sync').sourceSets.test.output
implementation project(':driver-legacy').sourceSets.test.output
implementation project(':driver-reactive-streams').sourceSets.test.output
implementation "org.mongodb:mongodb-crypt:$mongoCryptVersion"
implementation 'org.slf4j:slf4j-api:2.0.12'
implementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation platform("io.projectreactor:reactor-bom:$projectReactorVersion")
Expand Down
39 changes: 39 additions & 0 deletions mongocrypt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
*~
.#*
.git
*#

# os x stuff
*Thumbs.db*
*.DS_Store

# Build artifacts
build
out

# Eclipse files
.classpath
.project
.settings

# Intellij IDEA files
*.ipr
*.iws
*.iml
*.idea
workspace.xml
atlassian-ide-plugin.xml

# gradle
.gradle

# local settings
**/gradle.properties
local.properties
Copy link
Contributor

@NathanQingyangXu NathanQingyangXu Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super minor, just for fun of tech discussion. In .gitignore, "filrname" means the same as "**/filename" but the latter takes effect only after git v1.8.2

The only reason to use "**" is for such example: a/**/b

No need to change if it has been a pattern elsewhere already. Feel free to ignore, without saying.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the insightful comment! We currently lack consistency in the root .gitignore. We could consider addressing this if it becomes a source of confusion.

As for now, I've removed the .gitignore from this module since we don’t need an additional one; there’s already a .gitignore in the root folder of our repo.


# jenv
.java-version

# bin
/bin
/benchmarks/bin
189 changes: 189 additions & 0 deletions mongocrypt/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* Copyright 2019-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import de.undercouch.gradle.tasks.download.Download
import java.io.ByteArrayOutputStream

buildscript {
repositories {
mavenCentral()
google()
}
dependencies {
"classpath"(group = "net.java.dev.jna", name = "jna", version = "5.11.0")
}
}

plugins {
// Needed to download libmongocrypt from s3.
id("de.undercouch.download") version "5.6.0"
}

group = "org.mongodb"
base.archivesBaseName = "mongodb-crypt"
description = "MongoDB client-side crypto support"

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
api(project(path = ":bson", configuration = "default"))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest version of BSON is now used, as opposed to the version specified in the libmongocrypt repository. For reference, see the previous dependency listed here: libmongocrypt build.gradle.kts.

api("net.java.dev.jna:jna:5.11.0")

// Tests
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("ch.qos.logback:logback-classic:1.2.11")
}

/*
* Git version information
*/
// Returns a String representing the output of `git describe`
val gitDescribe by lazy {
val describeStdOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "describe", "--tags", "--always", "--dirty")
standardOutput = describeStdOut
}
describeStdOut.toString().trim()
}

val isJavaTag by lazy { gitDescribe.startsWith("java") }
val gitVersion by lazy { gitDescribe.subSequence(gitDescribe.toCharArray().indexOfFirst { it.isDigit() }, gitDescribe.length).toString() }

val defaultDownloadRevision = "9a88ac5698e8e3ffcd6580b98c247f0126f26c40" // r.1.11.0

/*
* Jna copy or download resources
*/
val jnaDownloadsDir = "$buildDir/jnaLibs/downloads/"
val jnaResourcesDir = "$buildDir/jnaLibs/resources/"
val jnaLibPlatform: String = if (com.sun.jna.Platform.RESOURCE_PREFIX.startsWith("darwin")) "darwin" else com.sun.jna.Platform.RESOURCE_PREFIX
val jnaLibsPath: String = System.getProperty("jnaLibsPath", "${jnaResourcesDir}${jnaLibPlatform}")
val jnaResources: String = System.getProperty("jna.library.path", jnaLibsPath)

// Download jnaLibs that match the git to jnaResourcesBuildDir
val downloadRevision: String = System.getProperties().computeIfAbsent("gitRevision") { k -> defaultDownloadRevision }.toString()
val binariesArchiveName = "libmongocrypt-java.tar.gz"

val downloadUrl: String = "https://mciuploads.s3.amazonaws.com/libmongocrypt/java/$downloadRevision/$binariesArchiveName"

val jnaMapping: Map<String, String> = mapOf(
"rhel-62-64-bit" to "linux-x86-64",
"rhel72-zseries-test" to "linux-s390x",
"rhel-71-ppc64el" to "linux-ppc64le",
"ubuntu1604-arm64" to "linux-aarch64",
"windows-test" to "win32-x86-64",
"macos" to "darwin"
)

sourceSets {
main {
java {
resources {
srcDirs(jnaResourcesDir)
}
}
}
}

tasks.register<Download>("downloadJava") {
src(downloadUrl)
dest("${jnaDownloadsDir}/$binariesArchiveName")
overwrite(true)
}

// The `processResources` task (defined by the `java-library` plug-in) consumes files in the main source set.
// Add a dependency on `unzipJava`. `unzipJava` adds libmongocrypt libraries to the main source set.
tasks.processResources {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
mustRunAfter(tasks.named("unzipJava"))
}

tasks.register<Copy>("unzipJava") {
outputs.upToDateWhen { false }
from(tarTree(resources.gzip("${jnaDownloadsDir}/$binariesArchiveName")))
include(jnaMapping.keys.flatMap {
listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/lib/**/libmongocrypt.dylib", "${it}/bin/**/mongocrypt.dll" )
})
eachFile {
path = "${jnaMapping[path.substringBefore("/")]}/${name}"
}
into(jnaResourcesDir)
mustRunAfter("downloadJava")

doLast {
println("jna.library.path contents: \n ${fileTree(jnaResourcesDir).files.joinToString(",\n ")}")
}
}

tasks.register("downloadJnaLibs") {
dependsOn("downloadJava", "unzipJava")
}

tasks.test {
systemProperty("jna.debug_load", "true")
systemProperty("jna.library.path", jnaResources)
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}

doFirst {
println("jna.library.path contents:")
println(fileTree(jnaResources) {
this.setIncludes(listOf("*.*"))
}.files.joinToString(",\n ", " "))
}
dependsOn("downloadJnaLibs", "downloadJava", "unzipJava")
}

tasks.withType<AbstractPublishToMaven> {
description = """$description
| System properties:
| =================
|
| jnaLibsPath : Custom local JNA library path for inclusion into the build (rather than downloading from s3)
| gitRevision : Optional Git Revision to download the built resources for from s3.
""".trimMargin()
}

tasks.jar {
manifest {
attributes(
"-exportcontents" to "com.mongodb.crypt.capi.*;-noimport:=true",
"Automatic-Module-Name" to "com.mongodb.crypt.capi",
"Import-Package" to "org.bson.*",
"Build-Version" to gitVersion,
"Bundle-Version" to gitVersion,
"Bundle-Name" to "MongoCrypt",
"Bundle-SymbolicName" to "com.mongodb.crypt.capi",
"Private-Package" to ""
)
}

//NOTE this enables depending on the mongocrypt from driver-core
dependsOn("downloadJnaLibs")
}

tasks.javadoc {
jyemin marked this conversation as resolved.
Show resolved Hide resolved
if (JavaVersion.current().isJava9Compatible) {
(options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
}
}
45 changes: 45 additions & 0 deletions mongocrypt/src/main/com/mongodb/crypt/capi/BinaryHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2008-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.mongodb.crypt.capi;

import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t;

import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_destroy;

// Wrap JNA memory and a mongocrypt_binary_t that references that memory, in order to ensure that the JNA Memory is not GC'd before the
// mongocrypt_binary_t is destroyed
class BinaryHolder implements AutoCloseable {

private final DisposableMemory memory;
private final mongocrypt_binary_t binary;

BinaryHolder(final DisposableMemory memory, final mongocrypt_binary_t binary) {
this.memory = memory;
this.binary = binary;
}

mongocrypt_binary_t getBinary() {
return binary;
}

@Override
public void close() {
mongocrypt_binary_destroy(binary);
memory.dispose();
}
}
Loading