diff --git a/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java b/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java index 91f722e8e1..f509f8b3ea 100644 --- a/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java @@ -16,6 +16,8 @@ package com.mongodb.client.model.vault; +import com.mongodb.annotations.Alpha; +import com.mongodb.annotations.Reason; import com.mongodb.lang.Nullable; import org.bson.BsonBinary; @@ -31,6 +33,7 @@ public class EncryptOptions { private Long contentionFactor; private String queryType; private RangeOptions rangeOptions; + private TextOptions textOptions; /** * Construct an instance with the given algorithm. @@ -51,8 +54,13 @@ public EncryptOptions(final String algorithm) { *
The "TextPreview" algorithm is in preview and should be used for experimental workloads only. + * These features are unstable and their security is not guaranteed until released as Generally Available (GA). + * The GA version of these features may not be backwards compatible with the preview version.
+ * * @return the encryption algorithm */ public String getAlgorithm() { @@ -141,8 +149,8 @@ public Long getContentionFactor() { /** * The QueryType. * - *Currently, we support only "equality" or "range" queryType.
- *It is an error to set queryType when the algorithm is not "Indexed" or "Range".
+ *Currently, we support only "equality", "range", "prefixPreview", "suffixPreview" or "substringPreview" queryType.
+ *It is an error to set queryType when the algorithm is not "Indexed", "Range" or "TextPreview".
* @param queryType the query type * @return this * @since 4.7 @@ -194,6 +202,36 @@ public RangeOptions getRangeOptions() { return rangeOptions; } + /** + * The TextOptions + * + *It is an error to set TextOptions when the algorithm is not "TextPreview". + * @param textOptions the text options + * @return this + * @since 5.6 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ + @Alpha(Reason.SERVER) + public EncryptOptions textOptions(@Nullable final TextOptions textOptions) { + this.textOptions = textOptions; + return this; + } + + /** + * Gets the TextOptions + * @see #textOptions(TextOptions) + * @return the text options or null if not set + * @since 5.6 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ + @Alpha(Reason.SERVER) + @Nullable + public TextOptions getTextOptions() { + return textOptions; + } + @Override public String toString() { return "EncryptOptions{" diff --git a/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java b/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java new file mode 100644 index 0000000000..34dcd0d806 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java @@ -0,0 +1,187 @@ +/* + * 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.client.model.vault; + +import com.mongodb.annotations.Alpha; +import com.mongodb.annotations.Reason; +import com.mongodb.lang.Nullable; +import org.bson.BsonDocument; + +/** + * Text options for a Queryable Encryption field that supports text queries. + * + *
Note: TextOptions is in Alpha and subject to backwards breaking changes. + * + * @since 5.6 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ +@Alpha(Reason.SERVER) +public class TextOptions { + private Boolean caseSensitive; + private Boolean diacriticSensitive; + @Nullable + private BsonDocument prefixOptions; + @Nullable + private BsonDocument suffixOptions; + @Nullable + private BsonDocument substringOptions; + + /** + * Construct a new instance + */ + public TextOptions() { + } + + /** + * @return true if text indexes for this field are case sensitive. + */ + public boolean getCaseSensitive() { + return caseSensitive; + } + + /** + * Set case sensitivity + * + * @param caseSensitive true if text indexes are case sensitive + * @return this + */ + public TextOptions caseSensitive(final boolean caseSensitive) { + this.caseSensitive = caseSensitive; + return this; + } + + /** + * @return true if text indexes are diacritic sensitive + */ + public boolean getDiacriticSensitive() { + return diacriticSensitive; + } + + /** + * Set diacritic sensitivity + * + * @param diacriticSensitive true if text indexes are diacritic sensitive + * @return this + */ + public TextOptions diacriticSensitive(final boolean diacriticSensitive) { + this.diacriticSensitive = diacriticSensitive; + return this; + } + + /** + * Set the prefix options. + * + *
Expected to be a {@link BsonDocument} in the format of:
+ * + *+ * {@code + * { + * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error. + * strMinQueryLength: BsonInt32, + * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error. + * strMaxQueryLength: BsonInt32 + * } + * } + *+ * + * @param prefixOptions the prefix options or null + * @return this + */ + public TextOptions prefixOptions(@Nullable final BsonDocument prefixOptions) { + this.prefixOptions = prefixOptions; + return this; + } + + /** + * @see #prefixOptions(BsonDocument) + * @return the prefix options document or null + */ + @Nullable + public BsonDocument getPrefixOptions() { + return prefixOptions; + } + + /** + * Set the suffix options. + * + *
Expected to be a {@link BsonDocument} in the format of:
+ * + *+ * {@code + * { + * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error. + * strMinQueryLength: BsonInt32, + * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error. + * strMaxQueryLength: BsonInt32 + * } + * } + *+ * + * @param suffixOptions the suffix options or null + * @return this + */ + public TextOptions suffixOptions(@Nullable final BsonDocument suffixOptions) { + this.suffixOptions = suffixOptions; + return this; + } + + /** + * @see #suffixOptions(BsonDocument) + * @return the suffix options document or null + */ + @Nullable + public BsonDocument getSuffixOptions() { + return suffixOptions; + } + + /** + * Set the substring options. + * + *
Expected to be a {@link BsonDocument} in the format of:
+ * + *+ * {@code + * { + * // strMaxLength is the maximum allowed length to insert. Inserting longer strings will error. + * strMaxLength: BsonInt32, + * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error. + * strMinQueryLength: BsonInt32, + * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error. + * strMaxQueryLength: BsonInt32 + * } + * } + *+ * + * @param substringOptions the substring options or null + * @return this + */ + public TextOptions substringOptions(@Nullable final BsonDocument substringOptions) { + this.substringOptions = substringOptions; + return this; + } + + /** + * @see #substringOptions(BsonDocument) + * @return the substring options document or null + */ + @Nullable + public BsonDocument getSubstringOptions() { + return substringOptions; + } + +} diff --git a/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java b/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java index 640707d94d..2b472668d9 100644 --- a/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java +++ b/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java @@ -17,7 +17,9 @@ import com.mongodb.client.model.vault.EncryptOptions; import com.mongodb.client.model.vault.RangeOptions; +import com.mongodb.client.model.vault.TextOptions; import com.mongodb.internal.crypt.capi.MongoExplicitEncryptOptions; +import org.bson.BsonBoolean; import org.bson.BsonDocument; import org.bson.BsonInt32; import org.bson.BsonInt64; @@ -70,6 +72,30 @@ public static MongoExplicitEncryptOptions asMongoExplicitEncryptOptions(final En } encryptOptionsBuilder.rangeOptions(rangeOptionsBsonDocument); } + + TextOptions textOptions = options.getTextOptions(); + if (textOptions != null) { + BsonDocument textOptionsDocument = new BsonDocument(); + textOptionsDocument.put("caseSensitive", BsonBoolean.valueOf(textOptions.getCaseSensitive())); + textOptionsDocument.put("diacriticSensitive", BsonBoolean.valueOf(textOptions.getDiacriticSensitive())); + + BsonDocument substringOptions = textOptions.getSubstringOptions(); + if (substringOptions != null) { + textOptionsDocument.put("substring", substringOptions); + } + + BsonDocument prefixOptions = textOptions.getPrefixOptions(); + if (prefixOptions != null) { + textOptionsDocument.put("prefix", prefixOptions); + } + + BsonDocument suffixOptions = textOptions.getSuffixOptions(); + if (suffixOptions != null) { + textOptionsDocument.put("suffix", suffixOptions); + } + encryptOptionsBuilder.textOptions(textOptionsDocument); + } + return encryptOptionsBuilder.build(); } private EncryptOptionsHelper() { diff --git a/driver-core/src/test/functional/com/mongodb/ClusterFixture.java b/driver-core/src/test/functional/com/mongodb/ClusterFixture.java index 7ed6ad3c36..30a7f274bb 100644 --- a/driver-core/src/test/functional/com/mongodb/ClusterFixture.java +++ b/driver-core/src/test/functional/com/mongodb/ClusterFixture.java @@ -64,6 +64,7 @@ import com.mongodb.internal.connection.StreamFactoryFactory; import com.mongodb.internal.connection.TlsChannelStreamFactoryFactory; import com.mongodb.internal.connection.netty.NettyStreamFactoryFactory; +import com.mongodb.internal.crypt.capi.CAPI; import com.mongodb.internal.operation.BatchCursor; import com.mongodb.internal.operation.CommandReadOperation; import com.mongodb.internal.operation.DropDatabaseOperation; @@ -148,6 +149,7 @@ public final class ClusterFixture { private static final Map
+ * This class is responsible for configuring and managing the native libmongocrypt context, + * handling encryption and decryption operations, and bridging Java cryptographic hooks + * when required. It wraps the native resource and provides context creation methods for + * various cryptographic operations. + *
+ * Key responsibilities: + *
+ * Registers log handlers, cryptographic hooks, and sets up KMS providers and other options. + * Throws MongoCryptException if initialization fails. + */ MongoCryptImpl(final MongoCryptOptions options) { closed = new AtomicBoolean(); wrapped = mongocrypt_new(); @@ -161,9 +184,8 @@ class MongoCryptImpl implements MongoCrypt { } if (options.getLocalKmsProviderOptions() != null) { - try (BinaryHolder localMasterKeyBinaryHolder = toBinary(options.getLocalKmsProviderOptions().getLocalMasterKey())) { - configure(() -> mongocrypt_setopt_kms_provider_local(wrapped, localMasterKeyBinaryHolder.getBinary())); - } + withBinaryHolder(options.getLocalKmsProviderOptions().getLocalMasterKey(), + binary -> configure(() -> mongocrypt_setopt_kms_provider_local(wrapped, binary))); } if (options.getAwsKmsProviderOptions() != null) { @@ -177,18 +199,15 @@ class MongoCryptImpl implements MongoCrypt { } if (options.getKmsProviderOptions() != null) { - try (BinaryHolder binaryHolder = toBinary(options.getKmsProviderOptions())) { - configure(() -> mongocrypt_setopt_kms_providers(wrapped, binaryHolder.getBinary())); - } + withBinaryHolder(options.getKmsProviderOptions(), + binary -> configure(() -> mongocrypt_setopt_kms_providers(wrapped, binary))); } if (options.getLocalSchemaMap() != null) { BsonDocument localSchemaMapDocument = new BsonDocument(); localSchemaMapDocument.putAll(options.getLocalSchemaMap()); - try (BinaryHolder localSchemaMapBinaryHolder = toBinary(localSchemaMapDocument)) { - configure(() -> mongocrypt_setopt_schema_map(wrapped, localSchemaMapBinaryHolder.getBinary())); - } + withBinaryHolder(localSchemaMapDocument, binary -> configure(() -> mongocrypt_setopt_schema_map(wrapped, binary))); } if (options.isBypassQueryAnalysis()) { @@ -204,9 +223,8 @@ class MongoCryptImpl implements MongoCrypt { BsonDocument localEncryptedFieldsMap = new BsonDocument(); localEncryptedFieldsMap.putAll(options.getEncryptedFieldsMap()); - try (BinaryHolder localEncryptedFieldsMapHolder = toBinary(localEncryptedFieldsMap)) { - configure(() -> mongocrypt_setopt_encrypted_field_config_map(wrapped, localEncryptedFieldsMapHolder.getBinary())); - } + withBinaryHolder(localEncryptedFieldsMap, + binary -> configure(() -> mongocrypt_setopt_encrypted_field_config_map(wrapped, binary))); } options.getSearchPaths().forEach(p -> mongocrypt_setopt_append_crypt_shared_lib_search_path(wrapped, new cstring(p))); @@ -217,116 +235,93 @@ class MongoCryptImpl implements MongoCrypt { configure(() -> mongocrypt_init(wrapped)); } + /** + * Creates an encryption context for the given database and command document. + */ @Override public MongoCryptContext createEncryptionContext(final String database, final BsonDocument commandDocument) { isTrue("open", !closed.get()); notNull("database", database); notNull("commandDocument", commandDocument); - mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); - if (context == null) { - throwExceptionFromStatus(); - } - - try (BinaryHolder commandDocumentBinaryHolder = toBinary(commandDocument)) { - configure(() -> mongocrypt_ctx_encrypt_init(context, new cstring(database), -1, - commandDocumentBinaryHolder.getBinary()), context); - return new MongoCryptContextImpl(context); - } + return createMongoCryptContext(commandDocument, createNewMongoCryptContext(), + (context, binary) -> mongocrypt_ctx_encrypt_init(context, new cstring(database), -1, binary)); } + /** + * Creates a decryption context for the given document. + */ @Override public MongoCryptContext createDecryptionContext(final BsonDocument document) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); - if (context == null) { - throwExceptionFromStatus(); - } - try (BinaryHolder documentBinaryHolder = toBinary(document)){ - configure(() -> mongocrypt_ctx_decrypt_init(context, documentBinaryHolder.getBinary()), context); - } - return new MongoCryptContextImpl(context); + return createMongoCryptContext(document, createNewMongoCryptContext(), CAPI::mongocrypt_ctx_decrypt_init); } + /** + * Creates a data key context for the specified KMS provider and options. + */ @Override public MongoCryptContext createDataKeyContext(final String kmsProvider, final MongoDataKeyOptions options) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); - if (context == null) { - throwExceptionFromStatus(); - } + mongocrypt_ctx_t context = createNewMongoCryptContext(); BsonDocument keyDocument = new BsonDocument("provider", new BsonString(kmsProvider)); BsonDocument masterKey = options.getMasterKey(); if (masterKey != null) { masterKey.forEach(keyDocument::append); } - try (BinaryHolder masterKeyHolder = toBinary(keyDocument)) { - configure(() -> mongocrypt_ctx_setopt_key_encryption_key(context, masterKeyHolder.getBinary()), context); - } + withBinaryHolder(keyDocument, + binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_encryption_key(context, binary))); if (options.getKeyAltNames() != null) { for (String cur : options.getKeyAltNames()) { - try (BinaryHolder keyAltNameBinaryHolder = toBinary(new BsonDocument("keyAltName", new BsonString(cur)))) { - configure(() -> mongocrypt_ctx_setopt_key_alt_name(context, keyAltNameBinaryHolder.getBinary()), context); - } + withBinaryHolder(new BsonDocument("keyAltName", new BsonString(cur)), + binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_alt_name(context, binary))); } } if (options.getKeyMaterial() != null) { - try (BinaryHolder keyMaterialBinaryHolder = toBinary(new BsonDocument("keyMaterial", new BsonBinary(options.getKeyMaterial())))) { - configure(() -> mongocrypt_ctx_setopt_key_material(context, keyMaterialBinaryHolder.getBinary()), context); - } + withBinaryHolder(new BsonDocument("keyMaterial", new BsonBinary(options.getKeyMaterial())), + binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_material(context, binary))); } - if (!mongocrypt_ctx_datakey_init(context)) { - MongoCryptContextImpl.throwExceptionFromStatus(context); - } + configureContext(context, () -> mongocrypt_ctx_datakey_init(context)); return new MongoCryptContextImpl(context); } + /** + * Creates an explicit encryption context + */ @Override public MongoCryptContext createExplicitEncryptionContext(final BsonDocument document, final MongoExplicitEncryptOptions options) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = configureExplicitEncryption(options); - - try (BinaryHolder documentBinaryHolder = toBinary(document)) { - configure(() -> mongocrypt_ctx_explicit_encrypt_init(context, documentBinaryHolder.getBinary()), context); - } - - return new MongoCryptContextImpl(context); + return createMongoCryptContext(document, configureExplicitEncryption(options), CAPI::mongocrypt_ctx_explicit_encrypt_init); } + /** + * Creates an explicit encrypt *expression* context + */ @Override public MongoCryptContext createEncryptExpressionContext(final BsonDocument document, final MongoExplicitEncryptOptions options) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = configureExplicitEncryption(options); - - try (BinaryHolder documentBinaryHolder = toBinary(document)) { - configure(() -> mongocrypt_ctx_explicit_encrypt_expression_init(context, documentBinaryHolder.getBinary()), context); - } - return new MongoCryptContextImpl(context); + return createMongoCryptContext(document, configureExplicitEncryption(options), CAPI::mongocrypt_ctx_explicit_encrypt_expression_init); } + /** + * Creates an explicit decryption context + */ @Override public MongoCryptContext createExplicitDecryptionContext(final BsonDocument document) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); - if (context == null) { - throwExceptionFromStatus(); - } - try (BinaryHolder binaryHolder = toBinary(document)) { - configure(() -> mongocrypt_ctx_explicit_decrypt_init(context, binaryHolder.getBinary()), context); - } - return new MongoCryptContextImpl(context); + return createMongoCryptContext(document, createNewMongoCryptContext(), CAPI::mongocrypt_ctx_explicit_decrypt_init); } + /** + * Creates a rewrap many data keys context + */ @Override public MongoCryptContext createRewrapManyDatakeyContext(final BsonDocument filter, final MongoRewrapManyDataKeyOptions options) { isTrue("open", !closed.get()); - mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); - if (context == null) { - throwExceptionFromStatus(); - } + mongocrypt_ctx_t context = createNewMongoCryptContext(); if (options != null && options.getProvider() != null) { BsonDocument keyDocument = new BsonDocument("provider", new BsonString(options.getProvider())); @@ -334,23 +329,27 @@ public MongoCryptContext createRewrapManyDatakeyContext(final BsonDocument filte if (masterKey != null) { masterKey.forEach(keyDocument::append); } - try (BinaryHolder binaryHolder = toBinary(keyDocument)) { - configure(() -> mongocrypt_ctx_setopt_key_encryption_key(context, binaryHolder.getBinary()), context); - } + withBinaryHolder(keyDocument, + binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_encryption_key(context, binary))); } - try (BinaryHolder binaryHolder = toBinary(filter)) { - configure(() -> mongocrypt_ctx_rewrap_many_datakey_init(context, binaryHolder.getBinary()), context); - } - return new MongoCryptContextImpl(context); + return createMongoCryptContext(filter, context, CAPI::mongocrypt_ctx_rewrap_many_datakey_init); } + /** + * Returns the version string of the loaded crypt shared library. + */ @Override public String getCryptSharedLibVersionString() { cstring versionString = mongocrypt_crypt_shared_lib_version_string(wrapped, null); return versionString == null ? null : versionString.toString(); } + /** + * Closes the native libmongocrypt resource. + *
+ * This should be called when the instance is no longer needed to release native resources. + */ @Override public void close() { if (!closed.getAndSet(true)) { @@ -358,52 +357,100 @@ public void close() { } } - private mongocrypt_ctx_t configureExplicitEncryption(final MongoExplicitEncryptOptions options) { + /** + * Helper to create a MongoCryptContext from a BSON document and a native context. + *
+ * Applies the given configuration function and checks for errors.
+ */
+ private MongoCryptContext createMongoCryptContext(final BsonDocument document, final mongocrypt_ctx_t context,
+ final BiFunction
+ * Throws if context creation fails.
+ */
+ private mongocrypt_ctx_t createNewMongoCryptContext() {
mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped);
if (context == null) {
throwExceptionFromStatus();
}
+ return context;
+ }
+ /**
+ * Configures explicit encryption options on a new native context.
+ *
+ * Applies key ID, key alt name, algorithm, query type, contention factor, and other options.
+ */
+ private mongocrypt_ctx_t configureExplicitEncryption(final MongoExplicitEncryptOptions options) {
+ mongocrypt_ctx_t context = createNewMongoCryptContext();
if (options.getKeyId() != null) {
- try (BinaryHolder keyIdBinaryHolder = toBinary(ByteBuffer.wrap(options.getKeyId().getData()))) {
- configure(() -> mongocrypt_ctx_setopt_key_id(context, keyIdBinaryHolder.getBinary()), context);
- }
- } else if (options.getKeyAltName() != null) {
- try (BinaryHolder keyAltNameBinaryHolder = toBinary(new BsonDocument("keyAltName", new BsonString(options.getKeyAltName())))) {
- configure(() -> mongocrypt_ctx_setopt_key_alt_name(context, keyAltNameBinaryHolder.getBinary()), context);
- }
+ withBinaryHolder(ByteBuffer.wrap(options.getKeyId().getData()),
+ binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_id(context, binary)));
+ }
+
+ if (options.getKeyAltName() != null) {
+ withBinaryHolder(new BsonDocument("keyAltName", new BsonString(options.getKeyAltName())),
+ binary -> configureContext(context, () -> mongocrypt_ctx_setopt_key_alt_name(context, binary)));
}
if (options.getAlgorithm() != null) {
- configure(() -> mongocrypt_ctx_setopt_algorithm(context, new cstring(options.getAlgorithm()), -1), context);
+ configureContext(context, () -> mongocrypt_ctx_setopt_algorithm(context, new cstring(options.getAlgorithm()), -1));
}
if (options.getQueryType() != null) {
- configure(() -> mongocrypt_ctx_setopt_query_type(context, new cstring(options.getQueryType()), -1), context);
+ configureContext(context, () -> mongocrypt_ctx_setopt_query_type(context, new cstring(options.getQueryType()), -1));
}
if (options.getContentionFactor() != null) {
- configure(() -> mongocrypt_ctx_setopt_contention_factor(context, options.getContentionFactor()), context);
+ configureContext(context, () -> mongocrypt_ctx_setopt_contention_factor(context, options.getContentionFactor()));
}
if (options.getRangeOptions() != null) {
- try (BinaryHolder rangeOptionsHolder = toBinary(options.getRangeOptions())) {
- configure(() -> mongocrypt_ctx_setopt_algorithm_range(context, rangeOptionsHolder.getBinary()), context);
- }
+ withBinaryHolder(options.getRangeOptions(),
+ binary -> configureContext(context, () -> mongocrypt_ctx_setopt_algorithm_range(context, binary)));
+ }
+ if (options.getTextOptions() != null) {
+ withBinaryHolder(options.getTextOptions(),
+ binary -> configureContext(context, () -> mongocrypt_ctx_setopt_algorithm_text(context, binary)));
}
return context;
}
-
+ /**
+ * Configures the main mongocrypt instance with the given supplier that indicates if configuration was successful or not.
+ *
+ * Throws an exception derived from the mongocrypt status if the configuration fails.
+ */
private void configure(final Supplier
+ * Throws an exception derived from the contexts mongocrypt status if the configuration fails.
+ */
+ private void configureContext(final mongocrypt_ctx_t context, final Supplier
+ * Handles different log levels and forwards messages to the appropriate logger method.
+ */
static class LogCallback implements mongocrypt_log_fn_t {
@Override
public void log(final int level, final cstring message, final int messageLength, final Pointer ctx) {
diff --git a/mongodb-crypt/src/main/com/mongodb/internal/crypt/capi/MongoExplicitEncryptOptions.java b/mongodb-crypt/src/main/com/mongodb/internal/crypt/capi/MongoExplicitEncryptOptions.java
index 9080a77374..c08608ca59 100644
--- a/mongodb-crypt/src/main/com/mongodb/internal/crypt/capi/MongoExplicitEncryptOptions.java
+++ b/mongodb-crypt/src/main/com/mongodb/internal/crypt/capi/MongoExplicitEncryptOptions.java
@@ -20,8 +20,6 @@
import org.bson.BsonBinary;
import org.bson.BsonDocument;
-import java.util.Objects;
-
/**
* Options for explicit encryption.
*/
@@ -32,6 +30,7 @@ public final class MongoExplicitEncryptOptions {
private final Long contentionFactor;
private final String queryType;
private final BsonDocument rangeOptions;
+ private final BsonDocument textOptions;
/**
* The builder for the options
@@ -43,6 +42,7 @@ public static final class Builder {
private Long contentionFactor;
private String queryType;
private BsonDocument rangeOptions;
+ private BsonDocument textOptions;
private Builder() {
}
@@ -87,7 +87,7 @@ public Builder algorithm(final String algorithm) {
/**
* The contention factor.
*
- * It is an error to set contentionFactor when algorithm is not "Indexed".
+ * Only applies when algorithm is "Indexed", "Range", or "TextPreview". It is an error to set queryType when algorithm is not "Indexed". Only applies when algorithm is "Indexed", "Range", or "TextPreview". It is an error to set rangeOptions when the algorithm is not "range". Only applies when algorithm is "Range". Only applies when algorithm is "TextPreview".