diff --git a/pom.xml b/pom.xml
index 7d76f6c..5de3b1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,12 @@
3.3
compile
+
+ org.apache.commons
+ commons-dbcp2
+ 2.1.1
+ compile
+
diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java
index 80b2ad8..800c2be 100644
--- a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java
+++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java
@@ -1,9 +1,9 @@
package org.gcube.datacatalogue.ckanutillibrary;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -15,6 +15,7 @@ import net.htmlparser.jericho.Renderer;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;
+import org.apache.commons.dbcp2.BasicDataSource;
import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
@@ -55,12 +56,19 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
private Integer CKAN_DB_PORT;
private String CKAN_TOKEN_SYS;
- // Connection to the db
- private Connection connection;
+ // use connections pool (multiple threads can use this CKanUtilsImpl instance)
+ private BasicDataSource ds;
+ /**
+ * The ckan catalogue url and database will be discovered in this scope
+ * @param scope
+ * @throws Exception if unable to find datacatalogue info
+ */
public CKanUtilsImpl(String scope) throws Exception{
CKanRunningCluster runningInstance = new CKanRunningCluster(scope);
+
+ // save information
CKAN_DB_URL = runningInstance.getDatabaseHosts().get(0);
CKAN_DB_NAME = runningInstance.getDataBaseName();
CKAN_DB_USER = runningInstance.getDataBaseUser();
@@ -68,26 +76,42 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Plain password first 3 chars are " + CKAN_DB_PASSWORD.substring(0, 3));
CKAN_TOKEN_SYS = runningInstance.getSysAdminToken();
logger.debug("Plain sys admin token first 3 chars are " + CKAN_TOKEN_SYS.substring(0, 3));
-
CKAN_DB_PORT = runningInstance.getDatabasePorts().get(0);
CKAN_CATALOGUE_URL = runningInstance.getDataCatalogueUrl().get(0);
+
+ // create connection pool
+ String url = "jdbc:postgresql://" + CKAN_DB_URL + ":" + CKAN_DB_PORT + "/" + CKAN_DB_NAME;
+ ds = new BasicDataSource();
+ ds.setDriverClassName("org.postgresql.Driver");
+ ds.setUsername(CKAN_DB_USER);
+ ds.setPassword(CKAN_DB_PASSWORD);
+ ds.setUrl(url);
- Class.forName("org.postgresql.Driver");
- connection = DriverManager.getConnection(
- "jdbc:postgresql://" + CKAN_DB_URL + ":" + CKAN_DB_PORT + "/" + CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD);
+ }
+
+ /**
+ * Retrieve connection from the pool
+ * @return
+ * @throws SQLException
+ */
+ private Connection getConnection() throws SQLException{
+
+ return ds.getConnection();
+
}
@Override
public String getApiKeyFromUsername(String username) {
+ logger.debug("Request api key for user = " + username);
+
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
- logger.debug("Request api key for user = " + username);
String apiToReturn = null;
try{
String query = "SELECT \"apikey\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;";
- PreparedStatement preparedStatement = connection.prepareStatement(query);
+ PreparedStatement preparedStatement = getConnection().prepareStatement(query);
preparedStatement.setString(1, ckanUsername);
preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
@@ -111,17 +135,13 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
CKanUserWrapper user = new CKanUserWrapper();
try{
String query = "SELECT * FROM \"user\" WHERE \"apikey\"=? and \"state\"=?;";
- PreparedStatement preparedStatement = connection.prepareStatement(query);
+ PreparedStatement preparedStatement = getConnection().prepareStatement(query);
preparedStatement.setString(1, apiKey);
preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
- // check if it is active
- if(State.DELETED.equals(rs.getString("state")))
- break;
-
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setApiKey(apiKey);
@@ -149,7 +169,6 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
- List organizationIds = getOrganizationsIds();
String userId = getUserIdByUsername(ckanUsername);
// list to return
@@ -159,10 +178,12 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
CkanClient client = new CkanClient(CKAN_CATALOGUE_URL);
try{
+ List organizationIds = getOrganizationsIds();
+
// for each org id, check if the user is included
for (String orgId : organizationIds) {
String query = "SELECT * FROM \"member\" WHERE \"table_id\"=? and \"group_id\"=? and \"table_name\"=? and \"state\"=?;";
- PreparedStatement preparedStatement = connection.prepareStatement(query);
+ PreparedStatement preparedStatement = getConnection().prepareStatement(query);
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
@@ -173,7 +194,6 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("User " + ckanUsername + " belongs to organization with id " + orgId);
toReturn.add(client.getOrganization(orgId));
}
-
}
}catch(Exception e){
logger.error("Unable to get user's organizations", e);
@@ -193,13 +213,12 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
- // get its key
- String apiKey = getApiKeyFromUsername(ckanUsername);
-
- // retrieve the user and if it is a sys_admin, for every organizations will be created in the map, add also
+ // retrieve the user and if it is a sys_admin, for every organizations that will be created in the map add also
// the sys_admin role
boolean isSysAdmin = false;
if(rolesToMatch.contains(RolesIntoOrganization.SYSADMIN)){
+ // get its key
+ String apiKey = getApiKeyFromUsername(ckanUsername);
isSysAdmin = isSysAdmin(ckanUsername, apiKey);
}
@@ -208,17 +227,14 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
// get id from the user
String userId = getUserIdByUsername(ckanUsername);
- // use the above method to require the list of user's organizations
- List usersOrganizations = getOrganizationsByUser(ckanUsername);
+ // get the id of all the organizations
+ List organizationIds = getOrganizationsIds();
- for (CkanOrganization ckanOrganization : usersOrganizations) {
-
- // get the org id
- String orgId = ckanOrganization.getId();
+ for (String orgId : organizationIds) {
// go to the member table, that says which role has this user into the org
String query = "SELECT * FROM \"member\" WHERE \"table_id\"=? and \"group_id\"=? and \"table_name\"=? and \"state\"=?;";
- PreparedStatement preparedStatement = connection.prepareStatement(query);
+ PreparedStatement preparedStatement = getConnection().prepareStatement(query);
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
@@ -236,9 +252,8 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
// check
String role = rs.getString("capacity");
if(rolesToMatch.contains(RolesIntoOrganization.valueOf(role))){
-
rolesIntoOrg.add(RolesIntoOrganization.valueOf(role));
- logger.debug("User " + ckanUsername + " has role " + role + " into organization " + ckanOrganization.getName());
+ logger.debug("User " + ckanUsername + " has role " + role + " into organization with id " + orgId);
}
}
@@ -262,18 +277,11 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
-
- String userId = null;
+
+ String userId = null;
try{
- String query = "SELECT \"id\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;";
- PreparedStatement preparedStatement = connection.prepareStatement(query);
- preparedStatement.setString(1, ckanUsername);
- preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
- ResultSet rs = preparedStatement.executeQuery();
- while (rs.next()) {
- userId = rs.getString("id");
- break;
- }
+ CkanClient client = new CkanClient(CKAN_CATALOGUE_URL);
+ client.getUser(ckanUsername).getId();
logger.debug("User id retrieved for " + ckanUsername + " "+ userId);
}catch(Exception e){
logger.error("Unable to retrieve user with name " + ckanUsername, e);
@@ -314,7 +322,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
List orgs = getOrganizationsByUser(ckanUsername);
-
+
List orgsName = new ArrayList();
for (CkanOrganization ckanOrganization : orgs) {
orgsName.add(ckanOrganization.getName());
@@ -651,7 +659,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Request for checking if " + username + " into " + organizationName + " has role " + correspondentRoleToCheck);
if(correspondentRoleToCheck.equals(RolesIntoOrganization.SYSADMIN)){
-
+
logger.debug("SYSADMIN role cannot be created programmatically... The user role will be turned into admin");
correspondentRoleToCheck = RolesIntoOrganization.ADMIN;
}
@@ -679,7 +687,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try {
-
+
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token
StringEntity params = new StringEntity(parameter);
@@ -715,7 +723,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
@Override
protected void finalize() throws Throwable {
- logger.debug("Closing connection on finalize()");
- connection.close();
+ logger.debug("Closing connection poolon finalize()");
+ ds.close();
}
}