org.kawanfw.sql.servlet.connection.ConnectionStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aceql-http Show documentation
Show all versions of aceql-http Show documentation
AceQL HTTP is a framework of REST like http APIs that allow to access to remote SQL databases over http from any device that supports http.
AceQL HTTP is provided with four client SDK:
- The AceQL C# Client SDK allows to wrap the HTTP APIs using Microsoft SQL Server like calls in their code, just like they would for a local database.
- The AceQL Java Client SDK allows to wrap the HTTP APIs using JDBC calls in their code, just like they would for a local database.
- The AceQL Python Client SDK allows SQL calls to be encoded with standard unmodified DB-API 2.0 syntax
/*
* Copyright (c)2022 KawanSoft S.A.S. All rights reserved.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-11-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
package org.kawanfw.sql.servlet.connection;
import java.sql.Array;
import java.sql.Connection;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.kawanfw.sql.api.server.connectionstore.ConnectionKey;
import org.kawanfw.sql.util.FrameworkDebug;
/**
*
* Stores the Connection in static for subsequent new calls by remote device/PC
* clients.
*
* @author Nicolas de Pomereu
*/
public class ConnectionStore {
private static boolean DEBUG = FrameworkDebug.isSet(ConnectionStore.class);
/**
* The connection store key composed of client username and client connection id
*/
private ConnectionKey connectionKey = null;
/** Map of (username + sessionId + connectionId), connection= */
private static Map connectionMap = new ConcurrentHashMap<>();
/** The map of Savepoints */
private static Map> savepointMap = new ConcurrentHashMap<>();
/** The map of Arrays */
private static Map> arrayMap = new ConcurrentHashMap<>();
/** The map of RowIds */
private static Map> rowIdMap = new ConcurrentHashMap<>();
/**
* Constructor
*
* @param username
* @param sessionId
* @param connectionId
*/
public ConnectionStore(String username, String sessionId, String connectionId) {
if (username == null) {
throw new IllegalArgumentException("username is null!");
}
if (sessionId == null) {
throw new IllegalArgumentException("sessionId is null!");
}
//8.0: Connections Id is still not mandatory!
// Because of legacy with API without languages.
this.connectionKey = new ConnectionKey(username, sessionId, connectionId);
}
/**
* Stores the Connection in static for username + connectionId
*
* @param connection the Connection to store
*/
public void put(Connection connection) {
debug("Creating a Connection for user: " + connectionKey);
if (connection == null) {
throw new IllegalArgumentException("connection is null!");
}
connectionMap.put(connectionKey, connection);
}
/**
* Stores the Savepoint in static for username + connectionId
*
* @param savepoint the Savepoint to store
*/
public void put(Savepoint savepoint) {
debug("Creating a Savepoint for user: " + connectionKey);
if (savepoint == null) {
throw new IllegalArgumentException("savepoint is null!");
}
Set savepointSet = savepointMap.get(connectionKey);
if (savepointSet == null) {
savepointSet = new LinkedHashSet();
}
savepointSet.add(savepoint);
savepointMap.put(connectionKey, savepointSet);
}
/**
* Returns the Savepoint associated to username + connectionId and Savepoint ID
*
* @param savepointId the ID of the Savepoint
*
* @return the Savepoint associated to username + connectionId and Savepoint ID
*/
public Savepoint getSavepoint(int savepointId) {
Set savepointSet = savepointMap.get(connectionKey);
for (Iterator iterator = savepointSet.iterator(); iterator.hasNext();) {
Savepoint savepoint = iterator.next();
try {
if (savepoint.getSavepointId() == savepointId) {
return savepoint;
}
} catch (Throwable e) {
// Ignore. We don't care: it's a named Savepoint
}
}
return null;
}
/**
* Returns the Savepoint associated to username + connectionId and Savepoint Name
*
* @param savepointName the ID of the Savepoint
*
* @return the Savepoint associated to username + connectionId and Savepoint Name
*/
public Savepoint getSavepoint(String savepointName) {
Set savepointSet = savepointMap.get(connectionKey);
for (Iterator iterator = savepointSet.iterator(); iterator.hasNext();) {
Savepoint savepoint = iterator.next();
try {
if (savepoint.getSavepointName().equals(savepointName)) {
return savepoint;
}
} catch (Throwable e) {
// Ignore. We don't care: it's a named Savepoint
}
}
return null;
}
/**
* Remove the Savepoint associated to username + connectionId and savepointInfo
*
* @param a Savepoint that is just a container with the info to find the real
* one
*
*/
public void remove(Savepoint savepointInfo) {
Set savepointSet = savepointMap.get(connectionKey);
for (Iterator iterator = savepointSet.iterator(); iterator.hasNext();) {
Savepoint savepoint = iterator.next();
try {
if (savepoint.getSavepointId() == savepointInfo.getSavepointId()) {
savepointSet.remove(savepoint);
}
} catch (SQLException e) {
// We don't care: it's a named Savepoint
}
try {
if (savepoint.getSavepointName().equals(savepointInfo.getSavepointName())) {
savepointSet.remove(savepoint);
}
} catch (SQLException e) {
// We don't care: it's a unnamed Savepoint
}
}
}
/**
* Stores the Array in static for username + connectionId
*
* @param array the Array to store
*/
public void put(Array array) {
debug("Creating an array for user: " + connectionKey);
if (array == null) {
throw new IllegalArgumentException("array is null!");
}
Set arraySet = arrayMap.get(connectionKey);
if (arraySet == null) {
arraySet = new LinkedHashSet();
}
arraySet.add(array);
arrayMap.put(connectionKey, arraySet);
}
/**
* Returns the Array associated to username + connectionId and savepointInfo
*
* @param arrayId the array id (it's haschode())
*
* @return the Array associated to username + connectionId and arrayId
*/
public Array getArray(int arrayId) {
Set arraySet = arrayMap.get(connectionKey);
for (Iterator iterator = arraySet.iterator(); iterator.hasNext();) {
Array array = iterator.next();
if (array.hashCode() == arrayId) {
return array;
}
}
return null;
}
/**
* Stores the RowId in static for username + connectionId
*
* @param rowId the RowId to store
*/
public void put(RowId rowId) {
debug("Creating a rowId for user: " + connectionKey);
if (rowId == null) {
throw new IllegalArgumentException("rowId is null!");
}
Set rowIdSet = rowIdMap.get(connectionKey);
if (rowIdSet == null) {
rowIdSet = new LinkedHashSet();
}
rowIdSet.add(rowId);
rowIdMap.put(connectionKey, rowIdSet);
}
/**
* Returns the RowId associated to username + connectionId and hashCode
*
* @param rowIdHashCode the RowId id (it's haschode())
*
* @return the Array associated to username + connectionId and arrayId
*/
public RowId getRowId(int rowIdHashCode) {
Set rowIdSet = rowIdMap.get(connectionKey);
for (Iterator iterator = rowIdSet.iterator(); iterator.hasNext();) {
RowId rowId = iterator.next();
if (rowId.hashCode() == rowIdHashCode) {
return rowId;
}
}
return null;
}
/**
* Returns the Connection associated to username + connectionId
*
* @return the Connection associated to username + connectionId
*/
public Connection get() {
return connectionMap.get(connectionKey);
}
/**
* Returns the full Map of Connections associated to username + connectionId
* @return the connectionMap
*/
public static Map getConnectionMap() {
return connectionMap;
}
/**
* Remove all stored instances in the ConnectionStore. This must be done only in
* a Logout stage ({@code Connection#close()}).
*/
public void remove() {
debug("Removing a Connection for user: " + connectionKey);
connectionMap.remove(connectionKey);
savepointMap.remove(connectionKey);
arrayMap.remove(connectionKey);
rowIdMap.remove(connectionKey);
}
/**
* Static remove. To be used by an JdbcInterceptorTest.
* @param connectionKey
*/
public static void remove(ConnectionKey connectionKey) {
connectionMap.remove(connectionKey);
savepointMap.remove(connectionKey);
arrayMap.remove(connectionKey);
rowIdMap.remove(connectionKey);
}
/**
* Returns the size of the Connection Store
*
* @return the size of the Connection Store
*/
public int size() {
return connectionMap.size();
}
/**
* Returns the keys of the store
*
* @return the keys of the store
*/
public static Set getKeys() {
return connectionMap.keySet();
}
public static Set getAllConnections(String username, String sessionId) {
Set connections = new HashSet<>();
for (ConnectionKey connectionKey : connectionMap.keySet()) {
if (connectionKey.getUsername().equals(username) && connectionKey.getSessionId().equals(sessionId)) {
Connection connection = connectionMap.get(connectionKey);
connections.add(connection);
}
}
return connections;
}
/**
* Returns the first available Connection of all Connections for
* couple(username, sessionId)
*
* @return the first available Connection of all Connections for
* couple(username, sessionId)
*/
public Connection getFirst() throws SQLException {
Set connections = getAllConnections(this.connectionKey.getUsername(),
this.connectionKey.getSessionId());
if (connections.isEmpty()) {
throw new SQLException("No Connection stored for (" + this.connectionKey.getUsername() + ", "
+ this.connectionKey.getSessionId() + ")");
}
List connectionsList = new ArrayList<>();
connectionsList.addAll(connections);
return connectionsList.get(0);
}
public static void removeAll(String username, String sessionId) {
// No!! Will trigger a ConcurrentModificationException!
/**
for (ConnectionKey connectionKey : connectionMap.keySet()) {
if (connectionKey.getUsername().equals(username) && connectionKey.getSessionId().equals(sessionId)) {
connectionMap.remove(connectionKey);
}
}
*/
// Intermediate Collection to avoid ConcurrentModificationException on Map
Set connectionsKeys = new HashSet<>(connectionMap.keySet());
for (ConnectionKey connectionKey : connectionsKeys) {
if (connectionKey.getUsername().equals(username) && connectionKey.getSessionId().equals(sessionId)) {
connectionMap.remove(connectionKey);
}
}
}
/**
* Method called by children Servlet for debug purpose Println is done only if
* class name name is in kawansoft-debug.ini
*/
public static void debug(String s) {
if (DEBUG) {
System.out.println(new Date() + " " + s);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy