com.hazelcast.org.apache.calcite.avatica.UnregisteredDriver Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in com.hazelcast.com.liance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.com.hazelcast.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.hazelcast.org.apache.calcite.avatica;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Implementation of JDBC driver that does not register itself.
*
* You can easily create a "vanity driver" that recognizes its own
* URL prefix as a sub-class of this class. Per the JDBC specification it
* must register itself when the class is loaded.
*
* Derived classes must implement {@link #createDriverVersion()} and
* {@link #getConnectStringPrefix()}, and may override
* {@link #createFactory()}.
*
* The provider must implement:
*
* - {@link Meta#prepare(Meta.ConnectionHandle, String, long)}
*
- {@link Meta#createIterable(com.hazelcast.org.apache.calcite.avatica.Meta.StatementHandle, com.hazelcast.org.apache.calcite.avatica.QueryState, com.hazelcast.org.apache.calcite.avatica.Meta.Signature, java.util.List, Meta.Frame)}
*
*/
public abstract class UnregisteredDriver implements java.sql.Driver {
final DriverVersion version;
protected final AvaticaFactory factory;
public final Handler handler;
protected UnregisteredDriver() {
this.factory = createFactory();
this.version = createDriverVersion();
this.handler = createHandler();
}
/**
* Creates a factory for JDBC objects (connection, statement).
* Called from the driver constructor.
*
* The default implementation calls {@link JdbcVersion#current},
* then {@link #getFactoryClassName} with that version,
* then passes that class name to {@link #instantiateFactory(String)}.
* This approach is recommended it does not include in the code references
* to classes that may not be instantiable in all JDK versions.
* But drivers are free to do it their own way.
*
* @return JDBC object factory
*/
protected AvaticaFactory createFactory() {
return instantiateFactory(getFactoryClassName(JdbcVersion.current()));
}
/** Creates a Handler. */
protected Handler createHandler() {
return new HandlerImpl();
}
/**
* Returns the name of a class to be factory for JDBC objects
* (connection, statement) appropriate for the current JDBC version.
*/
protected String getFactoryClassName(JdbcVersion jdbcVersion) {
switch (jdbcVersion) {
case JDBC_30:
case JDBC_40:
throw new IllegalArgumentException("JDBC version not supported: "
+ jdbcVersion);
case JDBC_41:
default:
return "com.hazelcast.org.apache.calcite.avatica.AvaticaJdbc41Factory";
}
}
/**
* Creates an object describing the name and version of this driver.
* Called from the driver constructor.
*/
protected abstract DriverVersion createDriverVersion();
/**
* Returns the connection properties supported by this driver.
*/
protected Collection getConnectionProperties() {
return Arrays.asList(
BuiltInConnectionProperty.values());
}
/** Helper method for creating factories. */
protected static AvaticaFactory instantiateFactory(String factoryClassName) {
try {
final Class clazz = Class.forName(factoryClassName);
return (AvaticaFactory) clazz.getConstructor().newInstance();
} catch (Throwable e) {
// It is not usually good to catch Throwable. But class loading can fail
// with serious errors such as java.lang.NoClassDefFoundError
throw handle("Error loading factory " + factoryClassName, e);
}
}
private static RuntimeException handle(String msg, Throwable e) {
Logger.getLogger("").log(Level.SEVERE, msg, e);
throw new RuntimeException(msg, e);
}
public Connection connect(String url, Properties info) throws SQLException {
if (!acceptsURL(url)) {
return null;
}
final String prefix = getConnectStringPrefix();
assert url.startsWith(prefix);
final String urlSuffix = url.substring(prefix.length());
final Properties info2 = ConnectStringParser.parse(urlSuffix, info);
final AvaticaConnection connection =
factory.newConnection(this, factory, url, info2);
handler.onConnectionInit(connection);
return connection;
}
public boolean acceptsURL(String url) throws SQLException {
return url.startsWith(getConnectStringPrefix());
}
/** Returns the prefix of the connect string that this driver will recognize
* as its own. For example, "jdbc:calcite:". */
protected abstract String getConnectStringPrefix();
public DriverPropertyInfo[] getPropertyInfo(
String url, Properties info) throws SQLException {
List list = new ArrayList();
// First, add the contents of info
for (Map.Entry