Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* 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.internal;

import com.mongodb.annotations.Immutable;
import com.mongodb.internal.connection.InternalConnectionPoolSettings;

import java.util.Objects;

/**
* Internal settings for MongoClient that are not part of the public API.
* Used for testing and internal configuration purposes.
*
* <p>This class is not part of the public API and may be removed or changed at any time</p>
*/
@Immutable
public final class InternalMongoClientSettings {

private static final InternalMongoClientSettings DEFAULTS = builder().build();

private final InternalConnectionPoolSettings internalConnectionPoolSettings;
private final boolean recordEverything;

private InternalMongoClientSettings(final Builder builder) {
this.internalConnectionPoolSettings = builder.internalConnectionPoolSettings != null
? builder.internalConnectionPoolSettings
: InternalConnectionPoolSettings.builder().build();
this.recordEverything = builder.recordEverything;
}

/**
* Gets the default internal settings for production use.
*
* @return the default settings
*/
public static InternalMongoClientSettings getDefaults() {
return DEFAULTS;
}

/**
* Creates a new builder for InternalMongoClientSettings.
*
* @return the builder
*/
public static Builder builder() {
return new Builder();
}

/**
* Gets the internal connection pool settings.
*
* @return the internal connection pool settings
*/
public InternalConnectionPoolSettings getInternalConnectionPoolSettings() {
return internalConnectionPoolSettings;
}

/**
* Indicates whether to record all commands including security-sensitive commands
* (like authentication commands) to the command listener.
* <p>
* When disabled (the default for production), security-sensitive commands are not recorded
* to the command listener for security reasons. When enabled, all commands are recorded,
* which is useful for testing authentication and handshake behavior.
* </p>
*
* @return true if all commands should be recorded
*/
public boolean isRecordEverything() {
return recordEverything;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
InternalMongoClientSettings that = (InternalMongoClientSettings) o;
return recordEverything == that.recordEverything
&& Objects.equals(internalConnectionPoolSettings, that.internalConnectionPoolSettings);
}

@Override
public int hashCode() {
return Objects.hash(internalConnectionPoolSettings, recordEverything);
}

@Override
public String toString() {
return "InternalMongoClientSettings{"
+ "internalConnectionPoolSettings=" + internalConnectionPoolSettings
+ ", recordEverything=" + recordEverything
+ '}';
}

/**
* A builder for InternalMongoClientSettings.
*/
public static final class Builder {
private InternalConnectionPoolSettings internalConnectionPoolSettings = InternalConnectionPoolSettings.builder().build();
private boolean recordEverything = false;

private Builder() {
}

/**
* Sets the internal connection pool settings.
*
* @param internalConnectionPoolSettings the internal connection pool settings
* @return this
*/
public Builder internalConnectionPoolSettings(
final InternalConnectionPoolSettings internalConnectionPoolSettings) {
this.internalConnectionPoolSettings = internalConnectionPoolSettings;
return this;
}

/**
* Sets whether to record all commands including security-sensitive commands.
* <p>
* Default is {@code false} for production use. Set to {@code true} for testing
* authentication and handshake behavior.
* </p>
*
* @param recordEverything whether to record all commands
* @return this
*/
public Builder recordEverything(final boolean recordEverything) {
this.recordEverything = recordEverything;
return this;
}

/**
* Builds the InternalMongoClientSettings.
*
* @return the internal settings
*/
public InternalMongoClientSettings build() {
return new InternalMongoClientSettings(this);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.mongodb.event.CommandListener;
import com.mongodb.event.ServerListener;
import com.mongodb.event.ServerMonitorListener;
import com.mongodb.internal.InternalMongoClientSettings;
import com.mongodb.internal.TimeoutSettings;
import com.mongodb.internal.VisibleForTesting;
import com.mongodb.internal.diagnostics.logging.Logger;
Expand Down Expand Up @@ -60,7 +61,7 @@ public final class DefaultClusterFactory {

public Cluster createCluster(final ClusterSettings originalClusterSettings, final ServerSettings originalServerSettings,
final ConnectionPoolSettings connectionPoolSettings,
final InternalConnectionPoolSettings internalConnectionPoolSettings,
final InternalMongoClientSettings internalSettings,
final TimeoutSettings clusterTimeoutSettings,
final StreamFactory streamFactory,
final TimeoutSettings heartbeatTimeoutSettings,
Expand Down Expand Up @@ -113,12 +114,12 @@ public Cluster createCluster(final ClusterSettings originalClusterSettings, fina

if (clusterSettings.getMode() == ClusterConnectionMode.LOAD_BALANCED) {
ClusterableServerFactory serverFactory = new LoadBalancedClusterableServerFactory(serverSettings,
connectionPoolSettings, internalConnectionPoolSettings, streamFactory, credential, loggerSettings, commandListener,
connectionPoolSettings, internalSettings, streamFactory, credential, loggerSettings, commandListener,
compressorList, serverApi, clusterOperationContextFactory);
return new LoadBalancedCluster(clusterId, clusterSettings, serverFactory, clientMetadata, dnsSrvRecordMonitorFactory);
} else {
ClusterableServerFactory serverFactory = new DefaultClusterableServerFactory(serverSettings,
connectionPoolSettings, internalConnectionPoolSettings,
connectionPoolSettings, internalSettings,
clusterOperationContextFactory, streamFactory, heartBeatOperationContextFactory, heartbeatStreamFactory, credential,
loggerSettings, commandListener, compressorList,
serverApi, FaasEnvironment.getFaasEnvironment() != FaasEnvironment.UNKNOWN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.mongodb.connection.ServerSettings;
import com.mongodb.event.CommandListener;
import com.mongodb.event.ServerListener;
import com.mongodb.internal.InternalMongoClientSettings;
import com.mongodb.internal.inject.SameObjectProvider;
import com.mongodb.lang.Nullable;

Expand All @@ -41,7 +42,7 @@
public class DefaultClusterableServerFactory implements ClusterableServerFactory {
private final ServerSettings serverSettings;
private final ConnectionPoolSettings connectionPoolSettings;
private final InternalConnectionPoolSettings internalConnectionPoolSettings;
private final InternalMongoClientSettings internalSettings;
private final InternalOperationContextFactory clusterOperationContextFactory;
private final StreamFactory streamFactory;
private final InternalOperationContextFactory heartbeatOperationContextFactory;
Expand All @@ -56,15 +57,15 @@ public class DefaultClusterableServerFactory implements ClusterableServerFactory

public DefaultClusterableServerFactory(
final ServerSettings serverSettings, final ConnectionPoolSettings connectionPoolSettings,
final InternalConnectionPoolSettings internalConnectionPoolSettings,
final InternalMongoClientSettings internalSettings,
final InternalOperationContextFactory clusterOperationContextFactory, final StreamFactory streamFactory,
final InternalOperationContextFactory heartbeatOperationContextFactory, final StreamFactory heartbeatStreamFactory,
@Nullable final MongoCredential credential, final LoggerSettings loggerSettings,
@Nullable final CommandListener commandListener,
final List<MongoCompressor> compressorList, @Nullable final ServerApi serverApi, final boolean isFunctionAsAServiceEnvironment) {
this.serverSettings = serverSettings;
this.connectionPoolSettings = connectionPoolSettings;
this.internalConnectionPoolSettings = internalConnectionPoolSettings;
this.internalSettings = internalSettings;
this.clusterOperationContextFactory = clusterOperationContextFactory;
this.streamFactory = streamFactory;
this.heartbeatOperationContextFactory = heartbeatOperationContextFactory;
Expand All @@ -87,13 +88,13 @@ public ClusterableServer create(final Cluster cluster, final ServerAddress serve
ServerMonitor serverMonitor = new DefaultServerMonitor(serverId, serverSettings,
// no credentials, compressor list, or command listener for the server monitor factory
new InternalStreamConnectionFactory(clusterMode, true, heartbeatStreamFactory, null, clientMetadata,
emptyList(), loggerSettings, null, serverApi),
emptyList(), loggerSettings, null, serverApi, internalSettings.isRecordEverything()),
clusterMode, serverApi, isFunctionAsAServiceEnvironment, sdamProvider, heartbeatOperationContextFactory);

ConnectionPool connectionPool = new DefaultConnectionPool(serverId,
new InternalStreamConnectionFactory(clusterMode, streamFactory, credential, clientMetadata,
compressorList, loggerSettings, commandListener, serverApi),
connectionPoolSettings, internalConnectionPoolSettings, sdamProvider, clusterOperationContextFactory);
new InternalStreamConnectionFactory(clusterMode, false, streamFactory, credential, clientMetadata,
compressorList, loggerSettings, commandListener, serverApi, internalSettings.isRecordEverything()),
connectionPoolSettings, internalSettings.getInternalConnectionPoolSettings(), sdamProvider, clusterOperationContextFactory);
ServerListener serverListener = singleServerListener(serverSettings);
SdamServerDescriptionManager sdam = new DefaultSdamServerDescriptionManager(cluster, serverId, serverListener, serverMonitor,
connectionPool, clusterMode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,6 @@
@NotThreadSafe
public class InternalStreamConnection implements InternalConnection {

private static volatile boolean recordEverything = false;

/**
* Will attempt to record events to the command listener that are usually
* suppressed.
*
* @param recordEverything whether to attempt to record everything
*/
@VisibleForTesting(otherwise = VisibleForTesting.AccessModifier.PRIVATE)
public static void setRecordEverything(final boolean recordEverything) {
InternalStreamConnection.recordEverything = recordEverything;
}

private static final Set<String> SECURITY_SENSITIVE_COMMANDS = new HashSet<>(asList(
"authenticate",
"saslStart",
Expand Down Expand Up @@ -160,6 +147,7 @@ public static void setRecordEverything(final boolean recordEverything) {
private volatile boolean hasMoreToCome;
private volatile int responseTo;
private int generation = NOT_INITIALIZED_GENERATION;
private final boolean recordEverything;

// Package-level access provided to avoid duplicating the list in test code
static Set<String> getSecuritySensitiveCommands() {
Expand All @@ -177,7 +165,7 @@ public InternalStreamConnection(final ClusterConnectionMode clusterConnectionMod
final StreamFactory streamFactory, final List<MongoCompressor> compressorList,
final CommandListener commandListener, final InternalConnectionInitializer connectionInitializer) {
this(clusterConnectionMode, null, false, serverId, connectionGenerationSupplier, streamFactory, compressorList,
LoggerSettings.builder().build(), commandListener, connectionInitializer);
LoggerSettings.builder().build(), commandListener, connectionInitializer, false);
}

public InternalStreamConnection(final ClusterConnectionMode clusterConnectionMode,
Expand All @@ -188,6 +176,19 @@ public InternalStreamConnection(final ClusterConnectionMode clusterConnectionMod
final StreamFactory streamFactory, final List<MongoCompressor> compressorList,
final LoggerSettings loggerSettings,
final CommandListener commandListener, final InternalConnectionInitializer connectionInitializer) {
this(clusterConnectionMode, authenticator, isMonitoringConnection, serverId, connectionGenerationSupplier,
streamFactory, compressorList, loggerSettings, commandListener, connectionInitializer, false);
}

public InternalStreamConnection(final ClusterConnectionMode clusterConnectionMode,
@Nullable final Authenticator authenticator,
final boolean isMonitoringConnection,
final ServerId serverId,
final ConnectionGenerationSupplier connectionGenerationSupplier,
final StreamFactory streamFactory, final List<MongoCompressor> compressorList,
final LoggerSettings loggerSettings,
final CommandListener commandListener, final InternalConnectionInitializer connectionInitializer,
final boolean recordEverything) {
this.clusterConnectionMode = clusterConnectionMode;
this.authenticator = authenticator;
this.isMonitoringConnection = isMonitoringConnection;
Expand All @@ -199,6 +200,7 @@ public InternalStreamConnection(final ClusterConnectionMode clusterConnectionMod
this.loggerSettings = loggerSettings;
this.commandListener = commandListener;
this.connectionInitializer = notNull("connectionInitializer", connectionInitializer);
this.recordEverything = recordEverything;
description = new ConnectionDescription(serverId);
initialServerDescription = ServerDescription.builder()
.address(serverId.getAddress())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class InternalStreamConnectionFactory implements InternalConnectionFactory {
@Nullable
private final ServerApi serverApi;
private final MongoCredentialWithCache credential;
private final boolean recordEverything;

InternalStreamConnectionFactory(final ClusterConnectionMode clusterConnectionMode,
final StreamFactory streamFactory,
Expand All @@ -49,15 +50,16 @@ class InternalStreamConnectionFactory implements InternalConnectionFactory {
final LoggerSettings loggerSettings, @Nullable final CommandListener commandListener,
@Nullable final ServerApi serverApi) {
this(clusterConnectionMode, false, streamFactory, credential, clientMetadata, compressorList,
loggerSettings, commandListener, serverApi);
loggerSettings, commandListener, serverApi, false);
}

InternalStreamConnectionFactory(final ClusterConnectionMode clusterConnectionMode, final boolean isMonitoringConnection,
final StreamFactory streamFactory,
@Nullable final MongoCredentialWithCache credential,
final ClientMetadata clientMetadata,
final List<MongoCompressor> compressorList,
final LoggerSettings loggerSettings, @Nullable final CommandListener commandListener, @Nullable final ServerApi serverApi) {
final List<MongoCompressor> compressorList,
final LoggerSettings loggerSettings, @Nullable final CommandListener commandListener,
@Nullable final ServerApi serverApi, final boolean recordEverything) {
this.clusterConnectionMode = clusterConnectionMode;
this.isMonitoringConnection = isMonitoringConnection;
this.streamFactory = notNull("streamFactory", streamFactory);
Expand All @@ -67,6 +69,7 @@ class InternalStreamConnectionFactory implements InternalConnectionFactory {
this.serverApi = serverApi;
this.clientMetadata = clientMetadata;
this.credential = credential;
this.recordEverything = recordEverything;
}

@Override
Expand All @@ -78,7 +81,7 @@ public InternalConnection create(final ServerId serverId, final ConnectionGenera
clusterConnectionMode, authenticator,
isMonitoringConnection, serverId, connectionGenerationSupplier,
streamFactory, compressorList, loggerSettings, commandListener,
connectionInitializer);
connectionInitializer, recordEverything);
}

private Authenticator createAuthenticator(final MongoCredentialWithCache credential) {
Expand Down
Loading