DRILL-7494: Unable to connect to Drill using JDBC driver when using custom authenticator
closes #1938
diff --git a/common/src/main/java/org/apache/drill/common/util/GuavaPatcher.java b/common/src/main/java/org/apache/drill/common/util/GuavaPatcher.java
index 5924df8..a618d05 100644
--- a/common/src/main/java/org/apache/drill/common/util/GuavaPatcher.java
+++ b/common/src/main/java/org/apache/drill/common/util/GuavaPatcher.java
@@ -29,6 +29,8 @@
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewMethod;
+import javassist.scopedpool.ScopedClassPoolRepository;
+import javassist.scopedpool.ScopedClassPoolRepositoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +53,7 @@
*/
private static void patchStopwatch() {
try {
- ClassPool cp = ClassPool.getDefault();
+ ClassPool cp = getClassPool();
CtClass cc = cp.get("com.google.common.base.Stopwatch");
// Expose the constructor for Stopwatch for old libraries who use the pattern new Stopwatch().start().
@@ -77,7 +79,7 @@
private static void patchCloseables() {
try {
- ClassPool cp = ClassPool.getDefault();
+ ClassPool cp = getClassPool();
CtClass cc = cp.get("com.google.common.io.Closeables");
// Add back the Closeables.closeQuietly() method for old consumers.
@@ -100,7 +102,7 @@
*/
private static void patchPreconditions() {
try {
- ClassPool cp = ClassPool.getDefault();
+ ClassPool cp = getClassPool();
CtClass cc = cp.get("com.google.common.base.Preconditions");
// Javassist does not support varargs, generate methods with varying number of arguments
@@ -192,4 +194,17 @@
logger.warn("Unable to patch Guava classes.", e);
}
}
+
+ /**
+ * Returns {@link javassist.scopedpool.ScopedClassPool} instance which uses the same class loader
+ * which was used for loading current class.
+ *
+ * @return {@link javassist.scopedpool.ScopedClassPool} instance
+ */
+ private static ClassPool getClassPool() {
+ ScopedClassPoolRepository classPoolRepository = ScopedClassPoolRepositoryImpl.getInstance();
+ // sets prune flag to false to avoid freezing and pruning classes right after obtaining CtClass instance
+ classPoolRepository.setPrune(false);
+ return classPoolRepository.createScopedClassPool(GuavaPatcher.class.getClassLoader(), null);
+ }
}
diff --git a/common/src/main/java/org/apache/drill/common/util/ProtobufPatcher.java b/common/src/main/java/org/apache/drill/common/util/ProtobufPatcher.java
index 3556eec..f8b6c51 100644
--- a/common/src/main/java/org/apache/drill/common/util/ProtobufPatcher.java
+++ b/common/src/main/java/org/apache/drill/common/util/ProtobufPatcher.java
@@ -25,6 +25,8 @@
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.Modifier;
+import javassist.scopedpool.ScopedClassPoolRepository;
+import javassist.scopedpool.ScopedClassPoolRepositoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,7 +56,7 @@
*/
private static void patchByteString() {
try {
- ClassPool classPool = ClassPool.getDefault();
+ ClassPool classPool = getClassPool();
CtClass byteString = classPool.get("com.google.protobuf.ByteString");
removeFinal(byteString.getDeclaredMethod("toString"));
removeFinal(byteString.getDeclaredMethod("hashCode"));
@@ -92,7 +94,7 @@
*/
private static void patchGeneratedMessageLite() {
try {
- ClassPool classPool = ClassPool.getDefault();
+ ClassPool classPool = getClassPool();
CtClass generatedMessageLite = classPool.get("com.google.protobuf.GeneratedMessageLite");
removeFinal(generatedMessageLite.getDeclaredMethod("getParserForType"));
removeFinal(generatedMessageLite.getDeclaredMethod("isInitialized"));
@@ -102,7 +104,8 @@
generatedMessageLite.addMethod(CtNewMethod.make("protected void makeExtensionsImmutable() { }", generatedMessageLite));
// A constructor with this signature was removed. Adding it back.
- generatedMessageLite.addConstructor(CtNewConstructor.make("protected GeneratedMessageLite(com.google.protobuf.GeneratedMessageLite.Builder builder) { }", generatedMessageLite));
+ String className = "com.google.protobuf.GeneratedMessageLite.Builder";
+ generatedMessageLite.addConstructor(CtNewConstructor.make("protected GeneratedMessageLite(" + className + " builder) { }", generatedMessageLite));
// This single method was added instead of several abstract methods.
// MapR-DB client doesn't use it, but it was added in overridden equals() method.
@@ -111,7 +114,8 @@
classPool.get("com.google.protobuf.GeneratedMessageLite$MethodToInvoke"),
classPool.get("java.lang.Object"),
classPool.get("java.lang.Object")});
- addImplementation(dynamicMethod, "if ($1.equals(com.google.protobuf.GeneratedMessageLite.MethodToInvoke.GET_DEFAULT_INSTANCE)) {" +
+ className = "com.google.protobuf.GeneratedMessageLite.MethodToInvoke";
+ addImplementation(dynamicMethod, "if ($1.equals(" + className + ".GET_DEFAULT_INSTANCE)) {" +
" return this;" +
"} else {" +
" return null;" +
@@ -130,7 +134,7 @@
*/
private static void patchGeneratedMessageLiteBuilder() {
try {
- ClassPool classPool = ClassPool.getDefault();
+ ClassPool classPool = getClassPool();
CtClass builder = classPool.get("com.google.protobuf.GeneratedMessageLite$Builder");
removeFinal(builder.getDeclaredMethod("isInitialized"));
removeFinal(builder.getDeclaredMethod("clear"));
@@ -183,4 +187,17 @@
int modifiers = Modifier.clear(ctMethod.getModifiers(), Modifier.ABSTRACT);
ctMethod.setModifiers(modifiers);
}
+
+ /**
+ * Returns {@link javassist.scopedpool.ScopedClassPool} instance which uses the same class loader
+ * which was used for loading current class.
+ *
+ * @return {@link javassist.scopedpool.ScopedClassPool} instance
+ */
+ private static ClassPool getClassPool() {
+ ScopedClassPoolRepository classPoolRepository = ScopedClassPoolRepositoryImpl.getInstance();
+ // sets prune flag to false to avoid freezing and pruning classes right after obtaining CtClass instance
+ classPoolRepository.setPrune(false);
+ return classPoolRepository.createScopedClassPool(ProtobufPatcher.class.getClassLoader(), null);
+ }
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
index dcb599b..c215a93 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
@@ -454,8 +454,8 @@
Thread.currentThread().setContextClassLoader(oldThreadCtxtCL);
startSaslHandshake(connectionHandler, saslProperties, ugi, factory, RpcType.SASL_MESSAGE);
- } catch (final IOException e) {
- logger.error("Failed while doing setup for starting SASL handshake for connection", connection.getName());
+ } catch (IOException e) {
+ logger.error("Failed while doing setup for starting SASL handshake for connection {}", connection.getName());
final Exception ex = new RpcException(String.format("Failed to initiate authentication for connection %s",
connection.getName()), e);
connectionHandler.connectionFailed(RpcConnectionHandler.FailureType.AUTHENTICATION, ex);
diff --git a/exec/jdbc-all/pom.xml b/exec/jdbc-all/pom.xml
index ab6bf7b..a4bd523 100644
--- a/exec/jdbc-all/pom.xml
+++ b/exec/jdbc-all/pom.xml
@@ -342,7 +342,6 @@
<exclude>commons-beanutils:commons-beanutils-core:jar:*</exclude>
<exclude>commons-beanutils:commons-beanutils:jar:*</exclude>
<exclude>io.netty:netty-tcnative:jar:*</exclude>
- <exclude>com.fasterxml.woodstox:woodstox-core:jar:*</exclude>
<exclude>com.google.code.findbugs:jsr305:*</exclude>
<exclude>com.esri.geometry:esri-geometry-api:*</exclude>
<exclude>fr.bmartel:pcapngdecoder:*</exclude>
@@ -409,7 +408,7 @@
<relocation><pattern>org.apache.xpath.</pattern><shadedPattern>oadd.org.apache.xpath.</shadedPattern></relocation>
<relocation><pattern>org.apache.zookeeper.</pattern><shadedPattern>oadd.org.apache.zookeeper.</shadedPattern></relocation>
<relocation><pattern>org.apache.hadoop.</pattern><shadedPattern>oadd.org.apache.hadoop.</shadedPattern></relocation>
- <relocation><pattern>com.fasterxml.woodstox.</pattern><shadedPattern>oadd.com.fasterxml.woodstox.</shadedPattern></relocation>
+ <relocation><pattern>com.ctc.wstx.</pattern><shadedPattern>oadd.com.ctc.wstx.</shadedPattern></relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/Driver.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/Driver.java
index 39e0ad1..6b8dd32 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/Driver.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/Driver.java
@@ -21,9 +21,10 @@
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
+import org.apache.drill.common.util.GuavaPatcher;
+import org.apache.drill.common.util.ProtobufPatcher;
import org.apache.drill.jdbc.impl.DriverImpl;
@@ -42,6 +43,8 @@
// DriverManager access it:
static {
+ ProtobufPatcher.patch();
+ GuavaPatcher.patch();
// Upon loading of class, register an instance with DriverManager.
try {
DriverManager.registerDriver(new Driver());
@@ -100,7 +103,7 @@
}
@Override
- public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ public java.util.logging.Logger getParentLogger() {
return impl.getParentLogger();
}
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ConnectionMultiListener.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ConnectionMultiListener.java
index 3fee5d7..3944a2c 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ConnectionMultiListener.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ConnectionMultiListener.java
@@ -77,7 +77,7 @@
private class ConnectionHandler implements GenericFutureListener<ChannelFuture> {
@Override
- public void operationComplete(ChannelFuture future) throws Exception {
+ public void operationComplete(ChannelFuture future) {
boolean isInterrupted = false;
// We want to wait for at least 120 secs when interrupts occur. Establishing a connection fails/succeeds quickly,
@@ -131,7 +131,7 @@
private class SSLConnectionHandler implements GenericFutureListener<Future<Channel>> {
@Override
- public void operationComplete(Future<Channel> future) throws Exception {
+ public void operationComplete(Future<Channel> future) {
// send the handshake
parent.send(handshakeSendHandler, handshakeValue, true);
}
@@ -165,9 +165,9 @@
} catch (NonTransientRpcException ex) {
logger.error("Failure while validating client and server sasl compatibility", ex);
connectionListener.connectionFailed(RpcConnectionHandler.FailureType.AUTHENTICATION, ex);
- } catch (Exception ex) {
- logger.error("Failure while validating handshake", ex);
- connectionListener.connectionFailed(RpcConnectionHandler.FailureType.HANDSHAKE_VALIDATION, ex);
+ } catch (Throwable t) {
+ logger.error("Failure while validating handshake", t);
+ connectionListener.connectionFailed(RpcConnectionHandler.FailureType.HANDSHAKE_VALIDATION, t);
}
}
diff --git a/pom.xml b/pom.xml
index fb6735c..224b615 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,7 +66,7 @@
<zookeeper.version>3.4.12</zookeeper.version>
<mapr.release.version>6.1.0-mapr</mapr.release.version>
<ojai.version>3.0-mapr-1808</ojai.version>
- <kerby.version>1.0.0-RC2</kerby.version>
+ <kerby.version>1.0.0</kerby.version>
<findbugs.version>3.0.0</findbugs.version>
<netty.tcnative.classifier />
<commons.io.version>2.4</commons.io.version>