1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.security.ldap;
24  
25  import com.liferay.portal.NoSuchUserException;
26  import com.liferay.portal.NoSuchUserGroupException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.SystemException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.log.LogUtil;
32  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
33  import com.liferay.portal.kernel.util.PropertiesUtil;
34  import com.liferay.portal.kernel.util.StringMaker;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.StringUtil;
37  import com.liferay.portal.kernel.util.Validator;
38  import com.liferay.portal.model.Company;
39  import com.liferay.portal.model.Contact;
40  import com.liferay.portal.model.User;
41  import com.liferay.portal.model.UserGroup;
42  import com.liferay.portal.service.CompanyLocalServiceUtil;
43  import com.liferay.portal.service.UserGroupLocalServiceUtil;
44  import com.liferay.portal.service.UserLocalServiceUtil;
45  import com.liferay.portal.util.PrefsPropsUtil;
46  import com.liferay.portal.util.PropsUtil;
47  import com.liferay.util.ldap.LDAPUtil;
48  import com.liferay.util.ldap.Modifications;
49  
50  import java.util.Calendar;
51  import java.util.List;
52  import java.util.Locale;
53  import java.util.Properties;
54  
55  import javax.naming.Binding;
56  import javax.naming.Context;
57  import javax.naming.NameNotFoundException;
58  import javax.naming.NamingEnumeration;
59  import javax.naming.directory.Attribute;
60  import javax.naming.directory.Attributes;
61  import javax.naming.directory.ModificationItem;
62  import javax.naming.directory.SearchControls;
63  import javax.naming.directory.SearchResult;
64  import javax.naming.ldap.InitialLdapContext;
65  import javax.naming.ldap.LdapContext;
66  
67  /**
68   * <a href="PortalLDAPUtil.java.html"><b><i>View Source</i></b></a>
69   *
70   * @author Michael Young
71   * @author Brian Wing Shun Chan
72   * @author Jerry Niu
73   * @author Scott Lee
74   * @author Hervé Ménage
75   *
76   */
77  public class PortalLDAPUtil {
78  
79      public static final String IMPORT_BY_USER = "user";
80  
81      public static final String IMPORT_BY_GROUP = "group";
82  
83      public static void exportToLDAP(Contact contact) throws Exception {
84          long companyId = contact.getCompanyId();
85  
86          if (!isAuthEnabled(companyId) || !isExportEnabled(companyId)) {
87              return;
88          }
89  
90          LdapContext ctx = getContext(companyId);
91  
92          if (ctx == null) {
93              return;
94          }
95  
96          User user = UserLocalServiceUtil.getUserByContactId(
97              contact.getContactId());
98  
99          Properties userMappings = getUserMappings(companyId);
100         Binding binding = getUser(contact.getCompanyId(), user.getScreenName());
101         String name = StringPool.BLANK;
102 
103         if (binding == null) {
104 
105             // Generate full DN based on user DN
106 
107             StringMaker sm = new StringMaker();
108 
109             sm.append(userMappings.getProperty("screenName"));
110             sm.append(StringPool.EQUAL);
111             sm.append(user.getScreenName());
112             sm.append(StringPool.COMMA);
113             sm.append(getUsersDN(companyId));
114 
115             name = sm.toString();
116 
117             // Create new user in LDAP
118 
119             LDAPUser ldapUser = (LDAPUser)Class.forName(
120                 PropsUtil.get(PropsUtil.LDAP_USER_IMPL)).newInstance();
121 
122             ldapUser.setUser(user);
123 
124             ctx.bind(name, ldapUser);
125         }
126         else {
127 
128             // Modify existing LDAP user record
129 
130             name = getNameInNamespace(companyId, binding);
131 
132             Modifications mods = Modifications.getInstance();
133 
134             mods.addItem(
135                 userMappings.getProperty("firstName"), contact.getFirstName());
136             mods.addItem(
137                 userMappings.getProperty("lastName"), contact.getLastName());
138 
139             ModificationItem[] modItems = mods.getItems();
140 
141             ctx.modifyAttributes(name, modItems);
142         }
143     }
144 
145     public static void exportToLDAP(User user) throws Exception {
146         long companyId = user.getCompanyId();
147 
148         if (!isAuthEnabled(companyId) || !isExportEnabled(companyId)) {
149             return;
150         }
151 
152         LdapContext ctx = getContext(companyId);
153 
154         if (ctx == null) {
155             return;
156         }
157 
158         Properties userMappings = getUserMappings(companyId);
159         Binding binding = getUser(user.getCompanyId(), user.getScreenName());
160         String name = StringPool.BLANK;
161 
162         if (binding == null) {
163 
164             // Generate full DN based on user DN
165 
166             StringMaker sm = new StringMaker();
167 
168             sm.append(userMappings.getProperty("screenName"));
169             sm.append(StringPool.EQUAL);
170             sm.append(user.getScreenName());
171             sm.append(StringPool.COMMA);
172             sm.append(getUsersDN(companyId));
173 
174             name = sm.toString();
175 
176             // Create new user in LDAP
177 
178             LDAPUser ldapUser = (LDAPUser)Class.forName(
179                 PropsUtil.get(PropsUtil.LDAP_USER_IMPL)).newInstance();
180 
181             ldapUser.setUser(user);
182 
183             ctx.bind(name, ldapUser);
184         }
185         else {
186 
187             // Modify existing LDAP user record
188 
189             name = getNameInNamespace(companyId, binding);
190 
191             Modifications mods = Modifications.getInstance();
192 
193             if (user.isPasswordModified() &&
194                 Validator.isNotNull(user.getPasswordUnencrypted())) {
195 
196                 mods.addItem(
197                     userMappings.getProperty("password"),
198                     user.getPasswordUnencrypted());
199             }
200 
201             mods.addItem(
202                 userMappings.getProperty("emailAddress"),
203                 user.getEmailAddress());
204 
205             ModificationItem[] modItems = mods.getItems();
206 
207             ctx.modifyAttributes(name, modItems);
208         }
209     }
210 
211     public static String getAuthSearchFilter(
212             long companyId, String emailAddress, String screenName,
213             String userId)
214         throws PortalException, SystemException {
215 
216         String filter = PrefsPropsUtil.getString(
217             companyId, PropsUtil.LDAP_AUTH_SEARCH_FILTER);
218 
219         if (_log.isDebugEnabled()) {
220             _log.debug("Search filter before transformation " + filter);
221         }
222 
223         filter = StringUtil.replace(
224             filter,
225             new String[] {
226                 "@company_id@", "@email_address@", "@screen_name@", "@user_id@"
227             },
228             new String[] {
229                 String.valueOf(companyId), emailAddress, screenName,
230                 userId
231             });
232 
233         if (_log.isDebugEnabled()) {
234             _log.debug("Search filter after transformation " + filter);
235         }
236 
237         return filter;
238     }
239 
240     public static LdapContext getContext(long companyId) throws Exception {
241         Properties env = new Properties();
242 
243         env.put(
244             Context.INITIAL_CONTEXT_FACTORY,
245             PrefsPropsUtil.getString(
246                 companyId, PropsUtil.LDAP_FACTORY_INITIAL));
247         env.put(
248             Context.PROVIDER_URL,
249             PrefsPropsUtil.getString(
250                 companyId, PropsUtil.LDAP_BASE_PROVIDER_URL));
251         env.put(
252             Context.SECURITY_PRINCIPAL,
253             PrefsPropsUtil.getString(
254                 companyId, PropsUtil.LDAP_SECURITY_PRINCIPAL));
255         env.put(
256             Context.SECURITY_CREDENTIALS,
257             PrefsPropsUtil.getString(
258                 companyId, PropsUtil.LDAP_SECURITY_CREDENTIALS));
259 
260         LogUtil.debug(_log, env);
261 
262         LdapContext ctx = null;
263 
264         try {
265             ctx = new InitialLdapContext(env, null);
266         }
267         catch (Exception e) {
268             if (_log.isWarnEnabled()) {
269                 _log.warn("Failed to bind to the LDAP server");
270             }
271 
272             if (_log.isDebugEnabled()) {
273                 _log.debug(e);
274             }
275         }
276 
277         return ctx;
278     }
279 
280     public static Properties getGroupMappings(long companyId)
281         throws Exception {
282 
283         Properties groupMappings = PropertiesUtil.load(
284             PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_GROUP_MAPPINGS));
285 
286         LogUtil.debug(_log, groupMappings);
287 
288         return groupMappings;
289     }
290 
291     public static String getNameInNamespace(long companyId, Binding binding)
292         throws Exception {
293 
294         String baseDN = PrefsPropsUtil.getString(
295             companyId, PropsUtil.LDAP_BASE_DN);
296 
297         if (Validator.isNull(baseDN)) {
298             return binding.getName();
299         }
300         else {
301             StringMaker sm = new StringMaker();
302 
303             sm.append(binding.getName());
304             sm.append(StringPool.COMMA);
305             sm.append(baseDN);
306 
307             return sm.toString();
308         }
309     }
310 
311     public static Binding getUser(long companyId, String screenName)
312         throws Exception {
313 
314         LdapContext ctx = getContext(companyId);
315 
316         if (ctx == null) {
317             return null;
318         }
319 
320         String name = getUsersDN(companyId);
321 
322         Properties userMappings = getUserMappings(companyId);
323 
324         StringMaker filter = new StringMaker();
325 
326         filter.append(StringPool.OPEN_PARENTHESIS);
327         filter.append(userMappings.getProperty("screenName"));
328         filter.append(StringPool.EQUAL);
329         filter.append(screenName);
330         filter.append(StringPool.CLOSE_PARENTHESIS);
331 
332         SearchControls cons = new SearchControls(
333             SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);
334 
335         NamingEnumeration enu = ctx.search(name, filter.toString(), cons);
336 
337         if (enu.hasMore()) {
338             Binding binding = (Binding)enu.next();
339 
340             return binding;
341         }
342         else {
343             return null;
344         }
345     }
346 
347     public static Properties getUserMappings(long companyId) throws Exception {
348         Properties userMappings = PropertiesUtil.load(
349             PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USER_MAPPINGS));
350 
351         LogUtil.debug(_log, userMappings);
352 
353         return userMappings;
354     }
355 
356     public static String getUsersDN(long companyId) throws Exception {
357         return PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USERS_DN);
358     }
359 
360     public static boolean hasUser(long companyId, String screenName)
361         throws Exception {
362 
363         if (getUser(companyId, screenName) != null) {
364             return true;
365         }
366         else {
367             return false;
368         }
369     }
370 
371     public static void importFromLDAP() throws Exception {
372         List companies = CompanyLocalServiceUtil.getCompanies();
373 
374         for (int i = 0; i < companies.size(); i++) {
375             Company company = (Company)companies.get(i);
376 
377             importFromLDAP(company.getCompanyId());
378         }
379     }
380 
381     public static void importFromLDAP(long companyId) throws Exception {
382         if (!isImportEnabled(companyId)) {
383             return;
384         }
385 
386         LdapContext ctx = getContext(companyId);
387 
388         if (ctx == null) {
389             return;
390         }
391 
392         try {
393             String importMethod = PrefsPropsUtil.getString(
394                 companyId, PropsUtil.LDAP_IMPORT_METHOD);
395 
396             String userDN = PrefsPropsUtil.getString(
397                 companyId, PropsUtil.LDAP_USERS_DN);
398             String groupDN = PrefsPropsUtil.getString(
399                 companyId, PropsUtil.LDAP_GROUPS_DN);
400             String userFilter = PrefsPropsUtil.getString(
401                 companyId, PropsUtil.LDAP_IMPORT_USER_SEARCH_FILTER);
402             String groupFilter = PrefsPropsUtil.getString(
403                 companyId, PropsUtil.LDAP_IMPORT_GROUP_SEARCH_FILTER);
404             SearchControls cons = new SearchControls(
405                 SearchControls.SUBTREE_SCOPE, 0, 0, null, false, false);
406 
407             if (importMethod.equals(IMPORT_BY_USER)) {
408                 NamingEnumeration enu = ctx.search(userDN, userFilter, cons);
409 
410                 // Loop through all LDAP users
411 
412                 while (enu.hasMore()) {
413                     SearchResult result = (SearchResult)enu.next();
414 
415                     importLDAPUser(
416                         companyId, ctx, result.getAttributes(), true);
417                 }
418             }
419             else if (importMethod.equals(IMPORT_BY_GROUP)) {
420                 NamingEnumeration enu = ctx.search(groupDN, groupFilter, cons);
421 
422                 // Loop through all LDAP groups
423 
424                 while (enu.hasMore()) {
425                     SearchResult result = (SearchResult)enu.next();
426 
427                     importLDAPGroup(
428                         companyId, ctx, result.getAttributes(), true);
429                 }
430             }
431         }
432         catch (Exception e) {
433             _log.error("Error importing LDAP users and groups", e);
434         }
435         finally {
436             if (ctx != null) {
437                 ctx.close();
438             }
439         }
440     }
441 
442     public static UserGroup importLDAPGroup(
443             long companyId, LdapContext ctx, Attributes attrs,
444             boolean importGroupMembership)
445         throws Exception {
446 
447         Properties groupMappings = getGroupMappings(companyId);
448 
449         LogUtil.debug(_log, groupMappings);
450 
451         String name = LDAPUtil.getAttributeValue(
452             attrs, groupMappings.getProperty("groupName")).toLowerCase();
453         String description = LDAPUtil.getAttributeValue(
454             attrs, groupMappings.getProperty("description"));
455 
456         long creatorUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
457 
458         // Get or create user group
459 
460         UserGroup userGroup = null;
461 
462         try {
463             userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId, name);
464 
465             UserGroupLocalServiceUtil.updateUserGroup(
466                 companyId, userGroup.getUserGroupId(), name, description);
467         }
468         catch (NoSuchUserGroupException nsuge) {
469             userGroup = UserGroupLocalServiceUtil.addUserGroup(
470                 creatorUserId, companyId, name, description);
471         }
472 
473         // Import users and membership
474 
475         if (importGroupMembership && (userGroup != null)) {
476             Attribute attr = attrs.get(groupMappings.getProperty("user"));
477 
478             if (attr != null){
479                 _importUsersAndMembershipFromLDAPGroup(
480                     companyId, ctx, userGroup.getUserGroupId(), attr);
481             }
482         }
483 
484         return userGroup;
485     }
486 
487     public static User importLDAPUser(
488             long companyId, LdapContext ctx, Attributes attrs,
489             boolean importGroupMembership)
490         throws Exception {
491 
492         // Import used on interval import
493 
494         Properties userMappings = getUserMappings(companyId);
495 
496         LogUtil.debug(_log, userMappings);
497 
498         boolean autoPassword = true;
499         String password = StringPool.BLANK;
500         String screenName = LDAPUtil.getAttributeValue(
501             attrs, userMappings.getProperty("screenName")).toLowerCase();
502         String emailAddress = LDAPUtil.getAttributeValue(
503             attrs, userMappings.getProperty("emailAddress"));
504 
505         User user = _importLDAPUser(
506             companyId, ctx, attrs, userMappings, autoPassword, password,
507             screenName, emailAddress, false, importGroupMembership);
508 
509         return user;
510     }
511 
512     public static User importLDAPUser(
513             long companyId, LdapContext ctx, Attributes attrs,
514             String emailAddress, String screenName, String password,
515             boolean importGroupMembership)
516         throws Exception {
517 
518         // Import used on user login
519 
520         Properties userMappings = getUserMappings(companyId);
521 
522         LogUtil.debug(_log, userMappings);
523 
524         boolean autoPassword = false;
525 
526         if (Validator.isNull(screenName)) {
527             screenName = LDAPUtil.getAttributeValue(
528                 attrs, userMappings.getProperty("screenName")).toLowerCase();
529         }
530 
531         if (Validator.isNull(emailAddress)) {
532             emailAddress = LDAPUtil.getAttributeValue(
533                 attrs, userMappings.getProperty("emailAddress"));
534         }
535 
536         User user = _importLDAPUser(
537             companyId, ctx, attrs, userMappings, autoPassword, password,
538             screenName, emailAddress, true, importGroupMembership);
539 
540         return user;
541     }
542 
543     public static boolean isAuthEnabled(long companyId)
544         throws PortalException, SystemException {
545 
546         if (PrefsPropsUtil.getBoolean(companyId, PropsUtil.LDAP_AUTH_ENABLED)) {
547             return true;
548         }
549         else {
550             return false;
551         }
552     }
553 
554     public static boolean isExportEnabled(long companyId)
555         throws PortalException, SystemException {
556 
557         if (PrefsPropsUtil.getBoolean(
558                 companyId, PropsUtil.LDAP_EXPORT_ENABLED)) {
559 
560             return true;
561         }
562         else {
563             return false;
564         }
565     }
566 
567     public static boolean isImportEnabled(long companyId)
568         throws PortalException, SystemException {
569 
570         if (PrefsPropsUtil.getBoolean(
571                 companyId, PropsUtil.LDAP_IMPORT_ENABLED)) {
572 
573             return true;
574         }
575         else {
576             return false;
577         }
578     }
579 
580     public static boolean isImportOnStartup(long companyId)
581         throws PortalException, SystemException {
582 
583         if (PrefsPropsUtil.getBoolean(
584                 companyId, PropsUtil.LDAP_IMPORT_ON_STARTUP)) {
585 
586             return true;
587         }
588         else {
589             return false;
590         }
591     }
592 
593     public static boolean isNtlmEnabled(long companyId)
594         throws PortalException, SystemException {
595 
596         if (!isAuthEnabled(companyId)) {
597             return false;
598         }
599 
600         if (PrefsPropsUtil.getBoolean(companyId, PropsUtil.NTLM_AUTH_ENABLED)) {
601             return true;
602         }
603         else {
604             return false;
605         }
606     }
607 
608     public static boolean isPasswordPolicyEnabled(long companyId)
609         throws PortalException, SystemException {
610 
611         if (PrefsPropsUtil.getBoolean(
612                 companyId, PropsUtil.LDAP_PASSWORD_POLICY_ENABLED)) {
613 
614             return true;
615         }
616         else {
617             return false;
618         }
619     }
620 
621     private static void _importGroupsAndMembershipFromLDAPUser(
622             long companyId, LdapContext ctx, long userId, Attribute attr)
623         throws Exception {
624 
625         Properties groupMappings = getGroupMappings(companyId);
626 
627         // Remove all user group membership from user
628 
629         UserGroupLocalServiceUtil.clearUserUserGroups(userId);
630 
631         long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
632             companyId);
633 
634         for (int i = 0; i < attr.size(); i++) {
635 
636             // Get LDAP group
637 
638             Attributes groupAttrs = null;
639 
640             String groupDN = (String)attr.get(i);
641 
642             try {
643                 groupAttrs = ctx.getAttributes(groupDN);
644             }
645             catch (NameNotFoundException nnfe) {
646                 _log.error(
647                     "Trying to import nonexistent LDAP group that was " +
648                         "referenced from LDAP user with groupDN " + groupDN);
649 
650                 _log.error(nnfe, nnfe);
651 
652                 continue;
653             }
654 
655             // Get portal user group corresponding to LDAP group
656 
657             UserGroup userGroup = null;
658 
659             String groupName = LDAPUtil.getAttributeValue(
660                 groupAttrs, groupMappings.getProperty("groupName"));
661             String description = LDAPUtil.getAttributeValue(
662                 groupAttrs, groupMappings.getProperty("description"));
663 
664             try {
665                 userGroup = UserGroupLocalServiceUtil.getUserGroup(
666                     companyId, groupName);
667             }
668             catch (NoSuchUserGroupException nsuge) {
669                 try {
670                     if (_log.isDebugEnabled()) {
671                         _log.debug(
672                             "Adding user group" + groupName + " at " + groupDN);
673                     }
674 
675                     userGroup = UserGroupLocalServiceUtil.addUserGroup(
676                         defaultUserId, companyId, groupName, description);
677                 }
678                 catch (Exception e) {
679                     if (_log.isWarnEnabled()) {
680                         _log.warn("Could not create user group " + groupName);
681                     }
682 
683                     if (_log.isDebugEnabled()) {
684                         _log.debug(e);
685                     }
686                 }
687             }
688 
689             // Add user to user group
690 
691             if (userGroup != null) {
692                 if (_log.isDebugEnabled()) {
693                     _log.debug("Adding " + userId + " to group " + groupName);
694                 }
695 
696                 UserLocalServiceUtil.addUserGroupUsers(
697                     userGroup.getUserGroupId(), new long[] {userId});
698             }
699         }
700     }
701 
702     private static User _importLDAPUser(
703             long companyId, LdapContext ctx, Attributes attrs,
704             Properties userMappings, boolean autoPassword, String password,
705             String screenName, String emailAddress, boolean updatePassword,
706             boolean importGroupMembership)
707         throws Exception {
708 
709         LogUtil.debug(_log, userMappings);
710 
711         User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
712 
713         long creatorUserId = 0;
714         boolean passwordReset = false;
715         boolean autoScreenName = false;
716         Locale locale = defaultUser.getLocale();
717         String firstName = LDAPUtil.getAttributeValue(
718             attrs, userMappings.getProperty("firstName"));
719         String middleName = LDAPUtil.getAttributeValue(
720             attrs, userMappings.getProperty("middleName"));
721         String lastName = LDAPUtil.getAttributeValue(
722             attrs, userMappings.getProperty("lastName"));
723 
724         if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
725             String fullName = LDAPUtil.getAttributeValue(
726                 attrs, userMappings.getProperty("fullName"));
727 
728             String[] names = LDAPUtil.splitFullName(fullName);
729 
730             firstName = names[0];
731             middleName = names[1];
732             lastName = names[2];
733         }
734 
735         int prefixId = 0;
736         int suffixId = 0;
737         boolean male = true;
738         int birthdayMonth = Calendar.JANUARY;
739         int birthdayDay = 1;
740         int birthdayYear = 1970;
741         String jobTitle = LDAPUtil.getAttributeValue(
742             attrs, userMappings.getProperty("jobTitle"));
743         long organizationId = 0;
744         long locationId = 0;
745         boolean sendEmail = false;
746 
747         if (_log.isDebugEnabled()) {
748             _log.debug(
749                 "Screen name " + screenName + " and email address " +
750                     emailAddress);
751         }
752 
753         if (Validator.isNull(screenName) || Validator.isNull(emailAddress)) {
754             if (_log.isWarnEnabled()) {
755                 _log.warn(
756                     "Cannot add user because screen name and email address " +
757                         "are required");
758             }
759 
760             return null;
761         }
762 
763         User user = null;
764 
765         try {
766             user = UserLocalServiceUtil.getUserByEmailAddress(
767                 companyId, emailAddress);
768 
769             Contact contact = user.getContact();
770 
771             Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
772 
773             birthdayCal.setTime(contact.getBirthday());
774 
775             birthdayMonth = birthdayCal.get(Calendar.MONTH);
776             birthdayDay = birthdayCal.get(Calendar.DATE);
777             birthdayYear = birthdayCal.get(Calendar.YEAR);
778 
779             // User exists so update user information
780 
781             if (updatePassword) {
782                 user = UserLocalServiceUtil.updatePassword(
783                     user.getUserId(), password, password, passwordReset,
784                     true);
785             }
786 
787             user = UserLocalServiceUtil.updateUser(
788                 user.getUserId(), password, screenName, emailAddress,
789                 user.getLanguageId(), user.getTimeZoneId(), user.getGreeting(),
790                 user.getComments(), firstName, middleName, lastName,
791                 contact.getPrefixId(), contact.getSuffixId(), contact.getMale(),
792                 birthdayMonth, birthdayDay, birthdayYear, contact.getSmsSn(),
793                 contact.getAimSn(), contact.getIcqSn(), contact.getJabberSn(),
794                 contact.getMsnSn(), contact.getSkypeSn(), contact.getYmSn(),
795                 jobTitle, user.getOrganization().getOrganizationId(),
796                 user.getLocation().getOrganizationId());
797         }
798         catch (NoSuchUserException nsue) {
799 
800             // User does not exist so create
801 
802         }
803 
804         if (user == null) {
805             try {
806                 user = UserLocalServiceUtil.addUser(
807                     creatorUserId, companyId, autoPassword, password, password,
808                     autoScreenName, screenName, emailAddress, locale, firstName,
809                     middleName, lastName, prefixId, suffixId, male,
810                     birthdayMonth, birthdayDay, birthdayYear, jobTitle,
811                     organizationId, locationId, sendEmail);
812             }
813             catch (Exception e){
814                 _log.error(
815                     "Problem adding user with screen name " + screenName +
816                         " and email address " + emailAddress,
817                     e);
818             }
819         }
820 
821         // Import user groups and membership
822 
823         if (importGroupMembership && (user != null)) {
824             String userMappingsGroup = userMappings.getProperty("group");
825 
826             if (userMappingsGroup != null) {
827                 Attribute attr = attrs.get(userMappingsGroup);
828 
829                 if (attr != null){
830                     _importGroupsAndMembershipFromLDAPUser(
831                         companyId, ctx, user.getUserId(), attr);
832                 }
833             }
834         }
835 
836         return user;
837     }
838 
839     private static void _importUsersAndMembershipFromLDAPGroup(
840             long companyId, LdapContext ctx, long userGroupId, Attribute attr)
841         throws Exception {
842 
843         Properties userMappings = getUserMappings(companyId);
844 
845         // Remove all user membership from user group
846 
847         UserLocalServiceUtil.clearUserGroupUsers(userGroupId);
848 
849         for (int i = 0; i < attr.size(); i++) {
850 
851             // Get LDAP user
852 
853             Attributes userAttrs = null;
854 
855             String userDN = (String)attr.get(i);
856 
857             try {
858                 userAttrs = ctx.getAttributes(userDN);
859             }
860             catch (NameNotFoundException nnfe) {
861                 _log.error(
862                     "Trying to import nonexistent LDAP user that was " +
863                         "referenced from LDAP group with userDN " + userDN);
864 
865                 _log.error(nnfe, nnfe);
866 
867                 continue;
868             }
869 
870             // Get portal user corresponding to LDAP user
871 
872             User user = null;
873 
874             String emailAddress = LDAPUtil.getAttributeValue(
875                 userAttrs, userMappings.getProperty("emailAddress"));
876 
877             try {
878                 user = UserLocalServiceUtil.getUserByEmailAddress(
879                     companyId, emailAddress);
880             }
881             catch (NoSuchUserException nsue) {
882                 try {
883                     if (_log.isDebugEnabled()) {
884                         _log.debug(
885                             "Adding user " + emailAddress + " at " + userDN);
886                     }
887 
888                     user = importLDAPUser(companyId, ctx, userAttrs, false);
889                 }
890                 catch (Exception e) {
891                     if (_log.isWarnEnabled()) {
892                         _log.warn("Could not create user " + userDN);
893                     }
894 
895                     if (_log.isDebugEnabled()) {
896                         _log.debug(e, e);
897                     }
898                 }
899             }
900 
901             // Add user to user group
902 
903             if (user != null) {
904                 if (_log.isDebugEnabled()) {
905                     _log.debug(
906                         "Adding " + user.getUserId() + " to group " +
907                             userGroupId);
908                 }
909 
910                 UserLocalServiceUtil.addUserGroupUsers(
911                     userGroupId, new long[] {user.getUserId()});
912             }
913         }
914     }
915 
916     private static Log _log = LogFactoryUtil.getLog(PortalLDAPUtil.class);
917 
918 }