001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.ldap;
016    
017    import com.liferay.portal.NoSuchRoleException;
018    import com.liferay.portal.NoSuchUserException;
019    import com.liferay.portal.NoSuchUserGroupException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
024    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Time;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.model.Company;
032    import com.liferay.portal.model.CompanyConstants;
033    import com.liferay.portal.model.Contact;
034    import com.liferay.portal.model.Group;
035    import com.liferay.portal.model.Role;
036    import com.liferay.portal.model.RoleConstants;
037    import com.liferay.portal.model.User;
038    import com.liferay.portal.model.UserGroup;
039    import com.liferay.portal.security.auth.ScreenNameGenerator;
040    import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
041    import com.liferay.portal.service.CompanyLocalServiceUtil;
042    import com.liferay.portal.service.GroupLocalServiceUtil;
043    import com.liferay.portal.service.LockLocalServiceUtil;
044    import com.liferay.portal.service.RoleLocalServiceUtil;
045    import com.liferay.portal.service.UserGroupLocalServiceUtil;
046    import com.liferay.portal.service.UserLocalServiceUtil;
047    import com.liferay.portal.util.PrefsPropsUtil;
048    import com.liferay.portal.util.PropsValues;
049    import com.liferay.portlet.expando.model.ExpandoBridge;
050    import com.liferay.portlet.expando.model.ExpandoTableConstants;
051    import com.liferay.portlet.expando.service.ExpandoValueLocalServiceUtil;
052    import com.liferay.portlet.expando.util.ExpandoConverterUtil;
053    import com.liferay.util.ldap.LDAPUtil;
054    
055    import java.io.Serializable;
056    
057    import java.text.DateFormat;
058    import java.text.ParseException;
059    
060    import java.util.ArrayList;
061    import java.util.Calendar;
062    import java.util.Date;
063    import java.util.List;
064    import java.util.Map;
065    import java.util.Properties;
066    
067    import javax.naming.Binding;
068    import javax.naming.NameNotFoundException;
069    import javax.naming.directory.Attribute;
070    import javax.naming.directory.Attributes;
071    import javax.naming.directory.SearchResult;
072    import javax.naming.ldap.LdapContext;
073    
074    /**
075     * @author Michael C. Han
076     * @author Brian Wing Shun Chan
077     */
078    public class PortalLDAPImporterImpl implements PortalLDAPImporter {
079    
080            public void importFromLDAP() throws Exception {
081                    List<Company> companies = CompanyLocalServiceUtil.getCompanies(false);
082    
083                    for (Company company : companies) {
084                            importFromLDAP(company.getCompanyId());
085                    }
086            }
087    
088            public void importFromLDAP(long companyId) throws Exception {
089                    if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
090                            return;
091                    }
092    
093                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
094    
095                    if (LockLocalServiceUtil.hasLock(
096                                    defaultUserId, PortalLDAPImporterUtil.class.getName(),
097                                    companyId)) {
098    
099                            if (_log.isDebugEnabled()) {
100                                    _log.debug(
101                                            "Skipping LDAP import for company " + companyId +
102                                                    "because another LDAP import is in process");
103                            }
104    
105                            return;
106                    }
107    
108                    LockLocalServiceUtil.lock(
109                            defaultUserId, PortalLDAPImporterUtil.class.getName(), companyId,
110                            PortalLDAPImporterImpl.class.getName(), false, Time.DAY);
111    
112                    try {
113                            long[] ldapServerIds = StringUtil.split(
114                                    PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
115    
116                            if (ldapServerIds.length <= 0) {
117                                    ldapServerIds = new long[] {0};
118                            }
119    
120                            for (long ldapServerId : ldapServerIds) {
121                                    importFromLDAP(ldapServerId, companyId);
122                            }
123                    }
124                    finally {
125                            LockLocalServiceUtil.unlock(
126                                    PortalLDAPImporterUtil.class.getName(), companyId);
127                    }
128            }
129    
130            public void importFromLDAP(long ldapServerId, long companyId)
131                    throws Exception {
132    
133                    if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
134                            return;
135                    }
136    
137                    LdapContext ldapContext = PortalLDAPUtil.getContext(
138                            ldapServerId, companyId);
139    
140                    if (ldapContext == null) {
141                            return;
142                    }
143    
144                    try {
145                            Properties userMappings = LDAPSettingsUtil.getUserMappings(
146                                    ldapServerId, companyId);
147                            Properties userExpandoMappings =
148                                    LDAPSettingsUtil.getUserExpandoMappings(
149                                            ldapServerId, companyId);
150                            Properties contactMappings = LDAPSettingsUtil.getContactMappings(
151                                    ldapServerId, companyId);
152                            Properties contactExpandoMappings =
153                                    LDAPSettingsUtil.getContactExpandoMappings(
154                                            ldapServerId, companyId);
155                            Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
156                                    ldapServerId, companyId);
157    
158                            String importMethod = PrefsPropsUtil.getString(
159                                    companyId, PropsKeys.LDAP_IMPORT_METHOD);
160    
161                            if (importMethod.equals(_IMPORT_BY_GROUP)) {
162                                    importFromLDAPByGroup(
163                                            ldapServerId, companyId, ldapContext, userMappings,
164                                            userExpandoMappings, contactMappings,
165                                            contactExpandoMappings, groupMappings);
166                            }
167                            else if (importMethod.equals(_IMPORT_BY_USER)) {
168                                    importFromLDAPByUser(
169                                            ldapServerId, companyId, ldapContext, userMappings,
170                                            userExpandoMappings, contactMappings,
171                                            contactExpandoMappings, groupMappings);
172                            }
173                    }
174                    catch (Exception e) {
175                            _log.error("Error importing LDAP users and groups", e);
176                    }
177                    finally {
178                            if (ldapContext != null) {
179                                    ldapContext.close();
180                            }
181                    }
182            }
183    
184            public User importLDAPUser(
185                            long ldapServerId, long companyId, LdapContext ldapContext,
186                            Attributes attributes, String password)
187                    throws Exception {
188    
189                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
190                            ldapServerId, companyId);
191                    Properties userExpandoMappings =
192                            LDAPSettingsUtil.getUserExpandoMappings(
193                                    ldapServerId, companyId);
194                    Properties contactMappings = LDAPSettingsUtil.getContactMappings(
195                            ldapServerId, companyId);
196                    Properties contactExpandoMappings =
197                            LDAPSettingsUtil.getContactExpandoMappings(ldapServerId, companyId);
198    
199                    User user = importUser(
200                            companyId, attributes, userMappings, userExpandoMappings,
201                            contactMappings, contactExpandoMappings, password);
202    
203                    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
204                            ldapServerId, companyId);
205    
206                    importGroups(
207                            ldapServerId, companyId, ldapContext, attributes, user,
208                            userMappings, groupMappings);
209    
210                    return user;
211            }
212    
213            public void setLDAPToPortalConverter(
214                    LDAPToPortalConverter ldapToPortalConverter) {
215    
216                    _ldapToPortalConverter = ldapToPortalConverter;
217            }
218    
219            protected void addRole(
220                            long companyId, LDAPGroup ldapGroup, UserGroup userGroup)
221                    throws Exception {
222    
223                    if (!PropsValues.LDAP_IMPORT_CREATE_ROLE_PER_GROUP) {
224                            return;
225                    }
226    
227                    Role role = null;
228    
229                    try {
230                            role = RoleLocalServiceUtil.getRole(
231                                    companyId, ldapGroup.getGroupName());
232                    }
233                    catch (NoSuchRoleException nsre) {
234                            User defaultUser = UserLocalServiceUtil.getDefaultUser(
235                                    companyId);
236    
237                            role = RoleLocalServiceUtil.addRole(
238                                    defaultUser.getUserId(), companyId, ldapGroup.getGroupName(),
239                                    null, "Autogenerated role from LDAP import",
240                                    RoleConstants.TYPE_REGULAR);
241                    }
242    
243                    Group group = userGroup.getGroup();
244    
245                    if (GroupLocalServiceUtil.hasRoleGroup(
246                                    role.getRoleId(), group.getGroupId())) {
247    
248                            return;
249                    }
250    
251                    GroupLocalServiceUtil.addRoleGroups(
252                            role.getRoleId(), new long[] {group.getGroupId()});
253            }
254    
255            protected User addUser(
256                            long companyId, LDAPUser ldapUser, String password)
257                    throws Exception {
258    
259                    if (_log.isDebugEnabled()) {
260                            _log.debug("Adding user " + ldapUser.getEmailAddress());
261                    }
262    
263                    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
264    
265                    birthdayCal.setTime(ldapUser.getBirthday());
266    
267                    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
268                    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
269                    int birthdayYear = birthdayCal.get(Calendar.YEAR);
270    
271                    return UserLocalServiceUtil.addUser(
272                            ldapUser.getCreatorUserId(), companyId, ldapUser.isAutoPassword(),
273                            password, password, ldapUser.isAutoScreenName(),
274                            ldapUser.getScreenName(), ldapUser.getEmailAddress(),
275                            ldapUser.getFacebookId(), ldapUser.getOpenId(),
276                            ldapUser.getLocale(), ldapUser.getFirstName(),
277                            ldapUser.getMiddleName(), ldapUser.getLastName(),
278                            ldapUser.getPrefixId(), ldapUser.getSuffixId(), ldapUser.isMale(),
279                            birthdayMonth, birthdayDay, birthdayYear, ldapUser.getJobTitle(),
280                            ldapUser.getGroupIds(), ldapUser.getOrganizationIds(),
281                            ldapUser.getRoleIds(), ldapUser.getUserGroupIds(),
282                            ldapUser.isSendEmail(), ldapUser.getServiceContext());
283            }
284    
285            protected User getUser(long companyId, LDAPUser ldapUser)
286                    throws Exception {
287    
288                    User user = null;
289    
290                    try {
291                            String authType = PrefsPropsUtil.getString(
292                                    companyId, PropsKeys.COMPANY_SECURITY_AUTH_TYPE,
293                                    PropsValues.COMPANY_SECURITY_AUTH_TYPE);
294    
295                            if (authType.equals(CompanyConstants.AUTH_TYPE_SN) &&
296                                    !ldapUser.isAutoScreenName()) {
297    
298                                    user = UserLocalServiceUtil.getUserByScreenName(
299                                            companyId, ldapUser.getScreenName());
300                            }
301                            else {
302                                    user = UserLocalServiceUtil.getUserByEmailAddress(
303                                            companyId, ldapUser.getEmailAddress());
304                            }
305                    }
306                    catch (NoSuchUserException nsue) {
307                    }
308    
309                    return user;
310            }
311    
312            protected Attribute getUsers(
313                            long ldapServerId, long companyId, LdapContext ldapContext,
314                            Attributes attributes, UserGroup userGroup,
315                            Properties groupMappings)
316                    throws Exception {
317    
318                    Attribute attribute = attributes.get(groupMappings.getProperty("user"));
319    
320                    if (attribute == null) {
321                            return null;
322                    }
323    
324                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
325    
326                    String baseDN = PrefsPropsUtil.getString(
327                            companyId, PropsKeys.LDAP_BASE_DN + postfix);
328    
329                    StringBundler sb = new StringBundler(7);
330    
331                    sb.append("(&");
332                    sb.append(
333                            PrefsPropsUtil.getString(
334                                    companyId,
335                                    PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
336                    sb.append("(");
337                    sb.append(groupMappings.getProperty("groupName"));
338                    sb.append("=");
339                    sb.append(userGroup.getName());
340                    sb.append("))");
341    
342                    return PortalLDAPUtil.getMultivaluedAttribute(
343                            companyId, ldapContext, baseDN, sb.toString(), attribute);
344            }
345    
346            protected void importFromLDAPByGroup(
347                            long ldapServerId, long companyId, LdapContext ldapContext,
348                            Properties userMappings, Properties userExpandoMappings,
349                            Properties contactMappings, Properties contactExpandoMappings,
350                            Properties groupMappings)
351                    throws Exception {
352    
353                    List<SearchResult> searchResults = PortalLDAPUtil.getGroups(
354                            ldapServerId, companyId, ldapContext, 0);
355    
356                    for (SearchResult searchResult : searchResults) {
357                            try {
358                                    Attributes attributes = PortalLDAPUtil.getGroupAttributes(
359                                            ldapServerId, companyId, ldapContext,
360                                            PortalLDAPUtil.getNameInNamespace(
361                                                    ldapServerId, companyId, searchResult),
362                                            true);
363    
364                                    UserGroup userGroup = importUserGroup(
365                                            companyId, attributes, groupMappings);
366    
367                                    Attribute usersAttribute = getUsers(
368                                            ldapServerId, companyId, ldapContext, attributes, userGroup,
369                                            groupMappings);
370    
371                                    if (usersAttribute == null) {
372                                            if (_log.isInfoEnabled()) {
373                                                    _log.info("No users found in " + userGroup.getName());
374                                            }
375    
376                                            continue;
377                                    }
378    
379                                    importUsers(
380                                            ldapServerId, companyId, ldapContext, userMappings,
381                                            userExpandoMappings, contactMappings,
382                                            contactExpandoMappings, userGroup.getUserGroupId(),
383                                            usersAttribute);
384                            }
385                            catch (Exception e) {
386                                    _log.error("Unable to import group " + searchResult, e);
387                            }
388                    }
389            }
390    
391            protected void importFromLDAPByUser(
392                            long ldapServerId, long companyId, LdapContext ldapContext,
393                            Properties userMappings, Properties userExpandoMappings,
394                            Properties contactMappings, Properties contactExpandoMappings,
395                            Properties groupMappings)
396                    throws Exception {
397    
398                    List<SearchResult> searchResults = PortalLDAPUtil.getUsers(
399                            ldapServerId, companyId, ldapContext, 0);
400    
401                    for (SearchResult searchResult : searchResults) {
402                            try {
403                                    Attributes userAttributes = PortalLDAPUtil.getUserAttributes(
404                                            ldapServerId, companyId, ldapContext,
405                                            PortalLDAPUtil.getNameInNamespace(
406                                                    ldapServerId, companyId, searchResult));
407    
408                                    User user = importUser(
409                                            companyId, userAttributes, userMappings,
410                                            userExpandoMappings, contactMappings,
411                                            contactExpandoMappings, StringPool.BLANK);
412    
413                                    importGroups(
414                                            ldapServerId, companyId, ldapContext, userAttributes, user,
415                                            userMappings, groupMappings);
416                            }
417                            catch (Exception e) {
418                                    _log.error("Unable to import user " + searchResult, e);
419                            }
420                    }
421            }
422    
423            protected void importGroups(
424                            long ldapServerId, long companyId, LdapContext ldapContext,
425                            Attributes attributes, User user, Properties userMappings,
426                            Properties groupMappings)
427                    throws Exception {
428    
429                    String userMappingsGroup = userMappings.getProperty("group");
430    
431                    if (Validator.isNull(userMappingsGroup)) {
432                            return;
433                    }
434    
435                    Attribute attribute = attributes.get(userMappingsGroup);
436    
437                    if (attribute == null) {
438                            return;
439                    }
440    
441                    attribute.clear();
442    
443                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
444    
445                    String baseDN = PrefsPropsUtil.getString(
446                            companyId, PropsKeys.LDAP_BASE_DN + postfix);
447    
448                    Binding binding = PortalLDAPUtil.getUser(
449                            ldapServerId, companyId, user.getScreenName());
450    
451                    String fullUserDN = PortalLDAPUtil.getNameInNamespace(
452                            ldapServerId, companyId, binding);
453    
454                    StringBundler sb = new StringBundler(9);
455    
456                    sb.append(StringPool.OPEN_PARENTHESIS);
457                    sb.append(StringPool.AMPERSAND);
458                    sb.append(
459                            PrefsPropsUtil.getString(
460                                    companyId,
461                                    PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
462                    sb.append(StringPool.OPEN_PARENTHESIS);
463                    sb.append(groupMappings.getProperty("user"));
464                    sb.append(StringPool.EQUAL);
465                    sb.append(fullUserDN);
466                    sb.append(StringPool.CLOSE_PARENTHESIS);
467                    sb.append(StringPool.CLOSE_PARENTHESIS);
468    
469                    List<SearchResult> searchResults = PortalLDAPUtil.searchLDAP(
470                            companyId, ldapContext, 0, baseDN, sb.toString(), null);
471    
472                    for (SearchResult searchResult : searchResults) {
473                            String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
474                                    ldapServerId, companyId, searchResult);
475    
476                            attribute.add(fullGroupDN);
477                    }
478    
479                    List<Long> newUserGroupIds = new ArrayList<Long>(attribute.size());
480    
481                    for (int i = 0; i < attribute.size(); i++) {
482                            String fullGroupDN = (String) attribute.get(i);
483    
484                            Attributes groupAttributes = null;
485    
486                            try {
487                                    groupAttributes = PortalLDAPUtil.getGroupAttributes(
488                                            ldapServerId, companyId, ldapContext, fullGroupDN);
489                            }
490                            catch (NameNotFoundException nnfe) {
491                                    _log.error(
492                                            "LDAP group not found with fullGroupDN " + fullGroupDN,
493                                            nnfe);
494    
495                                    continue;
496                            }
497    
498                            UserGroup userGroup = importUserGroup(
499                                    companyId, groupAttributes, groupMappings);
500    
501                            if (userGroup != null) {
502                                    if (_log.isDebugEnabled()) {
503                                            _log.debug(
504                                                    "Adding " + user.getUserId() + " to group " +
505                                                            userGroup.getUserGroupId());
506                                    }
507    
508                                    newUserGroupIds.add(userGroup.getUserGroupId());
509                            }
510                    }
511    
512                    UserGroupLocalServiceUtil.setUserUserGroups(
513                            user.getUserId(),
514                            ArrayUtil.toArray(
515                                    newUserGroupIds.toArray(new Long[newUserGroupIds.size()])));
516            }
517    
518            protected User importUser(
519                            long companyId, Attributes attributes, Properties userMappings,
520                            Properties userExpandoMappings, Properties contactMappings,
521                            Properties contactExpandoMappings,
522                            String password)
523                    throws Exception {
524    
525                    LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);
526    
527                    try {
528                            AttributesTransformer attributesTransformer =
529                                    AttributesTransformerFactory.getInstance();
530    
531                            attributes = attributesTransformer.transformUser(attributes);
532    
533                            LDAPUser ldapUser = _ldapToPortalConverter.importLDAPUser(
534                                    companyId, attributes, userMappings, userExpandoMappings,
535                                    contactMappings, contactExpandoMappings, password);
536    
537                            User user = getUser(companyId, ldapUser);
538    
539                            if ((user != null) && user.isDefaultUser()) {
540                                    return user;
541                            }
542    
543                            if (user != null) {
544    
545                                    // User already exists in the Liferay database. Skip import if
546                                    // user fields have been already synced, if import is part of a
547                                    // scheduled import, or if the LDAP entry has never been
548                                    // modified.
549    
550                                    String modifiedDate = LDAPUtil.getAttributeValue(
551                                            attributes, "modifyTimestamp");
552    
553                                    user = updateUser(
554                                            companyId, ldapUser, user, password, modifiedDate);
555                            }
556                            else {
557                                    user = addUser(companyId, ldapUser, password);
558                            }
559    
560                            updateExpandoAttributes(user, ldapUser);
561    
562                            return user;
563                    }
564                    finally {
565                            LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
566                    }
567            }
568    
569            protected UserGroup importUserGroup(
570                            long companyId, Attributes attributes, Properties groupMappings)
571                    throws Exception {
572    
573                    AttributesTransformer attributesTransformer =
574                            AttributesTransformerFactory.getInstance();
575    
576                    attributes = attributesTransformer.transformGroup(attributes);
577    
578                    LDAPGroup ldapGroup = _ldapToPortalConverter.importLDAPGroup(
579                            companyId, attributes, groupMappings);
580    
581                    UserGroup userGroup = null;
582    
583                    try {
584                            userGroup = UserGroupLocalServiceUtil.getUserGroup(
585                                    companyId, ldapGroup.getGroupName());
586    
587                            UserGroupLocalServiceUtil.updateUserGroup(
588                                    companyId, userGroup.getUserGroupId(), ldapGroup.getGroupName(),
589                                    ldapGroup.getDescription());
590                    }
591                    catch (NoSuchUserGroupException nsuge) {
592                            if (_log.isDebugEnabled()) {
593                                    _log.debug(
594                                            "Adding user group to portal " + ldapGroup.getGroupName());
595                            }
596    
597                            long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
598                                    companyId);
599    
600                            try {
601                                    userGroup = UserGroupLocalServiceUtil.addUserGroup(
602                                            defaultUserId, companyId, ldapGroup.getGroupName(),
603                                            ldapGroup.getDescription());
604                            }
605                            catch (Exception e) {
606                                    if (_log.isWarnEnabled()) {
607                                            _log.warn(
608                                                    "Unable to create user group " +
609                                                            ldapGroup.getGroupName());
610                                    }
611    
612                                    if (_log.isDebugEnabled()) {
613                                            _log.debug(e, e);
614                                    }
615                            }
616                    }
617    
618                    addRole(companyId, ldapGroup, userGroup);
619    
620                    return userGroup;
621            }
622    
623            protected void importUsers(
624                            long ldapServerId, long companyId, LdapContext ldapContext,
625                            Properties userMappings, Properties userExpandoMappings,
626                            Properties contactMappings, Properties contactExpandoMappings,
627                            long userGroupId, Attribute attribute)
628                    throws Exception {
629    
630                    List<Long> newUserIds = new ArrayList<Long>(attribute.size());
631    
632                    for (int i = 0; i < attribute.size(); i++) {
633                            String fullUserDN = (String)attribute.get(i);
634    
635                            Attributes userAttributes = null;
636    
637                            try {
638                                    userAttributes = PortalLDAPUtil.getUserAttributes(
639                                            ldapServerId, companyId, ldapContext, fullUserDN);
640                            }
641                            catch (NameNotFoundException nnfe) {
642                                    _log.error(
643                                            "LDAP user not found with fullUserDN " + fullUserDN, nnfe);
644    
645                                    continue;
646                            }
647    
648                            try {
649                                    User user = importUser(
650                                            companyId, userAttributes, userMappings,
651                                            userExpandoMappings, contactMappings,
652                                            contactExpandoMappings, StringPool.BLANK);
653    
654                                    if (user != null) {
655                                            if (_log.isDebugEnabled()) {
656                                                    _log.debug(
657                                                            "Adding " + user.getUserId() + " to group " +
658                                                                    userGroupId);
659                                            }
660    
661                                            newUserIds.add(user.getUserId());
662                                    }
663                            }
664                            catch (Exception e) {
665                                    _log.error("Unable to load user " + userAttributes, e);
666                            }
667                    }
668    
669                    UserLocalServiceUtil.setUserGroupUsers(
670                            userGroupId,
671                            ArrayUtil.toArray(newUserIds.toArray(new Long[newUserIds.size()])));
672            }
673    
674            protected void populateExpandoAttributes(
675                    ExpandoBridge expandoBridge, Map<String, String> expandoAttributes) {
676    
677                    for (Map.Entry<String, String> expandoAttribute :
678                                    expandoAttributes.entrySet()) {
679    
680                            String name = expandoAttribute.getKey();
681    
682                            if (!expandoBridge.hasAttribute(name)) {
683                                    continue;
684                            }
685    
686                            int type = expandoBridge.getAttributeType(name);
687    
688                            Serializable value = ExpandoConverterUtil.getAttributeFromString(
689                                    type, expandoAttribute.getValue());
690    
691                            try {
692                                    ExpandoValueLocalServiceUtil.addValue(
693                                            expandoBridge.getCompanyId(), expandoBridge.getClassName(),
694                                            ExpandoTableConstants.DEFAULT_TABLE_NAME, name,
695                                            expandoBridge.getClassPK(), value);
696                            }
697                            catch (Exception e) {
698                                    _log.error(e, e);
699                            }
700                    }
701            }
702    
703            protected void updateExpandoAttributes(User user, LDAPUser ldapUser)
704                    throws Exception {
705    
706                    ExpandoBridge userExpandoBridge = user.getExpandoBridge();
707    
708                    populateExpandoAttributes(
709                            userExpandoBridge, ldapUser.getUserExpandoAttributes());
710    
711                    Contact contact = user.getContact();
712    
713                    ExpandoBridge contactExpandoBridge = contact.getExpandoBridge();
714    
715                    populateExpandoAttributes(
716                            contactExpandoBridge , ldapUser.getContactExpandoAttributes());
717            }
718    
719            protected User updateUser(
720                            long companyId, LDAPUser ldapUser, User user, String password,
721                            String modifiedDate)
722                    throws Exception {
723    
724                    Date ldapUserModifiedDate = null;
725    
726                    try {
727                            if (Validator.isNull(modifiedDate)) {
728                                    if (_log.isInfoEnabled()) {
729                                            _log.info(
730                                                    "LDAP entry never modified, skipping user " +
731                                                            user.getEmailAddress());
732                                    }
733    
734                                    return user;
735                            }
736                            else {
737                                    DateFormat dateFormat =
738                                            DateFormatFactoryUtil.getSimpleDateFormat(
739                                                    "yyyyMMddHHmmss");
740    
741                                    ldapUserModifiedDate = dateFormat.parse(modifiedDate);
742                            }
743    
744                            if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
745                                    ldapUser.isAutoPassword()) {
746    
747                                    if (_log.isDebugEnabled()) {
748                                            _log.debug(
749                                                    "User is already synchronized, skipping user " +
750                                                            user.getEmailAddress());
751                                    }
752    
753                                    return user;
754                            }
755                    }
756                    catch (ParseException pe) {
757                            if (_log.isDebugEnabled()) {
758                                    _log.debug(
759                                            "Unable to parse LDAP modify timestamp " + modifiedDate,
760                                            pe);
761                            }
762                    }
763    
764                    if (Validator.isNull(ldapUser.getScreenName())) {
765                            ldapUser.setAutoScreenName(true);
766                    }
767    
768                    if (ldapUser.isAutoScreenName()) {
769                            ScreenNameGenerator screenNameGenerator =
770                                    ScreenNameGeneratorFactory.getInstance();
771    
772                            ldapUser.setScreenName(
773                                    screenNameGenerator.generate(
774                                            companyId, user.getUserId(), ldapUser.getEmailAddress()));
775                    }
776    
777                    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
778    
779                    birthdayCal.setTime(user.getContact().getBirthday());
780    
781                    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
782                    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
783                    int birthdayYear = birthdayCal.get(Calendar.YEAR);
784    
785                    if (ldapUser.isUpdatePassword()) {
786                            UserLocalServiceUtil.updatePassword(
787                                    user.getUserId(), password, password,
788                                    ldapUser.isPasswordReset(), true);
789                    }
790    
791                    user = UserLocalServiceUtil.updateUser(
792                            user.getUserId(), password, StringPool.BLANK, StringPool.BLANK,
793                            ldapUser.isPasswordReset(), ldapUser.getReminderQueryQuestion(),
794                            ldapUser.getReminderQueryAnswer(), ldapUser.getScreenName(),
795                            ldapUser.getEmailAddress(), ldapUser.getFacebookId(),
796                            ldapUser.getOpenId(), ldapUser.getLanguageId(),
797                            ldapUser.getTimeZoneId(), ldapUser.getGreeting(),
798                            ldapUser.getComments(), ldapUser.getFirstName(),
799                            ldapUser.getMiddleName(), ldapUser.getLastName(),
800                            ldapUser.getPrefixId(), ldapUser.getSuffixId(), ldapUser.isMale(),
801                            birthdayMonth, birthdayDay, birthdayYear, ldapUser.getSmsSn(),
802                            ldapUser.getAimSn(), ldapUser.getFacebookSn(), ldapUser.getIcqSn(),
803                            ldapUser.getJabberSn(), ldapUser.getMsnSn(),
804                            ldapUser.getMySpaceSn(), ldapUser.getSkypeSn(),
805                            ldapUser.getTwitterSn(), ldapUser.getYmSn(), ldapUser.getJobTitle(),
806                            ldapUser.getGroupIds(), ldapUser.getOrganizationIds(),
807                            ldapUser.getRoleIds(), ldapUser.getUserGroupRoles(),
808                            ldapUser.getUserGroupIds(), ldapUser.getServiceContext());
809    
810                    if (ldapUserModifiedDate != null) {
811                            user = UserLocalServiceUtil.updateModifiedDate(
812                                    user.getUserId(), ldapUserModifiedDate);
813                    }
814    
815                    return user;
816            }
817    
818            private static final String _IMPORT_BY_GROUP = "group";
819    
820            private static final String _IMPORT_BY_USER = "user";
821    
822            private static Log _log = LogFactoryUtil.getLog(
823                    PortalLDAPImporterImpl.class);
824    
825            private LDAPToPortalConverter _ldapToPortalConverter;
826    
827    }