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