future : futures) future.setException(t);
}
- });
+ },
+ MoreExecutors.directExecutor());
}
// If we didn't dequeue all events (or new ones arrived since we did), make sure we eventually
diff --git a/driver-core/src/main/java/com/datastax/driver/core/GuavaCompatibility.java b/driver-core/src/main/java/com/datastax/driver/core/GuavaCompatibility.java
deleted file mode 100644
index 069f550b049..00000000000
--- a/driver-core/src/main/java/com/datastax/driver/core/GuavaCompatibility.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright DataStax, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.datastax.driver.core;
-
-import com.datastax.driver.core.exceptions.DriverInternalError;
-import com.google.common.base.Function;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.Maps;
-import com.google.common.net.HostAndPort;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A compatibility layer to support a wide range of Guava versions.
- *
- * The driver is compatible with Guava 16.0.1 or higher, but Guava 20 introduced incompatible
- * breaking changes in its API, that could in turn be breaking for legacy driver clients if we
- * simply upgraded our dependency. We don't want to increment our major version "just" for Guava (we
- * have other changes planned).
- *
- *
Therefore we depend on Guava 19, which has both the deprecated and the new APIs, and detect
- * the actual version at runtime in order to call the relevant methods.
- *
- *
This is a hack, and might not work with subsequent Guava releases; the real fix is to stop
- * exposing Guava in our public API. We'll address that in version 4 of the driver.
- */
-@SuppressWarnings("deprecation")
-public abstract class GuavaCompatibility {
-
- private static final Logger logger = LoggerFactory.getLogger(GuavaCompatibility.class);
-
- /**
- * The unique instance of this class, that is compatible with the Guava version found in the
- * classpath.
- */
- public static final GuavaCompatibility INSTANCE = selectImplementation();
-
- /**
- * Force the initialization of the class. This should be called early to ensure a fast failure if
- * an incompatible version of Guava is in the classpath (the driver code calls it when loading the
- * {@link Cluster} class).
- */
- public static void init() {
- // nothing to do, we just want the static initializers to run
- }
-
- /**
- * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
- * primary input fails, from the {@code Future} provided by the {@code fallback}.
- *
- * @see Futures#withFallback(ListenableFuture, com.google.common.util.concurrent.FutureFallback)
- * @see Futures#catchingAsync(ListenableFuture, Class, AsyncFunction)
- */
- public abstract ListenableFuture withFallback(
- ListenableFuture extends V> input, AsyncFunction fallback);
-
- /**
- * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
- * primary input fails, from the {@code Future} provided by the {@code fallback}.
- *
- * @see Futures#withFallback(ListenableFuture, com.google.common.util.concurrent.FutureFallback,
- * Executor)
- * @see Futures#catchingAsync(ListenableFuture, Class, AsyncFunction, Executor)
- */
- public abstract ListenableFuture withFallback(
- ListenableFuture extends V> input, AsyncFunction fallback, Executor executor);
-
- /**
- * Registers separate success and failure callbacks to be run when the {@code Future}'s
- * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the
- * computation is already complete, immediately.
- *
- * The callback is run in {@link #sameThreadExecutor()}.
- *
- * @see Futures#addCallback(ListenableFuture, FutureCallback, Executor)
- */
- public void addCallback(ListenableFuture input, FutureCallback super I> callback) {
- addCallback(input, callback, sameThreadExecutor());
- }
-
- /**
- * Registers separate success and failure callbacks to be run when the {@code Future}'s
- * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the
- * computation is already complete, immediately.
- *
- * @see Futures#addCallback(ListenableFuture, FutureCallback, Executor)
- */
- public void addCallback(
- ListenableFuture input, FutureCallback super I> callback, Executor executor) {
- Futures.addCallback(input, callback, executor);
- }
-
- /**
- * Returns a new {@code ListenableFuture} whose result is the product of applying the given {@code
- * Function} to the result of the given {@code Future}.
- *
- *
The callback is run in {@link #sameThreadExecutor()}.
- *
- * @see Futures#transform(ListenableFuture, Function, Executor)
- */
- public ListenableFuture transform(
- ListenableFuture input, Function super I, ? extends O> function) {
- return transform(input, function, sameThreadExecutor());
- }
-
- /**
- * Returns a new {@code ListenableFuture} whose result is the product of applying the given {@code
- * Function} to the result of the given {@code Future}.
- *
- * @see Futures#transform(ListenableFuture, Function, Executor)
- */
- public ListenableFuture transform(
- ListenableFuture input, Function super I, ? extends O> function, Executor executor) {
- return Futures.transform(input, function, executor);
- }
-
- /**
- * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
- * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
- * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
- * original {@code Future}.
- *
- * @see Futures#transform(ListenableFuture, AsyncFunction)
- * @see Futures#transformAsync(ListenableFuture, AsyncFunction)
- */
- public abstract ListenableFuture transformAsync(
- ListenableFuture input, AsyncFunction super I, ? extends O> function);
-
- /**
- * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
- * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
- * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
- * original {@code Future}.
- *
- * @see Futures#transform(ListenableFuture, AsyncFunction, Executor)
- * @see Futures#transformAsync(ListenableFuture, AsyncFunction, Executor)
- */
- public abstract ListenableFuture transformAsync(
- ListenableFuture input, AsyncFunction super I, ? extends O> function, Executor executor);
-
- /**
- * Returns true if {@code target} is a supertype of {@code argument}. "Supertype" is defined
- * according to the rules for type arguments introduced with Java generics.
- *
- * @see TypeToken#isAssignableFrom(Type)
- * @see TypeToken#isSupertypeOf(Type)
- */
- public abstract boolean isSupertypeOf(TypeToken> target, TypeToken> argument);
-
- /**
- * Returns an {@link Executor} that runs each task in the thread that invokes {@link
- * Executor#execute execute}, as in {@link
- * java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy}.
- *
- * @see MoreExecutors#sameThreadExecutor()
- * @see MoreExecutors#directExecutor()
- */
- public abstract Executor sameThreadExecutor();
-
- /**
- * Returns the portion of the given {@link HostAndPort} instance that should represent the
- * hostname or IPv4/IPv6 literal.
- *
- * The method {@code HostAndPort.getHostText} has been replaced with {@code
- * HostAndPort.getHost} starting with Guava 20.0; it has been completely removed in Guava 22.0.
- */
- @SuppressWarnings("JavaReflectionMemberAccess")
- public String getHost(HostAndPort hostAndPort) {
- try {
- // Guava >= 20.0
- return (String) HostAndPort.class.getMethod("getHost").invoke(hostAndPort);
- } catch (Exception e) {
- // Guava < 22.0
- return hostAndPort.getHostText();
- }
- }
-
- private static GuavaCompatibility selectImplementation() {
- if (isGuava_19_0_OrHigher()) {
- logger.info("Detected Guava >= 19 in the classpath, using modern compatibility layer");
- return new Version19OrHigher();
- } else if (isGuava_16_0_1_OrHigher()) {
- logger.info("Detected Guava < 19 in the classpath, using legacy compatibility layer");
- return new Version18OrLower();
- } else {
- throw new DriverInternalError(
- "Detected incompatible version of Guava in the classpath. "
- + "You need 16.0.1 or higher.");
- }
- }
-
- private static class Version18OrLower extends GuavaCompatibility {
-
- @Override
- public ListenableFuture withFallback(
- ListenableFuture extends V> input, final AsyncFunction fallback) {
- return Futures.withFallback(
- input,
- new com.google.common.util.concurrent.FutureFallback() {
- @Override
- public ListenableFuture create(Throwable t) throws Exception {
- return fallback.apply(t);
- }
- });
- }
-
- @Override
- public ListenableFuture withFallback(
- ListenableFuture extends V> input,
- final AsyncFunction fallback,
- Executor executor) {
- return Futures.withFallback(
- input,
- new com.google.common.util.concurrent.FutureFallback() {
- @Override
- public ListenableFuture create(Throwable t) throws Exception {
- return fallback.apply(t);
- }
- },
- executor);
- }
-
- @Override
- public ListenableFuture transformAsync(
- ListenableFuture input, AsyncFunction super I, ? extends O> function) {
- return Futures.transform(input, function);
- }
-
- @Override
- public ListenableFuture transformAsync(
- ListenableFuture input,
- AsyncFunction super I, ? extends O> function,
- Executor executor) {
- return Futures.transform(input, function, executor);
- }
-
- @Override
- public boolean isSupertypeOf(TypeToken> target, TypeToken> argument) {
- return target.isAssignableFrom(argument);
- }
-
- @Override
- public Executor sameThreadExecutor() {
- return MoreExecutors.sameThreadExecutor();
- }
- }
-
- private static class Version19OrHigher extends GuavaCompatibility {
-
- @Override
- public ListenableFuture withFallback(
- ListenableFuture extends V> input, AsyncFunction fallback) {
- return withFallback(input, fallback, sameThreadExecutor());
- }
-
- @Override
- public ListenableFuture withFallback(
- ListenableFuture extends V> input,
- AsyncFunction fallback,
- Executor executor) {
- return Futures.catchingAsync(input, Throwable.class, fallback, executor);
- }
-
- @Override
- public ListenableFuture transformAsync(
- ListenableFuture input, AsyncFunction super I, ? extends O> function) {
- return transformAsync(input, function, sameThreadExecutor());
- }
-
- @Override
- public ListenableFuture transformAsync(
- ListenableFuture input,
- AsyncFunction super I, ? extends O> function,
- Executor executor) {
- return Futures.transformAsync(input, function, executor);
- }
-
- @Override
- public boolean isSupertypeOf(TypeToken> target, TypeToken> argument) {
- return target.isSupertypeOf(argument);
- }
-
- @Override
- public Executor sameThreadExecutor() {
- return MoreExecutors.directExecutor();
- }
- }
-
- private static boolean isGuava_19_0_OrHigher() {
- return methodExists(
- Futures.class,
- "transformAsync",
- ListenableFuture.class,
- AsyncFunction.class,
- Executor.class);
- }
-
- private static boolean isGuava_16_0_1_OrHigher() {
- // Cheap check for < 16.0
- if (!methodExists(Maps.class, "asConverter", BiMap.class)) {
- return false;
- }
- // More elaborate check to filter out 16.0, which has a bug in TypeToken. We need 16.0.1.
- boolean resolved = false;
- TypeToken