[NO ISSUE][JDBC] Move ADBProtocol into asterix-jdbc-driver
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Move ADBProtocol from asterix-jdbc-core into asterix-jdbc-driver
- Remove httpclient depenedency from asterix-jdbc-core
Change-Id: Ic075b43248c076cb5c9c76092c60e110038df8e7
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb-clients/+/13666
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Ian Maxon <imaxon@uci.edu>
Tested-by: Ian Maxon <imaxon@uci.edu>
diff --git a/asterixdb-jdbc/asterix-jdbc-core/pom.xml b/asterixdb-jdbc/asterix-jdbc-core/pom.xml
index 143ce8e..59f4b11 100644
--- a/asterixdb-jdbc/asterix-jdbc-core/pom.xml
+++ b/asterixdb-jdbc/asterix-jdbc-core/pom.xml
@@ -42,14 +42,6 @@
<dependencies>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
- </dependency>
- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
diff --git a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBDriverBase.java b/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBDriverBase.java
index 904c18b..9bd8641 100644
--- a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBDriverBase.java
+++ b/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBDriverBase.java
@@ -21,7 +21,6 @@
import java.net.URI;
import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
@@ -40,9 +39,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-
public abstract class ADBDriverBase {
static final int JDBC_MAJOR_VERSION = 4;
@@ -72,18 +68,12 @@
}
}
- private static void parseConnectionProperties(List<NameValuePair> inProps1, Properties inProps2,
- ADBDriverContext driverContext, Map<ADBDriverProperty, Object> outProperties, SQLWarning outWarning)
- throws SQLException {
- for (NameValuePair pair : inProps1) {
- String name = pair.getName();
- String value = pair.getValue();
- parseConnectionProperty(name, value, driverContext, outProperties, outWarning);
- }
- if (inProps2 != null) {
- for (Enumeration<?> en = inProps2.propertyNames(); en.hasMoreElements();) {
+ private static void parseConnectionProperties(Properties inProps, ADBDriverContext driverContext,
+ Map<ADBDriverProperty, Object> outProperties, SQLWarning outWarning) throws SQLException {
+ if (inProps != null) {
+ for (Enumeration<?> en = inProps.propertyNames(); en.hasMoreElements();) {
String name = en.nextElement().toString();
- String value = inProps2.getProperty(name);
+ String value = inProps.getProperty(name);
parseConnectionProperty(name, value, driverContext, outProperties, outWarning);
}
}
@@ -156,12 +146,14 @@
port = defaultApiPort;
}
- List<NameValuePair> urlParams = URLEncodedUtils.parse(subUri, StandardCharsets.UTF_8);
+ Properties uriParams = getURIParameters(subUri);
ADBDriverContext driverContext = getOrCreateDriverContext();
- Map<ADBDriverProperty, Object> properties = new HashMap<>();
SQLWarning warning = new SQLWarning();
- parseConnectionProperties(urlParams, info, driverContext, properties, warning);
+ Map<ADBDriverProperty, Object> properties = new HashMap<>();
+ parseConnectionProperties(uriParams, driverContext, properties, warning);
+ parseConnectionProperties(info, driverContext, properties, warning);
+
warning = warning.getNextWarning() != null ? warning.getNextWarning() : null;
String path = subUri.getPath();
@@ -247,4 +239,6 @@
throws SQLException {
return new ADBConnection(protocol, url, databaseVersion, dataverseCanonicalName, properties, connectWarning);
}
+
+ protected abstract Properties getURIParameters(URI uri) throws SQLException;
}
diff --git a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBErrorReporter.java b/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBErrorReporter.java
index 4f409b7..8ae76f3 100644
--- a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBErrorReporter.java
+++ b/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBErrorReporter.java
@@ -28,161 +28,162 @@
import java.sql.SQLNonTransientConnectionException;
import java.sql.SQLTimeoutException;
import java.sql.SQLTransientConnectionException;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-import org.apache.http.conn.ConnectTimeoutException;
-
import com.fasterxml.jackson.core.JsonProcessingException;
-final class ADBErrorReporter {
+public class ADBErrorReporter {
- private static final List<Class<? extends IOException>> TRANSIENT_CONNECTION_ERRORS =
- Arrays.asList(java.net.NoRouteToHostException.class, org.apache.http.NoHttpResponseException.class,
- org.apache.http.conn.HttpHostConnectException.class);
-
- protected SQLException errorObjectClosed(Class<?> jdbcInterface) {
+ public SQLException errorObjectClosed(Class<?> jdbcInterface) {
return new SQLException(String.format("%s is closed", jdbcInterface.getSimpleName()));
}
- protected SQLFeatureNotSupportedException errorMethodNotSupported(Class<?> jdbcInterface, String methodName) {
+ public SQLFeatureNotSupportedException errorMethodNotSupported(Class<?> jdbcInterface, String methodName) {
return new SQLFeatureNotSupportedException(
String.format("Method %s.%s() is not supported", jdbcInterface.getName(), methodName));
}
- protected SQLClientInfoException errorClientInfoMethodNotSupported(Class<?> jdbcInterface, String methodName) {
+ public SQLClientInfoException errorClientInfoMethodNotSupported(Class<?> jdbcInterface, String methodName) {
return new SQLClientInfoException(
String.format("Method %s.%s() is not supported", jdbcInterface.getName(), methodName),
Collections.emptyMap());
}
- protected SQLException errorParameterNotSupported(String parameterName) {
+ public SQLException errorParameterNotSupported(String parameterName) {
return new SQLException(String.format("Unsupported parameter %s", parameterName));
}
- protected String warningParameterNotSupported(String parameterName) {
+ public String warningParameterNotSupported(String parameterName) {
return String.format("Unsupported parameter %s", parameterName);
}
- protected SQLException errorParameterValueNotSupported(String parameterName) {
+ public SQLException errorParameterValueNotSupported(String parameterName) {
return new SQLException(String.format("Unsupported or invalid value of %s parameter", parameterName));
}
- protected String warningParameterValueNotSupported(String parameterName) {
+ public String warningParameterValueNotSupported(String parameterName) {
return String.format("Ignored unsupported or invalid value of %s parameter", parameterName);
}
- protected SQLException errorIncompatibleMode(String mode) {
+ public SQLException errorIncompatibleMode(String mode) {
return new SQLException(String.format("Operation cannot be performed in %s mode", mode));
}
- protected SQLException errorInProtocol() {
+ public SQLException errorInProtocol() {
return new SQLNonTransientConnectionException("Protocol error", SQLState.CONNECTION_FAILURE.code);
}
- protected SQLException errorInProtocol(String badValue) {
+ public SQLException errorInProtocol(String badValue) {
return new SQLNonTransientConnectionException(String.format("Protocol error. Unexpected %s", badValue),
SQLState.CONNECTION_FAILURE.code);
}
- protected SQLException errorInProtocol(JsonProcessingException e) {
+ public SQLException errorInProtocol(JsonProcessingException e) {
return new SQLNonTransientConnectionException(String.format("Protocol error. %s", getMessage(e)),
SQLState.CONNECTION_FAILURE.code, e);
}
- protected SQLException errorInConnection(String badValue) {
+ public SQLException errorInConnection(String badValue) {
return new SQLNonTransientConnectionException(String.format("Connection error. Unexpected %s", badValue),
SQLState.CONNECTION_FAILURE.code);
}
- protected SQLException errorInConnection(IOException e) {
+ public SQLException errorInConnection(IOException e) {
String message = String.format("Connection error. %s", getMessage(e));
- return e instanceof ConnectTimeoutException ? errorTimeout(message, e)
- : couldBeTransientConnectionError(e)
+ return isTimeoutConnectionError(e) ? errorTimeout(message, e)
+ : isTransientConnectionError(e)
? new SQLTransientConnectionException(message, SQLState.CONNECTION_FAILURE.code, e)
: new SQLNonTransientConnectionException(message, SQLState.CONNECTION_FAILURE.code, e);
}
- protected SQLException errorClosingResource(IOException e) {
+ public SQLException errorClosingResource(IOException e) {
return new SQLException(String.format("Error closing resources. %s", getMessage(e)), e);
}
- protected SQLInvalidAuthorizationSpecException errorAuth() {
+ public SQLInvalidAuthorizationSpecException errorAuth() {
return new SQLInvalidAuthorizationSpecException("Authentication/authorization error",
SQLState.INVALID_AUTH_SPEC.code);
}
- protected SQLException errorColumnNotFound(String columnNameOrNumber) {
+ public SQLException errorColumnNotFound(String columnNameOrNumber) {
return new SQLException(String.format("Column %s was not found", columnNameOrNumber));
}
- protected SQLException errorUnexpectedColumnValue(ADBDatatype type, String columnName) {
+ public SQLException errorUnexpectedColumnValue(ADBDatatype type, String columnName) {
return new SQLException(
String.format("Unexpected value of type %s for column %s", type.getTypeName(), columnName));
}
- protected SQLException errorUnwrapTypeMismatch(Class<?> iface) {
+ public SQLException errorUnwrapTypeMismatch(Class<?> iface) {
return new SQLException(String.format("Cannot unwrap to %s", iface.getName()));
}
- protected SQLException errorInvalidStatementCategory() {
+ public SQLException errorInvalidStatementCategory() {
return new SQLException("Invalid statement category");
}
- protected SQLException errorUnexpectedType(Class<?> type) {
+ public SQLException errorUnexpectedType(Class<?> type) {
return new SQLException(String.format("Unexpected type %s", type.getName()), SQLState.INVALID_DATE_TYPE.code);
}
- protected SQLException errorUnexpectedType(byte typeTag) {
+ public SQLException errorUnexpectedType(byte typeTag) {
return new SQLException(String.format("Unexpected type %s", typeTag), SQLState.INVALID_DATE_TYPE.code);
}
- protected SQLException errorUnexpectedType(ADBDatatype type) {
+ public SQLException errorUnexpectedType(ADBDatatype type) {
return new SQLException(String.format("Unexpected type %s", type.getTypeName()),
SQLState.INVALID_DATE_TYPE.code);
}
- protected SQLException errorInvalidValueOfType(ADBDatatype type) {
+ public SQLException errorInvalidValueOfType(ADBDatatype type) {
return new SQLException(String.format("Invalid value of type %s", type), SQLState.INVALID_DATE_TYPE.code);
}
- protected SQLException errorNoResult() {
+ public SQLException errorNoResult() {
return new SQLException("Result is unavailable");
}
- protected SQLException errorBadResultSignature() {
+ public SQLException errorBadResultSignature() {
return new SQLException("Cannot infer result columns");
}
- protected SQLException errorNoCurrentRow() {
+ public SQLException errorNoCurrentRow() {
return new SQLException("No current row", SQLState.INVALID_CURSOR_POSITION.code);
}
- protected SQLException errorInRequestGeneration(IOException e) {
+ public SQLException errorInRequestGeneration(IOException e) {
return new SQLException(String.format("Cannot create request. %s", getMessage(e)), e);
}
- protected SQLException errorInRequestURIGeneration(URISyntaxException e) {
+ public SQLException errorInRequestURIGeneration(URISyntaxException e) {
return new SQLException(String.format("Cannot create request URI. %s", getMessage(e)), e);
}
- protected SQLException errorInResultHandling(IOException e) {
+ public SQLException errorInResultHandling(IOException e) {
return new SQLException(String.format("Cannot reading result. %s", getMessage(e)), e);
}
- protected SQLTimeoutException errorTimeout() {
+ public SQLTimeoutException errorTimeout() {
return new SQLTimeoutException();
}
- protected SQLTimeoutException errorTimeout(String message, IOException cause) {
+ public SQLTimeoutException errorTimeout(String message, IOException cause) {
return new SQLTimeoutException(message, cause);
}
- protected boolean couldBeTransientConnectionError(IOException e) {
+ protected boolean isTimeoutConnectionError(IOException e) {
+ return false;
+ }
+
+ protected boolean isTransientConnectionError(IOException e) {
+ return false;
+ }
+
+ protected boolean isInstanceOf(IOException e, List<Class<? extends IOException>> classList) {
if (e != null) {
- for (Class<? extends IOException> c : TRANSIENT_CONNECTION_ERRORS) {
+ for (Class<? extends IOException> c : classList) {
if (c.isInstance(e)) {
return true;
}
@@ -192,7 +193,7 @@
return false;
}
- protected String getMessage(Exception e) {
+ public String getMessage(Exception e) {
String message = e != null ? e.getMessage() : null;
return message != null ? message : "";
}
diff --git a/asterixdb-jdbc/asterix-jdbc-driver/pom.xml b/asterixdb-jdbc/asterix-jdbc-driver/pom.xml
index 3a68e8c..8bbf17a 100644
--- a/asterixdb-jdbc/asterix-jdbc-driver/pom.xml
+++ b/asterixdb-jdbc/asterix-jdbc-driver/pom.xml
@@ -48,6 +48,22 @@
<artifactId>asterix-jdbc-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBProtocol.java b/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/ADBProtocol.java
similarity index 95%
rename from asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBProtocol.java
rename to asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/ADBProtocol.java
index 38afb84..5bc0d9e 100644
--- a/asterixdb-jdbc/asterix-jdbc-core/src/main/java/org/apache/asterix/jdbc/core/ADBProtocol.java
+++ b/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/ADBProtocol.java
@@ -17,16 +17,19 @@
* under the License.
*/
-package org.apache.asterix.jdbc.core;
+package org.apache.asterix.jdbc;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.NoRouteToHostException;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -34,11 +37,16 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.apache.asterix.jdbc.core.ADBDriverContext;
+import org.apache.asterix.jdbc.core.ADBDriverProperty;
+import org.apache.asterix.jdbc.core.ADBErrorReporter;
+import org.apache.asterix.jdbc.core.ADBProtocolBase;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
+import org.apache.http.NoHttpResponseException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
@@ -52,7 +60,9 @@
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.SocketConfig;
+import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.EntityTemplate;
@@ -71,12 +81,18 @@
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
-public class ADBProtocol extends ADBProtocolBase {
+final class ADBProtocol extends ADBProtocolBase {
private static final String QUERY_SERVICE_ENDPOINT_PATH = "/query/service";
private static final String QUERY_RESULT_ENDPOINT_PATH = "/query/service/result";
private static final String ACTIVE_REQUESTS_ENDPOINT_PATH = "/admin/requests/running";
+ static final List<Class<? extends IOException>> TIMEOUT_CONNECTION_ERRORS =
+ Collections.singletonList(ConnectTimeoutException.class);
+
+ static final List<Class<? extends IOException>> TRANSIENT_CONNECTION_ERRORS =
+ Arrays.asList(NoRouteToHostException.class, NoHttpResponseException.class, HttpHostConnectException.class);
+
final URI queryEndpoint;
final URI queryResultEndpoint;
final URI activeRequestsEndpoint;
diff --git a/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/Driver.java b/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/Driver.java
index f13ac05..97fb256 100644
--- a/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/Driver.java
+++ b/asterixdb-jdbc/asterix-jdbc-driver/src/main/java/org/apache/asterix/jdbc/Driver.java
@@ -19,14 +19,20 @@
package org.apache.asterix.jdbc;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
+import java.util.List;
import java.util.Map;
+import java.util.Properties;
import org.apache.asterix.jdbc.core.ADBDriverBase;
import org.apache.asterix.jdbc.core.ADBDriverContext;
import org.apache.asterix.jdbc.core.ADBDriverProperty;
-import org.apache.asterix.jdbc.core.ADBProtocol;
-import org.apache.asterix.jdbc.core.ADBProtocolBase;
+import org.apache.asterix.jdbc.core.ADBErrorReporter;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
public class Driver extends ADBDriverBase implements java.sql.Driver {
@@ -44,8 +50,36 @@
}
@Override
- protected ADBProtocolBase createProtocol(String host, int port, Map<ADBDriverProperty, Object> properties,
+ protected ADBProtocol createProtocol(String host, int port, Map<ADBDriverProperty, Object> properties,
ADBDriverContext driverContext) throws SQLException {
return new ADBProtocol(host, port, properties, driverContext);
}
+
+ @Override
+ protected Properties getURIParameters(URI uri) {
+ List<NameValuePair> params = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8);
+ if (params.isEmpty()) {
+ return null;
+ }
+ Properties properties = new Properties();
+ for (NameValuePair pair : params) {
+ properties.setProperty(pair.getName(), pair.getValue());
+ }
+ return properties;
+ }
+
+ @Override
+ protected ADBErrorReporter createErrorReporter() {
+ return new ADBErrorReporter() {
+ @Override
+ protected boolean isTimeoutConnectionError(IOException e) {
+ return isInstanceOf(e, ADBProtocol.TIMEOUT_CONNECTION_ERRORS);
+ }
+
+ @Override
+ protected boolean isTransientConnectionError(IOException e) {
+ return isInstanceOf(e, ADBProtocol.TRANSIENT_CONNECTION_ERRORS);
+ }
+ };
+ }
}