--- /dev/null
+package com.pentila.entSavoie.synchroLdap.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.naming.directory.Attributes;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.exception.SystemException;
+import com.liferay.portal.kernel.log.Log;
+import com.liferay.portal.kernel.log.LogFactoryUtil;
+import com.liferay.portal.kernel.util.PrefsPropsUtil;
+import com.liferay.portal.model.Organization;
+import com.liferay.portal.model.User;
+import com.liferay.portal.model.UserGroup;
+import com.liferay.portal.security.ldap.LDAPConstants;
+import com.liferay.portal.security.ldap.PortalLDAPUtil;
+import com.liferay.portal.service.OrganizationLocalServiceUtil;
+import com.liferay.portal.service.UserLocalServiceUtil;
+import com.pentila.entSavoie.communityInfos.service.OrganizationMappingLocalServiceUtil;
+import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
+import com.pentila.entSavoie.utils.ENTOrganizationsUtil;
+import com.pentila.util.Logger;
+
+/**
+ * Tools used by the synchronization process
+ * @author Cedric Lecarpentier
+ *
+ */
+public class SynchronizationUtils {
+
+ /**
+ * Returns the list of classes and groups for the given usr, based on its LDAP attributes
+ * @param user
+ * @param userAttributes
+ * @return the list of classes and groups
+ */
+ public static List<String> getUserClassesAndGroups(User user, Attributes userAttributes) {
+
+ List<String> list = new ArrayList<String>();
+ String[] attributeNames = {LDAPConstants.LDAP_ATTRIBUTE_ENTELEVECLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEGROUPES};
+ for (String attributeName : attributeNames) {
+ if (userAttributes.get(attributeName) != null) {
+ for (int i=0; i<userAttributes.get(attributeName).size(); i++) {
+ try {
+ String classe = userAttributes.get(attributeName).get(i).toString();
+ // class format is 'cn=xxxx$yyy,ou=groups,etc...'
+ String[] classeTab = classe.split(",");
+ if (classeTab != null && classeTab.length > 0) {
+ list.add(classeTab[0].substring(3));
+ }
+
+ } catch (Exception e) {
+ _log.error("Error while reading LDAP attribute "+attributeName+" for user "+user.getFullName(), e);
+ }
+ }
+ }
+ }
+ return list;
+ }
+
+
+ /**
+ * Returns a map for a given teacher that contains, for each school, the list of its classes and groups
+ * @param user
+ * @param userAttributes
+ * @return
+ */
+ public static Map<Organization, List<String>> getTeacherSchoolClassesMap(User user, Attributes userAttributes) {
+
+ Map<Organization, List<String>> resultMap = new HashMap<Organization, List<String>>();
+
+ String[] attributeNames = {LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSGROUPES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL};
+ for (String attributeName : attributeNames) {
+ if (userAttributes.get(attributeName) != null) {
+ for (int i=0; i<userAttributes.get(attributeName).size(); i++) {
+ try {
+
+ String classe = userAttributes.get(attributeName).get(i).toString();
+ // class format is 'cn=xxxx$yyy,ou=groups,etc...'
+
+ Organization organization = getSchoolFromClassName(classe);
+ if (organization != null) {
+ String[] classeTab = classe.split(",");
+ if (classeTab != null && classeTab.length > 0) {
+ String shortClassName = classeTab[0].substring(3);
+ if (resultMap.containsKey(organization)) {
+ resultMap.get(organization).add(shortClassName);
+
+ } else {
+ List<String> classList = new ArrayList<String>();
+ classList.add(shortClassName);
+ resultMap.put(organization, classList);
+ }
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error while reading LDAP attribute "+attributeName+" for user "+user.getFullName(), e);
+ }
+ }
+ }
+ }
+
+ // Also add to the list of organizations (if not present), the rattach school
+ // This manages teachers that have changed school but that do not have classes or groups yet
+ Organization rattachSchool = SynchronizationManager.getRattachSchool(user);
+ if (!resultMap.containsKey(rattachSchool)) {
+ _log.debug("getTeacherSchoolClassesMap : add rattach school "+rattachSchool.getName()+" without classes or groups");
+ resultMap.put(rattachSchool, new ArrayList<String>());
+ }
+
+ // Parse ENTPersonStructRattach is the org list is empty in order to manage technical people
+ List<Organization> entPersonFonctionOrgs = getEntPersonFonctionsSchools(user, userAttributes);
+ for (Organization entPersonFonctionOrg : entPersonFonctionOrgs) {
+ if (!resultMap.containsKey(entPersonFonctionOrg)) {
+ _log.debug("getTeacherSchoolClassesMap : add entpersonfonction school "+entPersonFonctionOrg.getName()+" without classes or groups");
+ resultMap.put(entPersonFonctionOrg, new ArrayList<String>());
+ }
+ }
+
+ return resultMap;
+ }
+
+
+ /**
+ * Returns the Organization associated to the class name found in LDAP
+ * @param className
+ * @return
+ */
+ public static Organization getSchoolFromClassName(String className) {
+
+ if (SynchronizationManager.getEtabOuMap() == null || SynchronizationManager.getEtabOuMap().isEmpty()) {
+ SynchronizationManager.initializeSchoolMaps();
+ }
+
+ Organization orga = null;
+
+ // Skip fake class/group names
+ if (!className.startsWith("cn=fakeDn")) {
+ String[] classeTab = className.split(",");
+ if (classeTab != null && classeTab.length > 0) {
+
+ String[] shortClasseTab = classeTab[0].split("\\$");
+ if (shortClasseTab != null && shortClasseTab.length > 0) {
+ String etabOuId = shortClasseTab[0].substring(3);
+ orga = getSchoolFromOu(etabOuId);
+ }
+ }
+ }
+ return orga;
+ }
+
+
+ /**
+ * Returns the Organization mapped to the 'ou' value in the LDAP
+ * @param etabOuId
+ * @return the organization
+ */
+ private static Organization getSchoolFromOu(String etabOuId){
+
+ // Loop over etabOuMap
+ if (SynchronizationManager.getEtabOuMap() == null || SynchronizationManager.getEtabOuMap().size() == 0) {
+ SynchronizationManager.initializeSchoolMaps();
+ }
+ for (String ou : SynchronizationManager.getEtabOuMap().keySet()) {
+
+ if (ou.contains(etabOuId)) {
+ String entStructureUAI = SynchronizationManager.getEtabOuMap().get(etabOuId);
+ try {
+ long organizationId = OrganizationMappingLocalServiceUtil.getOrganizationMapping(entStructureUAI).getOrganizationId();
+ return OrganizationLocalServiceUtil.getOrganization(organizationId);
+ } catch (Exception e) {
+ _log.error("Error when getting organization mapping for entStructureUAI="+entStructureUAI, e);
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Loop over ENTPersonFonctions attributes and return the list of associated schools
+ * If subject is 'SANS OBJET' , we skip the ENTPersonFonction
+ * @param user
+ * @param userAttributes
+ * @return
+ */
+ public static List<Organization> getEntPersonFonctionsSchools(User user, Attributes userAttributes) {
+
+ List<Organization> orgList = new ArrayList<Organization>();
+
+ try {
+ if (userAttributes != null && userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS) != null) {
+ for (int i=0; i<userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).size(); i++) {
+
+ String entPersonFonctions = userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).get(i).toString();
+ String[] fonctionTab = entPersonFonctions.split("\\$");
+ if (fonctionTab != null && fonctionTab.length > 2) {
+
+ // ENTPersonFonction is for example '6291$ENS$ENSEIGNEMENT$L0202$LETTRES MODERNES' or '6610$-$SANS OBJET$-$SANS OBJET'
+ String etabOuId = fonctionTab[0];
+ Organization orga = getSchoolFromOu(etabOuId);
+ if (orga != null) {
+ orgList.add(orga);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error when reading ENTPersonFonctions attribute for user "+user.getFullName(), e);
+ }
+
+ return orgList;
+ }
+
+
+ /**
+ * Adds or remove a given user from the given organization
+ * @param user
+ * @param parentOrg
+ * @param mustHave
+ * @param suffixe
+ * @return
+ * @throws PortalException
+ * @throws SystemException
+ */
+ public static Organization addOrRemoveUserFromOrg(User user, Organization org, Boolean mustHave, String suffixe) throws PortalException, SystemException {
+
+ Organization suffixedOrg = ENTOrganizationsUtil.getOrCreateOrganization(user.getCompanyId(), org.getName() + suffixe, org.getOrganizationId());
+
+ boolean hasUserOrganization = OrganizationLocalServiceUtil.hasUserOrganization(user.getUserId(), suffixedOrg.getOrganizationId());
+
+ if (hasUserOrganization && !mustHave) {
+ UserLocalServiceUtil.unsetOrganizationUsers(suffixedOrg.getOrganizationId(), new long[]{user.getUserId()});
+ }
+ if (!hasUserOrganization && mustHave) {
+ UserLocalServiceUtil.addOrganizationUsers(suffixedOrg.getOrganizationId(), new long[]{user.getUserId()});
+ }
+ return suffixedOrg;
+
+ }
+
+
+ /**
+ * Print the given list of users as a string, by removing last comma
+ * @param userList
+ * @return
+ */
+ public static String printAsString(List<User> userList) {
+ String result = "";
+ for (int idx = 0 ; idx < userList.size() ; idx++) {
+ User user = userList.get(idx);
+ result += user.getFullName();
+ if (idx != userList.size() - 1) {
+ result+= ", ";
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Returns the list of users with unique users
+ * @param userList
+ * @return
+ */
+ public static List<User> unique(List<User> userList) {
+ List<User> uniqueUserList = new ArrayList<User>();
+ for (User user : userList) {
+ if (!uniqueUserList.contains(user)) {
+ uniqueUserList.add(user);
+ }
+ }
+ return uniqueUserList;
+ }
+
+
+ /**
+ * Returns the organization (and the associated parent org) for the given usergroup
+ * Does the mapping between the 'LDAP' way of describing groups and the 'Liferay' way
+ * @param userGrp
+ * @return
+ * @throws Exception
+ */
+ public static Map<String, Organization> checkAndGetOrganizationCreation(UserGroup userGrp) throws Exception {
+ Map<String, Organization> currentOrg = new HashMap<String, Organization>();
+
+ // Get organization's school
+ Organization school = null;
+ try {
+ school = ENTOrganizationsUtil.getOrCreateSchool(userGrp.getCompanyId(), getSchoolName(userGrp));
+ } catch (Exception e) {
+ _log.error("Error when getting organization associated to user group "+userGrp.getUserGroupId(), e);
+ }
+
+ if (school == null) {
+ return currentOrg;
+ }
+
+ // Build the organization name based on the usergroup
+ String orgName = getOrgName(userGrp);
+
+ // Get the organization
+ Organization org = null;
+ try {
+ _log.info("Looking for org with name -"+orgName+"-");
+ org = OrganizationLocalServiceUtil.getOrganization(userGrp.getCompanyId(), orgName);
+ } catch (Exception e) {
+ _log.error("Could not get organization with name "+orgName);
+ }
+
+ if (org == null && !MembershipManager.isSchoolImportTypeAAF(school.getOrganizationId())) {
+ _log.info("Organization "+orgName+" does not exist but school is not AAF mode => do not create it");
+ }
+
+ // If it does not exist, create it only if the school has AAF mode
+ if (org == null && MembershipManager.isSchoolImportTypeAAF(school.getOrganizationId())) {
+ org = ENTOrganizationsUtil.getOrCreateOrganization(userGrp.getCompanyId(), orgName, school.getOrganizationId());
+ }
+
+ // If organization if finally found, get associated parent organization and return both
+ if (org != null) {
+ currentOrg.put("classe", org);
+ _log.debug("checkAndGetOrganizationCreation : retrieved orga for usergroupid="+userGrp.getUserGroupId()+" has name "+org.getName());
+
+ // Get associated parent organization
+ if (ENTMainUtilsLocalServiceUtil.getEntSchoolImportType(userGrp.getCompanyId())) {
+ Organization parentOrg = ENTOrganizationsUtil.getOrCreateOrganization(userGrp.getCompanyId(), orgName+" - Parents", school.getOrganizationId());
+ currentOrg.put("parent", parentOrg);
+ }
+ }
+ return currentOrg;
+
+ }
+
+
+ /**
+ * Returns the organization name mapped to the given usergroup
+ * @param userGroup
+ * @return
+ */
+ public static String getOrgName(UserGroup userGroup) {
+ String initName = userGroup.getName();
+ String retName = initName;
+ if (!ENTMainUtilsLocalServiceUtil.isSchemaSupann(userGroup.getCompanyId())){
+ Pattern classPattern = Pattern.compile("^[0-9]+\\$");
+ Matcher classMatcher = classPattern.matcher(initName);
+ if (classMatcher.find()) {
+ retName = getSchoolName(userGroup)+" - "+initName.substring(classMatcher.end());
+ }
+ }
+ return retName;
+ }
+
+ /**
+ * Returns the school name from a given usergroup
+ * usergroup name is formatted like '<etabOu>$<orgName>'
+ * @param userGroup
+ * @return
+ */
+ private static String getSchoolName(UserGroup userGroup) {
+ String initName = userGroup.getName();
+ String cacheName = null;
+
+
+ if (ENTMainUtilsLocalServiceUtil.isSchemaSupann(userGroup.getCompanyId())){
+ return ENTMainUtilsLocalServiceUtil.getENTOrgRootName(userGroup.getCompanyId());
+ }
+ try {
+ // Extract the school 'ou'
+ Pattern classPattern = Pattern.compile("^[0-9]+\\$");
+ Matcher classMatcher = classPattern.matcher(initName);
+ if (classMatcher.find()) {
+
+ String schoolOu = initName.substring(classMatcher.start(), classMatcher.end()-1);
+
+ for (String schoolDn : SynchronizationManager.getEtabMap().keySet()) {
+ if (schoolDn.contains(schoolOu)) {
+ return SynchronizationManager.getEtabMap().get(schoolDn).getName();
+ }
+ }
+
+ // If not found in school map, target the LDAP
+ _log.info("getSchoolName : school not found in etabMap for usergroup "+userGroup.getUserGroupId());
+
+ try {
+ Attributes attrs = PortalLDAPUtil.getContext(userGroup.getCompanyId()).getAttributes("ou=" + schoolOu + ",ou=etablissements,"+
+ PrefsPropsUtil.getString(userGroup.getCompanyId(), "ldap.base.dn"));
+ cacheName = attrs.get("ENTStructureNomCourant").get(0).toString();
+
+ // Manage 'classic' and 'full' mode
+ String etabNameType = ENTMainUtilsLocalServiceUtil.getENTSynchroEtabName(userGroup.getCompanyId());
+ if (etabNameType.equals("full")) {
+ if (attrs.get("l")!=null) {
+ cacheName += " - " + attrs.get(
+ "l").get().toString();
+ }
+ if (attrs.get("ENTStructureUAI")!=null) {
+ cacheName += " - " + attrs.get(
+ "ENTStructureUAI").get().toString();
+ }
+ }
+
+ } catch (Exception e) {
+ _log.info("Exception while getting LDAP attribute for school "+schoolOu, e);
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error when getting the school name from the user group "+userGroup.getUserGroupId(), e);
+ }
+ return cacheName;
+ }
+
+
+ private static Log _log = LogFactoryUtil.getLog(SynchronizationUtils.class);
+
+
+}