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                    byte[] cookie = new byte[0];
354    
355                    while (cookie != null) {
356                            List<SearchResult> searchResults = new ArrayList<SearchResult>();
357    
358                            cookie = PortalLDAPUtil.getGroups(
359                                    ldapServerId, companyId, ldapContext, cookie, 0, searchResults);
360    
361                            for (SearchResult searchResult : searchResults) {
362                                    try {
363                                            Attributes attributes = PortalLDAPUtil.getGroupAttributes(
364                                                    ldapServerId, companyId, ldapContext,
365                                                    PortalLDAPUtil.getNameInNamespace(
366                                                            ldapServerId, companyId, searchResult),
367                                                    true);
368    
369                                            UserGroup userGroup = importUserGroup(
370                                                    companyId, attributes, groupMappings);
371    
372                                            Attribute usersAttribute = getUsers(
373                                                    ldapServerId, companyId, ldapContext, attributes,
374                                                    userGroup, groupMappings);
375    
376                                            if (usersAttribute == null) {
377                                                    if (_log.isInfoEnabled()) {
378                                                            _log.info(
379                                                                    "No users found in " + userGroup.getName());
380                                                    }
381    
382                                                    continue;
383                                            }
384    
385                                            importUsers(
386                                                    ldapServerId, companyId, ldapContext, userMappings,
387                                                    userExpandoMappings, contactMappings,
388                                                    contactExpandoMappings, userGroup.getUserGroupId(),
389                                                    usersAttribute);
390                                    }
391                                    catch (Exception e) {
392                                            _log.error("Unable to import group " + searchResult, e);
393                                    }
394                            }
395                    }
396            }
397    
398            protected void importFromLDAPByUser(
399                            long ldapServerId, long companyId, LdapContext ldapContext,
400                            Properties userMappings, Properties userExpandoMappings,
401                            Properties contactMappings, Properties contactExpandoMappings,
402                            Properties groupMappings)
403                    throws Exception {
404    
405                    byte[] cookie = new byte[0];
406    
407                    while (cookie != null) {
408                            List<SearchResult> searchResults = new ArrayList<SearchResult>();
409    
410                            cookie = PortalLDAPUtil.getUsers(
411                                    ldapServerId, companyId, ldapContext, cookie, 0, searchResults);
412    
413                            for (SearchResult searchResult : searchResults) {
414                                    try {
415                                            Attributes userAttributes =
416                                                    PortalLDAPUtil.getUserAttributes(
417                                                            ldapServerId, companyId, ldapContext,
418                                                            PortalLDAPUtil.getNameInNamespace(
419                                                                    ldapServerId, companyId, searchResult));
420    
421                                            User user = importUser(
422                                                    companyId, userAttributes, userMappings,
423                                                    userExpandoMappings, contactMappings,
424                                                    contactExpandoMappings, StringPool.BLANK);
425    
426                                            importGroups(
427                                                    ldapServerId, companyId, ldapContext, userAttributes,
428                                                    user, userMappings, groupMappings);
429                                    }
430                                    catch (Exception e) {
431                                            _log.error("Unable to import user " + searchResult, e);
432                                    }
433                            }
434                    }
435            }
436    
437            protected void importGroups(
438                            long ldapServerId, long companyId, LdapContext ldapContext,
439                            Attributes attributes, User user, Properties userMappings,
440                            Properties groupMappings)
441                    throws Exception {
442    
443                    String userMappingsGroup = userMappings.getProperty("group");
444    
445                    if (Validator.isNotNull(userMappingsGroup) &&
446                            (attributes.get(userMappingsGroup) == null)) {
447    
448                            return;
449                    }
450    
451                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
452    
453                    String baseDN = PrefsPropsUtil.getString(
454                            companyId, PropsKeys.LDAP_BASE_DN + postfix);
455    
456                    Binding binding = PortalLDAPUtil.getUser(
457                            ldapServerId, companyId, user.getScreenName());
458    
459                    String fullUserDN = PortalLDAPUtil.getNameInNamespace(
460                            ldapServerId, companyId, binding);
461    
462                    StringBundler sb = new StringBundler(9);
463    
464                    sb.append(StringPool.OPEN_PARENTHESIS);
465                    sb.append(StringPool.AMPERSAND);
466                    sb.append(
467                            PrefsPropsUtil.getString(
468                                    companyId,
469                                    PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
470                    sb.append(StringPool.OPEN_PARENTHESIS);
471                    sb.append(groupMappings.getProperty("user"));
472                    sb.append(StringPool.EQUAL);
473                    sb.append(fullUserDN);
474                    sb.append(StringPool.CLOSE_PARENTHESIS);
475                    sb.append(StringPool.CLOSE_PARENTHESIS);
476    
477                    byte[] cookie = new byte[0];
478    
479                    List<Long> newUserGroupIds = new ArrayList<Long>();
480    
481                    while (cookie != null) {
482                            List<SearchResult> searchResults = new ArrayList<SearchResult>();
483    
484                            PortalLDAPUtil.searchLDAP(
485                                    companyId, ldapContext, cookie, 0, baseDN, sb.toString(), null,
486                                    searchResults);
487    
488                            for (SearchResult searchResult : searchResults) {
489                                    String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
490                                            ldapServerId, companyId, searchResult);
491    
492                                    Attributes groupAttributes = null;
493    
494                                    try {
495                                            groupAttributes = PortalLDAPUtil.getGroupAttributes(
496                                                    ldapServerId, companyId, ldapContext, fullGroupDN);
497                                    }
498                                    catch (NameNotFoundException nnfe) {
499                                            _log.error(
500                                                    "LDAP group not found with fullGroupDN " + fullGroupDN,
501                                                    nnfe);
502    
503                                            continue;
504                                    }
505    
506                                    UserGroup userGroup = importUserGroup(
507                                            companyId, groupAttributes, groupMappings);
508    
509                                    if (userGroup != null) {
510                                            if (_log.isDebugEnabled()) {
511                                                    _log.debug(
512                                                            "Adding " + user.getUserId() + " to group " +
513                                                                    userGroup.getUserGroupId());
514                                            }
515    
516                                            newUserGroupIds.add(userGroup.getUserGroupId());
517                                    }
518                            }
519                    }
520    
521                    UserGroupLocalServiceUtil.setUserUserGroups(
522                            user.getUserId(),
523                            ArrayUtil.toArray(
524                                    newUserGroupIds.toArray(new Long[newUserGroupIds.size()])));
525            }
526    
527            protected User importUser(
528                            long companyId, Attributes attributes, Properties userMappings,
529                            Properties userExpandoMappings, Properties contactMappings,
530                            Properties contactExpandoMappings,
531                            String password)
532                    throws Exception {
533    
534                    LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);
535    
536                    try {
537                            AttributesTransformer attributesTransformer =
538                                    AttributesTransformerFactory.getInstance();
539    
540                            attributes = attributesTransformer.transformUser(attributes);
541    
542                            LDAPUser ldapUser = _ldapToPortalConverter.importLDAPUser(
543                                    companyId, attributes, userMappings, userExpandoMappings,
544                                    contactMappings, contactExpandoMappings, password);
545    
546                            User user = getUser(companyId, ldapUser);
547    
548                            if ((user != null) && user.isDefaultUser()) {
549                                    return user;
550                            }
551    
552                            if (user != null) {
553    
554                                    // User already exists in the Liferay database. Skip import if
555                                    // user fields have been already synced, if import is part of a
556                                    // scheduled import, or if the LDAP entry has never been
557                                    // modified.
558    
559                                    String modifiedDate = LDAPUtil.getAttributeValue(
560                                            attributes, "modifyTimestamp");
561    
562                                    user = updateUser(
563                                            companyId, ldapUser, user, password, modifiedDate);
564                            }
565                            else {
566                                    user = addUser(companyId, ldapUser, password);
567                            }
568    
569                            updateExpandoAttributes(user, ldapUser);
570    
571                            return user;
572                    }
573                    finally {
574                            LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
575                    }
576            }
577    
578            protected UserGroup importUserGroup(
579                            long companyId, Attributes attributes, Properties groupMappings)
580                    throws Exception {
581    
582                    AttributesTransformer attributesTransformer =
583                            AttributesTransformerFactory.getInstance();
584    
585                    attributes = attributesTransformer.transformGroup(attributes);
586    
587                    LDAPGroup ldapGroup = _ldapToPortalConverter.importLDAPGroup(
588                            companyId, attributes, groupMappings);
589    
590                    UserGroup userGroup = null;
591    
592                    try {
593                            userGroup = UserGroupLocalServiceUtil.getUserGroup(
594                                    companyId, ldapGroup.getGroupName());
595    
596                            UserGroupLocalServiceUtil.updateUserGroup(
597                                    companyId, userGroup.getUserGroupId(), ldapGroup.getGroupName(),
598                                    ldapGroup.getDescription());
599                    }
600                    catch (NoSuchUserGroupException nsuge) {
601                            if (_log.isDebugEnabled()) {
602                                    _log.debug(
603                                            "Adding user group to portal " + ldapGroup.getGroupName());
604                            }
605    
606                            long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
607                                    companyId);
608    
609                            try {
610                                    userGroup = UserGroupLocalServiceUtil.addUserGroup(
611                                            defaultUserId, companyId, ldapGroup.getGroupName(),
612                                            ldapGroup.getDescription());
613                            }
614                            catch (Exception e) {
615                                    if (_log.isWarnEnabled()) {
616                                            _log.warn(
617                                                    "Unable to create user group " +
618                                                            ldapGroup.getGroupName());
619                                    }
620    
621                                    if (_log.isDebugEnabled()) {
622                                            _log.debug(e, e);
623                                    }
624                            }
625                    }
626    
627                    addRole(companyId, ldapGroup, userGroup);
628    
629                    return userGroup;
630            }
631    
632            protected void importUsers(
633                            long ldapServerId, long companyId, LdapContext ldapContext,
634                            Properties userMappings, Properties userExpandoMappings,
635                            Properties contactMappings, Properties contactExpandoMappings,
636                            long userGroupId, Attribute attribute)
637                    throws Exception {
638    
639                    List<Long> newUserIds = new ArrayList<Long>(attribute.size());
640    
641                    for (int i = 0; i < attribute.size(); i++) {
642                            String fullUserDN = (String)attribute.get(i);
643    
644                            Attributes userAttributes = null;
645    
646                            try {
647                                    userAttributes = PortalLDAPUtil.getUserAttributes(
648                                            ldapServerId, companyId, ldapContext, fullUserDN);
649                            }
650                            catch (NameNotFoundException nnfe) {
651                                    _log.error(
652                                            "LDAP user not found with fullUserDN " + fullUserDN, nnfe);
653    
654                                    continue;
655                            }
656    
657                            try {
658                                    User user = importUser(
659                                            companyId, userAttributes, userMappings,
660                                            userExpandoMappings, contactMappings,
661                                            contactExpandoMappings, StringPool.BLANK);
662    
663                                    if (user != null) {
664                                            if (_log.isDebugEnabled()) {
665                                                    _log.debug(
666                                                            "Adding " + user.getUserId() + " to group " +
667                                                                    userGroupId);
668                                            }
669    
670                                            newUserIds.add(user.getUserId());
671                                    }
672                            }
673                            catch (Exception e) {
674                                    _log.error("Unable to load user " + userAttributes, e);
675                            }
676                    }
677    
678                    UserLocalServiceUtil.setUserGroupUsers(
679                            userGroupId,
680                            ArrayUtil.toArray(newUserIds.toArray(new Long[newUserIds.size()])));
681            }
682    
683            protected void populateExpandoAttributes(
684                    ExpandoBridge expandoBridge, Map<String, String> expandoAttributes) {
685    
686                    for (Map.Entry<String, String> expandoAttribute :
687                                    expandoAttributes.entrySet()) {
688    
689                            String name = expandoAttribute.getKey();
690    
691                            if (!expandoBridge.hasAttribute(name)) {
692                                    continue;
693                            }
694    
695                            int type = expandoBridge.getAttributeType(name);
696    
697                            Serializable value = ExpandoConverterUtil.getAttributeFromString(
698                                    type, expandoAttribute.getValue());
699    
700                            try {
701                                    ExpandoValueLocalServiceUtil.addValue(
702                                            expandoBridge.getCompanyId(), expandoBridge.getClassName(),
703                                            ExpandoTableConstants.DEFAULT_TABLE_NAME, name,
704                                            expandoBridge.getClassPK(), value);
705                            }
706                            catch (Exception e) {
707                                    _log.error(e, e);
708                            }
709                    }
710            }
711    
712            protected void updateExpandoAttributes(User user, LDAPUser ldapUser)
713                    throws Exception {
714    
715                    ExpandoBridge userExpandoBridge = user.getExpandoBridge();
716    
717                    populateExpandoAttributes(
718                            userExpandoBridge, ldapUser.getUserExpandoAttributes());
719    
720                    Contact contact = user.getContact();
721    
722                    ExpandoBridge contactExpandoBridge = contact.getExpandoBridge();
723    
724                    populateExpandoAttributes(
725                            contactExpandoBridge , ldapUser.getContactExpandoAttributes());
726            }
727    
728            protected User updateUser(
729                            long companyId, LDAPUser ldapUser, User user, String password,
730                            String modifiedDate)
731                    throws Exception {
732    
733                    Date ldapUserModifiedDate = null;
734    
735                    try {
736                            if (Validator.isNull(modifiedDate)) {
737                                    if (_log.isInfoEnabled()) {
738                                            _log.info(
739                                                    "LDAP entry never modified, skipping user " +
740                                                            user.getEmailAddress());
741                                    }
742    
743                                    return user;
744                            }
745                            else {
746                                    DateFormat dateFormat =
747                                            DateFormatFactoryUtil.getSimpleDateFormat(
748                                                    "yyyyMMddHHmmss");
749    
750                                    ldapUserModifiedDate = dateFormat.parse(modifiedDate);
751                            }
752    
753                            if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
754                                    ldapUser.isAutoPassword()) {
755    
756                                    if (_log.isDebugEnabled()) {
757                                            _log.debug(
758                                                    "User is already synchronized, skipping user " +
759                                                            user.getEmailAddress());
760                                    }
761    
762                                    return user;
763                            }
764                    }
765                    catch (ParseException pe) {
766                            if (_log.isDebugEnabled()) {
767                                    _log.debug(
768                                            "Unable to parse LDAP modify timestamp " + modifiedDate,
769                                            pe);
770                            }
771                    }
772    
773                    if (Validator.isNull(ldapUser.getScreenName())) {
774                            ldapUser.setAutoScreenName(true);
775                    }
776    
777                    if (ldapUser.isAutoScreenName()) {
778                            ScreenNameGenerator screenNameGenerator =
779                                    ScreenNameGeneratorFactory.getInstance();
780    
781                            ldapUser.setScreenName(
782                                    screenNameGenerator.generate(
783                                            companyId, user.getUserId(), ldapUser.getEmailAddress()));
784                    }
785    
786                    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
787    
788                    birthdayCal.setTime(user.getContact().getBirthday());
789    
790                    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
791                    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
792                    int birthdayYear = birthdayCal.get(Calendar.YEAR);
793    
794                    if (ldapUser.isUpdatePassword()) {
795                            UserLocalServiceUtil.updatePassword(
796                                    user.getUserId(), password, password,
797                                    ldapUser.isPasswordReset(), true);
798                    }
799    
800                    user = UserLocalServiceUtil.updateUser(
801                            user.getUserId(), password, StringPool.BLANK, StringPool.BLANK,
802                            ldapUser.isPasswordReset(), ldapUser.getReminderQueryQuestion(),
803                            ldapUser.getReminderQueryAnswer(), ldapUser.getScreenName(),
804                            ldapUser.getEmailAddress(), ldapUser.getFacebookId(),
805                            ldapUser.getOpenId(), ldapUser.getLanguageId(),
806                            ldapUser.getTimeZoneId(), ldapUser.getGreeting(),
807                            ldapUser.getComments(), ldapUser.getFirstName(),
808                            ldapUser.getMiddleName(), ldapUser.getLastName(),
809                            ldapUser.getPrefixId(), ldapUser.getSuffixId(), ldapUser.isMale(),
810                            birthdayMonth, birthdayDay, birthdayYear, ldapUser.getSmsSn(),
811                            ldapUser.getAimSn(), ldapUser.getFacebookSn(), ldapUser.getIcqSn(),
812                            ldapUser.getJabberSn(), ldapUser.getMsnSn(),
813                            ldapUser.getMySpaceSn(), ldapUser.getSkypeSn(),
814                            ldapUser.getTwitterSn(), ldapUser.getYmSn(), ldapUser.getJobTitle(),
815                            ldapUser.getGroupIds(), ldapUser.getOrganizationIds(),
816                            ldapUser.getRoleIds(), ldapUser.getUserGroupRoles(),
817                            ldapUser.getUserGroupIds(), ldapUser.getServiceContext());
818    
819                    if (ldapUserModifiedDate != null) {
820                            user = UserLocalServiceUtil.updateModifiedDate(
821                                    user.getUserId(), ldapUserModifiedDate);
822                    }
823    
824                    return user;
825            }
826    
827            private static final String _IMPORT_BY_GROUP = "group";
828    
829            private static final String _IMPORT_BY_USER = "user";
830    
831            private static Log _log = LogFactoryUtil.getLog(
832                    PortalLDAPImporterImpl.class);
833    
834            private LDAPToPortalConverter _ldapToPortalConverter;
835    
836    }