package org.gcube.datacatalogue.utillibrary.server; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.datacatalogue.utillibrary.ckan.ExtendCkanClient; import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject; import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject.METHOD; import org.gcube.datacatalogue.utillibrary.db.DBCaller; import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller; import org.gcube.datacatalogue.utillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; import org.gcube.datacatalogue.utillibrary.server.utils.CKANConveter; import org.gcube.datacatalogue.utillibrary.server.utils.CatalogueUtilMethods; import org.gcube.datacatalogue.utillibrary.server.utils.GCubeUtils; import org.gcube.datacatalogue.utillibrary.server.utils.GcubeContext; import org.gcube.datacatalogue.utillibrary.server.utils.url.EntityContext; import org.gcube.datacatalogue.utillibrary.shared.LandingPages; import org.gcube.datacatalogue.utillibrary.shared.ResourceBean; import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg; import org.gcube.datacatalogue.utillibrary.shared.State; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanGroup; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanLicense; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanOrganization; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanPair; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanResource; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanUser; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.exceptions.JackanException; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is the Ckan Utils implementation class. * * revisited by * @author Francesco Mangiacrapa at ISTI-CNR * * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) */ public class DataCatalogueImpl implements DataCatalogue { private static final Logger LOG = LoggerFactory.getLogger(DataCatalogueImpl.class); private String CKAN_CATALOGUE_URL; private String CKAN_DB_NAME; private String CKAN_DB_USER; private String CKAN_DB_PASSWORD; private String CKAN_DB_URL; private Integer CKAN_DB_PORT; private String PORTLET_URL_FOR_SCOPE; private String SOLR_URL; private String CKAN_TOKEN_SYS; private String CKAN_EMAIL; private String URI_RESOLVER_URL; private boolean MANAGE_PRODUCT_BUTTON; private boolean SOCIAL_POST; private boolean ALERT_USERS_ON_POST_CREATION; private String CONTEXT; private Map extendRoleInOrganization; public Map mapAccessURLToCatalogue; private static final String CATALOGUE_TAB_ENDING_URL = "/catalogue"; // gCat client private GCatCaller gCatCaller; // db client private DBCaller dbCaller; // ckan client private ExtendCkanClient ckanCaller; // hashmap for ckan api keys private ConcurrentHashMap apiKeysMap; //http ckan caller //private DirectCkanCaller directCkanCaller; //is not needed anymore? // apikey bean expires after X minutes in the above map private static final int EXPIRE_KEY_TIME = 60 * 60 * 1000; /** * The ckan catalogue url and database will be discovered in this scope. * * @param scope the scope * @throws Exception if unable to find datacatalogue info */ public DataCatalogueImpl(String scope) throws Exception{ DataCatalogueRunningCluster runningInstance = new DataCatalogueRunningCluster(scope); // save information CKAN_DB_URL = runningInstance.getDatabaseHosts().get(0).trim(); CKAN_DB_PORT = runningInstance.getDatabasePorts().get(0); CKAN_DB_NAME = runningInstance.getDataBaseName().trim(); CKAN_DB_USER = runningInstance.getDataBaseUser().trim(); CKAN_DB_PASSWORD = runningInstance.getDataBasePassword().trim(); CKAN_TOKEN_SYS = runningInstance.getSysAdminToken().trim(); CKAN_EMAIL = runningInstance.getEmailCatalogue().trim(); CKAN_CATALOGUE_URL = runningInstance.getDataCatalogueUrl().get(0).trim(); PORTLET_URL_FOR_SCOPE = runningInstance.getPortletUrl().trim(); mapAccessURLToCatalogue = runningInstance.getMapAccessURLToCatalogue(); MANAGE_PRODUCT_BUTTON = runningInstance.isManageProductEnabled(); URI_RESOLVER_URL = runningInstance.getUrlResolver(); SOCIAL_POST = runningInstance.isSocialPostEnabled(); ALERT_USERS_ON_POST_CREATION = runningInstance.isAlertEnabled(); SOLR_URL = runningInstance.getUrlSolr(); LOG.info("In the scope: "+scope+", I read the catalogue URL: " + CKAN_CATALOGUE_URL); // build the clients gCatCaller = new GCatCaller(CKAN_CATALOGUE_URL); dbCaller = new DBCaller(CKAN_DB_URL, CKAN_DB_PORT, CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD); ckanCaller = new ExtendCkanClient(CKAN_CATALOGUE_URL); //directCkanCaller = new DirectCkanCaller(CKAN_CATALOGUE_URL); //is not needed anymore? // init map apiKeysMap = new ConcurrentHashMap(); // save the context CONTEXT = scope; // extended roles extendRoleInOrganization = runningInstance.getExtendRoleInOrganization(); } /** * The ckan catalogue url and database will be discovered in this scope. * * @param scope the scope * @param sysAuthentication if true perform the sys authentication * @throws Exception if unable to find datacatalogue info */ public DataCatalogueImpl(String scope, boolean sysAuthentication) throws Exception{ this(scope); if(sysAuthentication) ckanCaller = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS); } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getCatalogueUrl() */ @Override public String getCatalogueUrl() { return CKAN_CATALOGUE_URL; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getPortletUrl() */ @Override public String getPortletUrl() { //PATCHED By Francesco ScopeBean context = new ScopeBean(CONTEXT); if(context.is(Type.INFRASTRUCTURE)) { LOG.info("Working with the {} scope returning the path read from GR 'Ckan-Porltet': {}", Type.INFRASTRUCTURE.toString(), PORTLET_URL_FOR_SCOPE); return PORTLET_URL_FOR_SCOPE; } String vreNameLower = context.name().toLowerCase(); //CHECKING IF THE PORTLET URL CONTAINS THE VRE NAME INTO URL if(PORTLET_URL_FOR_SCOPE.toLowerCase().contains(vreNameLower)){ //THE PORLTET URL READ FROM GENERIC RESOUCE 'CkanPortlet' SHOULD BE ALREADY VALID, POITING TO CKAN PORTLET return PORTLET_URL_FOR_SCOPE; }else{ //ADDING VRE getApiKeyFromUsernameNAME AND THE SUFFIX 'CATALOGUE_TAB_ENDING_URL' TO URL String buildedUrl = PORTLET_URL_FOR_SCOPE.endsWith("/") ? PORTLET_URL_FOR_SCOPE : PORTLET_URL_FOR_SCOPE + "/"; String defaultSuffix = vreNameLower + CATALOGUE_TAB_ENDING_URL; buildedUrl+= defaultSuffix; LOG.warn("The Portlet URL read from Generic Resource 'Ckan-Porltet' does not contain the portlet suffix, so I added the default: "+defaultSuffix); return buildedUrl; } } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#findLicenseIdByLicenseTitle(java.lang.String) */ @Override public String findLicenseIdByLicenseTitle(String chosenLicense) { LOG.debug("Requested license id"); // checks checkNotNull(chosenLicense); //retrieve the list of available licenses List licenses = ckanCaller.getLicenseList(); for (CkanLicense ckanLicense : licenses) { if(ckanLicense.getTitle().equals(chosenLicense)) return ckanLicense.getId(); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLicenseTitles() */ @Override public List getLicenseTitles() { LOG.debug("Request for CKAN licenses"); // get the url and the api key of the user List result = new ArrayList(); // retrieve the list of available licenses List licenses = ckanCaller.getLicenseList(); for (CkanLicense ckanLicense : licenses) { result.add(ckanLicense.getTitle()); LOG.debug("License is " + ckanLicense.getTitle() + " and id " + ckanLicense.getId()); } return result; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLicenses() */ @Override public List getLicenses() { LOG.debug("Request for CKAN licenses (original jackan objects are going to be retrieved)"); // retrieve the list of available licenses return ckanCaller.getLicenseList(); } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getDataset(java.lang.String, java.lang.String) */ @Override public CkanDataset getDataset(String datasetIdOrName, String username) { LOG.info("Called getDataset with id or name" + datasetIdOrName+ " and username: "+username); // checks checkNotNull(datasetIdOrName); checkArgument(!datasetIdOrName.isEmpty()); try { if (username != null && !username.isEmpty()) { LOG.info("username found. Calling the " + ExtendCkanClient.class.getSimpleName()); String apiKey = getApiKeyFromUsername(username); ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey); return client.getDataset(datasetIdOrName); } LOG.info("No username found. Calling Ckan Client without API-KEY"); return ckanCaller.getDataset(datasetIdOrName); } catch (Exception e) { LOG.error("Unable to retrieve such dataset, returning null ...", e); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUnencryptedUrlFromDatasetIdOrName(java.lang.String) */ @Override public String getUnencryptedUrlFromDatasetIdOrName(String datasetIdOrName) { LOG.debug("Request coming for getting dataset url (not encrypted) of dataset with name/id " + datasetIdOrName); // checks checkNotNull(datasetIdOrName); checkArgument(!datasetIdOrName.isEmpty()); String url = null; try { // get the dataset from name ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS); CkanDataset dataset = client.getDataset(datasetIdOrName); String name = dataset.getName(); if (dataset != null) { if (getUriResolverUrl() != null) url = getUrlForProduct(CONTEXT, EntityContext.DATASET, name); if (url == null || url.isEmpty()) url = getPortletUrl() + "?" + URLEncoder.encode("path=/dataset/" + name, "UTF-8"); } } catch (Exception e) { LOG.error("Error while retrieving dataset with id/name=" + datasetIdOrName, e); } // requestEntity.put("clear_url", Boolean.toString(unencrypted)); return url; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUserRoleByGroup(java.lang.String) */ @Override public Map> getUserRoleByGroup(String username) { LOG.info("Get user role by group called. The username is: " + username); checkNotNull(username); Map> toReturn = new HashMap>(); try { String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); Map partialResult = dbCaller.getGroupsByUserFromDB(ckanUsername); for (String groupID : partialResult.keySet()) { CkanGroup group = ckanCaller.getGroup(groupID); HashMap subMap = new HashMap(); subMap.put(group, partialResult.get(groupID)); toReturn.put(groupID, subMap); } LOG.debug("Returning map " + toReturn); LOG.info("Found " + toReturn.size() + " group/s with the user " + username); } catch (Exception e) { LOG.error("Failed to retrieve roles of user in his/her own groups", e); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUserRoleByOrganization(java.lang.String) */ @Override public Map> getUserRoleByOrganization(String username) { LOG.info("Get user role by organization called. The username is: " + username); checkNotNull(username); Map> toReturn = new HashMap>(); try { String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); Map partialResult = dbCaller.getOrganizationsByUserFromDB(ckanUsername); for (String orgID : partialResult.keySet()) { CkanOrganization org = ckanCaller.getOrganization(orgID); HashMap subMap = new HashMap(); subMap.put(org, partialResult.get(orgID)); toReturn.put(orgID, subMap); LOG.debug("For organisation: " + org.getName() + ", the user " + username + " has role: " + subMap); } LOG.debug("Returning map " + toReturn); LOG.info("Found " + toReturn.size() + " organization/s with the user " + username); } catch (Exception e) { LOG.error("Failed to retrieve roles of user in his/her own groups", e); } return toReturn; } /** * Retrieve an url for the tuple scope, entity, entity name. * * @param context the context * @param entityContext the entity context * @param entityName the entity name * @return the url for product */ private String getUrlForProduct(String context, EntityContext entityContext, String entityName) { String toReturn = null; try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { HttpPost httpPostRequest = new HttpPost(getUriResolverUrl()); JSONObject requestEntity = new JSONObject(); requestEntity.put("gcube_scope", context); requestEntity.put("entity_context", entityContext.toString()); requestEntity.put("entity_name", entityName); StringEntity params = new StringEntity(requestEntity.toJSONString(), ContentType.APPLICATION_JSON); httpPostRequest.setEntity(params); HttpResponse response = httpClient.execute(httpPostRequest); if (response.getStatusLine().getStatusCode() != 200) throw new Exception("There was an error while creating an url " + response.getStatusLine()); toReturn = EntityUtils.toString(response.getEntity()); LOG.debug("Result is " + toReturn); } catch (Exception e) { LOG.error("Failed to get an url for this product", e); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLandingPages() */ @Override public LandingPages getLandingPages() throws Exception { LandingPages landingPages = new LandingPages(); landingPages.setUrlGroups(PORTLET_URL_FOR_SCOPE + "?path=/group/"); landingPages.setUrlItems(PORTLET_URL_FOR_SCOPE + "?path=/dataset/"); landingPages.setUrlOrganizations(PORTLET_URL_FOR_SCOPE + "?path=/organization/"); landingPages.setUrlTypes(PORTLET_URL_FOR_SCOPE + "?path=/type/"); return landingPages; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUriResolverUrl() */ @Override public String getUriResolverUrl() { return URI_RESOLVER_URL; } /** * Check if the manage product is enabled. * * @return true, if is manage product enabled */ @Override public boolean isManageProductEnabled() { return MANAGE_PRODUCT_BUTTON; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getGroupByName(java.lang.String) */ @Override public CkanGroup getGroupByName(String name) { String ckanName = CatalogueUtilMethods.fromGroupTitleToName(name); try{ return ckanCaller.getGroup(ckanName); }catch(Exception e){ LOG.error("Failed to retrieve the group with name" + name, e); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#isNotificationToUsersEnabled() */ @Override public boolean isNotificationToUsersEnabled() { return ALERT_USERS_ON_POST_CREATION; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsByUser(java.lang.String) */ @Override public List getOrganizationsByUser(String username) { LOG.debug("Requested organizations for user " + username); // checks checkNotNull(username); // in order to avoid errors, the username is always converted String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); // list to return List toReturn = new ArrayList(); try { Map partialResult = dbCaller.getOrganizationsByUserFromDB(ckanUsername); for (String orgID : partialResult.keySet()) { CkanOrganization org = ckanCaller.getOrganization(orgID, false); LOG.debug("User " + ckanUsername + " is into " + org.getName()); toReturn.add(org); } } catch (Exception e) { LOG.error("Unable to get user's organizations", e); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getGroupsByUser(java.lang.String) */ @Override public List getGroupsByUser(String username) { LOG.debug("Requested groups for user " + username); // checks checkNotNull(username); // in order to avoid errors, the username is always converted String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); // list to return List toReturn = new ArrayList(); try { Map partialResult = dbCaller.getGroupsByUserFromDB(ckanUsername); for (String groupID : partialResult.keySet()) { CkanGroup group = ckanCaller.getGroup(groupID, false); LOG.debug("User " + ckanUsername + " is into " + group.getName()); toReturn.add(group); } } catch (Exception e) { LOG.error("Unable to get user's groups", e); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsIds() */ @Override public List getOrganizationsIds() { List toReturn = new ArrayList(); List orgs = ckanCaller.getOrganizationList(); for (CkanOrganization ckanOrganization : orgs) { LOG.debug("Retrieved org " + ckanOrganization.getName()); toReturn.add(ckanOrganization.getId()); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsNames() */ @Override public List getOrganizationsNames() { List toReturn = new ArrayList(); List orgs = ckanCaller.getOrganizationList(); for (CkanOrganization ckanOrganization : orgs) { LOG.debug("Retrieved org " + ckanOrganization.getName()); toReturn.add(ckanOrganization.getName()); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsNamesByUser(java.lang.String) */ @Override public List getOrganizationsNamesByUser(String username) { LOG.debug("Requested organizations for user " + username); // checks checkNotNull(username); // in order to avoid errors, the username is always converted String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); List orgs = getOrganizationsByUser(ckanUsername); List orgsName = new ArrayList(); for (CkanOrganization ckanOrganization : orgs) { orgsName.add(ckanOrganization.getName()); LOG.debug("Organization name is " + ckanOrganization.getName()); } return orgsName; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getRoleOfUserInOrganization(java.lang.String, java.lang.String) */ @Override public String getRoleOfUserInOrganization(String username, String orgName) { String toReturn = null; String apiKey = getApiKeyFromUsername(username); String usernameCkan = CatalogueUtilMethods.fromUsernameToCKanUsername(username); try { ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey); List users = client.getOrganization(orgName).getUsers(); for (CkanUser ckanUser : users) { if (ckanUser.getName().equals(usernameCkan)) { toReturn = ckanUser.getCapacity(); break; } } } catch (Exception e) { LOG.error("Unable to retrieve the role the user has into organization: " + orgName, e); } return toReturn; } /** * Check if the user is valid by checking if its API_KEY is present into DB. * * @param username the username * @return true, if successful */ @Override public boolean checkValidUser(String username) { String apiKey = getApiKeyFromUsername(username); return apiKey != null; } /** * Gets the api key from username. * * @param username the username * @return the api key from username */ private String getApiKeyFromUsername(String username) { LOG.debug("Request api key for user = " + username); // checks checkNotNull(username); checkArgument(!username.isEmpty()); // in order to avoid errors, the username is always converted String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); LOG.debug("username: "+username + " converted to ckanUsername: "+ckanUsername); // check in the hashmap first if (apiKeysMap.containsKey(ckanUsername)) { CKANTokenBean bean = apiKeysMap.get(ckanUsername); if (bean.timestamp + EXPIRE_KEY_TIME > System.currentTimeMillis()) { // it's still ok return bean.apiKey; } } LOG.debug("Api key was not in cache or it expired"); try { String apiToReturn = dbCaller.getApiKeyFromUsername(ckanUsername, State.ACTIVE.name().toLowerCase()); // save into the hashmap if (apiToReturn != null) apiKeysMap.put(ckanUsername, new CKANTokenBean(apiToReturn, System.currentTimeMillis())); return apiToReturn; } catch (Exception e) { LOG.error("Unable to retrieve key for user " + ckanUsername, e); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#existProductWithNameOrId(java.lang.String) */ @Override public boolean existProductWithNameOrId(String nameOrId) { checkNotNull(nameOrId); checkArgument(!nameOrId.isEmpty()); try { ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS); CkanDataset product = client.getDataset(nameOrId); return product != null; } catch (Exception e) { LOG.debug("A dataset with name " + nameOrId + " doesn't exist"); return false; } } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationByIdOrName(java.lang.String) */ @Override public CkanOrganization getOrganizationByIdOrName(String idOrName) { checkNotNull(idOrName); String ckanName = idOrName.toLowerCase(); try { return ckanCaller.getOrganization(ckanName); } catch (Exception e) { LOG.warn("Failed to retrieve the organization with name " + idOrName + " on the ckan: " + ckanCaller.getCatalogUrl(), e); } return null; } /** * Check if the user has this role into the organization/group with * groupOrOrganization name. * * @param ckanUsername the ckan username * @param groupOrOrganization the group or organization * @param correspondentRoleToCheck the correspondent role to check * @param group the group * @return true if he has the role, false otherwise * @throws Exception the exception */ protected boolean isRoleAlreadySet(String ckanUsername, String groupOrOrganization, RolesCkanGroupOrOrg correspondentRoleToCheck, boolean group) throws Exception { // get the users (if you try ckanOrganization.getUsers() it returns null.. maybe // a bug TODO) List users; if (group) users = ckanCaller.getGroup(groupOrOrganization).getUsers(); else users = ckanCaller.getOrganization(groupOrOrganization).getUsers(); for (CkanUser ckanUser : users) { if (ckanUser.getName().equals(ckanUsername)) if (ckanUser.getCapacity().equals(RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck))) return true; else break; } return false; } /** * Just check if the group exists. * * @param nameOrId the name or id * @return the ckan group */ private CkanGroup groupExists(String nameOrId) { CkanGroup toReturn = null; try { ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS); toReturn = client.getGroup(nameOrId); } catch (JackanException je) { LOG.error("The group " + nameOrId + " doesn't exist"); } return toReturn; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getParentGroups(java.lang.String, java.lang.String) */ @Override public List getParentGroups(String groupName, String apiKey) { // checks checkNotNull(groupName); checkNotNull(apiKey); try{ ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey); return client.getGroup(groupName).getGroups(); }catch(Exception e){ LOG.error("Something went wrong, returning null", e); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationByName(java.lang.String) */ @Override public CkanOrganization getOrganizationByName(String name) { checkNotNull(name); String ckanName = name.toLowerCase(); try{ return ckanCaller.getOrganization(ckanName); }catch(Exception e){ LOG.warn("Failed to retrieve the organization with name " +name+ " on the ckan: "+ckanCaller.getCatalogUrl(), e); } return null; } /** * ***************************************************************************** * * * WRITE OPERATIONS * * * *****************************************************************************. * * @param username the username * @param organizationName the organization name * @param correspondentRoleToCheck the correspondent role to check * @return true, if successful */ @Override public boolean checkRoleIntoOrganization(String username, String organizationName, RolesCkanGroupOrOrg correspondentRoleToCheck) { LOG.debug("Request for checking if " + username + " into organization " + organizationName + " has role " + correspondentRoleToCheck); // checks checkNotNull(username); checkNotNull(organizationName); checkNotNull(correspondentRoleToCheck); checkArgument(!username.isEmpty()); checkArgument(!organizationName.isEmpty()); // convert ckan username String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); // check if this role is already present in ckan for this user within the organization String organizationNameToCheck = organizationName.toLowerCase(); try{ boolean alreadyPresent = isRoleAlreadySet(ckanUsername, organizationNameToCheck, correspondentRoleToCheck, false); if(alreadyPresent) return true; // just return else{ //TODO PASS by GCAT? // we need to use the APIs to make it String path = "/api/3/action/organization_member_create"; JSONObject obj = new JSONObject(); obj.put("id", organizationNameToCheck); obj.put("username", ckanUsername); obj.put("role", RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck)); LOG.debug("API request for organization membership is going to be " + obj.toJSONString()); try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();) { HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path); request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token StringEntity params = new StringEntity(obj.toJSONString()); request.setEntity(params); HttpResponse response = httpClient.execute(request); LOG.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase()); return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK; }catch (Exception ex) { LOG.error("Error while trying to change the role for this user ", ex); } } }catch (Exception ex) { LOG.error("Unable to check if this role was already set, please check your parameters! ", ex); } return false; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#checkRoleIntoGroup(java.lang.String, java.lang.String, org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg) */ @Override public boolean checkRoleIntoGroup(String username, String groupName, RolesCkanGroupOrOrg correspondentRoleToCheck) { LOG.debug("Request for checking if " + username + " into group " + groupName + " has role " + correspondentRoleToCheck); // checks checkNotNull(username); checkNotNull(groupName); checkNotNull(correspondentRoleToCheck); checkArgument(!username.isEmpty()); checkArgument(!groupName.isEmpty()); // convert ckan username String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); // check if this role is already present in ckan for this user within the group String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupName); try{ boolean alreadyPresent = isRoleAlreadySet(ckanUsername, groupNameToCheck, correspondentRoleToCheck, true); if(alreadyPresent) return true; // just return else{ // we need to use the apis to make it String path = "/api/3/action/group_member_create"; JSONObject obj = new JSONObject(); obj.put("id", groupNameToCheck); obj.put("username", ckanUsername); obj.put("role", RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck)); LOG.debug("API request for organization membership is going to be " + obj.toJSONString()); try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();) { HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path); request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token StringEntity params = new StringEntity(obj.toJSONString()); request.setEntity(params); HttpResponse response = httpClient.execute(request); LOG.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase()); return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK; }catch (Exception ex) { LOG.error("Error while trying to change the role for this user ", ex); } } }catch (Exception ex) { LOG.error("Unable to check if this role was already set, please check your parameters! ", ex); } return false; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#createCkanDatasetMultipleCustomFields(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, long, java.lang.String, java.lang.String, java.util.List, java.util.Map, java.util.List, boolean, boolean, boolean) */ @Override public String createCkanDatasetMultipleCustomFields(String username, String title, String name, String organizationName, String author, String authorMail, String maintainer, String maintainerMail, long version, String description, String licenseId, List tags, Map> customFieldsMultiple, List resources, boolean setPublic, boolean setSearchable, boolean socialPost) throws Exception { LOG.info("Called createCkanDatasetMultipleCustomFields"); // checks (minimum) checkNotNull(username); //checkNotNull(organizationNameOrId); //checkArgument(!organizationNameOrId.isEmpty()); checkArgument(!(title == null && name == null || title.isEmpty() && name.isEmpty()), "Name and Title cannot be empty/null at the same time!"); GcubeContext gcubeContext = null; try { gcubeContext = GCubeUtils.detectTheOrgNameContexts(organizationName, username, true); String toPassOrganizationToGcat = null; //Not needed to pass this information to gCat, never. // String ckanUsername = getUserFromApiKey(apiKey).getName(); LOG.debug("The visibility parameter passed is (isPublic): "+setPublic); CkanDataset dataset = CKANConveter.toCkanDataset(ckanCaller, username, title, name, toPassOrganizationToGcat, author, authorMail, maintainer, maintainerMail, version, description, licenseId, tags, null, customFieldsMultiple, resources, setPublic, setSearchable); LOG.debug("The isPriv property into dataset is: "+dataset.isPriv()); // trying to create by gCat String jsonValueDataset = MarshUnmarshCkanObject.toJsonValueDataset(dataset,METHOD.TO_CREATE); LOG.info("Serialized dataset is: " + jsonValueDataset); jsonValueDataset = gCatCaller.createDataset(jsonValueDataset,socialPost); LOG.debug("Created dataset is: " + jsonValueDataset); if(jsonValueDataset != null){ CkanDataset toCkanDataset = MarshUnmarshCkanObject.toCkanDataset(jsonValueDataset,METHOD.TO_READ); LOG.info("Dataset with name " + toCkanDataset.getName() + " has been created correctly"); return toCkanDataset.getId(); } }catch (Exception e) { LOG.error("Error on creating the dataset: ", e); throw e; }finally { if(gcubeContext!=null) GCubeUtils.revertToSourceContext(gcubeContext); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#patchFieldsForDataset(java.lang.String, java.util.Map) */ @Override public boolean patchFieldsForDataset(String datasetIdOrName, Map mapFields) throws Exception { LOG.info("Called patchFieldsForDataset " + mapFields + " for dataset id/name: " + datasetIdOrName); checkNotNull(datasetIdOrName); checkNotNull(mapFields); try { CkanDataset dataset = ckanCaller.getDataset(datasetIdOrName); String datasetId = dataset.getId(); JSONObject jsonObj = new JSONObject(); for (String key : mapFields.keySet()) { jsonObj.put(key, mapFields.get(key)); } jsonObj.put("id", datasetId); LOG.debug("Json Dataset is: " + jsonObj); gCatCaller.patchDataset(dataset.getName(), jsonObj); LOG.info("Patch operation for dataset " + datasetId + " terminates without errors"); return true; } catch (Exception e) { LOG.error("Error occurred trying to patch the dataset with id: " + datasetIdOrName, e); throw new Exception("Unable to patch the dataset. Error: " + e.getMessage()); } } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#setSearchableFieldForDataset(java.lang.String, boolean) */ @Override public boolean setSearchableFieldForDataset(String datasetId, boolean searchable) throws Exception { LOG.info("Set searchalbe field as " + searchable + " for dataset id: " + datasetId); checkNotNull(datasetId); try { String searchableAsString = searchable ? "True" : "False"; JSONObject jsonObj = new JSONObject(); jsonObj.put("id", datasetId); // just to be sure jsonObj.put("searchable", searchableAsString); LOG.debug("Json Dataset is: " + jsonObj); gCatCaller.patchDataset(datasetId, jsonObj); LOG.info("Set 'searchable' field for dataset " + datasetId + " terminates without errors"); return true; } catch (Exception e) { LOG.error("Error occured trying to set the 'searchable' field for the dataset with id: " + datasetId, e.getMessage()); throw new Exception("Unable to set the 'searchable' field for this dataset. Error: " + e.getMessage()); } } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#addResourceToDataset(org.gcube.datacatalogue.utillibrary.shared.ResourceBean) */ @Override public String addResourceToDataset(ResourceBean resourceBean, String organizationName, String username) throws Exception { LOG.info("Called addResourceToDataset by this bean " + resourceBean); // checks checkNotNull(resourceBean); checkNotNull(resourceBean.getUrl()); //Commented since #21259 /*boolean isAccessibleURL = false; try { isAccessibleURL = CatalogueUtilMethods.resourceExists(resourceBean.getUrl()); } catch (Exception e) { throw new Exception("It seems the resource at this url " + resourceBean.getUrl()+" is not reachable. Error: "+e.getMessage()); } if(!isAccessibleURL){ throw new Exception("It seems there is no resource at this url " + resourceBean.getUrl()); }*/ GcubeContext gcubeContext = null; try { //Switch the context if needed gcubeContext = GCubeUtils.detectTheOrgNameContexts(organizationName, username, true); CkanResource resource = CKANConveter.toCkanResource(CKAN_CATALOGUE_URL, resourceBean); String jsonValueResource = MarshUnmarshCkanObject.toJsonValueResource(resource, METHOD.TO_CREATE); LOG.debug("Serialized resource is: " + jsonValueResource); jsonValueResource = gCatCaller.addResourceToDataset(resourceBean.getDatasetId(), jsonValueResource); LOG.debug("Added resource to dataset is: " + jsonValueResource); CkanResource createdRes = MarshUnmarshCkanObject.toCkanResource(jsonValueResource); if (createdRes != null) { LOG.info("Resource with id: " + createdRes.getId() + ", name: "+createdRes.getName()+" added correclty"); return createdRes.getId(); } }catch (Exception e) { LOG.error("Unable to add the resource "+resourceBean, e); }finally { //revert the context if needed if(gcubeContext!=null) GCubeUtils.revertToSourceContext(gcubeContext); } return null; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#deleteResourceFromDataset(java.lang.String) */ @Override public boolean deleteResourceFromDataset(String resourceId, String username) throws Exception { LOG.info("Called deleteResourceFromDataset - resource with id " + resourceId); // checks checkNotNull(resourceId); checkArgument(!resourceId.isEmpty()); GcubeContext gcubeContext = null; try{ CkanResource theResource = ckanCaller.getResource(resourceId); CkanDataset theDataset = getDataset(theResource.getPackageId(), username); //Switch the context if needed gcubeContext = GCubeUtils.detectTheOrgNameContexts(theDataset.getOrganization().getName(), username, true); gCatCaller.deleteResource(theResource.getPackageId(), resourceId); LOG.info("Resource with id: " + resourceId + " deleted correclty"); return true; }catch(Exception e){ LOG.error("Unable to delete resource whose id is " + resourceId, e); }finally { //revert the context if needed if(gcubeContext!=null) GCubeUtils.revertToSourceContext(gcubeContext); } return false; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#createGroup(java.lang.String, java.lang.String, java.lang.String) */ @Override public CkanGroup createGroup(String name, String title, String description) throws Exception { // checks checkNotNull(name); checkArgument(!name.trim().isEmpty()); // check if it exists CkanGroup toCreate = null; LOG.debug("Request for creating group with name " + name + " title " + title + " and description " + description); String normalizedName = CatalogueUtilMethods.fromGroupTitleToName(name); if((toCreate = groupExists(name))!= null) return toCreate; else{ try{ CkanGroup group = new CkanGroup(normalizedName); group.setTitle(title); group.setDisplayName(title); group.setDescription(description); String jsonValueGroup = MarshUnmarshCkanObject.toJsonValueGroup(group); LOG.trace("Serialized group is: " + jsonValueGroup); String theGroup = gCatCaller.createGroup(jsonValueGroup); toCreate = MarshUnmarshCkanObject.toCkanGroup(theGroup); LOG.info("Created the group with id: " + toCreate.getId() + ", name: "+toCreate.getName()); }catch(JackanException je){ LOG.error("Unable to create such group", je); } } return toCreate; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getRolesAndUsersGroup(java.lang.String) */ @Override public Map> getRolesAndUsersGroup(String groupName) { // checks checkNotNull(groupName); checkArgument(!groupName.isEmpty()); Map> capacityAndUsers = null; String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupName); CkanGroup group = ckanCaller.getGroup(groupNameToCheck); if(group != null){ capacityAndUsers = new HashMap>(); List users = group.getUsers(); for (CkanUser ckanUser : users) { List listUsers; if(capacityAndUsers.containsKey(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity()))){ listUsers = capacityAndUsers.get(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity())); }else listUsers = new ArrayList(); listUsers.add(ckanUser.getName()); capacityAndUsers.put(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity()), listUsers); } LOG.info("Returning " + capacityAndUsers); } return capacityAndUsers; } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#assignDatasetToGroup(java.lang.String, java.lang.String) */ //TODO HAS TO BE REVISITED by gCAT @Override public boolean assignDatasetToGroup(String groupNameOrId, String datasetNameOrId) { return assignDatasetToGroupBody(groupNameOrId, datasetNameOrId, false); } /* (non-Javadoc) * @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#patchProductCustomFields(java.lang.String, java.lang.String, java.util.Map, boolean) */ //TODO HAS TO BE REVISITED by gCAT @Override public boolean patchProductCustomFields(String productId, String username, Map> customFieldsToChange, boolean removeOld) { // checks checkNotNull(productId); checkNotNull(username); if(customFieldsToChange == null || customFieldsToChange.isEmpty()) // TODO.. remove all custom fields maybe?! return true; String apiKey = getApiKeyFromUsername(username); LOG.info("Going to change product with id " + productId +"." + " Request comes from user with key " + apiKey.substring(0, 5) + "****************"); LOG.info("The new values are " + customFieldsToChange); // Get already available custom fields Map> fromCKANCustomFields = new HashMap>(); ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey); List extras = client.getDataset(productId).getExtras(); if(extras == null) extras = new ArrayList(); // fill the above map with these values for (CkanPair ckanPair : extras) { List forThisValue = null; String key = ckanPair.getKey(); if(fromCKANCustomFields.containsKey(key)) forThisValue = fromCKANCustomFields.get(key); else forThisValue = new ArrayList(); forThisValue.add(ckanPair.getValue()); fromCKANCustomFields.put(key, forThisValue); } LOG.info("The generated map from jackan looks like " + fromCKANCustomFields + ". Going to merge them"); // merge them with the new values Iterator>> iteratorUserMap = customFieldsToChange.entrySet().iterator(); while (iteratorUserMap.hasNext()) { Map.Entry> entry = iteratorUserMap .next(); String key = entry.getKey(); List newValues = entry.getValue(); // get the unique set of values Set uniqueValues = new HashSet(); if(fromCKANCustomFields.containsKey(key)) if(!removeOld) uniqueValues.addAll(fromCKANCustomFields.get(key)); uniqueValues.addAll(newValues); fromCKANCustomFields.put(key, new ArrayList(uniqueValues)); } LOG.info("After merging it is " + fromCKANCustomFields); try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { String apiRequestUrl = CKAN_CATALOGUE_URL + "/api/3/action/package_patch"; HttpPost httpPostRequest = new HttpPost(apiRequestUrl); httpPostRequest.setHeader("Authorization", apiKey); // Request parameters to be replaced JSONObject jsonRequest = new JSONObject(); // build the json array for the "extras" field.. each object looks like {"key": ..., "value": ...} JSONArray extrasObject = new JSONArray(); Iterator>> iteratorNewFields = fromCKANCustomFields.entrySet().iterator(); while (iteratorNewFields.hasNext()) { Map.Entry> entry = iteratorNewFields .next(); String key = entry.getKey(); List values = entry.getValue(); for (String value : values) { JSONObject obj = new JSONObject(); obj.put("value", value); obj.put("key", key); extrasObject.add(obj); } } // perform the request jsonRequest.put("id", productId); jsonRequest.put("extras", extrasObject); LOG.debug("Request param is going to be " + jsonRequest); StringEntity params = new StringEntity(jsonRequest.toJSONString(), ContentType.APPLICATION_JSON); httpPostRequest.setEntity(params); HttpResponse response = httpClient.execute(httpPostRequest); if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() >= 300) { throw new RuntimeException("failed to patch the product. response status line from " + apiRequestUrl + " was: " + response.getStatusLine()); } return true; }catch(Exception e){ LOG.error("Failed to patch the product ", e); } return false; } /** * The real body of the assignDatasetToGroup. * * @param groupNameOrId the group name or id * @param datasetNameOrId the dataset name or id * @param addOnParents the add on parents * @return true, if successful */ private boolean assignDatasetToGroupBody(String groupNameOrId, String datasetNameOrId, boolean addOnParents) { // checks checkNotNull(groupNameOrId); checkArgument(!groupNameOrId.isEmpty()); checkNotNull(datasetNameOrId); checkArgument(!datasetNameOrId.isEmpty()); String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupNameOrId); try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){ ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS); // check the group exists CkanGroup group = client.getGroup(groupNameToCheck); // move to a list List groupNames = new ArrayList(); groupNames.add(group.getName()); if(group != null && addOnParents){ findHierarchyGroups(groupNames, CKAN_TOKEN_SYS); } // we need to use the apis to make it String pathPackageShow = CKAN_CATALOGUE_URL + "/api/3/action/package_show?id=" + datasetNameOrId; HttpGet getRequest = new HttpGet(pathPackageShow); getRequest.addHeader("Authorization", CKAN_TOKEN_SYS); HttpResponse response = httpClient.execute(getRequest); LOG.debug("Response is " + response.getStatusLine().getStatusCode() + " and message is " + response.getStatusLine().getReasonPhrase()); // read the json dataset and fetch the groups and fetch the groups' names, if any if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ // parse the json and convert to java beans String jsonAsString = EntityUtils.toString(response.getEntity()); JSONParser parser = new JSONParser(); JSONObject json = (JSONObject) parser.parse(jsonAsString); JSONObject resultJson = (JSONObject) json.get("result"); JSONArray groupsJson = (JSONArray)resultJson.get("groups"); Iterator it = groupsJson.iterator(); while (it.hasNext()) { JSONObject object = it.next(); try{ if(object.containsKey("name")) groupNames.add((String)object.get("name")); }catch(Exception e){ LOG.error("Error", e); } } // remove duplicates Set groupNamesSet = new HashSet(groupNames); LOG.debug("Groups to be added are " + groupNamesSet); // now we patch the dataset with the new group String pathUpdatePatch = CKAN_CATALOGUE_URL + "/api/3/action/package_patch"; JSONObject req = new JSONObject(); req.put("id", datasetNameOrId); JSONArray groups = new JSONArray(); Iterator iteratorNameSet = groupNamesSet.iterator(); while (iteratorNameSet.hasNext()) { String groupName = iteratorNameSet.next(); JSONObject groupJSON = new JSONObject(); groupJSON.put("name", groupName); groups.add(groupJSON); } req.put("groups", groups); LOG.debug("Request for patch is going to be " + req.toJSONString()); HttpPost request = new HttpPost(pathUpdatePatch); request.addHeader("Authorization", CKAN_TOKEN_SYS); StringEntity params = new StringEntity(req.toJSONString()); request.setEntity(params); HttpResponse responsePatch = httpClient.execute(request); LOG.debug("Response code is " + responsePatch.getStatusLine().getStatusCode() + " and response message is " + responsePatch.getStatusLine().getReasonPhrase()); if(responsePatch.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ LOG.info("Dataset Added to the group!!"); return true; } } }catch(Exception e){ LOG.error("Unable to make this association", e); } return false; } /** * Find the hierarchy of trees. * * @param groupsTitles the groups titles * @param apiKey the api key */ private void findHierarchyGroups( List groupsTitles, String apiKey) { ListIterator iterator = groupsTitles.listIterator(); while (iterator.hasNext()) { String group = iterator.next(); List parents = getParentGroups(group, apiKey); if(parents == null || parents.isEmpty()) return; for (CkanGroup ckanGroup : parents) { List parentsList = new ArrayList(Arrays.asList(ckanGroup.getName())); findHierarchyGroups(parentsList, apiKey); for (String parent : parentsList) { iterator.add(parent); } } } } /** * ***************************************************************************** * * * MANAGEMENT OPERATIONS * * * *****************************************************************************. * * @param username the username * @param sourceOrganization the source organization * @param currentRole the current role */ @Override public void assignRolesOtherOrganization(String username, String sourceOrganization, RolesCkanGroupOrOrg currentRole) { checkNotNull(username); checkNotNull(sourceOrganization); checkNotNull(currentRole); LOG.info("Request for assigning other roles for user " + username + ", whose current role is " + currentRole + " and organization " + sourceOrganization); Iterator> iterator = extendRoleInOrganization.entrySet().iterator(); LOG.debug("List of entries to check is " + extendRoleInOrganization); while (iterator.hasNext()) { Map.Entry entry = iterator .next(); String sourceOrg = entry.getKey(); LOG.debug("Found organization source " + sourceOrg); if(sourceOrg.equals(sourceOrganization)){ String[] values = entry.getValue().split(DataCatalogueRunningCluster.TUPLES_SEPARATOR); for(int i = 0; i < values.length; i++){ String destOrg = values[i].split("\\"+DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[0]; String role = values[i].split("\\"+DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[1]; LOG.debug("Role is " + role + " and organization is " + destOrg); RolesCkanGroupOrOrg ckanRole; if(role.equals(DataCatalogueRunningCluster.CKAN_GENERIC_ROLE)) ckanRole = currentRole; else ckanRole = RolesCkanGroupOrOrg.convertFromCapacity(role); LOG.info("Checking for extra role: role is " + ckanRole + " and organization is " + destOrg); checkRoleIntoOrganization(username, destOrg, ckanRole); } } } } }