diff --git a/changelog/README.md b/changelog/README.md index b399499f07a..baf1eb4efa8 100644 --- a/changelog/README.md +++ b/changelog/README.md @@ -11,6 +11,7 @@ - [improvement] JAVA-1241: Upgrade Netty to 4.1.x. - [improvement] JAVA-1287: Add CDC to TableOptionsMetadata and Schema Builder. - [improvement] JAVA-1392: Reduce lock contention in RPTokenFactory. +- [improvement] JAVA-1328: Provide compatibility with Guava 20. Merged from 3.1.x branch: diff --git a/driver-core/pom.xml b/driver-core/pom.xml index 16af50748f3..4725272b6ef 100644 --- a/driver-core/pom.xml +++ b/driver-core/pom.xml @@ -200,7 +200,7 @@ <_include>-osgi.bnd - + jar @@ -224,7 +224,7 @@ JNR does not provide OSGi bundles, so exclude it; the driver can live without it Explicitly import javax.security.cert because it's required by Netty, but Netty has been explicitly excluded --> - + com.datastax.shaded.* diff --git a/driver-core/src/main/java/com/datastax/driver/core/AbstractAddressableByIndexData.java b/driver-core/src/main/java/com/datastax/driver/core/AbstractAddressableByIndexData.java index c1b21810e5f..fc795b29578 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/AbstractAddressableByIndexData.java +++ b/driver-core/src/main/java/com/datastax/driver/core/AbstractAddressableByIndexData.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.reflect.TypeToken; import java.math.BigDecimal; @@ -280,7 +280,7 @@ public boolean equals(Object o) { Object thisValue = this.codecFor(i).deserialize(this.values[i], this.protocolVersion); Object thatValue = that.codecFor(i).deserialize(that.values[i], that.protocolVersion); - if (!Objects.equal(thisValue, thatValue)) + if (!MoreObjects.equal(thisValue, thatValue)) return false; } return true; diff --git a/driver-core/src/main/java/com/datastax/driver/core/AbstractData.java b/driver-core/src/main/java/com/datastax/driver/core/AbstractData.java index d4144162c26..80eaed6a2c4 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/AbstractData.java +++ b/driver-core/src/main/java/com/datastax/driver/core/AbstractData.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.reflect.TypeToken; import java.math.BigDecimal; @@ -575,7 +575,7 @@ public boolean equals(Object o) { Object thisValue = this.codecFor(i).deserialize(this.values[i], this.protocolVersion); Object thatValue = that.codecFor(i).deserialize(that.values[i], that.protocolVersion); - if (!Objects.equal(thisValue, thatValue)) + if (!MoreObjects.equal(thisValue, thatValue)) return false; } return true; diff --git a/driver-core/src/main/java/com/datastax/driver/core/AggregateMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/AggregateMetadata.java index e0717c7f133..635d2538bc0 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/AggregateMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/AggregateMetadata.java @@ -16,7 +16,7 @@ package com.datastax.driver.core; import com.datastax.driver.core.utils.Bytes; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.slf4j.Logger; @@ -376,11 +376,11 @@ public boolean equals(Object other) { AggregateMetadata that = (AggregateMetadata) other; return this.keyspace.getName().equals(that.keyspace.getName()) && this.argumentTypes.equals(that.argumentTypes) && - Objects.equal(this.finalFuncFullName, that.finalFuncFullName) && + MoreObjects.equal(this.finalFuncFullName, that.finalFuncFullName) && // Note: this might be a problem if a custom codec has been registered for the initCond's type, with a target Java type that // does not properly implement equals. We don't have any control over this, at worst this would lead to spurious change // notifications. - Objects.equal(this.initCond, that.initCond) && + MoreObjects.equal(this.initCond, that.initCond) && this.returnType.equals(that.returnType) && this.stateFuncFullName.equals(that.stateFuncFullName) && this.stateType.equals(that.stateType); @@ -390,7 +390,6 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(this.keyspace.getName(), this.argumentTypes, - this.finalFuncFullName, this.initCond, this.returnType, this.stateFuncFullName, this.stateType); + return MoreObjects.hashCode(this.keyspace.getName(), this.argumentTypes, this.finalFuncFullName, this.initCond, this.returnType, this.stateFuncFullName, this.stateType); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/CloseFuture.java b/driver-core/src/main/java/com/datastax/driver/core/CloseFuture.java index c72ae8fc28b..51effb25775 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/CloseFuture.java +++ b/driver-core/src/main/java/com/datastax/driver/core/CloseFuture.java @@ -28,7 +28,7 @@ * additional {@link #force} method that can be used to expedite the shutdown * process (see below). *

