All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aceql.jdbc.commons.AceQLConnection Maven / Gradle / Ivy

Go to download

The AceQL Java Client JDBC Driver allows to wrap the AceQL HTTP APIs and eliminates the tedious works of handling communications errors and parsing JSON results. Android and Java Desktop application developers can access remote SQL databases and/or SQL databases in the cloud by simply including standard JDBC calls in their code, just like they would for a local database.

The newest version!
/*
 * This file is part of AceQL JDBC Driver.
 * AceQL JDBC Driver: Remote JDBC access over HTTP with AceQL HTTP.
 * Copyright (c) 2023,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.
 *
 * 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.aceql.jdbc.commons;

import java.io.Closeable;
import java.net.HttpURLConnection;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import com.aceql.jdbc.commons.main.AceQLPreparedStatement;
import com.aceql.jdbc.commons.main.AceQLStatement;
import com.aceql.jdbc.commons.main.abstracts.AbstractConnection;
import com.aceql.jdbc.commons.main.advanced.caller.DatabaseMetaDataGetter;
import com.aceql.jdbc.commons.main.advanced.caller.PrepareCallGetter;
import com.aceql.jdbc.commons.main.http.AceQLHttpApi;
import com.aceql.jdbc.commons.main.util.AceQLConnectionUtil;
import com.aceql.jdbc.commons.main.util.framework.Tag;
import com.aceql.jdbc.commons.main.version.Version;
import com.aceql.jdbc.commons.metadata.RemoteDatabaseMetaData;
import com.aceql.jdbc.driver.free.AceQLDriver;

/**
 * Provides a Connection implementation that enable to use a
 * virtual JDBC Connection that is mapped to a Server JDBC
 * Connection in order to access a remote SQL database through
 * HTTP. 
* This class acts as a wrapper of AceQL HTTP APIs. *

* This Connection implementation supports: *

    *
  • Main JDBC data formats.
  • *
  • Blob updates.
  • *
  • Blob reads.
  • *
  • Transaction through commit and rollback orders. *
  • *
*

* Supplementary specific methods that are not of instance of * {@code java.sql.Connection} interface are also added.
* After getting the AceQLConnection with * {@link DriverManager#getConnection(String, Properties)} just use it like a * regular Connection to execute your * PreparedStatement and Statement, and to navigate * through your ResultSet. *

* Check the user documentation or the Javadoc of the AceQL JDBC Driver * for more info: {@link AceQLDriver}. *

* All thrown exceptions are of type {@link AceQLException}. Use * {@link SQLException#getCause()} to get the original wrapped Exception.
*
* The AceQL error_type value is available via the * {@code AceQLException#getErrorCode()} and the remote_stack value as a string * is available with {@link AceQLException#getRemoteStackTrace()}. * * The following dedicated AceQLConnection methods are specific to * the software and may be accessed with a cast: *

    *
  • {@link #getClientVersion()}: Gets the AceQL JDBC version info.
  • *
  • {@link #getServerVersion()}: Gets the AceQL HTTP Server version * info.
  • *
  • {@link #getConnectionInfo()}: Gets major options/Properties passed when * calling {@link DriverManager#getConnection(String, Properties)}.
  • *
  • {@link #setProgress(AtomicInteger)}: Allows to pass a sharable progress * value. See below.
  • *
  • {@link #setCancelled(AtomicBoolean)}: Allows to pass a sharable canceled * variable that will be used by the progress indicator to notify this instance * that the end user has cancelled the current Blob/Clob upload or download
  • *
*

* More info about the current AceQLConnection are accessible through the * {@link ConnectionInfo}:

* // Casts the current Connection to get an AceQLConnection object * AceQLConnection aceqlConnection = (AceQLConnection) connection; * ConnectionInfo connectionInfo = aceqlConnection.getConnectionInfo(); *

* All long Blobs update/reading that need to be run on a separated thread may * be followed in Swing using a JProgressBar, * ProgressMonitor or Android using a {@code ProgressDialog} *

* This is done by sharing two atomic variables that will be declared as fields: *

    *
  • An {@code AtomicInteger} that represents the Blob/Clob transfer progress * between 0 and 100.
  • *
  • An {@code AtomicBoolean} that says if the end user has cancelled the * Blob/Clob transfer.
  • *
*

* The atomic variables values will be shared by AceQL download/upload processes * and by the Progress Monitor used for the Progress Bar. The values are to be * initialized and passed to {@code AceQLConnection} before the JDBC actions * with the setters:
*

    *
  • {@link AceQLConnection#setProgress(AtomicInteger)}
  • *
  • {@link AceQLConnection#setCancelled(AtomicBoolean)}
  • *
*

* * Example:

* *
 * // Attempts to establish a connection to the remote database:
 * Connection connection = DriverManager.getConnection(url, info);
 *
 * // Pass the mutable & sharable progress and canceled to the
 * // underlying AceQLConnection.
 * // - progress value will be updated by the AceQLConnection and
 * // retrieved by progress monitors to increment the progress.
 * // - cancelled value will be updated to true if user cancels the
 * // task and AceQLConnection will interrupt the Blob(s) transfer.
 *
 * ((AceQLConnection) connection).setProgress(progress);
 * ((AceQLConnection) connection).setCancelled(cancelled);
 *
 * // Execute JDBC statement
 * 
* *
See the source code of SqlProgressMonitorDemo.java that demonstrates the use of atomic * variables when inserting a Blob.
*
* See also {@link AceQLBlob} that describes how to use Blobs. * * @author Nicolas de Pomereu * */ public class AceQLConnection extends AbstractConnection implements Connection, Cloneable, Closeable { /** The Http instance that does all Http stuff */ AceQLHttpApi aceQLHttpApi = null; /** is Connection open or closed */ private boolean closed = false; /** The Connections Advanced Options */ private ConnectionInfo connectionInfo; /** * Login on the AceQL server and connect to a database. * * @param connectionInfo Connection Info required for login. * @throws SQLException if any I/O error occurs */ AceQLConnection(ConnectionInfo connectionInfo) throws SQLException { try { this.connectionInfo = Objects.requireNonNull(connectionInfo, "connectionInfo can not be null!"); Objects.requireNonNull(connectionInfo.getUrl(), "url can not be null!"); Objects.requireNonNull(connectionInfo.getDatabase(), "database can not be null!"); Objects.requireNonNull(connectionInfo.getAuthentication(), "authentication can not be null!"); aceQLHttpApi = new AceQLHttpApi(connectionInfo); } catch (AceQLException aceQlException) { throw aceQlException; } catch (Exception e) { throw new AceQLException(e.getMessage(), 0, e, null, HttpURLConnection.HTTP_OK); } } /** * Private constructor for Clone * * @param aceQLHttpApi the AceQL http Api Clone */ private AceQLConnection(AceQLHttpApi aceQLHttpApi) { this.aceQLHttpApi = aceQLHttpApi; } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#createBlob() */ @Override public Blob createBlob() throws SQLException { if (isClosed()) { throw new SQLException(Tag.PRODUCT + " Can not create Blob because Connection is closed."); } AceQLBlob blob = new AceQLBlob(); return blob; } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#createClob() */ @Override public Clob createClob() throws SQLException { if (isClosed()) { throw new SQLException(Tag.PRODUCT + " Can not create Clob because Connection is closed."); } AceQLClob clob = new AceQLClob(this.connectionInfo.getClobReadCharset(), this.connectionInfo.getClobWriteCharset()); return clob; } @Override public DatabaseMetaData getMetaData() throws SQLException { DatabaseMetaDataGetter databaseMetaDataGetter = new DatabaseMetaDataGetter(); return databaseMetaDataGetter.getMetaData(this); } /** * Returns a RemoteDatabaseMetaData instance in order to retrieve metadata info * for all client SDKs. * * @return a RemoteDatabaseMetaData instance in order to retrieve metadata info. */ public RemoteDatabaseMetaData getRemoteDatabaseMetaData() { RemoteDatabaseMetaData remoteDatabaseMetaData = new RemoteDatabaseMetaData(this); return remoteDatabaseMetaData; } /* * (non-Javadoc) * * @see java.sql.Connection#close() */ @Override public void close() { this.closed = true; try { aceQLHttpApi.close(); } catch (AceQLException e) { // Because close() can not throw an Exception, we wrap the // AceQLException with a RuntimeException // throw new IllegalStateException(e.getMessage(), e); e.printStackTrace(); } } /** * Calls /logout AceQL HTTP API on server side. Will close all the opened JDBC * Connections on server side for the database in use. */ public void logout() { this.closed = true; try { aceQLHttpApi.logout(); } catch (AceQLException e) { // Because close() can not throw an Exception, we wrap the // AceQLException with a RuntimeException // throw new IllegalStateException(e.getMessage(), e); e.printStackTrace(); } } /* * (non-Javadoc) * * @see java.sql.Connection#commit() */ @Override public void commit() throws SQLException { aceQLHttpApi.commit(); } /* * (non-Javadoc) * * @see java.sql.Connection#rollback() */ @Override public void rollback() throws SQLException { aceQLHttpApi.rollback(); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setSavepoint() */ @Override public Savepoint setSavepoint() throws SQLException { return aceQLHttpApi.setSavepoint(); } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setSavepoint(String * name) */ @Override public Savepoint setSavepoint(String name) throws SQLException { return aceQLHttpApi.setSavePoint(name); } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#rollback(java.sql. * Savepoint) */ @Override public void rollback(Savepoint savepoint) throws SQLException { aceQLHttpApi.rollbback(savepoint); } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#releaseSavepoint( * java. sql.Savepoint) */ @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { aceQLHttpApi.releaseSavepoint(savepoint); } /* * (non-Javadoc) * * @see java.sql.Connection#setHoldability(int) */ @Override public void setTransactionIsolation(int level) throws SQLException { String levelStr = AceQLConnectionUtil.getTransactionIsolationAsString(level); aceQLHttpApi.setTransactionIsolation(levelStr); } /* * (non-Javadoc) * * @see java.sql.Connection#setHoldability(int) */ @Override public void setHoldability(int holdability) throws SQLException { String holdabilityStr = AceQLConnectionUtil.getHoldabilityAsString(holdability); aceQLHttpApi.setHoldability(holdabilityStr); } /* * (non-Javadoc) * * @see java.sql.Connection#setAutoCommit(boolean) */ @Override public void setAutoCommit(boolean autoCommit) throws SQLException { aceQLHttpApi.setAutoCommit(autoCommit); } /* * (non-Javadoc) * * @see java.sql.Connection#isReadOnly() */ @Override public boolean getAutoCommit() throws SQLException { return aceQLHttpApi.getAutoCommit(); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setReadOnly( * boolean) */ @Override public void setReadOnly(boolean readOnly) throws SQLException { // TODO Auto-generated method stub aceQLHttpApi.setReadOnly(readOnly); } /* * (non-Javadoc) * * @see java.sql.Connection#isReadOnly() */ @Override public boolean isReadOnly() throws SQLException { return aceQLHttpApi.isReadOnly(); } /* * (non-Javadoc) * * @see java.sql.Connection#getHoldability() */ @Override public int getHoldability() throws SQLException { String result = aceQLHttpApi.getHoldability(); return AceQLConnectionUtil.getHoldability(result); } /* * (non-Javadoc) * * @see java.sql.Connection#getTransactionIsolation() */ @Override public int getTransactionIsolation() throws SQLException { String result = aceQLHttpApi.getTransactionIsolation(); return AceQLConnectionUtil.getTransactionIsolation(result); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#getCatalog() */ @Override public String getCatalog() throws SQLException { return aceQLHttpApi.getCatalog(); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#getSchema() */ @Override public String getSchema() throws SQLException { return aceQLHttpApi.getSchema(); } /** * Creates a {@code CallableServerQuery} object for calling a remote {@code ServerQueryExecutor} implementation. * @return a new default {@code CallableServerQuery} object */ public CallableServerQuery createCallableServerQuery() { CallableServerQuery callableServerQuery = new CallableServerQuery(this); return callableServerQuery; } /* * (non-Javadoc) * * @see java.sql.Connection##createStatement() */ @Override public Statement createStatement() throws SQLException { AceQLStatement aceQLStatement = new AceQLStatement(this); return aceQLStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#createStatement( * int, int) */ @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { AceQLStatement aceQLStatement = new AceQLStatement(this); return aceQLStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#createStatement( * int, int, int) */ @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) { AceQLStatement aceQLStatement = new AceQLStatement(this); return aceQLStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement * (java.lang.String) */ @Override public PreparedStatement prepareStatement(String sql) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement( * java. lang.String, int, int) */ @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement( * java. lang.String, int, int, int) */ @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement( * java. lang.String, int) */ @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement( * java. lang.String, int[]) */ @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareStatement( * java. lang.String, java.lang.String[]) */ @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { AceQLPreparedStatement aceQLPreparedStatement = new AceQLPreparedStatement(this, sql); return aceQLPreparedStatement; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#prepareCall(java. * lang. String) */ @Override public CallableStatement prepareCall(String sql) throws SQLException { PrepareCallGetter prepareCallGetter = new PrepareCallGetter(); return prepareCallGetter.prepareCall(this, sql); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#getWarnings() */ @Override public SQLWarning getWarnings() throws SQLException { return null; } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ @Override public Connection clone() { AceQLHttpApi aceQLHttpApi = this.aceQLHttpApi.clone(); AceQLConnection aceQLConnection = new AceQLConnection(aceQLHttpApi); return aceQLConnection; } // ////////////////////////////////////////////////////////////// // / AceQLConnection methods // // ///////////////////////////////////////////////////////////// /** * Returns the SDK current Version. * * @return the SDK current Version */ public String getClientVersion() { return Version.getVersion(); } /** * Returns the server product version * * @return the server product version * * @throws AceQLException if any Exception occurs */ public String getServerVersion() throws AceQLException { return aceQLHttpApi.getServerVersion(); } /** * A shortcut to remote database metadata which returns remote database and * remote JDBC Driver main info. * * @return remote database and JDBC Driver main info. * @throws SQLException if any Exception occurs */ public DatabaseInfo getDatabaseInfo() throws SQLException { DatabaseInfo databaseInfo = InternalWrapper.databaseInfoBuilder(aceQLHttpApi); return databaseInfo; } /** * Gives info of limits defined on server side. * * @return Gives info of limits defined on server side.o. * @throws SQLException if any Exception occurs */ public LimitsInfo getLimitsInfo() throws SQLException { LimitsInfo limitsInfo = InternalWrapper.limitsInfoBuilder(aceQLHttpApi); return limitsInfo; } /** * Returns the cancelled value set by the progress indicator * * @return the cancelled value set by the progress indicator */ public AtomicBoolean getCancelled() { return aceQLHttpApi.getCancelled(); } /** * Returns the sharable progress variable that will store Blob/Clob upload or * download progress between 0 and 100 * * @return the sharable progress variable that will store Blob/Clob upload or * download progress between 0 and 100 * */ public AtomicInteger getProgress() { return aceQLHttpApi.getProgress(); } /** * Sets the sharable canceled variable that will be used by the progress * indicator to notify this instance that the user has cancelled the current * Blob/Clob upload or download. * * @param cancelled the sharable canceled variable that will be used by the * progress indicator to notify this instance that the end user * has cancelled the current Blob/Clob upload or download * */ public void setCancelled(AtomicBoolean cancelled) { aceQLHttpApi.setCancelled(cancelled); } /** * Sets the sharable progress variable that will store Blob/Clob upload or * download progress between 0 and 100. Will be used by progress indicators to * show the progress. * * @param progress the sharable progress variable */ public void setProgress(AtomicInteger progress) { aceQLHttpApi.setProgress(progress); } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#clearWarnings() */ @Override public void clearWarnings() throws SQLException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#isValid(int) */ @Override public boolean isValid(int timeout) throws SQLException { return true; } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#getClientInfo() */ @Override public Properties getClientInfo() throws SQLException { return null; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#getClientInfo(java. * lang. String) */ @Override public String getClientInfo(String name) throws SQLException { return null; } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setClientInfo(java. * util. Properties) */ @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setClientInfo(java. * lang. String, java.lang.String) */ @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setNetworkTimeout( * java. util.concurrent.Executor, int) */ @Override public void setNetworkTimeout(Executor arg0, int arg1) throws SQLException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see * com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setCatalog(java. * lang. String) */ @Override public void setCatalog(String catalog) throws SQLException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see com.aceql.jdbc.commons.main.abstracts.AbstractConnection#setSchema(java. * lang. String) */ @Override public void setSchema(String arg0) throws SQLException { // Do nothing for now. Future usage. } /* * (non-Javadoc) * * @see java.sql.Connection#close() */ @Override public boolean isClosed() throws SQLException { return closed; } /** * Gets all info of this {@code AceQLConnection} instance * * @return all info of this {@code AceQLConnection} instance */ public ConnectionInfo getConnectionInfo() { return connectionInfo; } @Override public String toString() { return "AceQLConnection [getClientVersion()=" + getClientVersion() + ", getConnectionInfo()=" + getConnectionInfo() + "]"; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy