1 package com.pentila.entSavoie.synchroLdap.impl;
3 import java.util.ArrayList;
4 import java.util.HashMap;
7 import java.util.regex.Matcher;
8 import java.util.regex.Pattern;
10 import javax.naming.directory.Attributes;
12 import com.liferay.portal.kernel.exception.PortalException;
13 import com.liferay.portal.kernel.exception.SystemException;
14 import com.liferay.portal.kernel.log.Log;
15 import com.liferay.portal.kernel.log.LogFactoryUtil;
16 import com.liferay.portal.kernel.util.PrefsPropsUtil;
17 import com.liferay.portal.model.Organization;
18 import com.liferay.portal.model.User;
19 import com.liferay.portal.model.UserGroup;
20 import com.liferay.portal.security.ldap.LDAPConstants;
21 import com.liferay.portal.security.ldap.PortalLDAPUtil;
22 import com.liferay.portal.service.OrganizationLocalServiceUtil;
23 import com.liferay.portal.service.UserLocalServiceUtil;
24 import com.pentila.entSavoie.communityInfos.service.OrganizationMappingLocalServiceUtil;
25 import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
26 import com.pentila.entSavoie.utils.ENTOrganizationsUtil;
27 import com.pentila.util.Logger;
30 * Tools used by the synchronization process
31 * @author Cedric Lecarpentier
34 public class SynchronizationUtils {
37 * Returns the list of classes and groups for the given usr, based on its LDAP attributes
39 * @param userAttributes
40 * @return the list of classes and groups
42 public static List<String> getUserClassesAndGroups(User user, Attributes userAttributes) {
44 List<String> list = new ArrayList<String>();
45 String[] attributeNames = {LDAPConstants.LDAP_ATTRIBUTE_ENTELEVECLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEGROUPES};
46 for (String attributeName : attributeNames) {
47 if (userAttributes.get(attributeName) != null) {
48 for (int i=0; i<userAttributes.get(attributeName).size(); i++) {
50 String classe = userAttributes.get(attributeName).get(i).toString();
51 // class format is 'cn=xxxx$yyy,ou=groups,etc...'
52 String[] classeTab = classe.split(",");
53 if (classeTab != null && classeTab.length > 0) {
54 list.add(classeTab[0].substring(3));
57 } catch (Exception e) {
58 _log.error("Error while reading LDAP attribute "+attributeName+" for user "+user.getFullName(), e);
68 * Returns a map for a given teacher that contains, for each school, the list of its classes and groups
70 * @param userAttributes
73 public static Map<Organization, List<String>> getTeacherSchoolClassesMap(User user, Attributes userAttributes) {
75 Map<Organization, List<String>> resultMap = new HashMap<Organization, List<String>>();
77 String[] attributeNames = {LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSGROUPES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL};
78 for (String attributeName : attributeNames) {
79 if (userAttributes.get(attributeName) != null) {
80 for (int i=0; i<userAttributes.get(attributeName).size(); i++) {
83 String classe = userAttributes.get(attributeName).get(i).toString();
84 // class format is 'cn=xxxx$yyy,ou=groups,etc...'
86 Organization organization = getSchoolFromClassName(classe);
87 if (organization != null) {
88 String[] classeTab = classe.split(",");
89 if (classeTab != null && classeTab.length > 0) {
90 String shortClassName = classeTab[0].substring(3);
91 if (resultMap.containsKey(organization)) {
92 resultMap.get(organization).add(shortClassName);
95 List<String> classList = new ArrayList<String>();
96 classList.add(shortClassName);
97 resultMap.put(organization, classList);
101 } catch (Exception e) {
102 _log.error("Error while reading LDAP attribute "+attributeName+" for user "+user.getFullName(), e);
108 // Also add to the list of organizations (if not present), the rattach school
109 // This manages teachers that have changed school but that do not have classes or groups yet
110 Organization rattachSchool = SynchronizationManager.getRattachSchool(user);
111 if (!resultMap.containsKey(rattachSchool)) {
112 _log.debug("getTeacherSchoolClassesMap : add rattach school "+rattachSchool.getName()+" without classes or groups");
113 resultMap.put(rattachSchool, new ArrayList<String>());
116 // Parse ENTPersonStructRattach is the org list is empty in order to manage technical people
117 List<Organization> entPersonFonctionOrgs = getEntPersonFonctionsSchools(user, userAttributes);
118 for (Organization entPersonFonctionOrg : entPersonFonctionOrgs) {
119 if (!resultMap.containsKey(entPersonFonctionOrg)) {
120 _log.debug("getTeacherSchoolClassesMap : add entpersonfonction school "+entPersonFonctionOrg.getName()+" without classes or groups");
121 resultMap.put(entPersonFonctionOrg, new ArrayList<String>());
130 * Returns the Organization associated to the class name found in LDAP
134 public static Organization getSchoolFromClassName(String className) {
136 if (SynchronizationManager.getEtabOuMap() == null || SynchronizationManager.getEtabOuMap().isEmpty()) {
137 SynchronizationManager.initializeSchoolMaps();
140 Organization orga = null;
142 // Skip fake class/group names
143 if (!className.startsWith("cn=fakeDn")) {
144 String[] classeTab = className.split(",");
145 if (classeTab != null && classeTab.length > 0) {
147 String[] shortClasseTab = classeTab[0].split("\\$");
148 if (shortClasseTab != null && shortClasseTab.length > 0) {
149 String etabOuId = shortClasseTab[0].substring(3);
150 orga = getSchoolFromOu(etabOuId);
159 * Returns the Organization mapped to the 'ou' value in the LDAP
161 * @return the organization
163 private static Organization getSchoolFromOu(String etabOuId){
165 // Loop over etabOuMap
166 if (SynchronizationManager.getEtabOuMap() == null || SynchronizationManager.getEtabOuMap().size() == 0) {
167 SynchronizationManager.initializeSchoolMaps();
169 for (String ou : SynchronizationManager.getEtabOuMap().keySet()) {
171 if (ou.contains(etabOuId)) {
172 String entStructureUAI = SynchronizationManager.getEtabOuMap().get(etabOuId);
174 long organizationId = OrganizationMappingLocalServiceUtil.getOrganizationMapping(entStructureUAI).getOrganizationId();
175 return OrganizationLocalServiceUtil.getOrganization(organizationId);
176 } catch (Exception e) {
177 _log.error("Error when getting organization mapping for entStructureUAI="+entStructureUAI, e);
186 * Loop over ENTPersonFonctions attributes and return the list of associated schools
187 * If subject is 'SANS OBJET' , we skip the ENTPersonFonction
189 * @param userAttributes
192 public static List<Organization> getEntPersonFonctionsSchools(User user, Attributes userAttributes) {
194 List<Organization> orgList = new ArrayList<Organization>();
197 if (userAttributes != null && userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS) != null) {
198 for (int i=0; i<userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).size(); i++) {
200 String entPersonFonctions = userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).get(i).toString();
201 String[] fonctionTab = entPersonFonctions.split("\\$");
202 if (fonctionTab != null && fonctionTab.length > 2) {
204 // ENTPersonFonction is for example '6291$ENS$ENSEIGNEMENT$L0202$LETTRES MODERNES' or '6610$-$SANS OBJET$-$SANS OBJET'
205 String etabOuId = fonctionTab[0];
206 Organization orga = getSchoolFromOu(etabOuId);
213 } catch (Exception e) {
214 _log.error("Error when reading ENTPersonFonctions attribute for user "+user.getFullName(), e);
222 * Adds or remove a given user from the given organization
228 * @throws PortalException
229 * @throws SystemException
231 public static Organization addOrRemoveUserFromOrg(User user, Organization org, Boolean mustHave, String suffixe) throws PortalException, SystemException {
233 Organization suffixedOrg = ENTOrganizationsUtil.getOrCreateOrganization(user.getCompanyId(), org.getName() + suffixe, org.getOrganizationId());
235 boolean hasUserOrganization = OrganizationLocalServiceUtil.hasUserOrganization(user.getUserId(), suffixedOrg.getOrganizationId());
237 if (hasUserOrganization && !mustHave) {
238 UserLocalServiceUtil.unsetOrganizationUsers(suffixedOrg.getOrganizationId(), new long[]{user.getUserId()});
240 if (!hasUserOrganization && mustHave) {
241 UserLocalServiceUtil.addOrganizationUsers(suffixedOrg.getOrganizationId(), new long[]{user.getUserId()});
249 * Print the given list of users as a string, by removing last comma
253 public static String printAsString(List<User> userList) {
255 for (int idx = 0 ; idx < userList.size() ; idx++) {
256 User user = userList.get(idx);
257 result += user.getFullName();
258 if (idx != userList.size() - 1) {
267 * Returns the list of users with unique users
271 public static List<User> unique(List<User> userList) {
272 List<User> uniqueUserList = new ArrayList<User>();
273 for (User user : userList) {
274 if (!uniqueUserList.contains(user)) {
275 uniqueUserList.add(user);
278 return uniqueUserList;
283 * Returns the organization (and the associated parent org) for the given usergroup
284 * Does the mapping between the 'LDAP' way of describing groups and the 'Liferay' way
289 public static Map<String, Organization> checkAndGetOrganizationCreation(UserGroup userGrp) throws Exception {
290 Map<String, Organization> currentOrg = new HashMap<String, Organization>();
292 // Get organization's school
293 Organization school = null;
295 school = ENTOrganizationsUtil.getOrCreateSchool(userGrp.getCompanyId(), getSchoolName(userGrp));
296 } catch (Exception e) {
297 _log.error("Error when getting organization associated to user group "+userGrp.getUserGroupId(), e);
300 if (school == null) {
304 // Build the organization name based on the usergroup
305 String orgName = getOrgName(userGrp);
307 // Get the organization
308 Organization org = null;
310 _log.info("Looking for org with name -"+orgName+"-");
311 org = OrganizationLocalServiceUtil.getOrganization(userGrp.getCompanyId(), orgName);
312 } catch (Exception e) {
313 _log.error("Could not get organization with name "+orgName);
316 if (org == null && !MembershipManager.isSchoolImportTypeAAF(school.getOrganizationId())) {
317 _log.info("Organization "+orgName+" does not exist but school is not AAF mode => do not create it");
320 // If it does not exist, create it only if the school has AAF mode
321 if (org == null && MembershipManager.isSchoolImportTypeAAF(school.getOrganizationId())) {
322 org = ENTOrganizationsUtil.getOrCreateOrganization(userGrp.getCompanyId(), orgName, school.getOrganizationId());
325 // If organization if finally found, get associated parent organization and return both
327 currentOrg.put("classe", org);
328 _log.debug("checkAndGetOrganizationCreation : retrieved orga for usergroupid="+userGrp.getUserGroupId()+" has name "+org.getName());
330 // Get associated parent organization
331 if (ENTMainUtilsLocalServiceUtil.getEntSchoolImportType(userGrp.getCompanyId())) {
332 Organization parentOrg = ENTOrganizationsUtil.getOrCreateOrganization(userGrp.getCompanyId(), orgName+" - Parents", school.getOrganizationId());
333 currentOrg.put("parent", parentOrg);
342 * Returns the organization name mapped to the given usergroup
346 public static String getOrgName(UserGroup userGroup) {
347 String initName = userGroup.getName();
348 String retName = initName;
349 if (!ENTMainUtilsLocalServiceUtil.isSchemaSupann(userGroup.getCompanyId())){
350 Pattern classPattern = Pattern.compile("^[0-9]+\\$");
351 Matcher classMatcher = classPattern.matcher(initName);
352 if (classMatcher.find()) {
353 retName = getSchoolName(userGroup)+" - "+initName.substring(classMatcher.end());
360 * Returns the school name from a given usergroup
361 * usergroup name is formatted like '<etabOu>$<orgName>'
365 private static String getSchoolName(UserGroup userGroup) {
366 String initName = userGroup.getName();
367 String cacheName = null;
370 if (ENTMainUtilsLocalServiceUtil.isSchemaSupann(userGroup.getCompanyId())){
371 return ENTMainUtilsLocalServiceUtil.getENTOrgRootName(userGroup.getCompanyId());
374 // Extract the school 'ou'
375 Pattern classPattern = Pattern.compile("^[0-9]+\\$");
376 Matcher classMatcher = classPattern.matcher(initName);
377 if (classMatcher.find()) {
379 String schoolOu = initName.substring(classMatcher.start(), classMatcher.end()-1);
381 for (String schoolDn : SynchronizationManager.getEtabMap().keySet()) {
382 if (schoolDn.contains(schoolOu)) {
383 return SynchronizationManager.getEtabMap().get(schoolDn).getName();
387 // If not found in school map, target the LDAP
388 _log.info("getSchoolName : school not found in etabMap for usergroup "+userGroup.getUserGroupId());
391 Attributes attrs = PortalLDAPUtil.getContext(userGroup.getCompanyId()).getAttributes("ou=" + schoolOu + ",ou=etablissements,"+
392 PrefsPropsUtil.getString(userGroup.getCompanyId(), "ldap.base.dn"));
393 cacheName = attrs.get("ENTStructureNomCourant").get(0).toString();
395 // Manage 'classic' and 'full' mode
396 String etabNameType = ENTMainUtilsLocalServiceUtil.getENTSynchroEtabName(userGroup.getCompanyId());
397 if (etabNameType.equals("full")) {
398 if (attrs.get("l")!=null) {
399 cacheName += " - " + attrs.get(
400 "l").get().toString();
402 if (attrs.get("ENTStructureUAI")!=null) {
403 cacheName += " - " + attrs.get(
404 "ENTStructureUAI").get().toString();
408 } catch (Exception e) {
409 _log.info("Exception while getting LDAP attribute for school "+schoolOu, e);
412 } catch (Exception e) {
413 _log.error("Error when getting the school name from the user group "+userGroup.getUserGroupId(), e);
419 private static Log _log = LogFactoryUtil.getLog(SynchronizationUtils.class);