diff --git a/src/main/java/org/gcube/vomanagement/usermanagement/impl/ws/LiferayWSUserManager.java b/src/main/java/org/gcube/vomanagement/usermanagement/impl/ws/LiferayWSUserManager.java index bf3b07f..b3996ea 100644 --- a/src/main/java/org/gcube/vomanagement/usermanagement/impl/ws/LiferayWSUserManager.java +++ b/src/main/java/org/gcube/vomanagement/usermanagement/impl/ws/LiferayWSUserManager.java @@ -6,10 +6,12 @@ import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpHost; @@ -83,6 +85,7 @@ public class LiferayWSUserManager implements UserManager{ // some pre-defined constants private static final String USER_LOCATION_INDUSTRY_KEY = "industry"; + private static final int USERS_EXECUTOR_FACTOR = 20; /** * In order to contact the json ws of Liferay, user and password are needed. The host in which the current JVM @@ -225,7 +228,7 @@ public class LiferayWSUserManager implements UserManager{ } /** - * Given the contactId value, retrieves the json object releted to this information + * Given the contactId value, retrieves the json object related to this information * @param contactId * @return */ @@ -368,23 +371,64 @@ public class LiferayWSUserManager implements UserManager{ } @Override + @SuppressWarnings("rawtypes") public List listUsersByGroup(long groupId) throws UserManagementSystemException, GroupRetrievalFault, UserRetrievalFault { try{ - List toReturn = new ArrayList(); + final List toReturn = new ArrayList(); String jsonUsers = HttpUtils.executeHTTPGETRequest(API_BASE_URL + GET_USERS_BY_GROUP.replace("$GROUP_ID", String.valueOf(groupId)), credsProvider, localContext, target); if(jsonUsers != null){ + logger.debug("Trying to parse json users array "); JSONParser parser = new JSONParser(); JSONArray array = (JSONArray)parser.parse(jsonUsers); - for (int i = 0; i < array.size(); i++) { - toReturn.add(mapLRUser(((JSONObject)array.get(i)).toJSONString())); + + // use executors to speed up this process + int numberOfThreads = (int) Math.ceil((double)array.size()/(double)USERS_EXECUTOR_FACTOR); + logger.trace("Number of concurrent threads is going to be " + numberOfThreads); + + // let do the job by some threads + ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); + int start = 0; + int offset = USERS_EXECUTOR_FACTOR; + + for(int i = 0; i < numberOfThreads; i++){ + start = USERS_EXECUTOR_FACTOR * i; + offset = (start + offset) > array.size() ? array.size() - start: offset; + logger.trace("Start = " + start + ", offset=" + offset); + final List usersPortion = array.subList(start, start + offset); + + executor.submit(new Runnable() { + @Override + public void run() { + logger.debug("Thread is " + Thread.currentThread().getName()); + + ArrayList localList = new ArrayList(); + for(int i = 0; i < usersPortion.size(); i++){ + localList.add(mapLRUser(((JSONObject)usersPortion.get(i)).toJSONString())); + } + + // avoid contention on a single retrieved value but add them all at the end + synchronized (toReturn){ + toReturn.addAll(localList); + } + } + }); + + // stop when ... + if((start + offset) >= array.size()) + break; } + + // wait threads to finish + executor.shutdown(); + executor.awaitTermination(2, TimeUnit.MINUTES); + }else return null; @@ -478,42 +522,91 @@ public class LiferayWSUserManager implements UserManager{ } @Override - public List listUsersByGroupAndRole(long groupId, long roleId) + public List listUsersByGroupAndRole(final long groupId, final long roleId) throws UserManagementSystemException, RoleRetrievalFault, GroupRetrievalFault, UserRetrievalFault { - List toReturn = listUsersByGroup(groupId); + final List toReturn = new ArrayList(0); + try { + final List usersInGroup = listUsersByGroup(groupId); + logger.debug("Number of users is " + usersInGroup.size()); - Iterator iterator = toReturn.iterator(); - while (iterator.hasNext()) { - GCubeUser gCubeUser = (GCubeUser) iterator.next(); - long userId = gCubeUser.getUserId(); + if(usersInGroup == null || usersInGroup.isEmpty()) + return toReturn; - String userRoles = - HttpUtils.executeHTTPGETRequest(API_BASE_URL + GET_ROLES_IN_GROUP_BY_USER.replace("$GROUP_ID", String.valueOf(groupId)).replace("$USER_ID", String.valueOf(userId)), - credsProvider, localContext, target); + // use executors to speed up this process + int numberOfThreads = (int) Math.ceil((double)usersInGroup.size()/(double)USERS_EXECUTOR_FACTOR); + logger.trace("Number of concurrent threads is going to be " + numberOfThreads); - boolean userHasRole = false; - JSONParser parser = new JSONParser(); - JSONArray array = (JSONArray)parser.parse(userRoles); - for (int i = 0; i < array.size(); i++) { - try { - GCubeRole role = LiferayWSRoleManager.mapLRRole(array.get(i).toString()); - if(role.getRoleId() == roleId){ - userHasRole = true; - break; + // let do the job by some threads + ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); + int start = 0; + int offset = USERS_EXECUTOR_FACTOR; + + for(int i = 0; i < numberOfThreads; i++){ + start = USERS_EXECUTOR_FACTOR * i; + offset = (start + offset) > usersInGroup.size() ? usersInGroup.size() - start: offset; + logger.trace("Start = " + start + ", offset=" + offset); + final List usersPortion = usersInGroup.subList(start, start + offset); + + executor.submit(new Runnable() { + + @Override + public void run() { + logger.debug("Thread is " + Thread.currentThread().getName()); + ArrayList localUsersHavingRole = new ArrayList(0); + + for(GCubeUser user: usersPortion){ + long userId = user.getUserId(); + String userRoles = + HttpUtils.executeHTTPGETRequest(API_BASE_URL + GET_ROLES_IN_GROUP_BY_USER.replace("$GROUP_ID", String.valueOf(groupId)).replace("$USER_ID", String.valueOf(userId)), + credsProvider, localContext, target); + + boolean userHasRole = false; + JSONParser parser = new JSONParser(); + JSONArray array; + try { + array = (JSONArray)parser.parse(userRoles); + + for (int i = 0; i < array.size(); i++) { + try { + GCubeRole role = LiferayWSRoleManager.mapLRRole(array.get(i).toString()); + if(role.getRoleId() == roleId){ + userHasRole = true; + break; + } + } catch (PortalException | SystemException | ParseException e) { + logger.warn("Failed to retrieve a role for user " + user.getUsername()); + } + } + + // add if he/she has + if(userHasRole) + localUsersHavingRole.add(user); + + } catch (ParseException e1) { + logger.warn("Failed to parse role for user " + user.getUsername()); + } } - } catch (PortalException | SystemException | ParseException e) { - logger.warn("Failed to retrieve a role for user " + gCubeUser.getUsername()); - } - } - if(!userHasRole) - iterator.remove(); + // avoid contention on a single retrieved value but add them all at the end + synchronized (toReturn) { + toReturn.addAll(localUsersHavingRole); + } + } + }); + + // stop when ... + if((start + offset) >= usersInGroup.size()) + break; } + // wait threads to finish + executor.shutdown(); + executor.awaitTermination(2, TimeUnit.MINUTES); + } catch (Exception e) { logger.warn("Failed to retrieve users that have role whit id " + roleId + " in group with id " + groupId); return null; diff --git a/src/test/java/org/gcube/vomanagement/usermanagement/test/LiferayWSUserTest.java b/src/test/java/org/gcube/vomanagement/usermanagement/test/LiferayWSUserTest.java index 4ce7de8..e8bfed5 100644 --- a/src/test/java/org/gcube/vomanagement/usermanagement/test/LiferayWSUserTest.java +++ b/src/test/java/org/gcube/vomanagement/usermanagement/test/LiferayWSUserTest.java @@ -34,7 +34,7 @@ public class LiferayWSUserTest{ userManager = new LiferayWSUserManager(user, password, host, schema, port); } - + //@Test public void getUserByUsername() throws UserManagementSystemException, UserRetrievalFault{ @@ -57,8 +57,26 @@ public class LiferayWSUserTest{ //@Test public void listUsersByGroup() throws UserManagementSystemException, UserRetrievalFault, GroupRetrievalFault{ + long init = System.currentTimeMillis(); List gcubeUsers = userManager.listUsersByGroup(21660); - logger.debug("Retrieved user object " + gcubeUsers); + logger.debug("Retrieved user object " + gcubeUsers.size()); + logger.debug("Time is " + (System.currentTimeMillis() - init) ); + } + + //@Test + public void getUsersHavingRole() throws UserManagementSystemException, RoleRetrievalFault, GroupRetrievalFault, UserRetrievalFault{ + + long roleId = 29548512; // data miner manager + long groupId = 21660; + long init = System.currentTimeMillis(); + List users = userManager.listUsersByGroupAndRole(groupId, roleId); + logger.debug("Time is " + (System.currentTimeMillis() - init) ); + logger.debug("Users are " + users); + + for (GCubeUser user:users) { + logger.debug("Username is " + user.getUsername() + "\n"); + + } } @@ -80,18 +98,6 @@ public class LiferayWSUserTest{ } - //@Test - public void getUsersHavingRole() throws UserManagementSystemException, RoleRetrievalFault, GroupRetrievalFault, UserRetrievalFault{ - - long roleId = 25184135; - long groupId = 21660; - long init = System.currentTimeMillis(); - List users = userManager.listUsersByGroupAndRole(groupId, roleId); - logger.debug("Time is " + (System.currentTimeMillis() - init) ); - logger.debug("Users are " + users); - - } - //@Test public void listUsersByGlobalRole(){