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

src.main.java.com.aceql.client.jdbc.AceQLConnection Maven / Gradle / Ivy

Go to download

The AceQL Java Client SDK allows to wrap the AceQL HTTP APIs and eliminate 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.

There is a newer version: 5.1
Show newest version
/*
 * This file is part of AceQL Client SDK.
 * AceQL Client SDK: Remote JDBC access over HTTP with AceQL HTTP.                                 
 * Copyright (C) 2017,  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.client.jdbc;

import java.io.Closeable;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URLConnection;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.kawanfw.driver.jdbc.abstracts.AbstractConnection;

import com.aceql.client.jdbc.http.AceQLHttpApi;
import com.aceql.client.jdbc.util.AceQLConnectionUtil;

/**
 * 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/Clob updates with clean streaming behavior when * uploading.
  • *
  • Blob/Clob reads with clean streaming behavior when * downloading.
  • *
  • Transaction through commit and rollback orders. *
  • *
*

* Supplementary specific methods that are not of instance of Connection are * also added. * * After creating the AceQLConnection, just use it like a regular * Connection to execute your PreparedStatement and * Statement, and to navigate through your ResultSet. *

* 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()} *

* Example:

* *
 * // Define URL of the path to the AceQL Manager Servlet
 * // We will use a secure SSL/TLS session. All uploads/downloads of SQL
 * // commands & data will be encrypted.
 * String url = "https://www.acme.org:9443/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
 * // {@code DatabaseConfigurator.login(username, password)} method.
 * String database = "mydatabase";
 * String username = "MyUsername";
 * String password = "MyPassword";
 * 
 * // Attempts to establish a connection to the remote database:
 * Connection connection = new AceQLConnection(serverUrl, database, username,
 * 	password);
 * 
 * // We can now use our remote JDBC Connection as a regular JDBC
 * // Connection for our queries and updates:
 * String sql = "SELECT CUSTOMER_ID, FNAME, LNAME FROM CUSTOMER "
 * 	+ "WHERE CUSTOMER_ID = ?";
 * PreparedStatement prepStatement = connection.prepareStatement(sql);
 * prepStatement.setInt(1, 1);
 * 
 * ResultSet rs = prepStatement.executeQuery();
 * while (rs.next()) {
 *     String customerId = rs.getString("customer_id");
 *     String fname = rs.getString("fname");
 *     String lname = rs.getString("lname");
 * 
 *     System.out.println("customer_id: " + customerId);
 *     System.out.println("fname      : " + fname);
 *     System.out.println("lname      : " + lname);
 *     // Etc.
 * }
 * 
*
* The following dedicated AceQLConnection methods are specific to * the software and may be accessed with a cast: *
    *
  • {@link #setCancelled(AtomicBoolean)}
  • *
  • {@link #setGzipResult(boolean)}
  • *
  • {@link #setPrettyPrinting(boolean)}
  • *
  • {@link #setProgress(AtomicInteger)}
  • *
*

*
* 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 = new AceQLConnection(url, username, password,
 * 	database);
 * 
 * // 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. * * @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; /** * Sets the connect timeout. * * @param connectTimeout * Sets a specified 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. See * {@link URLConnection#setConnectTimeout(int)} */ public static void setConnectTimeout(int connectTimeout) { AceQLHttpApi.setConnectTimeout(connectTimeout); } /** * Sets the read timeout. * * @param readTimeout * an int that specifies the read timeout value, in * milliseconds, to be used when an http connection is * established to the remote server. See * {@link URLConnection#setReadTimeout(int)} */ public static void setReadTimeout(int readTimeout) { AceQLHttpApi.setReadTimeout(readTimeout); } /** * Login on the AceQL server and connect to a database * * @param serverUrl * the URL of the AceQL server. Example: * http://localhost:9090/aceql * @param database * the server database to connect to. * @param username * the login * @param password * the password * @throws SQLException * if any I/O error occurs */ public AceQLConnection(String serverUrl, String database, String username, char[] password) throws SQLException { this(serverUrl, database, username, password, null, null); } /** * Login on the AceQL server and connect to a database * * @param serverUrl * the URL of the AceQL server. Example: * http://localhost:9090/aceql * @param database * the server database to connect to. * @param username * the login * @param password * the password * @param proxy * the proxy to use. null if none. * @param passwordAuthentication * the username and password holder to use for authenticated * proxy. Null if no proxy or if proxy does not require * authentication. * @throws SQLException * if any I/O error occurs */ public AceQLConnection(String serverUrl, String database, String username, char[] password, Proxy proxy, PasswordAuthentication passwordAuthentication) throws SQLException { try { if (serverUrl == null) { throw new NullPointerException("serverUrl is null!"); } if (database == null) { throw new NullPointerException("database is null!"); } if (username == null) { throw new NullPointerException("username is null!"); } if (password == null) { throw new NullPointerException("password is null!"); } aceQLHttpApi = new AceQLHttpApi(serverUrl, database, username, password, proxy, passwordAuthentication); } catch (Exception e) { if (e instanceof AceQLException) { throw (AceQLException) e; } else { 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 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 RuntimeException(e.getMessage(), e); } } public void logout() { try { aceQLHttpApi.logout(); } catch (AceQLException e) { // Because close() can not throw an Exception, we wrap the // AceQLException with a RuntimeException throw new RuntimeException(e.getMessage(), e); } } /* * (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 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 * org.kawanfw.driver.jdbc.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 java.sql.Connection##createStatement() */ @Override public Statement createStatement() throws SQLException { AceQLStatement aceQLStatement = new AceQLStatement(this); return aceQLStatement; } /* * (non-Javadoc) * * @see * org.kawanfw.driver.jdbc.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 org.kawanfw.driver.jdbc.abstracts.AbstractConnection#prepareCall(java.lang.String) */ @Override public CallableStatement prepareCall(String sql) throws SQLException { AceQLCallableStatement aceQLCallableStatement = new AceQLCallableStatement( this, sql); return aceQLCallableStatement; } /* * (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 aceQLHttpApi.getClientVersion(); } /** * Returns the server product version * * @return the server product version * * @throws AceQLException * if any Exception occurs */ public String getServerVersion() throws AceQLException { return aceQLHttpApi.getServerVersion(); } /** * Says if trace is on * * @return true if trace is on */ public static boolean isTraceOn() { return AceQLHttpApi.isTraceOn(); } /** * Sets the trace on/off * * @param traceOn * if true, trace will be on */ public static void setTraceOn(boolean traceOn) { AceQLHttpApi.setTraceOn(traceOn); } /** * Says if JSON contents are to be pretty printed. Defaults to false. * * @param prettyPrinting * if true, JSON contents are to be pretty printed */ public void setPrettyPrinting(boolean prettyPrinting) { aceQLHttpApi.setPrettyPrinting(prettyPrinting); } /** * Define if SQL result sets are returned compressed with the GZIP file * format before download. Defaults to true. * * @param gzipResult * if true, sets are compressed before download */ public void setGzipResult(boolean gzipResult) { aceQLHttpApi.setGzipResult(gzipResult); } /** * Returns the cancelled value set by the progress indicator * * @return the cancelled value set by the progress indicator */ public AtomicBoolean getCancelled() { return aceQLHttpApi.getCancelled(); } /** * 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); } /** * 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 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 java.sql.Connection#close() */ public boolean isClosed() throws SQLException { return closed; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy