![JAR search and dependency download from the Maven repository](/logo.png)
com.aceql.jdbc.driver.free.AceQLDriver Maven / Gradle / Ivy
Show all versions of aceql-http-client-jdbc-driver Show documentation
/*
* This file is part of AceQL.
* AceQL: Remote JDBC access over HTTP.
* Copyright (C) 2015, KawanSoft SAS
* (http://www.kawansoft.com). All rights reserved.
*
* AceQL is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* AceQL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Any modifications to this file must keep this entire header
* intact.
*/
package com.aceql.jdbc.driver.free;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import com.aceql.jdbc.commons.AceQLConnection;
import com.aceql.jdbc.commons.ConnectionInfo;
import com.aceql.jdbc.commons.InternalWrapper;
import com.aceql.jdbc.commons.driver.util.DriverPropertyInfoBuilder;
import com.aceql.jdbc.commons.driver.util.DriverUtil;
import com.aceql.jdbc.commons.main.util.AceQLConnectionUtil;
import com.aceql.jdbc.commons.main.util.framework.FrameworkDebug;
import com.aceql.jdbc.commons.main.util.framework.JdbcUrlHeader;
import com.aceql.jdbc.commons.main.util.framework.Tag;
import com.aceql.jdbc.commons.metadata.ResultSetMetaDataPolicy;
/**
*
* The AceQL JDBC Driver class in order to
* access remote SQL databases through HTTP from Android or Java desktop
* programs.
*
* user, password and database are the only required
* properties.
*
* Properties:
*
* - user: username to connect to the remote database as.
* - password: password to use when authenticating.
* - database: name of remote database as defined in the server
* {@code aceql-server.properties} file.
* - proxyType: java.net.Proxy Type to use: DIRECT, HTTP or SOCKS.
* Defaults to DIRECT.
* - proxyHostname: java.net.Proxy hostname to use.
* - proxyPort: java.net.Proxy Port to use.
* - proxyUsername: Proxy credential username.
* - proxyPassword: Proxy credential password.
* - connectTimeout: Timeout value, in milliseconds, to be used when
* opening a communications link to the remote server. If the timeout expires
* before the connection can be established, a java.net.SocketTimeoutException is
* raised. A timeout of zero is interpreted as an infinite timeout. Defaults to 0.
* - readTimeout: Read timeout to a specified timeout, in milliseconds.
* A non-zero value specifies the timeout when reading from Input stream when a
* connection is established to a resource. If the timeout expires before there
* is data available for read, a java.net.SocketTimeoutException is raised. A
* timeout of zero is interpreted as an infinite timeout. Defaults to 0.
*
- gzipResult: Boolean to say if the ResultSet is Gzipped before
* download. Defaults to
true
.
* - resultSetMetaDataPolicy: Defines the {@code ResultSet} metadata
* policy. Says if the {@code ResultSet} metadata is to be downloaded along with
* the ResultSet. Possible values are "on" and "off". Defaults to "on".
* - clobReadCharset: Name of the charset to use when
* reading a CLOB content with the {@code ResultSet} methods. Defaults
* to {@code null}.
* - clobWriteCharset: Name of the charset to use when
* writing a CLOB content with the {@code PreparedStatement} streaming methods. Defaults
* to "{@code UTF-8}".
*
*
* Usage of the AceQL JDBC Driver is straightforward:
*
*
* // Define URL of the path to the AceQL Manager Servlet
* // We will use a secure SSL/TLS session. All uploads/downloads of SQL
* // commands and data will be encrypted.
* String url = "http://localhost:9090/aceql";
*
* // The login info for strong authentication on server side.
* // These are *not* the username/password of the remote JDBC Driver,
* // but are the auth info checked by remote server
* // UserAuthenticator.login(username, password) method.
* String database = "sampledb";
* String user = "user1";
* String password = "password1";
*
* // Register and Load the Driver
* DriverManager.registerDriver(new AceQLDriver());
* String driverClassName = AceQLDriver.class.getName();
* Class.forName(driverClassName);
*
* // Attempts to establish a connection to the remote database:
* Properties info = new Properties();
* info.put("user", user);
* info.put("password", password);
* info.put("database", database);
*
* Connection connection = DriverManager.getConnection(url, info);
* return connection;
*
*
* An alternate way of passing connection info is to add them as request
* parameters to the URL:
*
*
* // Define URL of the path to the AceQL Manager Servlet, with all properties
* // passed as request parameters.
* // (We presume that the aceql_license_key.txt is installed in user.dir.)
* String url = "http://localhost:9090/aceql?user=user1&password=password1&database=sampledb";
*
* // Register and Load the Driver
* DriverManager.registerDriver(new AceQLDriver());
* String driverClassName = AceQLDriver.class.getName();
* Class.forName(driverClassName);
*
* // Attempts to establish a connection to the remote database:
* Connection connection = DriverManager.getConnection(url, new Properties());
*
*
* The {@code Connection} returned is now ready to be used as a regular or
* classic {@link java.sql.Connection}:
*
*
* String sql = "select * from customer where customer_id >= 1 order by customer_id";
* Statement statement = connection.createStatement();
* statement.execute(sql);
*
* ResultSet rs = statement.getResultSet();
* // Etc.
*
*
* The built {@code Connection} is an instance of {@code AceQLConnection} that
* contains some specific method. See {@link AceQLConnection} for more info.
*
*
*
* @since 6.0
* @author Nicolas de Pomereu
*/
final public class AceQLDriver implements java.sql.Driver {
static int LICENSE_INFO;
/** The debug flag */
private static boolean DEBUG = FrameworkDebug.isSet(AceQLDriver.class);
/**
* Attempts to make a database connection to the given URL.
*
* The driver will return "null" if it realizes it is the wrong kind of driver
* to connect to the given URL. {@link #acceptsURL} will return null.
*
*
* The driver will throwSQLException
if it is the right driver to
* connect to the given URL but has trouble connecting to the database.
*
*
* The java.util.Properties
argument can be used to pass arbitrary
* string tag/value pairs as connection arguments. At least "user", "password"
* and "database" properties should be included in the Properties
* object, or either passed through the URL parameter.
*
* @param url the URL of the database to which to connect
* @param info a list of arbitrary string tag/value pairs as connection
* arguments. At least a "user" and "password" property should be
* included.
* @return a Connection
object that represents a connection to the
* URL
* @exception SQLException if a database access error occurs
*/
@Override
public Connection connect(String url, Properties info) throws SQLException {
if (url == null) {
throw new SQLException("url not set. Please provide an url.");
}
if (!acceptsURL(url)) {
return null;
}
// Properties may be passed in URL
info = DriverUtil.addPropertiesFromUrl(url, info);
// Remove "aceql:jdbc" prefix & all parameters
url = DriverUtil.trimUrl(url);
String username = info.getProperty("user");
String password = info.getProperty("password");
String sessionId = info.getProperty("sessionId");
String database = info.getProperty("database");
DriverUtil.checkNonNullValues(username, password, database, sessionId);
// Add proxy lookup
String proxyType = info.getProperty("proxyType");
String proxyHostname = info.getProperty("proxyHostname");
String proxyPort = info.getProperty("proxyPort");
String proxyUsername = info.getProperty("proxyUsername");
String proxyPassword = info.getProperty("proxyPassword");
String clobReadCharset = info.getProperty("clobReadCharset");
String clobWriteCharset = info.getProperty("clobWriteCharset");
if (clobWriteCharset == null) {
clobWriteCharset = StandardCharsets.UTF_8.name();
}
debug("info.getProperty(\"clobReadCharset\") : " + clobReadCharset);
debug("info.getProperty(\"clobWriteCharset\"): " + clobWriteCharset);
boolean gzipResult = DriverUtil.getGzipResult(info);
int connectTimeout = DriverUtil.getConnectTimeout(info);
int readTimeout = DriverUtil.getReadTimeout(info);
ResultSetMetaDataPolicy resultSetMetaDataPolicy = DriverUtil.getResultSetMetaDataPolicy(info);
Proxy proxy = DriverUtil.buildProxy(proxyType, proxyHostname, proxyPort);
Map requestProperties = DriverUtil.getRequestProperties(info);
debug("requestProperties: " + requestProperties);
PasswordAuthentication proxyAuthentication = null;
if (proxy != null && proxyUsername != null) {
// Password cannot be null
if (proxyPassword == null) {
throw new SQLException(Tag.PRODUCT + " Defining an authenticated proxy: proxyPassword cannot be null!");
}
proxyAuthentication = new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray());
}
PasswordAuthentication authentication = null;
boolean passwordIsSessionId = false;
if (sessionId == null) {
authentication = new PasswordAuthentication(username, password.toCharArray());
passwordIsSessionId = false;
}
else {
authentication = new PasswordAuthentication(username, sessionId.toCharArray());
passwordIsSessionId = true;
}
ConnectionInfo connectionInfo = InternalWrapper.connectionInfoBuilder(url, database, authentication, passwordIsSessionId,
proxy, proxyAuthentication, connectTimeout, readTimeout, gzipResult,
resultSetMetaDataPolicy, requestProperties, clobReadCharset, clobWriteCharset);
AceQLConnection connection = InternalWrapper.connectionBuilder(connectionInfo);
if (!AceQLConnectionUtil.isVersion12_2OrHigher(connection)) {
throw new SQLException("AceQL Server version must be >= " + AceQLConnectionUtil.SERVER_VERSION_12_2
+ " in order to use the AceQL Client JDBC Driver.");
}
return connection;
}
/**
* Retrieves whether the driver thinks that it can open a connection to the
* given URL. Typically drivers will return true
if they understand
* the subprotocol specified in the URL and false
if they do not.
*
*
* The AceQL driver requires an URL which is an http url in the format:
* {@code jdbc:aceql:http(s):///}
*
*
* Example:
* {@code jdbc:aceql:https://www.acme.com:9443/aceql}
*
* Note that the {@code "jdbc:aceql:"} prefix is optional and thus an URL such
* as {@code https://www.aceql.com:9443/aceql} is accepted
*
* @param url the URL of the database
* @return true
if this driver understands the given URL;
* false
otherwise
* @exception SQLException if a database access error occurs
*/
@Override
public boolean acceptsURL(String url) throws SQLException {
if (url == null) {
throw new IllegalArgumentException("url is null!");
}
String urlHttpOnly = JdbcUrlHeader.getUrlHttpOnly(url);
return DriverUtil.isHttpProtocolUrl(urlHttpOnly);
}
/**
* Gets information about the possible properties for this driver.
*
* The getPropertyInfo
method is intended to allow a generic GUI
* tool to discover what properties it should prompt a human for in order to get
* enough information to connect to a database. Note that depending on the
* values the human has supplied so far, additional values may become necessary,
* so it may be necessary to iterate though several calls to the
* getPropertyInfo
method.
*
* @param url the URL of the database to which to connect
* @param info a proposed list of tag/value pairs that will be sent on connect
* open
* @return an array of DriverPropertyInfo
objects describing
* possible properties.
* @exception SQLException if a database access error occurs
*/
@Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
DriverPropertyInfoBuilder driverPropertyInfoBuilder = new DriverPropertyInfoBuilder();
List driverPropertyInfoList = driverPropertyInfoBuilder.build(info);
DriverPropertyInfo[] arrayOfDriverPropertyInfo = driverPropertyInfoList
.toArray(new DriverPropertyInfo[driverPropertyInfoList.size()]);
return arrayOfDriverPropertyInfo;
}
/**
* Retrieves this driver's major version number.
*
* @return this driver's major version number
*/
@Override
public int getMajorVersion() {
return 9;
}
/**
* Gets the driver's minor version number.
*
* @return this driver's minor version number
*/
@Override
public int getMinorVersion() {
return 3;
}
/**
* Reports whether this driver is a genuine JDBC Compliant ™ driver. A
* driver may only report true
here if it passes the JDBC
* compliance tests; otherwise it is required to return false
.
*
* JDBC compliance requires full support for the JDBC API and full support for
* SQL 92 Entry Level.
*
* Because the AceQL driver works as a special Driver over HTTP to support many
* SQL databases vendors, it does not aim to be a genuine JDBC Compliant ™
* driver. Thus, method returns false
.
*
* @return false
*/
@Override
public boolean jdbcCompliant() {
return false;
}
/**
* debug tool
*/
private static void debug(String s) {
if (DEBUG) {
System.out.println(new Date() + " " + s);
}
}
// /////////////////////////////////////////////////////////
// JAVA 7 METHOD EMULATION //
// /////////////////////////////////////////////////////////
/**
* Return the parent Logger of all the Loggers used by this driver. This should
* be the Logger farthest from the root Logger that is still an ancestor of all
* of the Loggers used by this driver. Configuring this Logger will affect all
* of the log messages generated by the driver. In the worst case, this may be
* the root Logger.
*
* @return the parent Logger for this driver
* @throws SQLFeatureNotSupportedException if the driver does not use
* java.util.logging
.
* @since 1.7
*/
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
}