diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
index dd60a2487fb..375d61a7982 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
@@ -869,14 +869,6 @@ public enum DefaultDriverOption implements DriverOption {
*/
NETTY_DAEMON("advanced.netty.daemon"),
- /**
- * The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a
- * service.
- *
- * Value-type: {@link String}
- */
- CLOUD_SECURE_CONNECT_BUNDLE("basic.cloud.secure-connect-bundle"),
-
/**
* Whether the slow replica avoidance should be enabled in the default LBP.
*
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
index af93e734ef1..7c9085270ed 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
@@ -685,12 +685,6 @@ public String toString() {
/** Whether the threads created by the driver should be daemon threads. */
public static final TypedDriverOption NETTY_DAEMON =
new TypedDriverOption<>(DefaultDriverOption.NETTY_DAEMON, GenericType.BOOLEAN);
- /**
- * The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a
- * service.
- */
- public static final TypedDriverOption CLOUD_SECURE_CONNECT_BUNDLE =
- new TypedDriverOption<>(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, GenericType.STRING);
/** Whether the slow replica avoidance should be enabled in the default LBP. */
public static final TypedDriverOption LOAD_BALANCING_POLICY_SLOW_AVOIDANCE =
new TypedDriverOption<>(
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java b/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java
index 4db44655dc2..d70bf780593 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java
@@ -36,7 +36,6 @@
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -68,7 +67,6 @@ public static Builder builder() {
private final ClassLoader classLoader;
private final AuthProvider authProvider;
private final SslEngineFactory sslEngineFactory;
- private final InetSocketAddress cloudProxyAddress;
private final UUID startupClientId;
private final String startupApplicationName;
private final String startupApplicationVersion;
@@ -88,7 +86,6 @@ private ProgrammaticArguments(
@Nullable ClassLoader classLoader,
@Nullable AuthProvider authProvider,
@Nullable SslEngineFactory sslEngineFactory,
- @Nullable InetSocketAddress cloudProxyAddress,
@Nullable UUID startupClientId,
@Nullable String startupApplicationName,
@Nullable String startupApplicationVersion,
@@ -107,7 +104,6 @@ private ProgrammaticArguments(
this.classLoader = classLoader;
this.authProvider = authProvider;
this.sslEngineFactory = sslEngineFactory;
- this.cloudProxyAddress = cloudProxyAddress;
this.startupClientId = startupClientId;
this.startupApplicationName = startupApplicationName;
this.startupApplicationVersion = startupApplicationVersion;
@@ -173,11 +169,6 @@ public SslEngineFactory getSslEngineFactory() {
return sslEngineFactory;
}
- @Nullable
- public InetSocketAddress getCloudProxyAddress() {
- return cloudProxyAddress;
- }
-
@Nullable
public UUID getStartupClientId() {
return startupClientId;
@@ -223,7 +214,6 @@ public static class Builder {
private ClassLoader classLoader;
private AuthProvider authProvider;
private SslEngineFactory sslEngineFactory;
- private InetSocketAddress cloudProxyAddress;
private UUID startupClientId;
private String startupApplicationName;
private String startupApplicationVersion;
@@ -388,12 +378,6 @@ public Builder withClassLoader(@Nullable ClassLoader classLoader) {
return this;
}
- @NonNull
- public Builder withCloudProxyAddress(@Nullable InetSocketAddress cloudAddress) {
- this.cloudProxyAddress = cloudAddress;
- return this;
- }
-
@NonNull
public Builder withAuthProvider(@Nullable AuthProvider authProvider) {
this.authProvider = authProvider;
@@ -456,7 +440,6 @@ public ProgrammaticArguments build() {
classLoader,
authProvider,
sslEngineFactory,
- cloudProxyAddress,
startupClientId,
startupApplicationName,
startupApplicationVersion,
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java b/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
index 8375f0ef30b..77c17fc7b41 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
@@ -30,7 +30,6 @@
import com.datastax.oss.driver.api.core.auth.ProgrammaticPlainTextAuthProvider;
import com.datastax.oss.driver.api.core.config.ClientRoutesConfig;
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
-import com.datastax.oss.driver.api.core.config.DriverConfig;
import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
import com.datastax.oss.driver.api.core.config.DriverExecutionProfile;
import com.datastax.oss.driver.api.core.context.DriverContext;
@@ -48,24 +47,16 @@
import com.datastax.oss.driver.api.core.type.codec.registry.MutableCodecRegistry;
import com.datastax.oss.driver.api.core.uuid.Uuids;
import com.datastax.oss.driver.internal.core.ContactPoints;
-import com.datastax.oss.driver.internal.core.config.cloud.CloudConfig;
-import com.datastax.oss.driver.internal.core.config.cloud.CloudConfigFactory;
import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader;
import com.datastax.oss.driver.internal.core.context.DefaultDriverContext;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
import com.datastax.oss.driver.internal.core.metadata.DefaultEndPoint;
import com.datastax.oss.driver.internal.core.session.DefaultSession;
-import com.datastax.oss.driver.internal.core.tracker.W3CContextRequestIdGenerator;
import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation;
import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.InputStream;
import java.net.InetSocketAddress;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -73,7 +64,6 @@
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.Callable;
import java.util.concurrent.CompletionStage;
import java.util.function.Predicate;
import javax.net.ssl.SSLContext;
@@ -92,8 +82,6 @@
@NotThreadSafe
public abstract class SessionBuilder {
- public static final String ASTRA_PAYLOAD_KEY = "traceparent";
-
private static final Logger LOG = LoggerFactory.getLogger(SessionBuilder.class);
@SuppressWarnings("unchecked")
@@ -102,11 +90,8 @@ public abstract class SessionBuilder {
protected DriverConfigLoader configLoader;
protected Set programmaticContactPoints = new HashSet<>();
protected CqlIdentifier keyspace;
- protected Callable cloudConfigInputStream;
protected ProgrammaticArguments.Builder programmaticArgumentsBuilder =
ProgrammaticArguments.builder();
- private boolean programmaticSslFactory = false;
- private boolean programmaticLocalDatacenter = false;
/**
* Sets the configuration loader to use.
@@ -427,7 +412,6 @@ public SelfT withCredentials(
*/
@NonNull
public SelfT withSslEngineFactory(@Nullable SslEngineFactory sslEngineFactory) {
- this.programmaticSslFactory = true;
this.programmaticArgumentsBuilder.withSslEngineFactory(sslEngineFactory);
return self;
}
@@ -465,7 +449,6 @@ public SelfT withSslContext(@Nullable SSLContext sslContext) {
* if you use a third-party implementation, refer to their documentation.
*/
public SelfT withLocalDatacenter(@NonNull String profileName, @NonNull String localDatacenter) {
- this.programmaticLocalDatacenter = true;
this.programmaticArgumentsBuilder.withLocalDatacenter(profileName, localDatacenter);
return self;
}
@@ -647,31 +630,6 @@ public SelfT withClassLoader(@Nullable ClassLoader classLoader) {
return self;
}
- /**
- * Configures this SessionBuilder for Cloud deployments by retrieving connection information from
- * the provided {@link Path}.
- *
- * To connect to a Cloud database, you must first download the secure database bundle from the
- * DataStax Astra console that contains the connection information, then instruct the driver to
- * read its contents using either this method or one if its variants.
- *
- *
For more information, please refer to the DataStax Astra documentation.
- *
- * @param cloudConfigPath Path to the secure connect bundle zip file.
- * @see #withCloudSecureConnectBundle(URL)
- * @see #withCloudSecureConnectBundle(InputStream)
- */
- @NonNull
- public SelfT withCloudSecureConnectBundle(@NonNull Path cloudConfigPath) {
- try {
- URL cloudConfigUrl = cloudConfigPath.toAbsolutePath().normalize().toUri().toURL();
- this.cloudConfigInputStream = cloudConfigUrl::openStream;
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Incorrect format of cloudConfigPath", e);
- }
- return self;
- }
-
/**
* Registers a CodecRegistry to use for the session.
*
@@ -684,72 +642,6 @@ public SelfT withCodecRegistry(@Nullable MutableCodecRegistry codecRegistry) {
return self;
}
- /**
- * Configures this SessionBuilder for Cloud deployments by retrieving connection information from
- * the provided {@link URL}.
- *
- *
To connect to a Cloud database, you must first download the secure database bundle from the
- * DataStax Astra console that contains the connection information, then instruct the driver to
- * read its contents using either this method or one if its variants.
- *
- *
For more information, please refer to the DataStax Astra documentation.
- *
- * @param cloudConfigUrl URL to the secure connect bundle zip file.
- * @see #withCloudSecureConnectBundle(Path)
- * @see #withCloudSecureConnectBundle(InputStream)
- */
- @NonNull
- public SelfT withCloudSecureConnectBundle(@NonNull URL cloudConfigUrl) {
- this.cloudConfigInputStream = cloudConfigUrl::openStream;
- return self;
- }
-
- /**
- * Configures this SessionBuilder for Cloud deployments by retrieving connection information from
- * the provided {@link InputStream}.
- *
- *
To connect to a Cloud database, you must first download the secure database bundle from the
- * DataStax Astra console that contains the connection information, then instruct the driver to
- * read its contents using either this method or one if its variants.
- *
- *
For more information, please refer to the DataStax Astra documentation.
- *
- *
Note that the provided stream will be consumed and closed when either {@link
- * #build()} or {@link #buildAsync()} are called; attempting to reuse it afterwards will result in
- * an error being thrown.
- *
- * @param cloudConfigInputStream A stream containing the secure connect bundle zip file.
- * @see #withCloudSecureConnectBundle(Path)
- * @see #withCloudSecureConnectBundle(URL)
- */
- @NonNull
- public SelfT withCloudSecureConnectBundle(@NonNull InputStream cloudConfigInputStream) {
- this.cloudConfigInputStream = () -> cloudConfigInputStream;
- return self;
- }
-
- /**
- * Configures this SessionBuilder to use the provided Cloud proxy endpoint.
- *
- *
Normally, this method should not be called directly; the normal and easiest way to configure
- * the driver for Cloud deployments is through a {@linkplain #withCloudSecureConnectBundle(URL)
- * secure connect bundle}.
- *
- *
Setting this option to any non-null address will make the driver use a special topology
- * monitor tailored for Cloud deployments. This topology monitor assumes that the target cluster
- * should be contacted through the proxy specified here, using SNI routing.
- *
- *
For more information, please refer to the DataStax Astra documentation.
- *
- * @param cloudProxyAddress The address of the Cloud proxy to use.
- * @see Server Name Indication
- */
- @NonNull
- public SelfT withCloudProxyAddress(@Nullable InetSocketAddress cloudProxyAddress) {
- this.programmaticArgumentsBuilder.withCloudProxyAddress(cloudProxyAddress);
- return self;
- }
-
/**
* Configures this session to use client routes for cloud private-endpoint deployments.
*
@@ -910,52 +802,8 @@ protected final CompletionStage buildDefaultSessionAsync() {
: defaultConfigLoader(programmaticArguments.getClassLoader());
DriverExecutionProfile defaultConfig = configLoader.getInitialConfig().getDefaultProfile();
- if (cloudConfigInputStream == null) {
- String configUrlString =
- defaultConfig.getString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, null);
- if (configUrlString != null) {
- cloudConfigInputStream = () -> getURL(configUrlString).openStream();
- }
- }
List configContactPoints =
defaultConfig.getStringList(DefaultDriverOption.CONTACT_POINTS, Collections.emptyList());
- if (cloudConfigInputStream != null) {
- // override request id generator, unless user has already set it
- if (programmaticArguments.getRequestIdGenerator() == null) {
- programmaticArgumentsBuilder.withRequestIdGenerator(
- new W3CContextRequestIdGenerator(ASTRA_PAYLOAD_KEY));
- LOG.debug(
- "A secure connect bundle is provided, using W3CContextRequestIdGenerator as request ID generator.");
- }
- if (!programmaticContactPoints.isEmpty() || !configContactPoints.isEmpty()) {
- LOG.info(
- "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority.");
- // clear the contact points provided in the setting file and via addContactPoints
- configContactPoints = Collections.emptyList();
- programmaticContactPoints = new HashSet<>();
- }
-
- if (programmaticSslFactory
- || defaultConfig.isDefined(DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS)) {
- LOG.info(
- "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority.");
- }
- CloudConfig cloudConfig =
- new CloudConfigFactory().createCloudConfig(cloudConfigInputStream.call());
- addContactEndPoints(cloudConfig.getEndPoints());
-
- boolean localDataCenterDefined =
- anyProfileHasDatacenterDefined(configLoader.getInitialConfig());
- if (programmaticLocalDatacenter || localDataCenterDefined) {
- LOG.info(
- "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority.");
- programmaticArgumentsBuilder.clearDatacenters();
- }
- withLocalDatacenter(cloudConfig.getLocalDatacenter());
- withSslEngineFactory(cloudConfig.getSslEngineFactory());
- withCloudProxyAddress(cloudConfig.getProxyAddress());
- programmaticArguments = programmaticArgumentsBuilder.build();
- }
boolean resolveAddresses =
defaultConfig.getBoolean(DefaultDriverOption.RESOLVE_CONTACT_POINTS, false);
@@ -980,36 +828,6 @@ protected final CompletionStage buildDefaultSessionAsync() {
}
}
- private boolean anyProfileHasDatacenterDefined(DriverConfig driverConfig) {
- for (DriverExecutionProfile driverExecutionProfile : driverConfig.getProfiles().values()) {
- if (driverExecutionProfile.isDefined(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns URL based on the configUrl setting. If the configUrl has no protocol provided, the
- * method will fallback to file:// protocol and return URL that has file protocol specified.
- *
- * @param configUrl url to config secure bundle
- * @return URL with file protocol if there was not explicit protocol provided in the configUrl
- * setting
- */
- private URL getURL(String configUrl) throws MalformedURLException {
- try {
- return new URL(configUrl);
- } catch (MalformedURLException e1) {
- try {
- return Paths.get(configUrl).toAbsolutePath().normalize().toUri().toURL();
- } catch (MalformedURLException e2) {
- e2.addSuppressed(e1);
- throw e2;
- }
- }
- }
-
/**
* This must return an instance of {@code InternalDriverContext} (it's not expressed
* directly in the signature to avoid leaking that type through the protected API).
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java
index 35190afa3f4..75e81b2475e 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java
@@ -23,11 +23,9 @@
*/
package com.datastax.oss.driver.internal.core.channel;
-import com.datastax.oss.driver.api.core.ConsistencyLevel;
import com.datastax.oss.driver.api.core.ProtocolVersion;
import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException;
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
-import com.datastax.oss.driver.api.core.config.DriverConfig;
import com.datastax.oss.driver.api.core.config.DriverExecutionProfile;
import com.datastax.oss.driver.api.core.context.DriverContext;
import com.datastax.oss.driver.api.core.metadata.EndPoint;
@@ -35,7 +33,6 @@
import com.datastax.oss.driver.api.core.metadata.NodeShardingInfo;
import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric;
import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric;
-import com.datastax.oss.driver.internal.core.config.typesafe.TypesafeDriverConfig;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
import com.datastax.oss.driver.internal.core.context.NettyOptions;
import com.datastax.oss.driver.internal.core.metadata.DefaultNode;
@@ -46,7 +43,6 @@
import com.datastax.oss.driver.internal.core.protocol.FrameEncoder;
import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting;
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
-import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import com.datastax.oss.protocol.internal.ProtocolFeatures;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
@@ -59,7 +55,6 @@
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -76,20 +71,8 @@ public class ChannelFactory {
private static final Logger LOG = LoggerFactory.getLogger(ChannelFactory.class);
- /**
- * A value for {@link #productType} that indicates that we are connected to DataStax Cloud. This
- * value matches the one defined at DSE DB server side at {@code ProductType.java}.
- */
- private static final String DATASTAX_CLOUD_PRODUCT_TYPE = "DATASTAX_APOLLO";
-
private static final AtomicBoolean LOGGED_ORPHAN_WARNING = new AtomicBoolean();
- /**
- * A value for {@link #productType} that indicates that the server does not report any product
- * type.
- */
- private static final String UNKNOWN_PRODUCT_TYPE = "UNKNOWN";
-
// The names of the handlers on the pipeline:
public static final String SSL_HANDLER_NAME = "ssl";
public static final String INBOUND_TRAFFIC_METER_NAME = "inboundTrafficMeter";
@@ -132,14 +115,6 @@ public static int effectiveMaxOrphanRequests(
private volatile String clusterName;
- /**
- * The value of the {@code PRODUCT_TYPE} option reported by the first channel we opened, in
- * response to a {@code SUPPORTED} request.
- *
- * If the server does not return that option, the value will be {@link #UNKNOWN_PRODUCT_TYPE}.
- */
- @VisibleForTesting volatile String productType;
-
public ChannelFactory(InternalDriverContext context) {
this.logPrefix = context.getSessionName();
this.context = context;
@@ -296,24 +271,6 @@ private void connect(
if (ChannelFactory.this.clusterName == null) {
ChannelFactory.this.clusterName = driverChannel.getClusterName();
}
- Map> supportedOptions = driverChannel.getOptions();
- if (ChannelFactory.this.productType == null && supportedOptions != null) {
- List productTypes = supportedOptions.get("PRODUCT_TYPE");
- String productType =
- productTypes != null && !productTypes.isEmpty()
- ? productTypes.get(0)
- : UNKNOWN_PRODUCT_TYPE;
- ChannelFactory.this.productType = productType;
- DriverConfig driverConfig = context.getConfig();
- if (driverConfig instanceof TypesafeDriverConfig
- && productType.equals(DATASTAX_CLOUD_PRODUCT_TYPE)) {
- ((TypesafeDriverConfig) driverConfig)
- .overrideDefaults(
- ImmutableMap.of(
- DefaultDriverOption.REQUEST_CONSISTENCY,
- ConsistencyLevel.LOCAL_QUORUM.name()));
- }
- }
resultFuture.complete(driverChannel);
} else {
Throwable error = connectFuture.cause();
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java b/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java
deleted file mode 100644
index 1a1076e9d78..00000000000
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.config.cloud;
-
-import com.datastax.oss.driver.api.core.metadata.EndPoint;
-import com.datastax.oss.driver.api.core.ssl.SslEngineFactory;
-import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import java.net.InetSocketAddress;
-import java.util.List;
-import net.jcip.annotations.ThreadSafe;
-
-@ThreadSafe
-public class CloudConfig {
-
- private final InetSocketAddress proxyAddress;
- private final List endPoints;
- private final String localDatacenter;
- private final SslEngineFactory sslEngineFactory;
-
- CloudConfig(
- @NonNull InetSocketAddress proxyAddress,
- @NonNull List endPoints,
- @NonNull String localDatacenter,
- @NonNull SslEngineFactory sslEngineFactory) {
- this.proxyAddress = proxyAddress;
- this.endPoints = ImmutableList.copyOf(endPoints);
- this.localDatacenter = localDatacenter;
- this.sslEngineFactory = sslEngineFactory;
- }
-
- @NonNull
- public InetSocketAddress getProxyAddress() {
- return proxyAddress;
- }
-
- @NonNull
- public List getEndPoints() {
- return endPoints;
- }
-
- @NonNull
- public String getLocalDatacenter() {
- return localDatacenter;
- }
-
- @NonNull
- public SslEngineFactory getSslEngineFactory() {
- return sslEngineFactory;
- }
-}
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java
deleted file mode 100644
index 817b3263d25..00000000000
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.config.cloud;
-
-import com.datastax.oss.driver.api.core.metadata.EndPoint;
-import com.datastax.oss.driver.internal.core.metadata.SniEndPoint;
-import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory;
-import com.datastax.oss.driver.shaded.guava.common.io.ByteStreams;
-import com.datastax.oss.driver.shaded.guava.common.net.HostAndPort;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.ConnectException;
-import java.net.InetSocketAddress;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManagerFactory;
-import net.jcip.annotations.ThreadSafe;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@ThreadSafe
-public class CloudConfigFactory {
- private static final Logger LOG = LoggerFactory.getLogger(CloudConfigFactory.class);
- /**
- * Creates a {@link CloudConfig} with information fetched from the specified Cloud configuration
- * URL.
- *
- * The target URL must point to a valid secure connect bundle archive in ZIP format.
- *
- * @param cloudConfigUrl the URL to fetch the Cloud configuration from; cannot be null.
- * @throws IOException If the Cloud configuration cannot be read.
- * @throws GeneralSecurityException If the Cloud SSL context cannot be created.
- */
- @NonNull
- public CloudConfig createCloudConfig(@NonNull URL cloudConfigUrl)
- throws IOException, GeneralSecurityException {
- Objects.requireNonNull(cloudConfigUrl, "cloudConfigUrl cannot be null");
- return createCloudConfig(cloudConfigUrl.openStream());
- }
-
- /**
- * Creates a {@link CloudConfig} with information fetched from the specified {@link InputStream}.
- *
- *
The stream must contain a valid secure connect bundle archive in ZIP format. Note that the
- * stream will be closed after a call to that method and cannot be used anymore.
- *
- * @param cloudConfig the stream to read the Cloud configuration from; cannot be null.
- * @throws IOException If the Cloud configuration cannot be read.
- * @throws GeneralSecurityException If the Cloud SSL context cannot be created.
- */
- @NonNull
- public CloudConfig createCloudConfig(@NonNull InputStream cloudConfig)
- throws IOException, GeneralSecurityException {
- Objects.requireNonNull(cloudConfig, "cloudConfig cannot be null");
- JsonNode configJson = null;
- ByteArrayOutputStream keyStoreOutputStream = null;
- ByteArrayOutputStream trustStoreOutputStream = null;
- ObjectMapper mapper = new ObjectMapper().configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
- try (ZipInputStream zipInputStream = new ZipInputStream(cloudConfig)) {
- ZipEntry entry;
- while ((entry = zipInputStream.getNextEntry()) != null) {
- String fileName = entry.getName();
- switch (fileName) {
- case "config.json":
- configJson = mapper.readTree(zipInputStream);
- break;
- case "identity.jks":
- keyStoreOutputStream = new ByteArrayOutputStream();
- ByteStreams.copy(zipInputStream, keyStoreOutputStream);
- break;
- case "trustStore.jks":
- trustStoreOutputStream = new ByteArrayOutputStream();
- ByteStreams.copy(zipInputStream, trustStoreOutputStream);
- break;
- }
- }
- }
- if (configJson == null) {
- throw new IllegalStateException("Invalid bundle: missing file config.json");
- }
- if (keyStoreOutputStream == null) {
- throw new IllegalStateException("Invalid bundle: missing file identity.jks");
- }
- if (trustStoreOutputStream == null) {
- throw new IllegalStateException("Invalid bundle: missing file trustStore.jks");
- }
- char[] keyStorePassword = getKeyStorePassword(configJson);
- char[] trustStorePassword = getTrustStorePassword(configJson);
- ByteArrayInputStream keyStoreInputStream =
- new ByteArrayInputStream(keyStoreOutputStream.toByteArray());
- ByteArrayInputStream trustStoreInputStream =
- new ByteArrayInputStream(trustStoreOutputStream.toByteArray());
- SSLContext sslContext =
- createSslContext(
- keyStoreInputStream, keyStorePassword, trustStoreInputStream, trustStorePassword);
- URL metadataServiceUrl = getMetadataServiceUrl(configJson);
- JsonNode proxyMetadataJson;
- try (BufferedReader proxyMetadata = fetchProxyMetadata(metadataServiceUrl, sslContext)) {
- proxyMetadataJson = mapper.readTree(proxyMetadata);
- }
- InetSocketAddress sniProxyAddress = getSniProxyAddress(proxyMetadataJson);
- List endPoints = getEndPoints(proxyMetadataJson, sniProxyAddress);
- String localDatacenter = getLocalDatacenter(proxyMetadataJson);
- SniSslEngineFactory sslEngineFactory = new SniSslEngineFactory(sslContext);
- validateIfBundleContainsUsernamePassword(configJson);
- return new CloudConfig(sniProxyAddress, endPoints, localDatacenter, sslEngineFactory);
- }
-
- @NonNull
- protected char[] getKeyStorePassword(JsonNode configFile) {
- if (configFile.has("keyStorePassword")) {
- return configFile.get("keyStorePassword").asText().toCharArray();
- } else {
- throw new IllegalStateException("Invalid config.json: missing field keyStorePassword");
- }
- }
-
- @NonNull
- protected char[] getTrustStorePassword(JsonNode configFile) {
- if (configFile.has("trustStorePassword")) {
- return configFile.get("trustStorePassword").asText().toCharArray();
- } else {
- throw new IllegalStateException("Invalid config.json: missing field trustStorePassword");
- }
- }
-
- @NonNull
- protected URL getMetadataServiceUrl(JsonNode configFile) throws MalformedURLException {
- if (configFile.has("host")) {
- String metadataServiceHost = configFile.get("host").asText();
- if (configFile.has("port")) {
- int metadataServicePort = configFile.get("port").asInt();
- return new URL("https", metadataServiceHost, metadataServicePort, "/metadata");
- } else {
- throw new IllegalStateException("Invalid config.json: missing field port");
- }
- } else {
- throw new IllegalStateException("Invalid config.json: missing field host");
- }
- }
-
- protected void validateIfBundleContainsUsernamePassword(JsonNode configFile) {
- if (configFile.has("username") || configFile.has("password")) {
- LOG.info(
- "The bundle contains config.json with username and/or password. Providing it in the bundle is deprecated and ignored.");
- }
- }
-
- @NonNull
- protected SSLContext createSslContext(
- @NonNull ByteArrayInputStream keyStoreInputStream,
- @NonNull char[] keyStorePassword,
- @NonNull ByteArrayInputStream trustStoreInputStream,
- @NonNull char[] trustStorePassword)
- throws IOException, GeneralSecurityException {
- KeyManagerFactory kmf = createKeyManagerFactory(keyStoreInputStream, keyStorePassword);
- TrustManagerFactory tmf = createTrustManagerFactory(trustStoreInputStream, trustStorePassword);
- SSLContext sslContext = SSLContext.getInstance("SSL");
- sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
- return sslContext;
- }
-
- @NonNull
- protected KeyManagerFactory createKeyManagerFactory(
- @NonNull InputStream keyStoreInputStream, @NonNull char[] keyStorePassword)
- throws IOException, GeneralSecurityException {
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(keyStoreInputStream, keyStorePassword);
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(ks, keyStorePassword);
- Arrays.fill(keyStorePassword, (char) 0);
- return kmf;
- }
-
- @NonNull
- protected TrustManagerFactory createTrustManagerFactory(
- @NonNull InputStream trustStoreInputStream, @NonNull char[] trustStorePassword)
- throws IOException, GeneralSecurityException {
- KeyStore ts = KeyStore.getInstance("JKS");
- ts.load(trustStoreInputStream, trustStorePassword);
- TrustManagerFactory tmf =
- TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(ts);
- Arrays.fill(trustStorePassword, (char) 0);
- return tmf;
- }
-
- @NonNull
- protected BufferedReader fetchProxyMetadata(
- @NonNull URL metadataServiceUrl, @NonNull SSLContext sslContext) throws IOException {
- try {
- HttpsURLConnection connection = (HttpsURLConnection) metadataServiceUrl.openConnection();
- connection.setSSLSocketFactory(sslContext.getSocketFactory());
- connection.setRequestMethod("GET");
- return new BufferedReader(
- new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
- } catch (ConnectException e) {
- throw new IllegalStateException(
- "Unable to connect to cloud metadata service. Please make sure your cluster is not parked or terminated",
- e);
- } catch (UnknownHostException e) {
- throw new IllegalStateException(
- "Unable to resolve host for cloud metadata service. Please make sure your cluster is not terminated",
- e);
- }
- }
-
- @NonNull
- protected String getLocalDatacenter(@NonNull JsonNode proxyMetadata) {
- JsonNode contactInfo = getContactInfo(proxyMetadata);
- if (contactInfo.has("local_dc")) {
- return contactInfo.get("local_dc").asText();
- } else {
- throw new IllegalStateException("Invalid proxy metadata: missing field local_dc");
- }
- }
-
- @NonNull
- protected InetSocketAddress getSniProxyAddress(@NonNull JsonNode proxyMetadata) {
- JsonNode contactInfo = getContactInfo(proxyMetadata);
- if (contactInfo.has("sni_proxy_address")) {
- HostAndPort sniProxyHostAndPort =
- HostAndPort.fromString(contactInfo.get("sni_proxy_address").asText());
- if (!sniProxyHostAndPort.hasPort()) {
- throw new IllegalStateException(
- "Invalid proxy metadata: missing port from field sni_proxy_address");
- }
- return InetSocketAddress.createUnresolved(
- sniProxyHostAndPort.getHost(), sniProxyHostAndPort.getPort());
- } else {
- throw new IllegalStateException("Invalid proxy metadata: missing field sni_proxy_address");
- }
- }
-
- @NonNull
- protected List getEndPoints(
- @NonNull JsonNode proxyMetadata, @NonNull InetSocketAddress sniProxyAddress) {
- JsonNode contactInfo = getContactInfo(proxyMetadata);
- if (contactInfo.has("contact_points")) {
- List endPoints = new ArrayList<>();
- JsonNode hostIdsJson = contactInfo.get("contact_points");
- for (int i = 0; i < hostIdsJson.size(); i++) {
- endPoints.add(new SniEndPoint(sniProxyAddress, hostIdsJson.get(i).asText()));
- }
- return endPoints;
- } else {
- throw new IllegalStateException("Invalid proxy metadata: missing field contact_points");
- }
- }
-
- @NonNull
- protected JsonNode getContactInfo(@NonNull JsonNode proxyMetadata) {
- if (proxyMetadata.has("contact_info")) {
- return proxyMetadata.get("contact_info");
- } else {
- throw new IllegalStateException("Invalid proxy metadata: missing field contact_info");
- }
- }
-}
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java
index f48d686573c..84426d5fe56 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java
@@ -41,7 +41,6 @@
import com.datastax.oss.driver.internal.core.specex.NoSpeculativeExecutionPolicy;
import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory;
import com.datastax.oss.driver.internal.core.ssl.JdkSslHandlerFactory;
-import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory;
import com.datastax.oss.driver.internal.core.ssl.SslHandlerFactory;
import com.datastax.oss.driver.internal.core.time.AtomicTimestampGenerator;
import com.datastax.oss.driver.internal.core.time.ServerSideTimestampGenerator;
@@ -1137,10 +1136,6 @@ private static Optional hostnameValidation(@Nullable SslEngineFactory e
} else if (engineFactory instanceof ProgrammaticSslEngineFactory) {
return Optional.of(
((ProgrammaticSslEngineFactory) engineFactory).isHostnameValidationRequired());
- } else if (engineFactory instanceof SniSslEngineFactory) {
- // No accessor to read: SniSslEngineFactory sets the "HTTPS" endpoint identification algorithm
- // on every engine it builds, unconditionally.
- return Optional.of(true);
}
return Optional.empty();
}
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java
index e6323b6b84c..58c61fb13d0 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java
@@ -62,7 +62,6 @@
import com.datastax.oss.driver.internal.core.config.typesafe.TypesafeDriverConfig;
import com.datastax.oss.driver.internal.core.control.ControlConnection;
import com.datastax.oss.driver.internal.core.metadata.ClientRoutesTopologyMonitor;
-import com.datastax.oss.driver.internal.core.metadata.CloudTopologyMonitor;
import com.datastax.oss.driver.internal.core.metadata.DefaultTopologyMonitor;
import com.datastax.oss.driver.internal.core.metadata.LoadBalancingPolicyWrapper;
import com.datastax.oss.driver.internal.core.metadata.MetadataManager;
@@ -114,7 +113,6 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import io.netty.buffer.ByteBuf;
-import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -254,7 +252,6 @@ public class DefaultDriverContext implements InternalDriverContext {
private final Map> nodeFiltersFromBuilder;
private final Map nodeDistanceEvaluatorsFromBuilder;
private final ClassLoader classLoader;
- private final InetSocketAddress cloudProxyAddress;
private final ClientRoutesConfig clientRoutesConfigFromBuilder;
private final LazyReference requestLogFormatterRef =
new LazyReference<>("requestLogFormatter", this::buildRequestLogFormatter, cycleDetector);
@@ -315,7 +312,6 @@ public DefaultDriverContext(
this.nodeFiltersFromBuilder = nodeFilters;
this.nodeDistanceEvaluatorsFromBuilder = programmaticArguments.getNodeDistanceEvaluators();
this.classLoader = programmaticArguments.getClassLoader();
- this.cloudProxyAddress = programmaticArguments.getCloudProxyAddress();
this.clientRoutesConfigFromBuilder = programmaticArguments.getClientRoutesConfig();
this.startupClientId = programmaticArguments.getStartupClientId();
this.startupApplicationName = programmaticArguments.getStartupApplicationName();
@@ -677,9 +673,6 @@ protected TopologyMonitor buildTopologyMonitor() {
ClientRoutesConfig clientRoutesConfig = resolveClientRoutesConfig();
validateClientRoutesConfiguration(clientRoutesConfig);
- if (cloudProxyAddress != null) {
- return new CloudTopologyMonitor(this, cloudProxyAddress);
- }
if (clientRoutesConfig != null) {
return new ClientRoutesTopologyMonitor(this, clientRoutesConfig);
}
@@ -690,12 +683,6 @@ private void validateClientRoutesConfiguration(ClientRoutesConfig clientRoutesCo
if (clientRoutesConfig == null) {
return;
}
- if (cloudProxyAddress != null) {
- throw new IllegalStateException(
- "Both a secure connect bundle and client routes configuration were provided. "
- + "They are mutually exclusive. Please use either a secure connect bundle OR "
- + "client routes configuration, but not both.");
- }
DriverExecutionProfile defaultProfile = getConfig().getDefaultProfile();
if (defaultProfile.isDefined(DefaultDriverOption.ADDRESS_TRANSLATOR_CLASS)) {
String className = defaultProfile.getString(DefaultDriverOption.ADDRESS_TRANSLATOR_CLASS);
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java
deleted file mode 100644
index 021824a9b16..00000000000
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.metadata;
-
-import com.datastax.oss.driver.api.core.metadata.EndPoint;
-import com.datastax.oss.driver.internal.core.adminrequest.AdminRow;
-import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-import java.net.InetSocketAddress;
-import java.util.Objects;
-import java.util.UUID;
-
-public class CloudTopologyMonitor extends DefaultTopologyMonitor {
-
- private final InetSocketAddress cloudProxyAddress;
-
- public CloudTopologyMonitor(InternalDriverContext context, InetSocketAddress cloudProxyAddress) {
- super(context);
- this.cloudProxyAddress = cloudProxyAddress;
- }
-
- @NonNull
- @Override
- protected EndPoint buildNodeEndPoint(
- @NonNull AdminRow row,
- @Nullable InetSocketAddress broadcastRpcAddress,
- @NonNull EndPoint localEndPoint) {
- UUID hostId = Objects.requireNonNull(row.getUuid("host_id"));
- return new SniEndPoint(cloudProxyAddress, hostId.toString());
- }
-}
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java
deleted file mode 100644
index d1ab8eec98d..00000000000
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.metadata;
-
-import com.datastax.oss.driver.api.core.metadata.EndPoint;
-import com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class SniEndPoint implements EndPoint {
- private static final AtomicInteger OFFSET = new AtomicInteger();
-
- private final InetSocketAddress proxyAddress;
- private final String serverName;
-
- /**
- * @param proxyAddress the address of the proxy. If it is {@linkplain
- * InetSocketAddress#isUnresolved() unresolved}, each call to {@link #resolve()} will
- * re-resolve it, fetch all of its A-records, and if there are more than 1 pick one in a
- * round-robin fashion.
- * @param serverName the SNI server name. In the context of Cloud, this is the string
- * representation of the host id.
- */
- public SniEndPoint(InetSocketAddress proxyAddress, String serverName) {
- this.proxyAddress = Objects.requireNonNull(proxyAddress, "SNI address cannot be null");
- this.serverName = Objects.requireNonNull(serverName, "SNI Server name cannot be null");
- }
-
- public String getServerName() {
- return serverName;
- }
-
- @NonNull
- @Override
- public InetSocketAddress resolve() {
- try {
- InetAddress[] aRecords = InetAddress.getAllByName(proxyAddress.getHostName());
- if (aRecords.length == 0) {
- // Probably never happens, but the JDK docs don't explicitly say so
- throw new IllegalArgumentException(
- "Could not resolve proxy address " + proxyAddress.getHostName());
- }
- // The order of the returned address is unspecified. Sort by IP to make sure we get a true
- // round-robin
- Arrays.sort(aRecords, IP_COMPARATOR);
- int index =
- (aRecords.length == 1)
- ? 0
- : OFFSET.getAndUpdate(x -> x == Integer.MAX_VALUE ? 0 : x + 1) % aRecords.length;
- return new InetSocketAddress(aRecords[index], proxyAddress.getPort());
- } catch (UnknownHostException e) {
- throw new IllegalArgumentException(
- "Could not resolve proxy address " + proxyAddress.getHostName(), e);
- }
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- } else if (other instanceof SniEndPoint) {
- SniEndPoint that = (SniEndPoint) other;
- return this.proxyAddress.equals(that.proxyAddress) && this.serverName.equals(that.serverName);
- } else {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(proxyAddress, serverName);
- }
-
- @Override
- public String toString() {
- // Note that this uses the original proxy address, so if there are multiple A-records it won't
- // show which one was selected. If that turns out to be a problem for debugging, we might need
- // to store the result of resolve() in Connection and log that instead of the endpoint.
- return proxyAddress.toString() + ":" + serverName;
- }
-
- @NonNull
- @Override
- public String asMetricPrefix() {
- String hostString = proxyAddress.getHostString();
- if (hostString == null) {
- throw new IllegalArgumentException(
- "Could not extract a host string from provided proxy address " + proxyAddress);
- }
- return hostString.replace('.', '_') + ':' + proxyAddress.getPort() + '_' + serverName;
- }
-
- @SuppressWarnings("UnnecessaryLambda")
- private static final Comparator IP_COMPARATOR =
- (InetAddress address1, InetAddress address2) ->
- UnsignedBytes.lexicographicalComparator()
- .compare(address1.getAddress(), address2.getAddress());
-}
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java
deleted file mode 100644
index 4d2cb69fbfc..00000000000
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.ssl;
-
-import com.datastax.oss.driver.api.core.metadata.EndPoint;
-import com.datastax.oss.driver.api.core.ssl.SslEngineFactory;
-import com.datastax.oss.driver.internal.core.metadata.SniEndPoint;
-import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import java.net.InetSocketAddress;
-import java.util.concurrent.CopyOnWriteArrayList;
-import javax.net.ssl.SNIHostName;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-
-public class SniSslEngineFactory implements SslEngineFactory {
-
- // An offset that gets added to our "fake" ports (see below). We pick this value because it is the
- // start of the ephemeral port range.
- private static final int FAKE_PORT_OFFSET = 49152;
-
- private final SSLContext sslContext;
- private final CopyOnWriteArrayList fakePorts = new CopyOnWriteArrayList<>();
- private final boolean allowDnsReverseLookupSan;
-
- public SniSslEngineFactory(SSLContext sslContext) {
- this(sslContext, true);
- }
-
- public SniSslEngineFactory(SSLContext sslContext, boolean allowDnsReverseLookupSan) {
- this.sslContext = sslContext;
- this.allowDnsReverseLookupSan = allowDnsReverseLookupSan;
- }
-
- @NonNull
- @Override
- public SSLEngine newSslEngine(@NonNull EndPoint remoteEndpoint) {
- if (!(remoteEndpoint instanceof SniEndPoint)) {
- throw new IllegalArgumentException(
- String.format(
- "Configuration error: can only use %s with SNI end points",
- this.getClass().getSimpleName()));
- }
- SniEndPoint sniEndPoint = (SniEndPoint) remoteEndpoint;
- InetSocketAddress address = sniEndPoint.resolve();
- String sniServerName = sniEndPoint.getServerName();
-
- // When hostname verification is enabled (with setEndpointIdentificationAlgorithm), the SSL
- // engine will try to match the server's certificate against the SNI host name; if that doesn't
- // work, it will fall back to the "advisory peer host" passed to createSSLEngine.
- //
- // In our case, the first check will never succeed because our SNI host name is not the DNS name
- // (we use the Cassandra host_id instead). So we *must* set the advisory peer information.
- //
- // However if we use the address as-is, this leads to another issue: the advisory peer
- // information is also used to cache SSL sessions internally. All of our nodes share the same
- // proxy address, so the JDK tries to reuse SSL sessions across nodes. But it doesn't update the
- // SNI host name every time, so it ends up opening connections to the wrong node.
- //
- // To avoid that, we create a unique "fake" port for every node. We still get session reuse for
- // a given node, but not across nodes. This is safe because the advisory port is only used for
- // session caching.
- String peerHost = allowDnsReverseLookupSan ? address.getHostName() : address.getHostString();
- SSLEngine engine = sslContext.createSSLEngine(peerHost, getFakePort(sniServerName));
- engine.setUseClientMode(true);
- SSLParameters parameters = engine.getSSLParameters();
- parameters.setServerNames(ImmutableList.of(new SNIHostName(sniServerName)));
- parameters.setEndpointIdentificationAlgorithm("HTTPS");
- engine.setSSLParameters(parameters);
- return engine;
- }
-
- private int getFakePort(String sniServerName) {
- fakePorts.addIfAbsent(sniServerName);
- return FAKE_PORT_OFFSET + fakePorts.indexOf(sniServerName);
- }
-
- @Override
- public void close() {
- // nothing to do
- }
-}
diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf
index 590784b70c5..3850c495bcc 100644
--- a/core/src/main/resources/reference.conf
+++ b/core/src/main/resources/reference.conf
@@ -257,20 +257,6 @@ datastax-java-driver {
# If this option is not defined, the driver defaults to true.
slow-replica-avoidance = true
}
- basic.cloud {
- # The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a
- # service.
- # This setting must be a valid URL.
- # If the protocol is not specified, it is implicitly assumed to be the `file://` protocol,
- # in which case the value is expected to be a valid path on the local filesystem.
- # For example, `/a/path/to/bundle` will be interpreted as `file:/a/path/to/bunde`.
- # If the protocol is provided explicitly, then the value will be used as is.
- #
- # Required: no
- # Modifiable at runtime: no
- # Overridable in a profile: no
- // secure-connect-bundle = /location/of/secure/connect/bundle
- }
# DataStax Insights monitoring.
basic.application {
diff --git a/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java b/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java
index 3e0872cb946..99986e3394d 100644
--- a/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java
@@ -37,8 +37,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Hex;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -242,12 +240,12 @@ public int size() {
}
@Test
- public void should_not_use_preallocate_serialized_size() throws DecoderException {
+ public void should_not_use_preallocate_serialized_size() {
// serialized CqlVector(1.0f, 2.5f, 3.0f) with size field adjusted to Integer.MAX_VALUE
byte[] suspiciousBytes =
- Hex.decodeHex(
- "aced000573720042636f6d2e64617461737461782e6f73732e6472697665722e6170692e636f72652e646174612e43716c566563746f722453657269616c697a6174696f6e50726f78790000000000000001030000787077047fffffff7372000f6a6176612e6c616e672e466c6f6174daedc9a2db3cf0ec02000146000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000078703f8000007371007e0002402000007371007e00024040000078"
- .toCharArray());
+ ByteUtils.getArray(
+ ByteUtils.fromHexString(
+ "0xaced000573720042636f6d2e64617461737461782e6f73732e6472697665722e6170692e636f72652e646174612e43716c566563746f722453657269616c697a6174696f6e50726f78790000000000000001030000787077047fffffff7372000f6a6176612e6c616e672e466c6f6174daedc9a2db3cf0ec02000146000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000078703f8000007371007e0002402000007371007e00024040000078"));
try {
new ObjectInputStream(new ByteArrayInputStream(suspiciousBytes)).readObject();
fail("Should not be able to deserialize bytes with incorrect size field");
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java
index 4734a8ffdeb..166e79cdccb 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java
@@ -86,6 +86,8 @@ public void should_check_cluster_name_for_next_connections() throws Throwable {
null,
DriverChannelOptions.DEFAULT,
NoopNodeMetricUpdater.INSTANCE);
+ writeInboundFrame(
+ readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value"));
writeInboundFrame(readOutboundFrame(), new Ready());
writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName"));
@@ -101,6 +103,8 @@ public void should_check_cluster_name_for_next_connections() throws Throwable {
null,
DriverChannelOptions.DEFAULT,
NoopNodeMetricUpdater.INSTANCE);
+ writeInboundFrame(
+ readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value"));
writeInboundFrame(readOutboundFrame(), new Ready());
writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("wrongClusterName"));
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java
index 87407921619..20f63291d37 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java
@@ -32,7 +32,7 @@
public class ChannelFactorySupportedOptionsTest extends ChannelFactoryTestBase {
@Test
- public void should_query_supported_options_on_first_channel() throws Throwable {
+ public void should_query_supported_options_on_every_channel() throws Throwable {
// Given
when(defaultProfile.isDefined(DefaultDriverOption.PROTOCOL_VERSION)).thenReturn(false);
when(protocolVersionRegistry.highestNonBeta()).thenReturn(DefaultProtocolVersion.V4);
@@ -65,12 +65,15 @@ public void should_query_supported_options_on_first_channel() throws Throwable {
null,
DriverChannelOptions.DEFAULT,
NoopNodeMetricUpdater.INSTANCE);
+ writeInboundFrame(
+ readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value"));
writeInboundFrame(readOutboundFrame(), new Ready());
writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName"));
// Then
assertThatStage(channelFuture2).isSuccess();
DriverChannel channel2 = channelFuture2.toCompletableFuture().get();
- assertThat(channel2.getOptions()).isNull();
+ assertThat(channel2.getOptions()).containsKey("mock_key");
+ assertThat(channel2.getOptions().get("mock_key")).containsOnly("mock_value");
}
}
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java
index ed6668a6c83..534c59236ec 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java
@@ -272,7 +272,7 @@ protected void initChannel(Channel channel) throws Exception {
endPoint,
options,
heartbeatHandler,
- productType == null);
+ true);
channel
.pipeline()
.addLast(ChannelFactory.INFLIGHT_HANDLER_NAME, inFlightHandler)
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java
deleted file mode 100644
index a0db82d298e..00000000000
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.internal.core.config.cloud;
-
-import static com.datastax.oss.driver.Assertions.assertThat;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.any;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.assertj.core.api.Assertions.catchThrowable;
-
-import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.github.tomakehurst.wiremock.common.JettySettings;
-import com.github.tomakehurst.wiremock.core.Options;
-import com.github.tomakehurst.wiremock.http.AdminRequestHandler;
-import com.github.tomakehurst.wiremock.http.HttpServer;
-import com.github.tomakehurst.wiremock.http.HttpServerFactory;
-import com.github.tomakehurst.wiremock.http.StubRequestHandler;
-import com.github.tomakehurst.wiremock.jetty9.JettyHttpServer;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-import com.google.common.base.Joiner;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import org.eclipse.jetty.io.NetworkTrafficListener;
-import org.eclipse.jetty.server.ConnectionFactory;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
-public class CloudConfigFactoryTest {
-
- private static final String BUNDLE_PATH = "/config/cloud/creds.zip";
-
- @Rule
- public WireMockRule wireMockRule =
- new WireMockRule(
- wireMockConfig()
- .httpsPort(30443)
- .dynamicPort()
- .httpServerFactory(new HttpsServerFactory())
- .needClientAuth(true)
- .keystorePath(path("/config/cloud/identity.jks").toString())
- .keystorePassword("fakePasswordForTests")
- .trustStorePath(path("/config/cloud/trustStore.jks").toString())
- .trustStorePassword("fakePasswordForTests2"));
-
- public CloudConfigFactoryTest() throws URISyntaxException {}
-
- @Test
- public void should_load_config_from_local_filesystem() throws Exception {
- // given
- URL configFile = getClass().getResource(BUNDLE_PATH);
- mockProxyMetadataService(jsonMetadata());
- // when
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- CloudConfig cloudConfig = cloudConfigFactory.createCloudConfig(configFile);
- // then
- assertCloudConfig(cloudConfig);
- }
-
- @Test
- public void should_load_config_from_external_location() throws Exception {
- // given
- mockHttpSecureBundle(secureBundle());
- mockProxyMetadataService(jsonMetadata());
- // when
- URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH);
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- CloudConfig cloudConfig = cloudConfigFactory.createCloudConfig(configFile);
- // then
- assertCloudConfig(cloudConfig);
- }
-
- @Test
- public void should_throw_when_bundle_not_found() throws Exception {
- // given
- stubFor(any(urlEqualTo(BUNDLE_PATH)).willReturn(aResponse().withStatus(404)));
- // when
- URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH);
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile));
- assertThat(t)
- .isInstanceOf(FileNotFoundException.class)
- .hasMessageContaining(configFile.toExternalForm());
- }
-
- @Test
- public void should_throw_when_bundle_not_readable() throws Exception {
- // given
- mockHttpSecureBundle("not a zip file".getBytes(StandardCharsets.UTF_8));
- // when
- URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH);
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile));
- assertThat(t)
- .isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("Invalid bundle: missing file config.json");
- }
-
- @Test
- public void should_throw_when_metadata_not_found() throws Exception {
- // given
- mockHttpSecureBundle(secureBundle());
- stubFor(any(urlPathEqualTo("/metadata")).willReturn(aResponse().withStatus(404)));
- // when
- URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH);
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile));
- assertThat(t).isInstanceOf(FileNotFoundException.class).hasMessageContaining("metadata");
- }
-
- @Test
- public void should_throw_when_metadata_not_readable() throws Exception {
- // given
- mockHttpSecureBundle(secureBundle());
- mockProxyMetadataService("not a valid json payload");
- // when
- URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH);
- CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
- Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile));
- assertThat(t).isInstanceOf(JsonParseException.class).hasMessageContaining("Unrecognized token");
- }
-
- private void mockHttpSecureBundle(byte[] body) {
- stubFor(
- any(urlEqualTo(BUNDLE_PATH))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/octet-stream")
- .withBody(body)));
- }
-
- private void mockProxyMetadataService(String jsonMetadata) {
- stubFor(
- any(urlPathEqualTo("/metadata"))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/json")
- .withBody(jsonMetadata)));
- }
-
- private byte[] secureBundle() throws IOException, URISyntaxException {
- return Files.readAllBytes(path(BUNDLE_PATH));
- }
-
- private String jsonMetadata() throws IOException, URISyntaxException {
- return Joiner.on('\n')
- .join(Files.readAllLines(path("/config/cloud/metadata.json"), StandardCharsets.UTF_8));
- }
-
- private Path path(String resource) throws URISyntaxException {
- return Paths.get(getClass().getResource(resource).toURI());
- }
-
- private void assertCloudConfig(CloudConfig config) {
- InetSocketAddress expectedProxyAddress = InetSocketAddress.createUnresolved("localhost", 30002);
- assertThat(config.getLocalDatacenter()).isEqualTo("dc1");
- assertThat(config.getProxyAddress()).isEqualTo(expectedProxyAddress);
- assertThat(config.getEndPoints()).extracting("proxyAddress").containsOnly(expectedProxyAddress);
- assertThat(config.getEndPoints())
- .extracting("serverName")
- .containsExactly(
- "4ac06655-f861-49f9-881e-3fee22e69b94",
- "2af7c253-3394-4a0d-bfac-f1ad81b5154d",
- "b17b6e2a-3f48-4d6a-81c1-20a0a1f3192a");
- assertThat(config.getSslEngineFactory()).isNotNull().isInstanceOf(SniSslEngineFactory.class);
- }
-
- static {
- javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
- (hostname, sslSession) -> hostname.equals("localhost"));
- }
-
- // see https://github.com/tomakehurst/wiremock/issues/874
- private static class HttpsServerFactory implements HttpServerFactory {
- @Override
- public HttpServer buildHttpServer(
- Options options,
- AdminRequestHandler adminRequestHandler,
- StubRequestHandler stubRequestHandler) {
- return new JettyHttpServer(options, adminRequestHandler, stubRequestHandler) {
- @Override
- protected ServerConnector createServerConnector(
- String bindAddress,
- JettySettings jettySettings,
- int port,
- NetworkTrafficListener listener,
- ConnectionFactory... connectionFactories) {
- if (port == options.httpsSettings().port()) {
- SslConnectionFactory sslConnectionFactory =
- (SslConnectionFactory) connectionFactories[0];
- SslContextFactory sslContextFactory = sslConnectionFactory.getSslContextFactory();
- sslContextFactory.setKeyStorePassword(options.httpsSettings().keyStorePassword());
- connectionFactories =
- new ConnectionFactory[] {sslConnectionFactory, connectionFactories[1]};
- }
- return super.createServerConnector(
- bindAddress, jettySettings, port, listener, connectionFactories);
- }
- };
- }
- }
-}
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java
index 083302494aa..0c1c570ebee 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java
@@ -27,7 +27,6 @@
import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader;
import com.datastax.oss.driver.internal.core.metadata.ClientRoutesTopologyMonitor;
import com.typesafe.config.ConfigFactory;
-import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
@@ -238,25 +237,6 @@ public void should_allow_client_routes_with_qualified_passthrough_address_transl
assertThat(ctx.getTopologyMonitor()).isInstanceOf(ClientRoutesTopologyMonitor.class);
}
- @Test
- public void should_throw_when_secure_connect_bundle_and_client_routes_both_configured() {
- ProgrammaticArguments args =
- ProgrammaticArguments.builder()
- .withCloudProxyAddress(new InetSocketAddress("127.0.0.1", 9042))
- .build();
- DefaultDriverContext ctx =
- contextFromHocon(
- "advanced.client-routes.endpoints = ["
- + " { connection-id = \"11111111-1111-1111-1111-111111111111\" }"
- + "]",
- args);
-
- assertThatThrownBy(ctx::getTopologyMonitor)
- .isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("secure connect bundle")
- .hasMessageContaining("client routes");
- }
-
@Test
public void should_throw_when_client_routes_and_unloadable_address_translator_class() {
DefaultDriverContext ctx =
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java
index 4122f82a399..5616734e178 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java
@@ -51,7 +51,6 @@
import com.datastax.oss.driver.internal.core.specex.NoSpeculativeExecutionPolicy;
import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory;
import com.datastax.oss.driver.internal.core.ssl.JdkSslHandlerFactory;
-import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory;
import com.datastax.oss.driver.internal.core.ssl.SslHandlerFactory;
import com.datastax.oss.driver.internal.core.time.AtomicTimestampGenerator;
import com.datastax.oss.driver.internal.core.time.ServerSideTimestampGenerator;
@@ -1534,7 +1533,6 @@ public void should_report_every_built_in_engine_factory() throws Exception {
// configured one, to the whole option-to-field-to-report chain.
assertThat(hostnameVerificationOf(new DefaultSslEngineFactory(policyConstructionContext())))
.isTrue();
- assertThat(hostnameVerificationOf(new SniSslEngineFactory(SSLContext.getDefault()))).isTrue();
assertThat(hostnameVerificationOf(new ProgrammaticSslEngineFactory(SSLContext.getDefault())))
.isFalse();
assertThat(
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java
index 892715a47c3..744438c7f71 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java
@@ -52,10 +52,10 @@
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet;
import com.datastax.oss.driver.shaded.guava.common.collect.Maps;
+import com.datastax.oss.driver.shaded.guava.common.collect.Streams;
import com.datastax.oss.protocol.internal.Message;
import com.datastax.oss.protocol.internal.ProtocolConstants;
import com.datastax.oss.protocol.internal.response.Error;
-import com.google.common.collect.Streams;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java
index 03d63230992..252ebab38eb 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java
@@ -23,9 +23,9 @@
import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata;
import com.datastax.oss.driver.internal.core.type.DefaultVectorType;
import com.datastax.oss.driver.internal.core.type.PrimitiveType;
+import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import com.datastax.oss.protocol.internal.ProtocolConstants.DataType;
-import com.google.common.collect.ImmutableList;
import java.util.UUID;
import org.junit.Test;
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java
index 339f9235dc2..8d7998c21f5 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java
@@ -19,7 +19,7 @@
import static org.assertj.core.api.Assertions.assertThat;
-import com.google.common.collect.ImmutableMap;
+import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import org.junit.Test;
public class DefaultMetricIdTest {
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java
index 809a7419ba4..cbc560ee35b 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java
@@ -28,7 +28,7 @@
import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric;
import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
-import com.google.common.collect.ImmutableMap;
+import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java
index d151da309c1..c493ccc2080 100644
--- a/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java
+++ b/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java
@@ -21,10 +21,10 @@
import static org.assertj.core.api.Assertions.fail;
import com.datastax.oss.driver.api.core.connection.CrcMismatchException;
+import com.datastax.oss.driver.shaded.guava.common.base.Strings;
import com.datastax.oss.protocol.internal.Compressor;
import com.datastax.oss.protocol.internal.Segment;
import com.datastax.oss.protocol.internal.SegmentCodec;
-import com.google.common.base.Strings;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
diff --git a/core/src/test/resources/config/cloud/creds.zip b/core/src/test/resources/config/cloud/creds.zip
deleted file mode 100644
index 3b5d1cb1cbd..00000000000
Binary files a/core/src/test/resources/config/cloud/creds.zip and /dev/null differ
diff --git a/core/src/test/resources/config/cloud/identity.jks b/core/src/test/resources/config/cloud/identity.jks
deleted file mode 100644
index bac5bbaa965..00000000000
Binary files a/core/src/test/resources/config/cloud/identity.jks and /dev/null differ
diff --git a/core/src/test/resources/config/cloud/metadata.json b/core/src/test/resources/config/cloud/metadata.json
deleted file mode 100644
index 35aa26f67f1..00000000000
--- a/core/src/test/resources/config/cloud/metadata.json
+++ /dev/null
@@ -1 +0,0 @@
-{"region":"local","contact_info":{"type":"sni_proxy","local_dc":"dc1","contact_points":["4ac06655-f861-49f9-881e-3fee22e69b94","2af7c253-3394-4a0d-bfac-f1ad81b5154d","b17b6e2a-3f48-4d6a-81c1-20a0a1f3192a"],"sni_proxy_address":"localhost:30002"}}
diff --git a/core/src/test/resources/config/cloud/trustStore.jks b/core/src/test/resources/config/cloud/trustStore.jks
deleted file mode 100644
index 8ee03f97da0..00000000000
Binary files a/core/src/test/resources/config/cloud/trustStore.jks and /dev/null differ
diff --git a/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java b/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java
deleted file mode 100644
index 7f4833c46d8..00000000000
--- a/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.examples.astra;
-
-import com.datastax.oss.driver.api.core.CqlSession;
-import com.datastax.oss.driver.api.core.cql.ResultSet;
-import com.datastax.oss.driver.api.core.cql.Row;
-import java.nio.file.Paths;
-
-/**
- * Connects to a DataStax Astra cluster and extracts basic information from it.
- *
- * Preconditions:
- *
- *
- * - A DataStax Astra cluster is running and accessible.
- *
- A DataStax Astra secure connect bundle for the running cluster.
- *
- *
- * Side effects: none.
- *
- * @see
- * Creating an Astra Database (GCP)
- * @see
- * Providing access to Astra databases (GCP)
- * @see
- * Obtaining Astra secure connect bundle (GCP)
- * @see Java Driver online
- * manual
- */
-public class AstraReadCassandraVersion {
-
- public static void main(String[] args) {
-
- // The Session is what you use to execute queries. It is thread-safe and should be
- // reused.
- try (CqlSession session =
- CqlSession.builder()
- // Change the path here to the secure connect bundle location (see javadocs above)
- .withCloudSecureConnectBundle(Paths.get("/path/to/secure-connect-database_name.zip"))
- // Change the user_name and password here for the Astra instance
- .withAuthCredentials("user_name", "fakePasswordForTests")
- // Uncomment the next line to use a specific keyspace
- // .withKeyspace("keyspace_name")
- .build()) {
-
- // We use execute to send a query to Cassandra. This returns a ResultSet, which
- // is essentially a collection of Row objects.
- ResultSet rs = session.execute("select release_version from system.local WHERE key='local'");
- // Extract the first row (which is the only one in this case).
- Row row = rs.one();
-
- // Extract the value of the first (and only) column from the row.
- assert row != null;
- String releaseVersion = row.getString("release_version");
- System.out.printf("Cassandra version is: %s%n", releaseVersion);
- }
- // The try-with-resources block automatically close the session after we’re done with it.
- // This step is important because it frees underlying resources (TCP connections, thread
- // pools...). In a real application, you would typically do this at shutdown
- // (for example, when undeploying your webapp).
- }
-}
diff --git a/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java b/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java
index 6284b16eac1..0f78821ee07 100644
--- a/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java
+++ b/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java
@@ -112,9 +112,8 @@ public static void main(String[] args) {
Video video = new Video();
video.setUserid(user.getUserid());
- video.setName(
- "Getting Started with DataStax Apache Cassandra as a Service on DataStax Astra");
- video.setLocation("https://www.youtube.com/watch?v=68xzKpcZURA");
+ video.setName("Getting Started with ScyllaDB Cloud");
+ video.setLocation("https://www.youtube.com/watch?v=jnWDMiuy9hM");
Set tags = new HashSet<>();
tags.add("apachecassandra");
tags.add("nosql");
@@ -146,8 +145,7 @@ public static void main(String[] args) {
// Update the existing video:
Video template = new Video();
template.setVideoid(video.getVideoid());
- template.setName(
- "Getting Started with DataStax Apache Cassandra® as a Service on DataStax Astra");
+ template.setName("Getting Started with ScyllaDB using the Java driver");
videoDao.update(template);
// Reload the whole entity and check the fields
video = videoDao.get(video.getVideoid());
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 7f481242fce..6ce4fc728e9 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -178,11 +178,6 @@
api-ldap-codec-standalone
test
-
- com.github.tomakehurst
- wiremock
- test
-
com.scylladb.oss.simulacron
simulacron-native-server
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java
deleted file mode 100644
index 81a191779ba..00000000000
--- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.api.core.cloud;
-
-import static com.datastax.oss.driver.internal.core.util.LoggerTest.setupTestLogger;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.any;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import com.datastax.oss.driver.api.core.AllNodesFailedException;
-import com.datastax.oss.driver.api.core.CqlSession;
-import com.datastax.oss.driver.api.core.auth.AuthenticationException;
-import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
-import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
-import com.datastax.oss.driver.api.core.cql.ResultSet;
-import com.datastax.oss.driver.api.core.session.SessionBuilder;
-import com.datastax.oss.driver.api.testinfra.session.SessionUtils;
-import com.datastax.oss.driver.categories.IsolatedTests;
-import com.datastax.oss.driver.internal.core.config.cloud.CloudConfigFactory;
-import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory;
-import com.datastax.oss.driver.internal.core.util.LoggerTest;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.NoSuchAlgorithmException;
-import java.util.Collections;
-import java.util.List;
-import javax.net.ssl.SSLContext;
-import org.junit.ClassRule;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-@Category(IsolatedTests.class)
-@Ignore("Disabled because it is causing trouble in Jenkins CI")
-public class CloudIT {
-
- private static final String BUNDLE_URL_PATH = "/certs/bundles/creds.zip";
-
- @ClassRule public static SniProxyRule proxyRule = new SniProxyRule();
-
- // Used only to host the secure connect bundle, for tests that require external URLs
- @Rule
- public WireMockRule wireMockRule =
- new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());
-
- @Test
- public void should_connect_to_proxy_using_path() {
- ResultSet set;
- Path bundle = proxyRule.getProxy().getDefaultBundlePath();
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withCloudSecureConnectBundle(bundle)
- .build()) {
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_and_log_info_that_config_json_with_username_password_was_provided() {
- ResultSet set;
- Path bundle = proxyRule.getProxy().getDefaultBundlePath();
- LoggerTest.LoggerSetup logger = setupTestLogger(CloudConfigFactory.class, Level.INFO);
-
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withCloudSecureConnectBundle(bundle)
- .build()) {
- set = session.execute("select * from system.local where key='local'");
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "The bundle contains config.json with username and/or password. Providing it in the bundle is deprecated and ignored.");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void
- should_fail_with_auth_error_when_connecting_using_bundle_with_username_password_in_config_json() {
- Path bundle = proxyRule.getProxy().getDefaultBundlePath();
-
- // fails with auth error because username/password from config.json is ignored
- AllNodesFailedException exception = null;
- try {
- CqlSession.builder().withCloudSecureConnectBundle(bundle).build();
- } catch (AllNodesFailedException ex) {
- exception = ex;
- }
- assertThat(exception).isNotNull();
- List errors = exception.getAllErrors().values().iterator().next();
- Throwable firstError = errors.get(0);
- assertThat(firstError).isInstanceOf(AuthenticationException.class);
- }
-
- @Test
- public void should_connect_to_proxy_without_credentials() {
- ResultSet set;
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
- try (CqlSession session =
- CqlSession.builder()
- .withCloudSecureConnectBundle(bundle)
- .withAuthCredentials("cassandra", "cassandra")
- .build()) {
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_non_normalized_path() {
- Path bundle = proxyRule.getProxy().getBundlesRootPath().resolve("../bundles/creds-v1.zip");
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withCloudSecureConnectBundle(bundle)
- .build()) {
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_input_stream() throws IOException {
- InputStream bundle = Files.newInputStream(proxyRule.getProxy().getDefaultBundlePath());
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withCloudSecureConnectBundle(bundle)
- .build()) {
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_URL() throws IOException {
- // given
- byte[] bundle = Files.readAllBytes(proxyRule.getProxy().getDefaultBundlePath());
- stubFor(
- any(urlEqualTo(BUNDLE_URL_PATH))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/octet-stream")
- .withBody(bundle)));
- URL bundleUrl =
- new URL(String.format("http://localhost:%d%s", wireMockRule.port(), BUNDLE_URL_PATH));
-
- // when
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withCloudSecureConnectBundle(bundleUrl)
- .build()) {
-
- // then
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_absolute_path_provided_in_the_session_setting() {
- // given
- String bundle = proxyRule.getProxy().getDefaultBundlePath().toString();
- DriverConfigLoader loader =
- DriverConfigLoader.programmaticBuilder()
- .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle)
- .build();
- // when
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withConfigLoader(loader)
- .build()) {
-
- // then
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_non_normalized_path_provided_in_the_session_setting() {
- // given
- String bundle =
- proxyRule.getProxy().getBundlesRootPath().resolve("../bundles/creds-v1.zip").toString();
- DriverConfigLoader loader =
- DriverConfigLoader.programmaticBuilder()
- .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle)
- .build();
- // when
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withConfigLoader(loader)
- .build()) {
-
- // then
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void
- should_connect_to_proxy_using_url_with_file_protocol_provided_in_the_session_setting() {
- // given
- String bundle = proxyRule.getProxy().getDefaultBundlePath().toString();
- DriverConfigLoader loader =
- DriverConfigLoader.programmaticBuilder()
- .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle)
- .build();
- // when
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withConfigLoader(loader)
- .build()) {
-
- // then
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void should_connect_to_proxy_using_url_with_http_protocol_provided_in_the_session_setting()
- throws IOException {
- // given
- byte[] bundle = Files.readAllBytes(proxyRule.getProxy().getDefaultBundlePath());
- stubFor(
- any(urlEqualTo(BUNDLE_URL_PATH))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/octet-stream")
- .withBody(bundle)));
- String bundleUrl = String.format("http://localhost:%d%s", wireMockRule.port(), BUNDLE_URL_PATH);
- DriverConfigLoader loader =
- DriverConfigLoader.programmaticBuilder()
- .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundleUrl)
- .build();
- // when
- ResultSet set;
- try (CqlSession session =
- CqlSession.builder()
- .withAuthCredentials("cassandra", "cassandra")
- .withConfigLoader(loader)
- .build()) {
-
- // then
- set = session.execute("select * from system.local where key='local'");
- }
- assertThat(set).isNotNull();
- }
-
- @Test
- public void
- should_connect_and_log_info_when_contact_points_and_secure_bundle_used_programmatic() {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withCloudSecureConnectBundle(bundle)
- .addContactPoint(new InetSocketAddress("127.0.0.1", 9042))
- .withAuthCredentials("cassandra", "cassandra")
- .build(); ) {
-
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority.");
-
- } finally {
- logger.close();
- }
- }
-
- @Test
- public void should_connect_and_log_info_when_contact_points_and_secure_bundle_used_config() {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- DriverConfigLoader loader =
- SessionUtils.configLoaderBuilder()
- .withStringList(
- DefaultDriverOption.CONTACT_POINTS, Collections.singletonList("localhost:9042"))
- .build();
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withConfigLoader(loader)
- .withCloudSecureConnectBundle(bundle)
- .withAuthCredentials("cassandra", "cassandra")
- .build(); ) {
-
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority.");
-
- } finally {
- logger.close();
- }
- }
-
- @Test
- public void should_connect_and_log_info_when_ssl_context_and_secure_bundle_used_programmatic()
- throws NoSuchAlgorithmException {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withCloudSecureConnectBundle(bundle)
- .withAuthCredentials("cassandra", "cassandra")
- .withSslContext(SSLContext.getInstance("SSL"))
- .build()) {
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority.");
- } finally {
- logger.close();
- }
- }
-
- @Test
- public void should_error_when_ssl_context_and_secure_bundle_used_config()
- throws NoSuchAlgorithmException {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- DriverConfigLoader loader =
- SessionUtils.configLoaderBuilder()
- .withBoolean(DefaultDriverOption.RECONNECT_ON_INIT, true)
- .withClass(DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS, DefaultSslEngineFactory.class)
- .build();
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withConfigLoader(loader)
- .withCloudSecureConnectBundle(bundle)
- .withAuthCredentials("cassandra", "cassandra")
- .build()) {
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority.");
- } finally {
- logger.close();
- }
- }
-
- @Test
- public void
- should_connect_and_log_info_when_local_data_center_and_secure_bundle_used_programmatic() {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- DriverConfigLoader loader =
- SessionUtils.configLoaderBuilder()
- .withString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, "dc-ignore")
- .build();
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withCloudSecureConnectBundle(bundle)
- .withConfigLoader(loader)
- .withAuthCredentials("cassandra", "cassandra")
- .build(); ) {
-
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority.");
-
- } finally {
- logger.close();
- }
- }
-
- @Test
- public void should_connect_and_log_info_when_local_data_center_and_secure_bundle_used_config() {
- // given
- LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO);
-
- Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath();
-
- try (CqlSession session =
- CqlSession.builder()
- .withCloudSecureConnectBundle(bundle)
- .withLocalDatacenter("dc-ignored")
- .withAuthCredentials("cassandra", "cassandra")
- .build(); ) {
-
- // when
- ResultSet set = session.execute("select * from system.local where key='local'");
- // then
- assertThat(set).isNotNull();
- verify(logger.appender, timeout(500).atLeast(1))
- .doAppend(logger.loggingEventCaptor.capture());
- assertThat(
- logger.loggingEventCaptor.getAllValues().stream()
- .map(ILoggingEvent::getFormattedMessage))
- .contains(
- "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority.");
-
- } finally {
- logger.close();
- }
- }
-}
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java
deleted file mode 100644
index fa009de78ae..00000000000
--- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.api.core.cloud;
-
-import org.junit.rules.ExternalResource;
-
-public class SniProxyRule extends ExternalResource {
-
- private final SniProxyServer proxy;
-
- public SniProxyRule() {
- proxy = new SniProxyServer();
- }
-
- @Override
- protected void before() {
- proxy.startProxy();
- }
-
- @Override
- protected void after() {
- proxy.stopProxy();
- }
-
- public SniProxyServer getProxy() {
- return proxy;
- }
-}
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java
deleted file mode 100644
index 809354a7daf..00000000000
--- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.datastax.oss.driver.api.core.cloud;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.concurrent.TimeUnit;
-import org.apache.commons.exec.CommandLine;
-import org.apache.commons.exec.DefaultExecutor;
-import org.apache.commons.exec.ExecuteStreamHandler;
-import org.apache.commons.exec.ExecuteWatchdog;
-import org.apache.commons.exec.Executor;
-import org.apache.commons.exec.LogOutputStream;
-import org.apache.commons.exec.PumpStreamHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SniProxyServer {
-
- private static final Logger LOG = LoggerFactory.getLogger(SniProxyServer.class);
-
- private final Path proxyPath;
- private final Path bundlesRootPath;
- private final Path defaultBundlePath;
- private final Path bundleWithoutCredentialsPath;
- private final Path bundleWithoutClientCertificatesPath;
- private final Path bundleWithInvalidCAPath;
- private final Path bundleWithUnreachableMetadataServicePath;
-
- private volatile boolean running = false;
-
- public SniProxyServer() {
- this(Paths.get(System.getProperty("proxy.path", "./")));
- }
-
- public SniProxyServer(Path proxyPath) {
- this.proxyPath = proxyPath.normalize().toAbsolutePath();
- bundlesRootPath = proxyPath.resolve("certs/bundles/");
- defaultBundlePath = bundlesRootPath.resolve("creds-v1.zip");
- bundleWithoutCredentialsPath = bundlesRootPath.resolve("creds-v1-wo-creds.zip");
- bundleWithoutClientCertificatesPath = bundlesRootPath.resolve("creds-v1-wo-cert.zip");
- bundleWithInvalidCAPath = bundlesRootPath.resolve("creds-v1-invalid-ca.zip");
- bundleWithUnreachableMetadataServicePath = bundlesRootPath.resolve("creds-v1-unreachable.zip");
- }
-
- public void startProxy() {
- CommandLine run = CommandLine.parse(proxyPath + "/run.sh");
- execute(run);
- running = true;
- }
-
- public void stopProxy() {
- if (running) {
- CommandLine findImageId =
- CommandLine.parse("docker ps -a -q --filter ancestor=single_endpoint");
- String id = execute(findImageId);
- CommandLine stop = CommandLine.parse("docker kill " + id);
- execute(stop);
- running = false;
- }
- }
-
- /** @return The root folder of the SNI proxy server docker image. */
- public Path getProxyPath() {
- return proxyPath;
- }
-
- /**
- * @return The root folder where secure connect bundles exposed by this SNI proxy for testing
- * purposes can be found.
- */
- public Path getBundlesRootPath() {
- return bundlesRootPath;
- }
-
- /**
- * @return The default secure connect bundle. It contains credentials and all certificates
- * required to connect.
- */
- public Path getDefaultBundlePath() {
- return defaultBundlePath;
- }
-
- /** @return A secure connect bundle without credentials in config.json. */
- public Path getBundleWithoutCredentialsPath() {
- return bundleWithoutCredentialsPath;
- }
-
- /** @return A secure connect bundle without client certificates (no identity.jks). */
- public Path getBundleWithoutClientCertificatesPath() {
- return bundleWithoutClientCertificatesPath;
- }
-
- /** @return A secure connect bundle with an invalid Certificate Authority. */
- public Path getBundleWithInvalidCAPath() {
- return bundleWithInvalidCAPath;
- }
-
- /** @return A secure connect bundle with an invalid address for the Proxy Metadata Service. */
- public Path getBundleWithUnreachableMetadataServicePath() {
- return bundleWithUnreachableMetadataServicePath;
- }
-
- private String execute(CommandLine cli) {
- LOG.debug("Executing: " + cli);
- ExecuteWatchdog watchDog = new ExecuteWatchdog(TimeUnit.MINUTES.toMillis(10));
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- try (LogOutputStream errStream =
- new LogOutputStream() {
- @Override
- protected void processLine(String line, int logLevel) {
- LOG.error("sniendpointerr> {}", line);
- }
- }) {
- Executor executor = new DefaultExecutor();
- ExecuteStreamHandler streamHandler = new PumpStreamHandler(outStream, errStream);
- executor.setStreamHandler(streamHandler);
- executor.setWatchdog(watchDog);
- executor.setWorkingDirectory(proxyPath.toFile());
- int retValue = executor.execute(cli);
- if (retValue != 0) {
- LOG.error("Non-zero exit code ({}) returned from executing ccm command: {}", retValue, cli);
- }
- return outStream.toString();
- } catch (IOException ex) {
- if (watchDog.killedProcess()) {
- throw new RuntimeException("The command '" + cli + "' was killed after 10 minutes");
- } else {
- throw new RuntimeException("The command '" + cli + "' failed to execute", ex);
- }
- }
- }
-}
diff --git a/manual/core/address_resolution/README.md b/manual/core/address_resolution/README.md
index ae44feea3ea..543aeedbfee 100644
--- a/manual/core/address_resolution/README.md
+++ b/manual/core/address_resolution/README.md
@@ -130,9 +130,8 @@ Note that `OptionsMap`-based configuration does not support client routes — us
API (`SessionBuilder.withClientRoutesConfig()`) instead, which can be combined with `OptionsMap`
for all other driver options.
-Client routes are **mutually exclusive** with:
-- A custom `AddressTranslator` (if both are provided, an `IllegalStateException` is thrown)
-- Cloud secure connect bundles (if both are provided, an `IllegalStateException` is thrown)
+Client routes are **mutually exclusive** with a custom `AddressTranslator`; if both are provided,
+an `IllegalStateException` is thrown.
#### Quick start (programmatic)
@@ -203,7 +202,7 @@ the JVM DNS cache TTL via the `networkaddress.cache.ttl` security property (e.g.
- Requires ScyllaDB Enterprise ≥ 2026.1 with `system.client_routes` support
(scylladb/scylladb#27323). Not yet available on ScyllaDB OSS.
- Not supported on Apache Cassandra.
-- Mutually exclusive with custom `AddressTranslator` and with cloud secure connect bundles.
+- Mutually exclusive with a custom `AddressTranslator`.
### Fixed proxy hostname
If your client applications access Cassandra through some kind of proxy (eg. with AWS PrivateLink when all Cassandra
diff --git a/pom.xml b/pom.xml
index 76caea447cc..cad28983488 100644
--- a/pom.xml
+++ b/pom.xml
@@ -487,11 +487,6 @@
api-ldap-codec-standalone
2.1.7
-
- com.github.tomakehurst
- wiremock
- 2.25.0
-
org.graalvm.sdk
graal-sdk
diff --git a/upgrade_guide/README.md b/upgrade_guide/README.md
index 83963f94775..148550bb6da 100644
--- a/upgrade_guide/README.md
+++ b/upgrade_guide/README.md
@@ -19,6 +19,33 @@ under the License.
## Upgrade guide
+### 4.19.2.2
+
+#### DataStax Astra secure-connect-bundle support was removed
+
+This release intentionally removes the DataStax Astra secure-connect-bundle integration and its
+public API. The following members are no longer available:
+
+- `SessionBuilder.withCloudSecureConnectBundle(Path)`
+- `SessionBuilder.withCloudSecureConnectBundle(URL)`
+- `SessionBuilder.withCloudSecureConnectBundle(InputStream)`
+- `SessionBuilder.withCloudProxyAddress(InetSocketAddress)`
+- `ProgrammaticArguments.getCloudProxyAddress()`
+- `ProgrammaticArguments.Builder.withCloudProxyAddress(InetSocketAddress)`
+- `SessionBuilder.ASTRA_PAYLOAD_KEY`
+- `DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE`
+- `TypedDriverOption.CLOUD_SECURE_CONNECT_BUNDLE`
+
+The old `datastax-java-driver.basic.cloud.secure-connect-bundle` configuration key is now an
+unknown option and no longer supplies connection information. If that was the only connection
+setting, the resulting configuration contains no contact points, so the driver falls back to its
+default contact point, `127.0.0.1:9042`.
+
+This is an intentional binary- and source-compatibility break. Applications must replace secure
+connect bundles with explicit `basic.contact-points` configuration or programmatic contact points.
+For supported ScyllaDB private-endpoint deployments, use
+[client routes](../manual/core/address_resolution/) together with an explicit contact point.
+
### 4.19.2.1
#### The driver reports a session identifier, and its configuration, at connection time
@@ -107,8 +134,8 @@ datastax-java-driver {
Key points:
-- **Mutually exclusive** with a custom `AddressTranslator` and with cloud secure connect bundles —
- providing both throws `IllegalStateException` at session build time.
+- **Mutually exclusive** with a custom `AddressTranslator` — providing both throws
+ `IllegalStateException` at session build time.
- **Requires ScyllaDB Enterprise ≥ 2026.1** (scylladb/scylladb#27323). The feature is not
available on ScyllaDB OSS or Apache Cassandra.