diff --git a/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java b/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java index a6c623364db..c5aec6517ce 100644 --- a/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java +++ b/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java @@ -67,8 +67,8 @@ private static String getFileAsString(final String fileName) { throw new RuntimeException("Could not find file " + fileName); } return new String(Files.readAllBytes(Paths.get(resource.toURI()))); - } catch (Throwable t) { - throw new RuntimeException("Could not parse file " + fileName, t); + } catch (Exception e) { + throw new RuntimeException("Could not parse file " + fileName, e); } } diff --git a/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java b/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java index 9ccb5ef0c8b..6a0d08ba123 100644 --- a/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java +++ b/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java @@ -26,6 +26,8 @@ import org.bson.BsonString; import org.bson.BsonValue; +import java.io.PrintStream; +import java.lang.Thread.UncaughtExceptionHandler; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -46,6 +48,42 @@ public static boolean isOperationTimeoutFromSocketException(final Throwable e) { return e instanceof MongoOperationTimeoutException && e.getCause() instanceof MongoSocketException; } + /** + * We must always propagate {@link Error}s, instead of wrapping them in / replacing them with {@link Exception}s, or swallowing them. + *

+ * This enables an application to decide how to deal with {@link Error} via {@link UncaughtExceptionHandler}. + * An {@link Error} is more likely to cause an invariant violation than an {@link Exception}, + * because it is less likely to be taken into account in code. An {@link AssertionError} outright informs about an invariant violation. + * Furthermore, a {@link VirtualMachineError} not only may happen in a peculiar situation, + * but also may be asynchronous. + * That is why it may be a good idea for an application to terminate on {@link Error}. + * We cannot make such a decision for an application, but we must do our best to give it an opportunity to react to an {@link Error}. + *

+ * If there is no {@link UncaughtExceptionHandler}, then the uncaught exception is + * {@linkplain Throwable#printStackTrace(PrintStream) printed} + * to {@link System#err}, see {@link ThreadGroup#uncaughtException(Thread, Throwable)}. + * + * @throws Error Iff {@code t} is {@link Error}. + * @see #mapUnlessError(Throwable, Function) + */ + public static void rethrowIfError(final Throwable t) { + if (t instanceof Error) { + throw (Error) t; + } + } + + /** + * See {@link #rethrowIfError(Throwable)}. + * + * @param mapper Is used iff {@code t} is not {@link Error}. + */ + public static Throwable mapUnlessError(final Throwable t, final Function mapper) { + if (t instanceof Error) { + return t; + } + return mapper.apply(t); + } + public static final class MongoCommandExceptionUtils { public static int extractErrorCode(final BsonDocument response) { return extractErrorCodeAsBson(response).intValue(); diff --git a/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java b/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java index da5a09a10b8..100a8b00b6d 100644 --- a/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java +++ b/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java @@ -20,6 +20,7 @@ import com.mongodb.lang.Nullable; import static com.mongodb.assertions.Assertions.notNull; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; /** *

This class is not part of the public API and may be removed or changed at any time.

@@ -47,6 +48,7 @@ public void onResult(@Nullable final T result, @Nullable final Throwable t) { wrapped.onResult(result, t); } catch (Throwable e) { logger.error("Callback onResult call produced an error", e); + rethrowIfError(e); } } diff --git a/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java b/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java index 240f5051c92..ed9aa52da26 100644 --- a/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java +++ b/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java @@ -199,8 +199,8 @@ public static void startProcess(final ProcessBuilder processBuilder) { processBuilder.redirectErrorStream(true); processBuilder.redirectOutput(new File(System.getProperty("os.name").startsWith("Windows") ? "NUL" : "/dev/null")); processBuilder.start(); - } catch (Throwable t) { - throw new MongoClientException("Exception starting mongocryptd process. Is `mongocryptd` on the system path?", t); + } catch (Exception e) { + throw new MongoClientException("Exception starting mongocryptd process. Is `mongocryptd` on the system path?", e); } } diff --git a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java index 4146d06c22e..6cedd8647e2 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java +++ b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java @@ -66,6 +66,7 @@ import static com.mongodb.connection.ServerDescription.MAX_DRIVER_WIRE_VERSION; import static com.mongodb.connection.ServerDescription.MIN_DRIVER_SERVER_VERSION; import static com.mongodb.connection.ServerDescription.MIN_DRIVER_WIRE_VERSION; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; import static com.mongodb.internal.Locks.withInterruptibleLock; import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE; import static com.mongodb.internal.connection.EventHelper.wouldDescriptionsGenerateEquivalentEvents; @@ -185,6 +186,7 @@ public void selectServerAsync(final ServerSelector serverSelector, final Operati final SingleResultCallback callback) { if (isClosed()) { callback.onResult(null, new MongoClientException("Cluster was closed during server selection.")); + return; } Timeout computedServerSelectionTimeout = operationContext.getTimeoutContext().computeServerSelectionTimeout(); @@ -280,7 +282,7 @@ private Timeout startMinWaitHeartbeatTimeout() { private boolean handleServerSelectionRequest( final ServerSelectionRequest request, final CountDownLatch currentPhase, final ClusterDescription description) { - + boolean requestOnResultCalled = false; try { OperationContext operationContext = request.getOperationContext(); if (currentPhase != request.phase) { @@ -303,6 +305,7 @@ private boolean handleServerSelectionRequest( ServerAddress serverAddress = serverTuple.getServerDescription().getAddress(); logServerSelectionSucceeded(operationContext, clusterId, serverAddress, request.originalSelector, description); serverDeprioritization.updateCandidate(serverAddress); + requestOnResultCalled = true; request.onResult(serverTuple, null); return true; } @@ -315,7 +318,10 @@ private boolean handleServerSelectionRequest( logAndThrowTimeoutException(operationContext, request.originalSelector, description); }); return false; - } catch (Exception e) { + } catch (Throwable e) { + if (requestOnResultCalled) { + throw e; + } request.onResult(null, e); return true; } @@ -455,8 +461,9 @@ private static final class ServerSelectionRequest { void onResult(@Nullable final ServerTuple serverTuple, @Nullable final Throwable t) { try { callback.onResult(serverTuple, t); - } catch (Throwable tr) { - // ignore + } catch (Throwable e) { + LOGGER.error("Callback onResult call produced an error", e); + rethrowIfError(e); } } diff --git a/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java b/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java index 27de4840633..5227221947f 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java +++ b/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java @@ -79,6 +79,8 @@ import static com.mongodb.assertions.Assertions.assertNull; import static com.mongodb.assertions.Assertions.isTrue; import static com.mongodb.assertions.Assertions.notNull; +import static com.mongodb.internal.ExceptionUtils.mapUnlessError; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; import static com.mongodb.internal.TimeoutContext.createMongoTimeoutException; import static com.mongodb.internal.async.AsyncRunnable.beginAsync; import static com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback; @@ -242,11 +244,8 @@ public void open(final OperationContext originalOperationContext) { initAfterHandshakeFinish(initializationDescription); } catch (Throwable t) { close(); - if (t instanceof MongoException) { - throw (MongoException) t; - } else { - throw new MongoException(t.toString(), t); - } + rethrowIfError(t); + throw MongoException.fromThrowableNonNull(t); } } @@ -961,12 +960,12 @@ public void completed(@Nullable final ByteBuf buffer) { @Override public void failed(final Throwable t) { close(); - callback.onResult(null, translateReadFailure(t, operationContext)); + callback.onResult(null, mapUnlessError(t, e -> translateReadException(e, operationContext))); } }); } catch (Throwable t) { close(); - callback.onResult(null, translateReadFailure(t, operationContext)); + callback.onResult(null, mapUnlessError(t, e -> translateReadException(e, operationContext))); } } @@ -990,17 +989,6 @@ private void updateSessionContext(final SessionContext sessionContext, final Res } } - /** - * Rethrows a fatal JVM {@link Error} (e.g. {@link OutOfMemoryError}) unchanged, so it is never downgraded to a - * catchable {@link MongoException}. Used by the paths that propagate a failure by throwing; the async read path - * delivers the failure as a callback value instead and uses {@link #translateReadFailure} for the same purpose. - */ - private static void rethrowIfError(final Throwable t) { - if (t instanceof Error) { - throw (Error) t; - } - } - private void throwTranslatedWriteException(final Throwable e, final OperationContext operationContext) { rethrowIfError(e); if (operationContext.getTimeoutContext().hasTimeoutMS()) { @@ -1026,18 +1014,6 @@ private void throwTranslatedWriteException(final Throwable e, final OperationCon } } - /** - * Translates a read failure for delivery to an async callback. {@link Error}s are passed through unchanged - * rather than wrapped in a {@link MongoException}, so a fatal JVM error (e.g. {@link OutOfMemoryError}) is not - * downgraded to a catchable exception. The sync read path uses {@link #rethrowIfError} for the same purpose. - */ - private Throwable translateReadFailure(final Throwable e, final OperationContext operationContext) { - if (e instanceof Error) { - return e; - } - return translateReadException(e, operationContext); - } - private MongoSocketWriteTimeoutException createWriteTimeoutException(final SocketTimeoutException e) { return new MongoSocketWriteTimeoutException("Timeout while sending message", getServerAddress(), e); } diff --git a/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java b/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java index 2401a9e014a..a83048096f8 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java +++ b/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java @@ -61,6 +61,7 @@ import static com.mongodb.assertions.Assertions.isTrue; import static com.mongodb.assertions.Assertions.notNull; import static com.mongodb.connection.ServerConnectionState.CONNECTING; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; import static com.mongodb.internal.connection.BaseCluster.logServerSelectionStarted; import static com.mongodb.internal.connection.BaseCluster.logServerSelectionSucceeded; import static com.mongodb.internal.connection.BaseCluster.logTopologyMonitoringStopping; @@ -445,16 +446,18 @@ OperationContext getOperationContext() { public void onSuccess(final ServerTuple serverTuple) { try { callback.onResult(serverTuple, null); - } catch (Exception e) { - LOGGER.warn("Unanticipated exception thrown from callback", e); + } catch (Throwable t) { + LOGGER.error("Callback onResult call produced an error", t); + rethrowIfError(t); } } public void onError(final Throwable exception) { try { callback.onResult(null, exception); - } catch (Exception e) { - LOGGER.warn("Unanticipated exception thrown from callback", e); + } catch (Throwable t) { + LOGGER.error("Callback onResult call produced an error", t); + rethrowIfError(t); } } } diff --git a/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java b/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java index 5150149fa6a..cdbd32cc625 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java +++ b/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java @@ -58,6 +58,7 @@ import java.util.function.Consumer; import java.util.function.LongConsumer; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; import static com.mongodb.internal.thread.InterruptionUtil.interruptAndCreateMongoInterruptedException; import static java.lang.String.format; @@ -233,6 +234,7 @@ public void execute(final Runnable r) { r.run(); } catch (Throwable t) { LOGGER.error(null, t); + rethrowIfError(t); } }); } @@ -427,8 +429,9 @@ private void loop() { processPendingInterests(); checkClosings(); } - } catch (Throwable e) { - LOGGER.error("error in selector loop", e); + } catch (Throwable t) { + LOGGER.error(this + " stopped working. You may want to recreate the MongoClient", t); + rethrowIfError(t); } finally { executor.shutdown(); // use shutdownNow to stop delayed tasks @@ -467,6 +470,7 @@ private void processWrite(RegisteredSocket socket) { doWrite(socket, op); } catch (Throwable e) { LOGGER.error("error in operation", e); + rethrowIfError(e); } }); } @@ -486,6 +490,7 @@ private void processRead(RegisteredSocket socket) { doRead(socket, op); } catch (Throwable e) { LOGGER.error("error in operation", e); + rethrowIfError(e); } }); } diff --git a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java index cf9f1dcf6c4..ac83c5618ea 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java @@ -40,6 +40,7 @@ import java.util.function.Consumer; import static com.mongodb.assertions.Assertions.assertNotNull; +import static com.mongodb.internal.ExceptionUtils.rethrowIfError; import static com.mongodb.internal.operation.ChangeStreamBatchCursorHelper.isResumableError; import static com.mongodb.internal.operation.SyncOperationHelper.withReadConnectionSource; @@ -239,6 +240,7 @@ private R execute(final BiFunction, OperationContext try { return function.apply(wrapped, operationContext); } catch (Throwable t) { + rethrowIfError(t); if (!isResumableError(t, maxWireVersion)) { throw MongoException.fromThrowableNonNull(t); } diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java index 511f9f62c6b..589084716f5 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java @@ -230,7 +230,9 @@ public Publisher abortTransaction() { return executor .execute(new AbortTransactionOperation(writeConcern) .recoveryToken(getRecoveryToken()), readConcern, this) - .onErrorResume(Throwable.class, (e) -> Mono.empty()) + .onErrorResume(Exception.class, e -> + // ignore exceptions from abort + Mono.empty()) .doOnTerminate(() -> { clearTransactionContext(); cleanupTransaction(TransactionState.ABORTED); diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java index 443ebbe14bd..826b662a70e 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java @@ -87,13 +87,13 @@ class CommandMarker implements Closeable { Mono mark(final String databaseName, final RawBsonDocument command, @Nullable final Timeout operationTimeout) { if (client != null) { return runCommand(databaseName, command, operationTimeout) - .onErrorResume(Throwable.class, e -> { + .onErrorResume(Exception.class, e -> { if (processBuilder == null || e instanceof MongoOperationTimeoutException) { throw MongoException.fromThrowable(e); } return Mono.fromRunnable(() -> startProcess(processBuilder)).then(runCommand(databaseName, command, operationTimeout)); }) - .onErrorMap(t -> new MongoClientException("Exception in encryption library: " + t.getMessage(), t)); + .onErrorMap(Exception.class, e -> new MongoClientException("Exception in encryption library: " + e.getMessage(), e)); } else { return Mono.fromCallable(() -> command); } diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java index a9407799dc7..0138c5859e5 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java @@ -46,6 +46,7 @@ import java.util.function.Supplier; import static com.mongodb.assertions.Assertions.notNull; +import static com.mongodb.internal.ExceptionUtils.mapUnlessError; import static com.mongodb.internal.client.vault.EncryptOptionsHelper.asMongoExplicitEncryptOptions; import static com.mongodb.internal.crypt.capi.MongoCryptContext.State; @@ -146,7 +147,7 @@ public Mono encrypt(final String databaseName, final RawBsonDoc public Mono decrypt(final RawBsonDocument commandResponse, @Nullable final Timeout timeout) { notNull("commandResponse", commandResponse); return executeStateMachine(() -> mongoCrypt.createDecryptionContext(commandResponse), timeout) - .onErrorMap(this::wrapInClientException); + .onErrorMap(Exception.class, Crypt::wrapInClientException); } /** @@ -247,7 +248,7 @@ private Mono executeStateMachine(final Suppliercreate(sink -> executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout)) - .onErrorMap(this::wrapInClientException) + .onErrorMap(Exception.class, Crypt::wrapInClientException) .doFinally(s -> cryptContext.close()); } catch (MongoCryptException e) { return Mono.error(wrapInClientException(e)); @@ -309,7 +310,7 @@ private void collInfo(final MongoCryptContext cryptContext, cryptContext.completeMongoOperation(); executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout); }) - .doOnError(t -> sink.error(MongoException.fromThrowableNonNull(t))) + .doOnError(t -> sink.error(mapUnlessError(t, MongoException::fromThrowableNonNull))) .subscribe(); } } @@ -330,7 +331,7 @@ private void mark(final MongoCryptContext cryptContext, cryptContext.completeMongoOperation(); executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout); }) - .doOnError(e -> sink.error(wrapInClientException(e))) + .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException))) .subscribe(); } } @@ -348,7 +349,7 @@ private void fetchKeys(final MongoCryptContext cryptContext, cryptContext.completeMongoOperation(); executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout); }) - .doOnError(t -> sink.error(MongoException.fromThrowableNonNull(t))) + .doOnError(t -> sink.error(mapUnlessError(t, MongoException::fromThrowableNonNull))) .subscribe(); } @@ -361,22 +362,22 @@ private void decryptKeys(final MongoCryptContext cryptContext, keyManagementService.decryptKey(keyDecryptor, operationTimeout) .contextWrite(sink.contextView()) .doOnSuccess(r -> decryptKeys(cryptContext, databaseName, sink, operationTimeout)) - .doOnError(e -> sink.error(wrapInClientException(e))) + .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException))) .subscribe(); } else { Mono.fromRunnable(cryptContext::completeKeyDecryptors) .contextWrite(sink.contextView()) .doOnSuccess(r -> executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout)) - .doOnError(e -> sink.error(wrapInClientException(e))) + .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException))) .subscribe(); } } - private Throwable wrapInClientException(final Throwable t) { + private static MongoClientException wrapInClientException(final Throwable t) { if (t instanceof MongoClientException) { - return t; + return (MongoClientException) t; + } else { + return new MongoClientException("Exception in encryption library: " + t.getMessage(), t); } - return new MongoClientException("Exception in encryption library: " + t.getMessage(), t); } - } diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java index 67ebf421c9c..b40ec164060 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java @@ -100,7 +100,7 @@ public void failed(final Throwable t) { handleError(t, operationContext, sink); } }); - }).onErrorMap(this::unWrapException); + }).onErrorMap(Exception.class, this::unWrapException); } private void streamWrite(final Stream stream, final MongoKeyDecryptor keyDecryptor, diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java index 5ae7f4815e5..9942bae926c 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java @@ -62,6 +62,7 @@ import java.util.stream.Collectors; import static com.mongodb.assertions.Assertions.notNull; +import static com.mongodb.internal.ExceptionUtils.mapUnlessError; import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE; import static com.mongodb.internal.capi.MongoCryptHelper.validateRewrapManyDataKeyOptions; import static com.mongodb.reactivestreams.client.internal.TimeoutHelper.collectionWithTimeout; @@ -304,9 +305,9 @@ public Publisher createEncryptedCollection(final MongoDatabase dat .createCollection(collectionName, new CreateCollectionOptions(createCollectionOptions) .encryptedFields(maybeUpdatedEncryptedFields)))) ) - .onErrorMap(e -> dataKeyMightBeCreated.get(), e -> + .onErrorMap(t -> dataKeyMightBeCreated.get(), t -> mapUnlessError(t, e -> new MongoUpdatedEncryptedFieldsException(maybeUpdatedEncryptedFields, - format("Failed to create %s.", namespace), e) + format("Failed to create %s.", namespace), e)) ) .thenReturn(maybeUpdatedEncryptedFields); }); diff --git a/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java b/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java index d694cf682a3..365b1fc49e1 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java +++ b/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java @@ -99,7 +99,7 @@ RawBsonDocument mark(final String databaseName, final RawBsonDocument command, @ return executeCommand(databaseName, command, timeout); } } catch (MongoException e) { - throw wrapInClientException(e); + throw new MongoClientException("Exception in encryption library: " + e.getMessage(), e); } } else { return command; @@ -126,8 +126,4 @@ private RawBsonDocument executeCommand( return databaseWithTimeout(mongoDatabase, TIMEOUT_ERROR_MESSAGE, timeout) .runCommand(markableCommand, RawBsonDocument.class); } - - private MongoClientException wrapInClientException(final MongoException e) { - return new MongoClientException("Exception in encryption library: " + e.getMessage(), e); - } } diff --git a/driver-sync/src/main/com/mongodb/client/internal/Crypt.java b/driver-sync/src/main/com/mongodb/client/internal/Crypt.java index 67fac13770c..a6fe46eecc3 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/Crypt.java +++ b/driver-sync/src/main/com/mongodb/client/internal/Crypt.java @@ -146,7 +146,7 @@ RawBsonDocument encrypt( try (MongoCryptContext encryptionContext = mongoCrypt.createEncryptionContext(databaseName, command)) { return executeStateMachine(encryptionContext, databaseName, timeout); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -161,7 +161,7 @@ RawBsonDocument decrypt(final RawBsonDocument commandResponse, @Nullable final try (MongoCryptContext decryptionContext = mongoCrypt.createDecryptionContext(commandResponse)) { return executeStateMachine(decryptionContext, null, timeoutOperation); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -184,7 +184,7 @@ BsonDocument createDataKey(final String kmsProvider, final DataKeyOptions option .build())) { return executeStateMachine(dataKeyCreationContext, null, operationTimeout); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -203,7 +203,7 @@ BsonBinary encryptExplicitly(final BsonValue value, final EncryptOptions options new BsonDocument("v", value), asMongoExplicitEncryptOptions(options))) { return executeStateMachine(encryptionContext, null, timeoutOperation).getBinary("v"); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -222,7 +222,7 @@ BsonDocument encryptExpression(final BsonDocument expression, final EncryptOptio new BsonDocument("v", expression), asMongoExplicitEncryptOptions(options))) { return executeStateMachine(encryptionContext, null, timeoutOperation).getDocument("v"); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -237,7 +237,7 @@ BsonValue decryptExplicitly(final BsonBinary value, @Nullable final Timeout time try (MongoCryptContext decryptionContext = mongoCrypt.createExplicitDecryptionContext(new BsonDocument("v", value))) { return assertNotNull(executeStateMachine(decryptionContext, null, timeoutOperation).get("v")); } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -260,7 +260,7 @@ BsonDocument rewrapManyDataKey(final BsonDocument filter, final RewrapManyDataKe return executeStateMachine(rewrapManyDatakeyContext, null, operationTimeout); } } catch (MongoCryptException e) { - throw wrapInMongoException(e); + throw wrapInClientException(e); } } @@ -321,8 +321,8 @@ private void collInfo(final MongoCryptContext cryptContext, final String databas cryptContext.addMongoOperationResult(result); } cryptContext.completeMongoOperation(); - } catch (Throwable t) { - throw MongoException.fromThrowableNonNull(t); + } catch (Exception e) { + throw MongoException.fromThrowableNonNull(e); } } @@ -331,8 +331,8 @@ private void mark(final MongoCryptContext cryptContext, final String databaseNam RawBsonDocument markedCommand = assertNotNull(commandMarker).mark(databaseName, cryptContext.getMongoOperation(), timeout); cryptContext.addMongoOperationResult(markedCommand); cryptContext.completeMongoOperation(); - } catch (Throwable t) { - throw wrapInMongoException(t); + } catch (Exception e) { + throw wrapInClientException(e); } } @@ -342,8 +342,8 @@ private void fetchKeys(final MongoCryptContext keyBroker, @Nullable final Timeou keyBroker.addMongoOperationResult(bsonDocument); } keyBroker.completeMongoOperation(); - } catch (Throwable t) { - throw MongoException.fromThrowableNonNull(t); + } catch (Exception e) { + throw MongoException.fromThrowableNonNull(e); } } @@ -355,9 +355,9 @@ private void decryptKeys(final MongoCryptContext cryptContext, @Nullable final T keyDecryptor = cryptContext.nextKeyDecryptor(); } cryptContext.completeKeyDecryptors(); - } catch (Throwable t) { - throw translateInterruptedException(t, "Interrupted while doing IO") - .orElseThrow(() -> wrapInMongoException(t)); + } catch (Exception e) { + throw translateInterruptedException(e, "Interrupted while doing IO") + .orElseThrow(() -> wrapInClientException(e)); } } @@ -378,11 +378,11 @@ private void decryptKey(final MongoKeyDecryptor keyDecryptor, @Nullable final Ti } } - private MongoException wrapInMongoException(final Throwable t) { - if (t instanceof MongoClientException) { - return (MongoException) t; + private static MongoClientException wrapInClientException(final Exception e) { + if (e instanceof MongoClientException) { + return (MongoClientException) e; } else { - return new MongoClientException("Exception in encryption library: " + t.getMessage(), t); + return new MongoClientException("Exception in encryption library: " + e.getMessage(), e); } } } diff --git a/gradle.properties b/gradle.properties index 733e8118433..9f2453d567e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ # limitations under the License. # -version=5.10.0-SNAPSHOT +version=5.11.0-SNAPSHOT org.gradle.daemon=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en