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