- * Note that this class implements Guava's {@code + * Note that this class implements Guava's {@code * ListenableFuture} and can so be used with Guava's future utilities. */ public abstract class CloseFuture extends AbstractFuture { diff --git a/driver-core/src/main/java/com/datastax/driver/core/Cluster.java b/driver-core/src/main/java/com/datastax/driver/core/Cluster.java index d4e6ea05bed..54cf8667179 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/Cluster.java +++ b/driver-core/src/main/java/com/datastax/driver/core/Cluster.java @@ -64,8 +64,8 @@ public class Cluster implements Closeable { private static final Logger logger = LoggerFactory.getLogger(Cluster.class); static { - // Perform sanity checks to inform user of possible environment misconfiguration. - SanityChecks.check(); + // Force initialization to fail fast if there is an issue detecting the version + GuavaCompatibility.init(); } @VisibleForTesting @@ -334,15 +334,15 @@ public ListenableFuture connectAsync(final String keyspace) { return sessionInitialized; } else { final String useQuery = "USE " + keyspace; - ListenableFuture keyspaceSet = Futures.transform(sessionInitialized, new AsyncFunction() { + ListenableFuture keyspaceSet = GuavaCompatibility.INSTANCE.transformAsync(sessionInitialized, new AsyncFunction() { @Override public ListenableFuture apply(Session session) throws Exception { return session.executeAsync(useQuery); } }); - ListenableFuture withErrorHandling = Futures.withFallback(keyspaceSet, new FutureFallback() { + ListenableFuture withErrorHandling = GuavaCompatibility.INSTANCE.withFallback(keyspaceSet, new AsyncFunction() { @Override - public ListenableFuture create(Throwable t) throws Exception { + public ListenableFuture apply(Throwable t) throws Exception { session.closeAsync(); if (t instanceof SyntaxError) { // Give a more explicit message, because it's probably caused by a bad keyspace name @@ -2373,7 +2373,7 @@ public void run() { rs.getExecutionInfo().setSchemaInAgreement(finalSchemaInAgreement); future.setResult(rs); } - }, MoreExecutors.sameThreadExecutor()); + }, GuavaCompatibility.INSTANCE.sameThreadExecutor()); } catch (Exception e) { logger.warn("Error while waiting for schema agreement", e); diff --git a/driver-core/src/main/java/com/datastax/driver/core/CodecRegistry.java b/driver-core/src/main/java/com/datastax/driver/core/CodecRegistry.java index e62957f8f71..2e8ef03dfa7 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/CodecRegistry.java +++ b/driver-core/src/main/java/com/datastax/driver/core/CodecRegistry.java @@ -16,7 +16,7 @@ package com.datastax.driver.core; import com.datastax.driver.core.exceptions.CodecNotFoundException; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.cache.*; import com.google.common.reflect.TypeToken; import com.google.common.util.concurrent.UncheckedExecutionException; @@ -216,12 +216,12 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; CacheKey cacheKey = (CacheKey) o; - return Objects.equal(cqlType, cacheKey.cqlType) && Objects.equal(javaType, cacheKey.javaType); + return MoreObjects.equal(cqlType, cacheKey.cqlType) && MoreObjects.equal(javaType, cacheKey.javaType); } @Override public int hashCode() { - return Objects.hashCode(cqlType, javaType); + return MoreObjects.hashCode(cqlType, javaType); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/ColumnMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/ColumnMetadata.java index 0e754721c1d..c4eb68e1b0d 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/ColumnMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/ColumnMetadata.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import java.util.Arrays; import java.util.HashMap; @@ -116,7 +116,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(name, isStatic, type); + return MoreObjects.hashCode(name, isStatic, type); } @Override diff --git a/driver-core/src/main/java/com/datastax/driver/core/Connection.java b/driver-core/src/main/java/com/datastax/driver/core/Connection.java index fc27f1262da..04727f8d388 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/Connection.java +++ b/driver-core/src/main/java/com/datastax/driver/core/Connection.java @@ -18,8 +18,8 @@ import com.datastax.driver.core.Responses.Result.SetKeyspace; import com.datastax.driver.core.exceptions.*; import com.datastax.driver.core.utils.MoreFutures; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Objects; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; import com.google.common.util.concurrent.*; @@ -179,13 +179,13 @@ public void operationComplete(ChannelFuture future) throws Exception { Executor initExecutor = factory.manager.configuration.getPoolingOptions().getInitializationExecutor(); - ListenableFuture initializeTransportFuture = Futures.transform(channelReadyFuture, + ListenableFuture initializeTransportFuture = GuavaCompatibility.INSTANCE.transformAsync(channelReadyFuture, onChannelReady(protocolVersion, initExecutor), initExecutor); // Fallback on initializeTransportFuture so we can properly propagate specific exceptions. - ListenableFuture initFuture = Futures.withFallback(initializeTransportFuture, new FutureFallback() { + ListenableFuture initFuture = GuavaCompatibility.INSTANCE.withFallback(initializeTransportFuture, new AsyncFunction() { @Override - public ListenableFuture create(Throwable t) throws Exception { + public ListenableFuture apply(Throwable t) throws Exception { SettableFuture future = SettableFuture.create(); // Make sure the connection gets properly closed. if (t instanceof ClusterNameMismatchException || t instanceof UnsupportedProtocolVersionException) { @@ -233,7 +233,7 @@ private AsyncFunction onChannelReady(final ProtocolVersion protocolV public ListenableFuture apply(Void input) throws Exception { ProtocolOptions.Compression compression = factory.configuration.getProtocolOptions().getCompression(); Future startupResponseFuture = write(new Requests.Startup(compression)); - return Futures.transform(startupResponseFuture, + return GuavaCompatibility.INSTANCE.transformAsync(startupResponseFuture, onStartupResponse(protocolVersion, initExecutor), initExecutor); } }; @@ -297,7 +297,7 @@ private ListenableFuture checkClusterName(ProtocolVersion protocolVersion, DefaultResultSetFuture clusterNameFuture = new DefaultResultSetFuture(null, protocolVersion, new Requests.Query("select cluster_name from system.local")); try { write(clusterNameFuture); - return Futures.transform(clusterNameFuture, + return GuavaCompatibility.INSTANCE.transformAsync(clusterNameFuture, new AsyncFunction() { @Override public ListenableFuture apply(ResultSet rs) throws Exception { @@ -323,7 +323,7 @@ private ListenableFuture authenticateV1(Authenticator authenticator, final Requests.Credentials creds = new Requests.Credentials(((ProtocolV1Authenticator) authenticator).getCredentials()); try { Future authResponseFuture = write(creds); - return Futures.transform(authResponseFuture, + return GuavaCompatibility.INSTANCE.transformAsync(authResponseFuture, new AsyncFunction() { @Override public ListenableFuture apply(Message.Response authResponse) throws Exception { @@ -350,7 +350,7 @@ private ListenableFuture authenticateV2(final Authenticator authenticator, try { Future authResponseFuture = write(new Requests.AuthResponse(initialResponse)); - return Futures.transform(authResponseFuture, onV2AuthResponse(authenticator, protocolVersion, executor), executor); + return GuavaCompatibility.INSTANCE.transformAsync(authResponseFuture, onV2AuthResponse(authenticator, protocolVersion, executor), executor); } catch (Exception e) { return Futures.immediateFailedFuture(e); } @@ -376,7 +376,7 @@ public ListenableFuture apply(Message.Response authResponse) throws Except // Otherwise, send the challenge response back to the server logger.trace("{} Sending Auth response to challenge", this); Future nextResponseFuture = write(new Requests.AuthResponse(responseToServer)); - return Futures.transform(nextResponseFuture, onV2AuthResponse(authenticator, protocolVersion, executor), executor); + return GuavaCompatibility.INSTANCE.transformAsync(nextResponseFuture, onV2AuthResponse(authenticator, protocolVersion, executor), executor); } case ERROR: // This is not very nice, but we're trying to identify if we @@ -471,7 +471,7 @@ void setKeyspace(String keyspace) throws ConnectionException { if (keyspace == null) return; - if (Objects.equal(keyspace(), keyspace)) + if (MoreObjects.equal(keyspace(), keyspace)) return; try { @@ -497,7 +497,7 @@ void setKeyspace(String keyspace) throws ConnectionException { ListenableFuture setKeyspaceAsync(final String keyspace) throws ConnectionException, BusyConnectionException { SetKeyspaceAttempt existingAttempt = targetKeyspace.get(); - if (Objects.equal(existingAttempt.keyspace, keyspace)) + if (MoreObjects.equal(existingAttempt.keyspace, keyspace)) return existingAttempt.future; final SettableFuture ksFuture = SettableFuture.create(); diff --git a/driver-core/src/main/java/com/datastax/driver/core/ControlConnection.java b/driver-core/src/main/java/com/datastax/driver/core/ControlConnection.java index d785b8e057a..1483190abb2 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/ControlConnection.java +++ b/driver-core/src/main/java/com/datastax/driver/core/ControlConnection.java @@ -16,8 +16,8 @@ package com.datastax.driver.core; import com.datastax.driver.core.exceptions.*; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Objects; import com.google.common.util.concurrent.ListenableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -519,7 +519,7 @@ private static void updateInfo(Host host, Row row, Cluster.Manager cluster, bool } private static void updateLocationInfo(Host host, String datacenter, String rack, boolean isInitialConnection, Cluster.Manager cluster) { - if (Objects.equal(host.getDatacenter(), datacenter) && Objects.equal(host.getRack(), rack)) + if (MoreObjects.equal(host.getDatacenter(), datacenter) && MoreObjects.equal(host.getRack(), rack)) return; // If the dc/rack information changes for an existing node, we need to update the load balancing policy. diff --git a/driver-core/src/main/java/com/datastax/driver/core/DataType.java b/driver-core/src/main/java/com/datastax/driver/core/DataType.java index 4849f6367c0..f92f4255371 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/DataType.java +++ b/driver-core/src/main/java/com/datastax/driver/core/DataType.java @@ -16,7 +16,7 @@ package com.datastax.driver.core; import com.datastax.driver.core.exceptions.DriverInternalError; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import io.netty.buffer.ByteBuf; @@ -662,7 +662,7 @@ public List getTypeArguments() { @Override public final int hashCode() { - return Objects.hashCode(name, typeArguments); + return MoreObjects.hashCode(name, typeArguments); } @Override @@ -740,7 +740,7 @@ public String getCustomTypeClassName() { @Override public final int hashCode() { - return Objects.hashCode(name, customClassName); + return MoreObjects.hashCode(name, customClassName); } @Override @@ -749,7 +749,7 @@ public final boolean equals(Object o) { return false; DataType.CustomType d = (DataType.CustomType) o; - return name == d.name && Objects.equal(customClassName, d.customClassName); + return name == d.name && MoreObjects.equal(customClassName, d.customClassName); } @Override diff --git a/driver-core/src/main/java/com/datastax/driver/core/FunctionMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/FunctionMetadata.java index fdbfdaab522..523dfeb9718 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/FunctionMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/FunctionMetadata.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.collect.ImmutableMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -321,6 +321,6 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(keyspace.getName(), arguments, body, calledOnNullInput, language, returnType); + return MoreObjects.hashCode(keyspace.getName(), arguments, body, calledOnNullInput, language, returnType); } } 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 new file mode 100644 index 00000000000..9ff0de2ff69 --- /dev/null +++ b/driver-core/src/main/java/com/datastax/driver/core/GuavaCompatibility.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2012-2015 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.Preconditions; +import com.google.common.reflect.TypeToken; +import com.google.common.util.concurrent.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.net.URL; +import java.util.Enumeration; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 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); + private static final Pattern GA_VERSION_EXTRACTOR = Pattern.compile("(\\d+\\.\\d+\\.\\d+).*"); + + /** + * 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, FutureFallback) + * @see Futures#catchingAsync(ListenableFuture, Class, AsyncFunction) + */ + public abstract ListenableFuture withFallback(ListenableFuture 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, FutureFallback, Executor) + * @see Futures#catchingAsync(ListenableFuture, Class, AsyncFunction, Executor) + */ + public abstract ListenableFuture withFallback(ListenableFuture input, + AsyncFunction fallback, Executor 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 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 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 ThreadPoolExecutor.CallerRunsPolicy}. + * + * @see MoreExecutors#sameThreadExecutor() + * @see MoreExecutors#directExecutor() + */ + public abstract Executor sameThreadExecutor(); + + private static GuavaCompatibility selectImplementation() { + String fullVersion = getBundleVersion(loadGuavaManifest()); + // Get rid of potential rc qualifier, as it could throw off the lexical comparisons + String version = stripQualifiers(fullVersion); + if (version.compareTo("16.0.1") < 0) { + throw new DriverInternalError(String.format( + "Detected incompatible version of Guava in the classpath (%s). " + + "You need 16.0.1 or higher.", fullVersion)); + } else if (version.compareTo("19.0") < 0) { + logger.info("Detected Guava {} in the classpath, using pre-19 compatibility layer", fullVersion); + return new Version18OrLower(); + } else { + logger.info("Detected Guava {} in the classpath, using 19+ compatibility layer", fullVersion); + return new Version19OrHigher(); + } + } + + private static Manifest loadGuavaManifest() { + InputStream in = null; + try { + Enumeration resources = Preconditions.class.getClassLoader() + .getResources("META-INF/MANIFEST.MF"); + while (resources.hasMoreElements()) { + in = resources.nextElement().openStream(); + Manifest manifest = new Manifest(in); + Attributes mainAttributes = manifest.getMainAttributes(); + String symbolicName = mainAttributes.getValue("Bundle-SymbolicName"); + if ("com.google.guava".equals(symbolicName)) { + return manifest; + } + } + throw new DriverInternalError("Error while looking up Guava manifest: " + + "no manifest with symbolic name 'com.google.guava' found in classpath."); + } catch (Exception e) { + throw new DriverInternalError("Error while looking up Guava manifest", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + private static String getBundleVersion(Manifest manifest) { + return manifest.getMainAttributes().getValue("Bundle-Version"); + } + + private static String stripQualifiers(String fullVersion) { + Matcher matcher = GA_VERSION_EXTRACTOR.matcher(fullVersion); + if (matcher.matches()) { + return matcher.group(1); + } else { + throw new DriverInternalError(String.format("Could not strip qualifiers from full Guava version %s", fullVersion)); + } + } + + private static class Version18OrLower extends GuavaCompatibility { + + @Override + public ListenableFuture withFallback(ListenableFuture input, + final AsyncFunction fallback) { + return Futures.withFallback(input, new FutureFallback() { + @Override + public ListenableFuture create(Throwable t) throws Exception { + return fallback.apply(t); + } + }); + } + + @Override + public ListenableFuture withFallback(ListenableFuture input, + final AsyncFunction fallback, + Executor executor) { + return Futures.withFallback(input, new FutureFallback() { + @Override + public ListenableFuture create(Throwable t) throws Exception { + return fallback.apply(t); + } + }, executor); + } + + @Override + public ListenableFuture transformAsync(ListenableFuture input, AsyncFunction function) { + return Futures.transform(input, function); + } + + @Override + public ListenableFuture transformAsync(ListenableFuture input, AsyncFunction 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 input, + AsyncFunction fallback) { + return Futures.catchingAsync(input, Throwable.class, fallback); + } + + @Override + public ListenableFuture withFallback(ListenableFuture input, + AsyncFunction fallback, Executor executor) { + return Futures.catchingAsync(input, Throwable.class, fallback, executor); + } + + @Override + public ListenableFuture transformAsync(ListenableFuture input, AsyncFunction function) { + return Futures.transformAsync(input, function); + } + + @Override + public ListenableFuture transformAsync(ListenableFuture input, AsyncFunction 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(); + } + } +} diff --git a/driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java b/driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java index 4d80ea57f2b..1dcfb336e6e 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java +++ b/driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java @@ -167,9 +167,9 @@ public void onFailure(Throwable t) { } private ListenableFuture handleErrors(ListenableFuture connectionInitFuture, Executor executor) { - return Futures.withFallback(connectionInitFuture, new FutureFallback() { + return GuavaCompatibility.INSTANCE.withFallback(connectionInitFuture, new AsyncFunction() { @Override - public ListenableFuture create(Throwable t) throws Exception { + public ListenableFuture apply(Throwable t) throws Exception { // Propagate these exceptions because they mean no connection will ever succeed. They will be handled // accordingly in SessionManager#maybeAddPool. Throwables.propagateIfInstanceOf(t, ClusterNameMismatchException.class); @@ -639,7 +639,7 @@ public void run() { if (connection.state.compareAndSet(OPEN, GONE)) open.decrementAndGet(); } - }, MoreExecutors.sameThreadExecutor()); + }, GuavaCompatibility.INSTANCE.sameThreadExecutor()); futures.add(future); } diff --git a/driver-core/src/main/java/com/datastax/driver/core/IndexMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/IndexMetadata.java index bf393104997..bf346b530b5 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/IndexMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/IndexMetadata.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; @@ -240,7 +240,7 @@ public boolean apply(Map.Entry input) { } public int hashCode() { - return Objects.hashCode(name, kind, target, options); + return MoreObjects.hashCode(name, kind, target, options); } public boolean equals(Object obj) { @@ -252,10 +252,10 @@ public boolean equals(Object obj) { IndexMetadata other = (IndexMetadata) obj; - return Objects.equal(name, other.name) - && Objects.equal(kind, other.kind) - && Objects.equal(target, other.target) - && Objects.equal(options, other.options); + return MoreObjects.equal(name, other.name) + && MoreObjects.equal(kind, other.kind) + && MoreObjects.equal(target, other.target) + && MoreObjects.equal(options, other.options); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/MaterializedViewMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/MaterializedViewMetadata.java index 7132328abfd..952541cb15e 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/MaterializedViewMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/MaterializedViewMetadata.java @@ -16,7 +16,7 @@ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -221,20 +221,19 @@ public boolean equals(Object other) { return false; MaterializedViewMetadata that = (MaterializedViewMetadata) other; - return Objects.equal(this.name, that.name) && - Objects.equal(this.id, that.id) && - Objects.equal(this.partitionKey, that.partitionKey) && - Objects.equal(this.clusteringColumns, that.clusteringColumns) && - Objects.equal(this.columns, that.columns) && - Objects.equal(this.options, that.options) && - Objects.equal(this.clusteringOrder, that.clusteringOrder) && - Objects.equal(this.baseTable.getName(), that.baseTable.getName()) && + return MoreObjects.equal(this.name, that.name) && + MoreObjects.equal(this.id, that.id) && + MoreObjects.equal(this.partitionKey, that.partitionKey) && + MoreObjects.equal(this.clusteringColumns, that.clusteringColumns) && + MoreObjects.equal(this.columns, that.columns) && + MoreObjects.equal(this.options, that.options) && + MoreObjects.equal(this.clusteringOrder, that.clusteringOrder) && + MoreObjects.equal(this.baseTable.getName(), that.baseTable.getName()) && this.includeAllColumns == that.includeAllColumns; } @Override public int hashCode() { - return Objects.hashCode(name, id, partitionKey, clusteringColumns, columns, options, clusteringOrder, - baseTable.getName(), includeAllColumns); + return MoreObjects.hashCode(name, id, partitionKey, clusteringColumns, columns, options, clusteringOrder, baseTable.getName(), includeAllColumns); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/PoolingOptions.java b/driver-core/src/main/java/com/datastax/driver/core/PoolingOptions.java index 38a080cbe37..ec6544a3d20 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/PoolingOptions.java +++ b/driver-core/src/main/java/com/datastax/driver/core/PoolingOptions.java @@ -17,7 +17,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -import com.google.common.util.concurrent.MoreExecutors; import java.util.Map; import java.util.concurrent.Executor; @@ -142,7 +141,7 @@ public class PoolingOptions { */ public static final int DEFAULT_HEARTBEAT_INTERVAL_SECONDS = 30; - private static final Executor DEFAULT_INITIALIZATION_EXECUTOR = MoreExecutors.sameThreadExecutor(); + private static final Executor DEFAULT_INITIALIZATION_EXECUTOR = GuavaCompatibility.INSTANCE.sameThreadExecutor(); private volatile Cluster.Manager manager; private volatile ProtocolVersion protocolVersion; diff --git a/driver-core/src/main/java/com/datastax/driver/core/ResultSetFuture.java b/driver-core/src/main/java/com/datastax/driver/core/ResultSetFuture.java index 52f9adeea1f..f91f3a10f81 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/ResultSetFuture.java +++ b/driver-core/src/main/java/com/datastax/driver/core/ResultSetFuture.java @@ -26,7 +26,7 @@ /** * A future on a {@link ResultSet}. *

- * Note that this class implements Guava's {@code + * Note that this class implements Guava's {@code * ListenableFuture} and can so be used with Guava's future utilities. */ public interface ResultSetFuture extends ListenableFuture { diff --git a/driver-core/src/main/java/com/datastax/driver/core/SanityChecks.java b/driver-core/src/main/java/com/datastax/driver/core/SanityChecks.java deleted file mode 100644 index c93020b4692..00000000000 --- a/driver-core/src/main/java/com/datastax/driver/core/SanityChecks.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012-2015 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.google.common.reflect.TypeToken; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Map; - -class SanityChecks { - - /** - * Performs a series of runtime checks to ensure the environment does not have any - * incompatible libraries or configurations. Depending on the severity of an - * incompatibility an {@link IllegalStateException} may be thrown or an ERROR or - * WARNING is logged. - * - * @throws IllegalStateException If an environment incompatibility is detected. - * @see #checkGuava - */ - static void check() { - checkGuava(); - } - - /** - * Detects if a version of guava older than 16.01 is present by attempting to create - * a {@link TypeToken} instance for Map<String,String> and ensures that the - * value type argument is of instance {@link String}. If using an older version of guava - * this will resolve to {@link Object} instead. In this case an {@link IllegalStateException} - * is thrown. - * - * @throws IllegalStateException if version of guava less than 16.01 is detected. - */ - static void checkGuava() { - boolean resolved = false; - TypeToken> mapOfString = TypeTokens.mapOf(String.class, String.class); - Type type = mapOfString.getType(); - if (type instanceof ParameterizedType) { - ParameterizedType pType = (ParameterizedType) type; - Type[] types = pType.getActualTypeArguments(); - if (types.length == 2) { - TypeToken valueType = TypeToken.of(types[1]); - resolved = valueType.getRawType().equals(String.class); - } - } - - if (!resolved) { - throw new IllegalStateException( - "Detected Guava issue #1635 which indicates that a version of Guava less than 16.01 is in use. " - + "This introduces codec resolution issues and potentially other incompatibility issues in the driver. " - + "Please upgrade to Guava 16.01 or later."); - } - } - -} diff --git a/driver-core/src/main/java/com/datastax/driver/core/SessionManager.java b/driver-core/src/main/java/com/datastax/driver/core/SessionManager.java index c9a15ac13f6..8702d24589c 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/SessionManager.java +++ b/driver-core/src/main/java/com/datastax/driver/core/SessionManager.java @@ -87,7 +87,7 @@ public ListenableFuture initAsync() { Collection hosts = cluster.getMetadata().allHosts(); ListenableFuture allPoolsCreatedFuture = createPools(hosts); - ListenableFuture allPoolsUpdatedFuture = Futures.transform(allPoolsCreatedFuture, + ListenableFuture allPoolsUpdatedFuture = GuavaCompatibility.INSTANCE.transformAsync(allPoolsCreatedFuture, new AsyncFunction() { @Override @SuppressWarnings("unchecked") @@ -193,7 +193,7 @@ public Session.State getState() { } private ListenableFuture toPreparedStatement(final String query, final Connection.Future future) { - return Futures.transform(future, new AsyncFunction() { + return GuavaCompatibility.INSTANCE.transformAsync(future, new AsyncFunction() { @Override public ListenableFuture apply(Response response) { switch (response.type) { @@ -433,7 +433,7 @@ ListenableFuture updateCreatedPools() { // Wait pool creation before removing, so we don't lose connectivity ListenableFuture allPoolsCreatedFuture = Futures.successfulAsList(poolCreatedFutures); - return Futures.transform(allPoolsCreatedFuture, new AsyncFunction>() { + return GuavaCompatibility.INSTANCE.transformAsync(allPoolsCreatedFuture, new AsyncFunction>() { @Override public ListenableFuture> apply(Object input) throws Exception { List> poolRemovedFuture = Lists.newArrayListWithCapacity(toRemove.size()); @@ -626,7 +626,7 @@ private ListenableFuture prepare(final PreparedStatement stat // the prepared query. So don't wait if no connection is available, simply abort. ListenableFuture connectionFuture = entry.getValue().borrowConnection( 0, TimeUnit.MILLISECONDS, 0); - ListenableFuture prepareFuture = Futures.transform(connectionFuture, + ListenableFuture prepareFuture = GuavaCompatibility.INSTANCE.transformAsync(connectionFuture, new AsyncFunction() { @Override public ListenableFuture apply(final Connection c) throws Exception { diff --git a/driver-core/src/main/java/com/datastax/driver/core/TableMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/TableMetadata.java index 2e9e6b1713f..3ff0cbdeadd 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/TableMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/TableMetadata.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -439,19 +439,19 @@ public boolean equals(Object other) { TableMetadata that = (TableMetadata) other; - return Objects.equal(this.name, that.name) && - Objects.equal(this.id, that.id) && - Objects.equal(this.partitionKey, that.partitionKey) && - Objects.equal(this.clusteringColumns, that.clusteringColumns) && - Objects.equal(this.columns, that.columns) && - Objects.equal(this.options, that.options) && - Objects.equal(this.clusteringOrder, that.clusteringOrder) && - Objects.equal(this.indexes, that.indexes) && - Objects.equal(this.views, that.views); + return MoreObjects.equal(this.name, that.name) && + MoreObjects.equal(this.id, that.id) && + MoreObjects.equal(this.partitionKey, that.partitionKey) && + MoreObjects.equal(this.clusteringColumns, that.clusteringColumns) && + MoreObjects.equal(this.columns, that.columns) && + MoreObjects.equal(this.options, that.options) && + MoreObjects.equal(this.clusteringOrder, that.clusteringOrder) && + MoreObjects.equal(this.indexes, that.indexes) && + MoreObjects.equal(this.views, that.views); } @Override public int hashCode() { - return Objects.hashCode(name, id, partitionKey, clusteringColumns, columns, options, clusteringOrder, indexes, views); + return MoreObjects.hashCode(name, id, partitionKey, clusteringColumns, columns, options, clusteringOrder, indexes, views); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/TableOptionsMetadata.java b/driver-core/src/main/java/com/datastax/driver/core/TableOptionsMetadata.java index cd0b290d9ed..49c1dfc7254 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/TableOptionsMetadata.java +++ b/driver-core/src/main/java/com/datastax/driver/core/TableOptionsMetadata.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.collect.ImmutableMap; import java.nio.ByteBuffer; @@ -398,30 +398,30 @@ public boolean equals(Object other) { TableOptionsMetadata that = (TableOptionsMetadata) other; return this.isCompactStorage == that.isCompactStorage && - Objects.equal(this.comment, that.comment) && + MoreObjects.equal(this.comment, that.comment) && this.readRepair == that.readRepair && this.localReadRepair == that.localReadRepair && this.replicateOnWrite == that.replicateOnWrite && this.gcGrace == that.gcGrace && this.bfFpChance == that.bfFpChance && - Objects.equal(this.caching, that.caching) && + MoreObjects.equal(this.caching, that.caching) && this.populateCacheOnFlush == that.populateCacheOnFlush && this.memtableFlushPeriodMs == that.memtableFlushPeriodMs && this.defaultTTL == that.defaultTTL && this.cdc == that.cdc && - Objects.equal(this.speculativeRetry, that.speculativeRetry) && - Objects.equal(this.indexInterval, that.indexInterval) && - Objects.equal(this.minIndexInterval, that.minIndexInterval) && - Objects.equal(this.maxIndexInterval, that.maxIndexInterval) && - Objects.equal(this.compaction, that.compaction) && - Objects.equal(this.compression, that.compression) && - Objects.equal(this.crcCheckChance, that.crcCheckChance) && - Objects.equal(this.extensions, that.extensions); + MoreObjects.equal(this.speculativeRetry, that.speculativeRetry) && + MoreObjects.equal(this.indexInterval, that.indexInterval) && + MoreObjects.equal(this.minIndexInterval, that.minIndexInterval) && + MoreObjects.equal(this.maxIndexInterval, that.maxIndexInterval) && + MoreObjects.equal(this.compaction, that.compaction) && + MoreObjects.equal(this.compression, that.compression) && + MoreObjects.equal(this.crcCheckChance, that.crcCheckChance) && + MoreObjects.equal(this.extensions, that.extensions); } @Override public int hashCode() { - return Objects.hashCode(isCompactStorage, comment, readRepair, localReadRepair, replicateOnWrite, gcGrace, + return MoreObjects.hashCode(isCompactStorage, comment, readRepair, localReadRepair, replicateOnWrite, gcGrace, bfFpChance, caching, populateCacheOnFlush, memtableFlushPeriodMs, defaultTTL, speculativeRetry, indexInterval, minIndexInterval, maxIndexInterval, compaction, compression, crcCheckChance, extensions, cdc); diff --git a/driver-core/src/main/java/com/datastax/driver/core/TokenRange.java b/driver-core/src/main/java/com/datastax/driver/core/TokenRange.java index 3b91c638075..81c9b1bc1c7 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/TokenRange.java +++ b/driver-core/src/main/java/com/datastax/driver/core/TokenRange.java @@ -15,8 +15,8 @@ */ package com.datastax.driver.core; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; @@ -295,15 +295,15 @@ public boolean equals(Object other) { return true; if (other instanceof TokenRange) { TokenRange that = (TokenRange) other; - return Objects.equal(this.start, that.start) && - Objects.equal(this.end, that.end); + return MoreObjects.equal(this.start, that.start) && + MoreObjects.equal(this.end, that.end); } return false; } @Override public int hashCode() { - return Objects.hashCode(start, end); + return MoreObjects.hashCode(start, end); } @Override diff --git a/driver-core/src/main/java/com/datastax/driver/core/TypeCodec.java b/driver-core/src/main/java/com/datastax/driver/core/TypeCodec.java index 4af6073848b..b58c98cf3d1 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/TypeCodec.java +++ b/driver-core/src/main/java/com/datastax/driver/core/TypeCodec.java @@ -23,6 +23,7 @@ import java.io.DataInput; import java.io.IOException; +import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; @@ -627,7 +628,7 @@ public boolean accepts(DataType cqlType) { * Implementation notes: *

    *
  1. The default implementation is covariant with respect to the passed - * argument (through the usage of {@link TypeToken#isAssignableFrom(TypeToken)} + * argument (through the usage of {@link TypeToken#isAssignableFrom(TypeToken)} or {@link TypeToken#isSupertypeOf(Type)}) * and it's strongly recommended not to modify this behavior. * This means that, by default, a codec will accept * any subtype of the Java type that it has been created for.
  2. @@ -647,7 +648,7 @@ public boolean accepts(DataType cqlType) { */ public boolean accepts(Object value) { checkNotNull(value, "Parameter value cannot be null"); - return this.javaType.isAssignableFrom(TypeToken.of(value.getClass())); + return GuavaCompatibility.INSTANCE.isSupertypeOf(this.javaType, TypeToken.of(value.getClass())); } @Override diff --git a/driver-core/src/main/java/com/datastax/driver/core/VersionNumber.java b/driver-core/src/main/java/com/datastax/driver/core/VersionNumber.java index 4dd4012d625..2efa03f136d 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/VersionNumber.java +++ b/driver-core/src/main/java/com/datastax/driver/core/VersionNumber.java @@ -15,7 +15,7 @@ */ package com.datastax.driver.core; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import java.util.Arrays; import java.util.Collections; @@ -228,12 +228,12 @@ public boolean equals(Object other) { && this.patch == that.patch && this.dsePatch == that.dsePatch && (this.preReleases == null ? that.preReleases == null : Arrays.equals(this.preReleases, that.preReleases)) - && Objects.equal(this.build, that.build); + && MoreObjects.equal(this.build, that.build); } @Override public int hashCode() { - return Objects.hashCode(major, minor, patch, dsePatch, preReleases, build); + return MoreObjects.hashCode(major, minor, patch, dsePatch, preReleases, build); } @Override diff --git a/driver-core/src/main/java/com/datastax/driver/core/policies/Policies.java b/driver-core/src/main/java/com/datastax/driver/core/policies/Policies.java index 943eb454781..20ede451e01 100644 --- a/driver-core/src/main/java/com/datastax/driver/core/policies/Policies.java +++ b/driver-core/src/main/java/com/datastax/driver/core/policies/Policies.java @@ -17,7 +17,6 @@ import com.datastax.driver.core.AtomicMonotonicTimestampGenerator; import com.datastax.driver.core.TimestampGenerator; -import com.google.common.base.Objects; /** * Policies configured for a {@link com.datastax.driver.core.Cluster} instance. @@ -280,12 +279,12 @@ public Builder withSpeculativeExecutionPolicy(SpeculativeExecutionPolicy specula */ public Policies build() { return new Policies( - loadBalancingPolicy == null ? Policies.defaultLoadBalancingPolicy() : loadBalancingPolicy, - Objects.firstNonNull(reconnectionPolicy, Policies.defaultReconnectionPolicy()), - Objects.firstNonNull(retryPolicy, Policies.defaultRetryPolicy()), - Objects.firstNonNull(addressTranslator, Policies.defaultAddressTranslator()), - Objects.firstNonNull(timestampGenerator, Policies.defaultTimestampGenerator()), - Objects.firstNonNull(speculativeExecutionPolicy, Policies.defaultSpeculativeExecutionPolicy())); + loadBalancingPolicy == null ? defaultLoadBalancingPolicy() : loadBalancingPolicy, + reconnectionPolicy == null ? defaultReconnectionPolicy() : reconnectionPolicy, + retryPolicy == null ? defaultRetryPolicy() : retryPolicy, + addressTranslator == null ? defaultAddressTranslator() : addressTranslator, + timestampGenerator == null ? defaultTimestampGenerator() : timestampGenerator, + speculativeExecutionPolicy == null ? defaultSpeculativeExecutionPolicy() : speculativeExecutionPolicy); } } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/schemabuilder/Create.java b/driver-core/src/main/java/com/datastax/driver/core/schemabuilder/Create.java index 6e6b07274a9..101473bf8b4 100755 --- a/driver-core/src/main/java/com/datastax/driver/core/schemabuilder/Create.java +++ b/driver-core/src/main/java/com/datastax/driver/core/schemabuilder/Create.java @@ -16,8 +16,8 @@ package com.datastax.driver.core.schemabuilder; import com.datastax.driver.core.DataType; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.base.Joiner; -import com.google.common.base.Objects; import com.google.common.base.Optional; import com.google.common.collect.Lists; @@ -238,14 +238,14 @@ public boolean equals(Object o) { } if (o instanceof ClusteringOrder) { ClusteringOrder that = (ClusteringOrder) o; - return Objects.equal(this.clusteringColumnName, that.clusteringColumnName) && Objects.equal(this.direction, that.direction); + return MoreObjects.equal(this.clusteringColumnName, that.clusteringColumnName) && MoreObjects.equal(this.direction, that.direction); } return false; } @Override public int hashCode() { - return Objects.hashCode(clusteringColumnName, direction); + return MoreObjects.hashCode(clusteringColumnName, direction); } } diff --git a/driver-core/src/main/java/com/datastax/driver/core/utils/MoreObjects.java b/driver-core/src/main/java/com/datastax/driver/core/utils/MoreObjects.java new file mode 100644 index 00000000000..4e7b32d1285 --- /dev/null +++ b/driver-core/src/main/java/com/datastax/driver/core/utils/MoreObjects.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012-2015 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.utils; + +import java.util.Arrays; + +/** + * Driver-specific implementation of utility object methods. + *

    + * They are available in some versions of Java/Guava, but not across all versions ranges supported by the driver, hence + * the custom implementation. + */ +public class MoreObjects { + public static boolean equal(Object first, Object second) { + return (first == second) || (first != null && first.equals(second)); + } + + public static int hashCode(Object... objects) { + return Arrays.hashCode(objects); + } +} diff --git a/driver-core/src/test/java/com/datastax/driver/core/AsyncQueryTest.java b/driver-core/src/test/java/com/datastax/driver/core/AsyncQueryTest.java index a7f1a58ab66..1054a767109 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/AsyncQueryTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/AsyncQueryTest.java @@ -97,7 +97,7 @@ public void should_init_cluster_and_session_if_needed() throws Exception { @Test(groups = "short", dataProvider = "keyspace", enabled = false, description = "disabled because the blocking USE call in the current pool implementation makes it deadlock") public void should_chain_query_on_async_session_init_with_same_executor(String keyspace) throws Exception { - ListenableFuture resultFuture = connectAndQuery(keyspace, MoreExecutors.sameThreadExecutor()); + ListenableFuture resultFuture = connectAndQuery(keyspace, GuavaCompatibility.INSTANCE.sameThreadExecutor()); Integer result = Uninterruptibles.getUninterruptibly(resultFuture); assertThat(result).isEqualTo(1); @@ -117,7 +117,7 @@ public void should_chain_query_on_async_session_init_with_different_executor(Str @Test(groups = "short") public void should_propagate_error_to_chained_query_if_session_init_fails() throws Exception { - ListenableFuture resultFuture = connectAndQuery("wrong_keyspace", MoreExecutors.sameThreadExecutor()); + ListenableFuture resultFuture = connectAndQuery("wrong_keyspace", GuavaCompatibility.INSTANCE.sameThreadExecutor()); try { Uninterruptibles.getUninterruptibly(resultFuture); @@ -209,7 +209,7 @@ private boolean isFailed(ListenableFuture future, Class expectedExcep private ListenableFuture connectAndQuery(String keyspace, Executor executor) { ListenableFuture sessionFuture = cluster().connectAsync(keyspace); - ListenableFuture queryFuture = Futures.transform(sessionFuture, new AsyncFunction() { + ListenableFuture queryFuture = GuavaCompatibility.INSTANCE.transformAsync(sessionFuture, new AsyncFunction() { @Override public ListenableFuture apply(Session session) throws Exception { return session.executeAsync("select v from foo where k = 1"); diff --git a/driver-core/src/test/java/com/datastax/driver/core/AsyncResultSetTest.java b/driver-core/src/test/java/com/datastax/driver/core/AsyncResultSetTest.java index 5074c9cfab2..fd440c25758 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/AsyncResultSetTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/AsyncResultSetTest.java @@ -58,7 +58,7 @@ private void should_iterate_result_set_asynchronously(int totalCount, int fetchS Statement statement = new SimpleStatement("select * from ints").setFetchSize(fetchSize); ResultsAccumulator results = new ResultsAccumulator(); - ListenableFuture future = Futures.transform( + ListenableFuture future = GuavaCompatibility.INSTANCE.transformAsync( session().executeAsync(statement), results); @@ -85,7 +85,7 @@ public ListenableFuture apply(ResultSet rs) throws Exception { if (wasLastPage) return Futures.immediateFuture(rs); else - return Futures.transform(rs.fetchMoreResults(), this); + return GuavaCompatibility.INSTANCE.transformAsync(rs.fetchMoreResults(), this); } } } diff --git a/driver-core/src/test/java/com/datastax/driver/core/ConnectionReleaseTest.java b/driver-core/src/test/java/com/datastax/driver/core/ConnectionReleaseTest.java index 9b27359f084..4aa06e7f7ed 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/ConnectionReleaseTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/ConnectionReleaseTest.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.scassandra.http.client.PrimingRequest; import org.testng.annotations.Test; @@ -97,7 +96,7 @@ public void should_release_connection_before_completing_future() throws Exceptio mockFutures.add(session.executeAsync("mock query")); - ListenableFuture future = Futures.transform(session.executeAsync("select c from test1 where k=1"), + ListenableFuture future = GuavaCompatibility.INSTANCE.transformAsync(session.executeAsync("select c from test1 where k=1"), new AsyncFunction() { @Override public ListenableFuture apply(ResultSet result) { diff --git a/driver-core/src/test/java/com/datastax/driver/core/LoadBalancingPolicyBootstrapTest.java b/driver-core/src/test/java/com/datastax/driver/core/LoadBalancingPolicyBootstrapTest.java index 20aac776a3d..ca649db9f93 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/LoadBalancingPolicyBootstrapTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/LoadBalancingPolicyBootstrapTest.java @@ -18,6 +18,7 @@ import com.datastax.driver.core.policies.DelegatingLoadBalancingPolicy; import com.datastax.driver.core.policies.LoadBalancingPolicy; import com.datastax.driver.core.policies.RoundRobinPolicy; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.Lists; import org.slf4j.Logger; @@ -156,12 +157,12 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(action, host); + return MoreObjects.hashCode(action, host); } @Override public String toString() { - return Objects.toStringHelper(this).add("action", action).add("host", host).toString(); + return String.format("Entry(action=%s, host=%s)", action, host); } } diff --git a/driver-core/src/test/java/com/datastax/driver/core/TableMetadataCDCTest.java b/driver-core/src/test/java/com/datastax/driver/core/TableMetadataCDCTest.java index 00cadee257d..6c1bc3cfe6a 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/TableMetadataCDCTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/TableMetadataCDCTest.java @@ -20,8 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat; -@CCMConfig(config = {"cdc_enabled:true"}) -@CassandraVersion(major = 3.8, description = "Requires CASSANDRA-12041 added in 3.8") +@CCMConfig(config = "cdc_enabled:true") +@CassandraVersion(value = "3.8", description = "Requires CASSANDRA-12041 added in 3.8") public class TableMetadataCDCTest extends CCMTestsSupport { /** diff --git a/driver-core/src/test/java/com/datastax/driver/core/TypeCodecEncapsulationIntegrationTest.java b/driver-core/src/test/java/com/datastax/driver/core/TypeCodecEncapsulationIntegrationTest.java index 8d278d82517..de3fd0578d4 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/TypeCodecEncapsulationIntegrationTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/TypeCodecEncapsulationIntegrationTest.java @@ -18,7 +18,7 @@ import com.datastax.driver.core.exceptions.InvalidTypeException; import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.utils.CassandraVersion; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.reflect.TypeParameter; import com.google.common.reflect.TypeToken; import org.testng.annotations.BeforeMethod; @@ -274,12 +274,12 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; NumberBox numberBox = (NumberBox) o; - return Objects.equal(number, numberBox.number); + return MoreObjects.equal(number, numberBox.number); } @Override public int hashCode() { - return Objects.hashCode(number); + return MoreObjects.hashCode(number); } } } diff --git a/driver-core/src/test/java/com/datastax/driver/core/TypeCodecNestedCollectionsIntegrationTest.java b/driver-core/src/test/java/com/datastax/driver/core/TypeCodecNestedCollectionsIntegrationTest.java index 25b2e44abe6..07306c47d3b 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/TypeCodecNestedCollectionsIntegrationTest.java +++ b/driver-core/src/test/java/com/datastax/driver/core/TypeCodecNestedCollectionsIntegrationTest.java @@ -18,7 +18,7 @@ import com.datastax.driver.core.exceptions.InvalidTypeException; import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.utils.CassandraVersion; -import com.google.common.base.Objects; +import com.datastax.driver.core.utils.MoreObjects; import com.google.common.collect.ImmutableMap; import com.google.common.reflect.TypeToken; import org.testng.annotations.BeforeClass; @@ -168,12 +168,12 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; MyInt myInt = (MyInt) o; - return Objects.equal(i, myInt.i); + return MoreObjects.equal(i, myInt.i); } @Override public int hashCode() { - return Objects.hashCode(i); + return MoreObjects.hashCode(i); } } diff --git a/driver-core/src/test/java/com/datastax/driver/core/policies/LimitingLoadBalancingPolicy.java b/driver-core/src/test/java/com/datastax/driver/core/policies/LimitingLoadBalancingPolicy.java index 8628257cfc7..8b869cdd784 100644 --- a/driver-core/src/test/java/com/datastax/driver/core/policies/LimitingLoadBalancingPolicy.java +++ b/driver-core/src/test/java/com/datastax/driver/core/policies/LimitingLoadBalancingPolicy.java @@ -19,7 +19,6 @@ import com.datastax.driver.core.Host; import com.datastax.driver.core.HostDistance; import com.datastax.driver.core.Statement; -import com.google.common.collect.Sets; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -40,8 +39,8 @@ public class LimitingLoadBalancingPolicy extends DelegatingLoadBalancingPolicy { private final int maxHosts; private final int threshold; - private final Set liveHosts = Sets.newSetFromMap(new ConcurrentHashMap()); - private final Set chosenHosts = Sets.newSetFromMap(new ConcurrentHashMap()); + private final Set liveHosts = Collections.newSetFromMap(new ConcurrentHashMap()); + private final Set chosenHosts = Collections.newSetFromMap(new ConcurrentHashMap()); private final Lock updateLock = new ReentrantLock(); private volatile Cluster cluster; diff --git a/driver-core/src/test/resources/log4j.properties b/driver-core/src/test/resources/log4j.properties index 12786f47391..8f9c901dcdb 100644 --- a/driver-core/src/test/resources/log4j.properties +++ b/driver-core/src/test/resources/log4j.properties @@ -31,6 +31,7 @@ log4j.logger.spray.can=ERROR #log4j.logger.org.scassandra.http.client=ERROR # These loggers can be quite verbose +log4j.logger.com.datastax.driver.core=INFO log4j.logger.com.datastax.driver.core.Cluster=ERROR log4j.logger.com.datastax.driver.core.policies.DCAwareRoundRobinPolicy=ERROR diff --git a/driver-extras/pom.xml b/driver-extras/pom.xml index f7ec269f27d..197c04906a5 100644 --- a/driver-extras/pom.xml +++ b/driver-extras/pom.xml @@ -230,7 +230,7 @@ com.datastax.driver.extras ${project.version} <_include>-osgi.bnd - + jar diff --git a/driver-extras/src/test/java/com/datastax/driver/extras/codecs/json/JacksonJsonCodecTest.java b/driver-extras/src/test/java/com/datastax/driver/extras/codecs/json/JacksonJsonCodecTest.java index b7688bc0a25..cb172cb75c9 100644 --- a/driver-extras/src/test/java/com/datastax/driver/extras/codecs/json/JacksonJsonCodecTest.java +++ b/driver-extras/src/test/java/com/datastax/driver/extras/codecs/json/JacksonJsonCodecTest.java @@ -18,9 +18,9 @@ import com.datastax.driver.core.*; import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.utils.CassandraVersion; +import com.datastax.driver.core.utils.MoreObjects; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.base.Objects; import com.google.common.collect.Lists; import org.testng.annotations.Test; @@ -204,13 +204,13 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; User user = (User) o; - return Objects.equal(id, user.id) && - Objects.equal(name, user.name); + return MoreObjects.equal(id, user.id) && + MoreObjects.equal(name, user.name); } @Override public int hashCode() { - return Objects.hashCode(id, name); + return MoreObjects.hashCode(id, name); } } } diff --git a/driver-mapping/pom.xml b/driver-mapping/pom.xml index 9c3aaf07217..a96ddf9974a 100644 --- a/driver-mapping/pom.xml +++ b/driver-mapping/pom.xml @@ -158,7 +158,7 @@ com.datastax.driver.mapping ${project.version} <_include>-osgi.bnd - + jar diff --git a/driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java b/driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java index 80eb804f6ea..699e8fbc2ff 100644 --- a/driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java +++ b/driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java @@ -19,12 +19,12 @@ import com.datastax.driver.core.querybuilder.Delete; import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.mapping.Mapper.Option.SaveNullFields; import com.datastax.driver.mapping.annotations.Accessor; import com.datastax.driver.mapping.annotations.Computed; import com.google.common.base.Function; import com.google.common.base.Functions; -import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.*; import org.slf4j.Logger; @@ -324,7 +324,7 @@ public ListenableFuture saveAsync(T entity, Option... options) { } private ListenableFuture submitVoidQueryAsync(ListenableFuture bsFuture) { - ListenableFuture rsFuture = Futures.transform(bsFuture, new AsyncFunction() { + ListenableFuture rsFuture = GuavaCompatibility.INSTANCE.transformAsync(bsFuture, new AsyncFunction() { @Override public ListenableFuture apply(BoundStatement bs) throws Exception { return session().executeAsync(bs); @@ -449,7 +449,7 @@ public T get(Object... objects) { */ public ListenableFuture getAsync(final Object... objects) { ListenableFuture bsFuture = getQueryAsync(objects); - ListenableFuture rsFuture = Futures.transform(bsFuture, new AsyncFunction() { + ListenableFuture rsFuture = GuavaCompatibility.INSTANCE.transformAsync(bsFuture, new AsyncFunction() { @Override public ListenableFuture apply(BoundStatement bs) throws Exception { return session().executeAsync(bs); @@ -1161,7 +1161,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(queryType, optionTypes, columns); + return MoreObjects.hashCode(queryType, optionTypes, columns); } } } diff --git a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncTest.java b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncTest.java index a57a1cf3e27..4087c77da6d 100644 --- a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncTest.java +++ b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncTest.java @@ -19,12 +19,12 @@ import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; import com.datastax.driver.core.utils.MoreFutures.SuccessCallback; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.mapping.annotations.Column; import com.datastax.driver.mapping.annotations.PartitionKey; import com.datastax.driver.mapping.annotations.Table; import com.google.common.base.Function; -import com.google.common.base.Objects; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.Uninterruptibles; @@ -172,14 +172,14 @@ public boolean equals(Object other) { return false; User that = (User) other; - return Objects.equal(userId, that.userId) - && Objects.equal(name, that.name) - && Objects.equal(email, that.email); + return MoreObjects.equal(userId, that.userId) + && MoreObjects.equal(name, that.name) + && MoreObjects.equal(email, that.email); } @Override public int hashCode() { - return Objects.hashCode(userId, name, email); + return MoreObjects.hashCode(userId, name, email); } } diff --git a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperDefaultKeyspaceTest.java b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperDefaultKeyspaceTest.java index 7fa9e7bfaf1..6a820125737 100644 --- a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperDefaultKeyspaceTest.java +++ b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperDefaultKeyspaceTest.java @@ -18,9 +18,9 @@ import com.datastax.driver.core.CCMTestsSupport; import com.datastax.driver.core.Session; import com.datastax.driver.core.utils.CassandraVersion; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.mapping.annotations.*; -import com.google.common.base.Objects; import org.testng.annotations.Test; import java.util.UUID; @@ -152,13 +152,13 @@ public boolean equals(Object other) { return false; Group that = (Group) other; - return Objects.equal(groupId, that.groupId) - && Objects.equal(name, that.name); + return MoreObjects.equal(groupId, that.groupId) + && MoreObjects.equal(name, that.name); } @Override public int hashCode() { - return Objects.hashCode(groupId, name); + return MoreObjects.hashCode(groupId, name); } } @@ -202,13 +202,13 @@ public boolean equals(Object other) { return false; Group2 that = (Group2) other; - return Objects.equal(groupId, that.groupId) - && Objects.equal(name, that.name); + return MoreObjects.equal(groupId, that.groupId) + && MoreObjects.equal(name, that.name); } @Override public int hashCode() { - return Objects.hashCode(groupId, name); + return MoreObjects.hashCode(groupId, name); } } @@ -246,7 +246,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(name); + return MoreObjects.hashCode(name); } } diff --git a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperTest.java b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperTest.java index 257408e6c0c..751ec0a9847 100644 --- a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperTest.java +++ b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperTest.java @@ -17,9 +17,9 @@ import com.datastax.driver.core.*; import com.datastax.driver.core.utils.CassandraVersion; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.mapping.annotations.*; -import com.google.common.base.Objects; import com.google.common.util.concurrent.ListenableFuture; import org.testng.annotations.Test; @@ -122,15 +122,15 @@ public boolean equals(Object other) { return false; User that = (User) other; - return Objects.equal(userId, that.userId) - && Objects.equal(name, that.name) - && Objects.equal(email, that.email) - && Objects.equal(year, that.year); + return MoreObjects.equal(userId, that.userId) + && MoreObjects.equal(name, that.name) + && MoreObjects.equal(email, that.email) + && MoreObjects.equal(year, that.year); } @Override public int hashCode() { - return Objects.hashCode(userId, name, email, year); + return MoreObjects.hashCode(userId, name, email, year); } } @@ -222,17 +222,17 @@ public boolean equals(Object other) { return false; Post that = (Post) other; - return Objects.equal(userId, that.userId) - && Objects.equal(postId, that.postId) - && Objects.equal(title, that.title) - && Objects.equal(content, that.content) - && Objects.equal(device, that.device) - && Objects.equal(tags, that.tags); + return MoreObjects.equal(userId, that.userId) + && MoreObjects.equal(postId, that.postId) + && MoreObjects.equal(title, that.title) + && MoreObjects.equal(content, that.content) + && MoreObjects.equal(device, that.device) + && MoreObjects.equal(tags, that.tags); } @Override public int hashCode() { - return Objects.hashCode(userId, postId, title, content, device, tags); + return MoreObjects.hashCode(userId, postId, title, content, device, tags); } } diff --git a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTCollectionsTest.java b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTCollectionsTest.java index 58ce1267b64..90aa474aeb7 100644 --- a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTCollectionsTest.java +++ b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTCollectionsTest.java @@ -17,8 +17,8 @@ import com.datastax.driver.core.CCMTestsSupport; import com.datastax.driver.core.utils.CassandraVersion; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.mapping.annotations.*; -import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import org.testng.annotations.Test; @@ -78,7 +78,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hashCode(i); + return MoreObjects.hashCode(i); } } @@ -170,12 +170,12 @@ public void setM3(Map m3) { public boolean equals(Object other) { if (other instanceof CollectionExamples) { CollectionExamples that = (CollectionExamples) other; - return Objects.equal(this.id, that.id) && - Objects.equal(this.l, that.l) && - Objects.equal(this.s, that.s) && - Objects.equal(this.m1, that.m1) && - Objects.equal(this.m2, that.m2) && - Objects.equal(this.m3, that.m3); + return MoreObjects.equal(this.id, that.id) && + MoreObjects.equal(this.l, that.l) && + MoreObjects.equal(this.s, that.s) && + MoreObjects.equal(this.m1, that.m1) && + MoreObjects.equal(this.m2, that.m2) && + MoreObjects.equal(this.m3, that.m3); } return false; } diff --git a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTTest.java b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTTest.java index d6452bd095c..d3933694ad9 100644 --- a/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTTest.java +++ b/driver-mapping/src/test/java/com/datastax/driver/mapping/MapperUDTTest.java @@ -20,9 +20,9 @@ import com.datastax.driver.core.exceptions.InvalidQueryException; import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.utils.CassandraVersion; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.mapping.annotations.*; -import com.google.common.base.Objects; import com.google.common.collect.Maps; import org.assertj.core.data.MapEntry; import org.testng.annotations.AfterMethod; @@ -123,27 +123,23 @@ public boolean equals(Object other) { return true; if (other instanceof User) { User that = (User) other; - return Objects.equal(this.userId, that.userId) && - Objects.equal(this.name, that.name) && - Objects.equal(this.mainAddress, that.mainAddress) && - Objects.equal(this.otherAddresses, that.otherAddresses); + return MoreObjects.equal(this.userId, that.userId) && + MoreObjects.equal(this.name, that.name) && + MoreObjects.equal(this.mainAddress, that.mainAddress) && + MoreObjects.equal(this.otherAddresses, that.otherAddresses); } return false; } @Override public int hashCode() { - return Objects.hashCode(this.userId, this.name, this.mainAddress, this.otherAddresses); + return MoreObjects.hashCode(this.userId, this.name, this.mainAddress, this.otherAddresses); } @Override public String toString() { - return Objects.toStringHelper(User.class) - .add("userId", userId) - .add("name", name) - .add("mainAddress", mainAddress) - .add("otherAddresses", otherAddresses) - .toString(); + return String.format("User(userId=%s, name=%s, mainAddress=%s, otherAddresses=%s)", + userId, name, mainAddress, otherAddresses); } } @@ -213,27 +209,23 @@ public boolean equals(Object other) { return true; if (other instanceof Address) { Address that = (Address) other; - return Objects.equal(this.street, that.street) && - Objects.equal(this.city, that.city) && - Objects.equal(this.zipCode, that.zipCode) && - Objects.equal(this.phones, that.phones); + return MoreObjects.equal(this.street, that.street) && + MoreObjects.equal(this.city, that.city) && + MoreObjects.equal(this.zipCode, that.zipCode) && + MoreObjects.equal(this.phones, that.phones); } return false; } @Override public int hashCode() { - return Objects.hashCode(this.street, this.city, this.zipCode, this.phones); + return MoreObjects.hashCode(this.street, this.city, this.zipCode, this.phones); } @Override public String toString() { - return Objects.toStringHelper(Address.class) - .add("street", street) - .add("city", city) - .add("zip", zipCode) - .add("phones", phones) - .toString(); + return String.format("Address(street=%s, city=%s, zip=%d, phones=%s)", + street, city, zipCode, phones); } } diff --git a/driver-tests/osgi/README.md b/driver-tests/osgi/README.md index 6a495a387a8..b01ed55f05f 100644 --- a/driver-tests/osgi/README.md +++ b/driver-tests/osgi/README.md @@ -45,6 +45,7 @@ configurations: 1. Default (default classifier with all dependencies) 2. Netty-Shaded (shaded classifier with all dependencies w/o Netty) -5. Guava 17 -6. Guava 18 -7. Guava 19 +3. Guava 17 +4. Guava 18 +5. Guava 19 +6. Guava 20 diff --git a/driver-tests/osgi/pom.xml b/driver-tests/osgi/pom.xml index 8322b8923b9..25423e9adab 100644 --- a/driver-tests/osgi/pom.xml +++ b/driver-tests/osgi/pom.xml @@ -229,7 +229,7 @@ com.datastax.driver.osgi.api,!com.datastax.driver.osgi.impl com.datastax.driver.osgi.impl.Activator <_include>-osgi.bnd - + jar diff --git a/driver-tests/osgi/src/main/java/com/datastax/driver/osgi/api/MailboxMessage.java b/driver-tests/osgi/src/main/java/com/datastax/driver/osgi/api/MailboxMessage.java index e2b9055c07b..10ca08b12ee 100644 --- a/driver-tests/osgi/src/main/java/com/datastax/driver/osgi/api/MailboxMessage.java +++ b/driver-tests/osgi/src/main/java/com/datastax/driver/osgi/api/MailboxMessage.java @@ -15,12 +15,12 @@ */ package com.datastax.driver.osgi.api; +import com.datastax.driver.core.utils.MoreObjects; import com.datastax.driver.extras.codecs.date.SimpleTimestampCodec; import com.datastax.driver.mapping.annotations.ClusteringColumn; import com.datastax.driver.mapping.annotations.Column; import com.datastax.driver.mapping.annotations.PartitionKey; import com.datastax.driver.mapping.annotations.Table; -import com.google.common.base.Objects; import static com.datastax.driver.osgi.api.MailboxMessage.TABLE; @@ -94,13 +94,13 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; MailboxMessage that = (MailboxMessage) o; return date == that.date && - Objects.equal(recipient, that.recipient) && - Objects.equal(sender, that.sender) && - Objects.equal(body, that.body); + MoreObjects.equal(recipient, that.recipient) && + MoreObjects.equal(sender, that.sender) && + MoreObjects.equal(body, that.body); } @Override public int hashCode() { - return Objects.hashCode(recipient, date, sender, body); + return MoreObjects.hashCode(recipient, date, sender, body); } } diff --git a/driver-tests/osgi/src/test/java/com/datastax/driver/osgi/MailboxServiceGuava20IT.java b/driver-tests/osgi/src/test/java/com/datastax/driver/osgi/MailboxServiceGuava20IT.java new file mode 100644 index 00000000000..833d71380f1 --- /dev/null +++ b/driver-tests/osgi/src/test/java/com/datastax/driver/osgi/MailboxServiceGuava20IT.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012-2015 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.osgi; + +import com.datastax.driver.osgi.api.MailboxException; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.testng.listener.PaxExam; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import static com.datastax.driver.osgi.BundleOptions.*; +import static org.ops4j.pax.exam.CoreOptions.options; + +@Listeners({CCMBridgeListener.class, PaxExam.class}) +public class MailboxServiceGuava20IT extends MailboxServiceTests { + + @Configuration + public Option[] guava20Config() { + return options( + defaultOptions(), + nettyBundles(), + guavaBundle().version("20.0"), + driverBundle(), + extrasBundle(), + mappingBundle(), + mailboxBundle() + ); + } + + /** + * Exercises a 'mailbox' service provided by an OSGi bundle that depends on the driver with + * Guava 20 explicitly enforced. + * + * @test_category packaging + * @expected_result Can create, retrieve and delete data using the mailbox service. + * @jira_ticket JAVA-620 + * @since 2.0.10, 2.1.5 + */ + @Test(groups = "short") + public void test_guava_20() throws MailboxException { + checkService(); + } +} diff --git a/manual/async/README.md b/manual/async/README.md index 7c71cfcd148..c834abbfe8a 100644 --- a/manual/async/README.md +++ b/manual/async/README.md @@ -133,6 +133,6 @@ There are still a few places where the driver will block internally * trying to read fields from a [query trace] will block if the trace hasn't been fetched already. -[ListenableFuture]: https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained +[ListenableFuture]: https://github.com/google/guava/wiki/ListenableFutureExplained [init]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Cluster.html#init-- [query trace]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/QueryTrace.html diff --git a/pom.xml b/pom.xml index 8a7b5a52e76..486b7ebfc11 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 1.6 1.2.17 1.7.6 - 16.0.1 + 19.0 4.1.8.Final 3.1.2 1.1.2.6 @@ -247,7 +247,7 @@ https://docs.oracle.com/javase/8/docs/api/ - http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/ + https://google.github.io/guava/releases/19.0/api/docs/ http://netty.io/4.0/api/ http://www.joda.org/joda-time/apidocs/ diff --git a/upgrade_guide/README.md b/upgrade_guide/README.md index 53cb3d0c6d7..1cce9a7610d 100644 --- a/upgrade_guide/README.md +++ b/upgrade_guide/README.md @@ -116,7 +116,7 @@ We've also seized the opportunity to remove code that was deprecated in 2.1. for `null` inputs. 3. The driver now depends on Guava 16.0.1 (instead of 14.0.1). - This update has been mainly motivated by Guava's [Issue #1635](https://code.google.com/p/guava-libraries/issues/detail?id=1635), + This update has been mainly motivated by Guava's [Issue #1635](https://github.com/google/guava/issues/1635), which affects `TypeToken`, and hence all `TypeCodec` implementations handling parameterized types. 4. `UDTMapper` (the type previously used to convert `@UDT`-annotated