1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.security.ldap;
16  
17  import com.liferay.portal.NoSuchUserException;
18  import com.liferay.portal.NoSuchUserGroupException;
19  import com.liferay.portal.UserEmailAddressException;
20  import com.liferay.portal.UserScreenNameException;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.log.LogUtil;
24  import com.liferay.portal.kernel.util.ArrayUtil;
25  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.PropsKeys;
28  import com.liferay.portal.kernel.util.StringBundler;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Time;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.model.Company;
34  import com.liferay.portal.model.CompanyConstants;
35  import com.liferay.portal.model.Contact;
36  import com.liferay.portal.model.ContactConstants;
37  import com.liferay.portal.model.User;
38  import com.liferay.portal.model.UserGroup;
39  import com.liferay.portal.model.UserGroupRole;
40  import com.liferay.portal.security.auth.FullNameGenerator;
41  import com.liferay.portal.security.auth.FullNameGeneratorFactory;
42  import com.liferay.portal.security.auth.ScreenNameGenerator;
43  import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
44  import com.liferay.portal.service.CompanyLocalServiceUtil;
45  import com.liferay.portal.service.LockLocalServiceUtil;
46  import com.liferay.portal.service.ServiceContext;
47  import com.liferay.portal.service.UserGroupLocalServiceUtil;
48  import com.liferay.portal.service.UserLocalServiceUtil;
49  import com.liferay.portal.util.PrefsPropsUtil;
50  import com.liferay.portal.util.PropsValues;
51  import com.liferay.util.ldap.LDAPUtil;
52  
53  import java.text.ParseException;
54  
55  import java.util.ArrayList;
56  import java.util.Calendar;
57  import java.util.Date;
58  import java.util.List;
59  import java.util.Locale;
60  import java.util.Properties;
61  
62  import javax.naming.Binding;
63  import javax.naming.NameNotFoundException;
64  import javax.naming.directory.Attribute;
65  import javax.naming.directory.Attributes;
66  import javax.naming.directory.SearchResult;
67  import javax.naming.ldap.LdapContext;
68  
69  /**
70   * <a href="PortalLDAPImporter.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Edward Han
73   * @author Michael C. Han
74   * @author Brian Wing Shun Chan
75   */
76  public class PortalLDAPImporter {
77  
78      public static final String IMPORT_BY_GROUP = "group";
79  
80      public static final String IMPORT_BY_USER = "user";
81  
82      public static void importFromLDAP() throws Exception {
83          List<Company> companies = CompanyLocalServiceUtil.getCompanies(false);
84  
85          for (Company company : companies) {
86              PortalLDAPImporter.importFromLDAP(company.getCompanyId());
87          }
88      }
89  
90      public static 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, PortalLDAPImporter.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, PortalLDAPImporter.class.getName(), companyId,
112             PortalLDAPImporter.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                 PortalLDAPImporter.class.getName(), companyId);
129         }
130     }
131 
132     public static 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             String importMethod = PrefsPropsUtil.getString(
148                 companyId, PropsKeys.LDAP_IMPORT_METHOD);
149 
150             if (importMethod.equals(IMPORT_BY_USER)) {
151                 byte[] cookie = new byte[0];
152 
153                 while (cookie != null) {
154                     List<SearchResult> searchResults =
155                         new ArrayList<SearchResult>();
156 
157                     Properties userMappings = LDAPSettingsUtil.getUserMappings(
158                         ldapServerId, companyId);
159 
160                     String userMappingsScreenName = GetterUtil.getString(
161                         userMappings.getProperty("screenName"))
162                         .toLowerCase();
163 
164                     cookie = PortalLDAPUtil.getUsers(
165                         ldapServerId, companyId, ldapContext, cookie, 0,
166                         new String[] {userMappingsScreenName},
167                         searchResults);
168 
169                     for (SearchResult searchResult : searchResults) {
170                         Attributes attributes =
171                             PortalLDAPUtil.getUserAttributes(
172                                 ldapServerId, companyId, ldapContext,
173                                     PortalLDAPUtil.getNameInNamespace(
174                                         ldapServerId, companyId, searchResult));
175 
176                         try {
177                             importLDAPUser(
178                                 ldapServerId, companyId, ldapContext,
179                                 attributes,StringPool.BLANK, true);
180                         }
181                         catch (Exception e) {
182                             _log.error(
183                                 "Unable to import user: " + searchResult, e);
184                         }
185                     }
186                 }
187             }
188             else if (importMethod.equals(IMPORT_BY_GROUP)) {
189                 byte[] cookie = new byte[0];
190 
191                 while (cookie != null) {
192                     List<SearchResult> searchResults =
193                         new ArrayList<SearchResult>();
194 
195                     Properties groupMappings =
196                         LDAPSettingsUtil.getGroupMappings(
197                             ldapServerId, companyId);
198 
199                     String groupMappingsGroupName = GetterUtil.getString(
200                         groupMappings.getProperty("groupName"))
201                         .toLowerCase();
202 
203                     cookie = PortalLDAPUtil.getGroups(
204                         ldapServerId, companyId, ldapContext, cookie, 0,
205                         new String[] {groupMappingsGroupName},
206                         searchResults);
207 
208                     for (SearchResult searchResult : searchResults) {
209                         Attributes attributes =
210                             PortalLDAPUtil.getGroupAttributes(
211                                     ldapServerId, companyId, ldapContext,
212                                     PortalLDAPUtil.getNameInNamespace(
213                                         ldapServerId, companyId, searchResult),
214                                     true);
215 
216                         importLDAPGroup(
217                             ldapServerId, companyId, ldapContext, attributes,
218                             true);
219                     }
220                 }
221             }
222         }
223         catch (Exception e) {
224             _log.error("Error importing LDAP users and groups", e);
225         }
226         finally {
227             if (ldapContext != null) {
228                 ldapContext.close();
229             }
230         }
231     }
232 
233     public static UserGroup importLDAPGroup(
234             long ldapServerId, long companyId, LdapContext ldapContext,
235             Attributes attributes, boolean importGroupMembership)
236         throws Exception {
237 
238         String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
239 
240         AttributesTransformer attributesTransformer =
241             AttributesTransformerFactory.getInstance();
242 
243         attributes = attributesTransformer.transformGroup(attributes);
244 
245         Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
246             ldapServerId, companyId);
247 
248         LogUtil.debug(_log, groupMappings);
249 
250         String groupName = LDAPUtil.getAttributeValue(
251             attributes, groupMappings.getProperty("groupName")).toLowerCase();
252         String description = LDAPUtil.getAttributeValue(
253             attributes, groupMappings.getProperty("description"));
254 
255         // Get or create user group
256 
257         UserGroup userGroup = null;
258 
259         try {
260             userGroup = UserGroupLocalServiceUtil.getUserGroup(
261                 companyId, groupName);
262 
263             UserGroupLocalServiceUtil.updateUserGroup(
264                 companyId, userGroup.getUserGroupId(), groupName, description);
265         }
266         catch (NoSuchUserGroupException nsuge) {
267             if (_log.isDebugEnabled()) {
268                 _log.debug("Adding user group to portal " + groupName);
269             }
270 
271             long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
272                 companyId);
273 
274             try {
275                 userGroup = UserGroupLocalServiceUtil.addUserGroup(
276                     defaultUserId, companyId, groupName, description);
277             }
278             catch (Exception e) {
279                 if (_log.isWarnEnabled()) {
280                     _log.warn("Could not create user group " + groupName);
281                 }
282 
283                 if (_log.isDebugEnabled()) {
284                     _log.debug(e, e);
285                 }
286             }
287         }
288 
289         // Import users and membership
290 
291         if (!importGroupMembership || (userGroup == null)) {
292             return userGroup;
293         }
294 
295         Attribute attribute = attributes.get(groupMappings.getProperty("user"));
296 
297         if (attribute == null) {
298             return userGroup;
299         }
300 
301         String baseDN = PrefsPropsUtil.getString(
302             companyId, PropsKeys.LDAP_BASE_DN + postfix);
303 
304         StringBundler sb = new StringBundler(7);
305 
306         sb.append("(&");
307         sb.append(
308             PrefsPropsUtil.getString(
309                 companyId,
310                 PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
311         sb.append("(");
312         sb.append(groupMappings.getProperty("groupName"));
313         sb.append("=");
314         sb.append(
315             LDAPUtil.getAttributeValue(
316                 attributes, groupMappings.getProperty("groupName")));
317         sb.append("))");
318 
319         attribute = PortalLDAPUtil.getMultivaluedAttribute(
320             companyId, ldapContext, baseDN, sb.toString(), attribute);
321 
322         _importUsersAndMembershipFromLDAPGroup(
323             ldapServerId, companyId, ldapContext, userGroup.getUserGroupId(),
324             attribute);
325 
326         return userGroup;
327     }
328 
329     public static User importLDAPUser(
330             long ldapServerId, long companyId, LdapContext ldapContext,
331             Attributes attributes, String password,
332             boolean importGroupMembership)
333         throws Exception {
334 
335         LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);
336 
337         try {
338             return _importLDAPUser(
339                 ldapServerId, companyId, ldapContext, attributes, password,
340                 importGroupMembership);
341         }
342         finally {
343             LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
344         }
345     }
346 
347     private static void _importGroupsAndMembershipFromLDAPUser(
348             long ldapServerId, long companyId, LdapContext ldapContext,
349             long userId, String[] fullGroupDNs)
350         throws Exception {
351 
352         List<Long> newUserGroupIds = new ArrayList<Long>(fullGroupDNs.length);
353 
354         for (String fullGroupDN : fullGroupDNs) {
355 
356             // Find group in LDAP
357 
358             Attributes groupAttributes = null;
359 
360             try {
361                 groupAttributes = PortalLDAPUtil.getGroupAttributes(
362                     ldapServerId, companyId, ldapContext, fullGroupDN);
363             }
364             catch (NameNotFoundException nnfe) {
365                 _log.error(
366                     "LDAP group not found with fullGroupDN " + fullGroupDN,
367                     nnfe);
368 
369                 continue;
370             }
371 
372             UserGroup userGroup = PortalLDAPImporter.importLDAPGroup(
373                 ldapServerId, companyId, ldapContext, groupAttributes, false);
374 
375             // Add user to user group
376 
377             if (userGroup != null) {
378                 if (_log.isDebugEnabled()) {
379                     _log.debug(
380                         "Adding " + userId + " to group " +
381                             userGroup.getUserGroupId());
382                 }
383 
384                 newUserGroupIds.add(userGroup.getUserGroupId());
385             }
386         }
387 
388         UserGroupLocalServiceUtil.setUserUserGroups(
389             userId,
390             ArrayUtil.toArray(
391                 newUserGroupIds.toArray(new Long[newUserGroupIds.size()])));
392     }
393 
394     private static User _importLDAPUser(
395             long ldapServerId, long companyId, LdapContext ldapContext,
396             Attributes attributes, String password,
397             boolean importGroupMembership)
398         throws Exception {
399 
400         AttributesTransformer attributesTransformer =
401             AttributesTransformerFactory.getInstance();
402 
403         attributes = attributesTransformer.transformUser(attributes);
404 
405         Properties userMappings = LDAPSettingsUtil.getUserMappings(
406             ldapServerId, companyId);
407 
408         LogUtil.debug(_log, userMappings);
409 
410         User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
411 
412         boolean autoPassword = false;
413         boolean updatePassword = true;
414 
415         if (password.equals(StringPool.BLANK)) {
416             autoPassword = true;
417             updatePassword = false;
418         }
419 
420         long creatorUserId = 0;
421         boolean passwordReset = false;
422         boolean autoScreenName = PrefsPropsUtil.getBoolean(
423             companyId, PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE);
424 
425         String screenName = LDAPUtil.getAttributeValue(
426             attributes, userMappings.getProperty("screenName")).toLowerCase();
427         String emailAddress = LDAPUtil.getAttributeValue(
428             attributes, userMappings.getProperty("emailAddress"));
429         String openId = StringPool.BLANK;
430         Locale locale = defaultUser.getLocale();
431         String firstName = LDAPUtil.getAttributeValue(
432             attributes, userMappings.getProperty("firstName"));
433         String middleName = LDAPUtil.getAttributeValue(
434             attributes, userMappings.getProperty("middleName"));
435         String lastName = LDAPUtil.getAttributeValue(
436             attributes, userMappings.getProperty("lastName"));
437 
438         if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
439             String fullName = LDAPUtil.getAttributeValue(
440                 attributes, userMappings.getProperty("fullName"));
441 
442             FullNameGenerator fullNameGenerator =
443                 FullNameGeneratorFactory.getInstance();
444 
445             String[] names = fullNameGenerator.splitFullName(fullName);
446 
447             firstName = names[0];
448             middleName = names[1];
449             lastName = names[2];
450         }
451 
452         int prefixId = 0;
453         int suffixId = 0;
454         boolean male = true;
455         int birthdayMonth = Calendar.JANUARY;
456         int birthdayDay = 1;
457         int birthdayYear = 1970;
458         String jobTitle = LDAPUtil.getAttributeValue(
459             attributes, userMappings.getProperty("jobTitle"));
460         long[] groupIds = null;
461         long[] organizationIds = null;
462         long[] roleIds = null;
463         List<UserGroupRole> userGroupRoles = null;
464         long[] userGroupIds = null;
465         boolean sendEmail = false;
466         ServiceContext serviceContext = new ServiceContext();
467 
468         if (_log.isDebugEnabled()) {
469             _log.debug(
470                 "Screen name " + screenName + " and email address " +
471                     emailAddress);
472         }
473 
474         if (Validator.isNull(screenName) && !autoScreenName) {
475             throw new UserScreenNameException(
476                 "Screen name cannot be null for " +
477                     ContactConstants.getFullName(
478                         firstName, middleName, lastName));
479         }
480 
481         if (Validator.isNull(emailAddress) &&
482             PrefsPropsUtil.getBoolean(
483                 companyId, PropsKeys.USERS_EMAIL_ADDRESS_REQUIRED)) {
484 
485             throw new UserEmailAddressException(
486                 "Email address cannot be null for " +
487                     ContactConstants.getFullName(
488                         firstName, middleName, lastName));
489         }
490 
491         User user = null;
492 
493         try {
494 
495             // Find corresponding portal user
496 
497             String authType = PrefsPropsUtil.getString(
498                 companyId, PropsKeys.COMPANY_SECURITY_AUTH_TYPE,
499                 PropsValues.COMPANY_SECURITY_AUTH_TYPE);
500 
501             if (authType.equals(CompanyConstants.AUTH_TYPE_SN) &&
502                 !autoScreenName) {
503 
504                 user = UserLocalServiceUtil.getUserByScreenName(
505                     companyId, screenName);
506             }
507             else {
508                 user = UserLocalServiceUtil.getUserByEmailAddress(
509                     companyId, emailAddress);
510             }
511 
512             // Skip if is default user
513 
514             if (user.isDefaultUser()) {
515                 return user;
516             }
517 
518             // User already exists in the Liferay database. Skip import if user
519             // fields have been already synced, if import is part of a scheduled
520             // import, or if the LDAP entry has never been modified.
521 
522             Date ldapUserModifiedDate = null;
523 
524             String modifiedDate = LDAPUtil.getAttributeValue(
525                 attributes, "modifyTimestamp");
526 
527             try {
528                 if (Validator.isNull(modifiedDate)) {
529                     if (_log.isInfoEnabled()) {
530                         _log.info(
531                             "LDAP entry never modified, skipping user " +
532                                 user.getEmailAddress());
533                     }
534 
535                     return user;
536                 }
537                 else {
538                     ldapUserModifiedDate = LDAPUtil.parseDate(modifiedDate);
539                 }
540 
541                 if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
542                     autoPassword) {
543 
544                     if (_log.isDebugEnabled()) {
545                         _log.debug(
546                             "User is already syncronized, skipping user " +
547                                 user.getEmailAddress());
548                     }
549 
550                     return user;
551                 }
552             }
553             catch (ParseException pe) {
554                 if (_log.isDebugEnabled()) {
555                     _log.debug(
556                         "Unable to parse LDAP modify timestamp " + modifiedDate,
557                         pe);
558                 }
559             }
560 
561             // LPS-443
562 
563             if (Validator.isNull(screenName) ||
564                 PrefsPropsUtil.getBoolean(
565                     companyId,
566                     PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE)) {
567 
568                 autoScreenName = true;
569             }
570 
571             if (autoScreenName) {
572                 ScreenNameGenerator screenNameGenerator =
573                     ScreenNameGeneratorFactory.getInstance();
574 
575                 screenName = screenNameGenerator.generate(
576                     companyId, user.getUserId(), emailAddress);
577             }
578 
579             Contact contact = user.getContact();
580 
581             Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
582 
583             birthdayCal.setTime(contact.getBirthday());
584 
585             birthdayMonth = birthdayCal.get(Calendar.MONTH);
586             birthdayDay = birthdayCal.get(Calendar.DATE);
587             birthdayYear = birthdayCal.get(Calendar.YEAR);
588 
589             // User exists so update user information
590 
591             if (updatePassword) {
592                 user = UserLocalServiceUtil.updatePassword(
593                     user.getUserId(), password, password, passwordReset, true);
594             }
595 
596             user = UserLocalServiceUtil.updateUser(
597                 user.getUserId(), password, StringPool.BLANK, StringPool.BLANK,
598                 user.isPasswordReset(), user.getReminderQueryQuestion(),
599                 user.getReminderQueryAnswer(), screenName, emailAddress, openId,
600                 user.getLanguageId(), user.getTimeZoneId(), user.getGreeting(),
601                 user.getComments(), firstName, middleName, lastName,
602                 contact.getPrefixId(), contact.getSuffixId(), contact.getMale(),
603                 birthdayMonth, birthdayDay, birthdayYear, contact.getSmsSn(),
604                 contact.getAimSn(), contact.getFacebookSn(), contact.getIcqSn(),
605                 contact.getJabberSn(), contact.getMsnSn(),
606                 contact.getMySpaceSn(), contact.getSkypeSn(),
607                 contact.getTwitterSn(), contact.getYmSn(), jobTitle, groupIds,
608                 organizationIds, roleIds, userGroupRoles, userGroupIds,
609                 serviceContext);
610 
611             if (ldapUserModifiedDate != null) {
612                 UserLocalServiceUtil.updateModifiedDate(
613                     user.getUserId(), ldapUserModifiedDate);
614             }
615         }
616         catch (NoSuchUserException nsue) {
617 
618             // User does not exist so create
619 
620         }
621         catch (Exception e) {
622             _log.error(
623                 "Error updating user with screen name " + screenName +
624                 " and email address " + emailAddress,
625                 e);
626 
627             return null;
628         }
629 
630         if (user == null) {
631             try {
632                 if (_log.isDebugEnabled()) {
633                     _log.debug(
634                         "Adding user to portal " + emailAddress);
635                 }
636 
637                 user = UserLocalServiceUtil.addUser(
638                     creatorUserId, companyId, autoPassword, password, password,
639                     autoScreenName, screenName, emailAddress, openId, locale,
640                     firstName, middleName, lastName, prefixId, suffixId, male,
641                     birthdayMonth, birthdayDay, birthdayYear, jobTitle,
642                     groupIds, organizationIds, roleIds, userGroupIds, sendEmail,
643                     serviceContext);
644             }
645             catch (Exception e) {
646                 _log.error(
647                     "Problem adding user with screen name " + screenName +
648                     " and email address " + emailAddress,
649                     e);
650             }
651         }
652 
653         // Import user groups and membership
654 
655         if (!importGroupMembership || (user == null)) {
656             return user;
657         }
658 
659         String userMappingsGroup = userMappings.getProperty("group");
660 
661         if (Validator.isNull(userMappingsGroup)) {
662             return user;
663         }
664 
665         Attribute userGroupAttribute = attributes.get(userMappingsGroup);
666 
667         if (userGroupAttribute == null) {
668             return user;
669         }
670 
671         if (PrefsPropsUtil.getBoolean(
672                 companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER_ENABLED)) {
673 
674             Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
675                 ldapServerId, companyId);
676 
677             String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
678 
679             String baseDN = PrefsPropsUtil.getString(
680                 companyId, PropsKeys.LDAP_BASE_DN + postfix);
681 
682             Binding binding = PortalLDAPUtil.getUser(
683                 ldapServerId, companyId, screenName);
684 
685             String fullUserDN = PortalLDAPUtil.getNameInNamespace(
686                 ldapServerId, companyId, binding);
687 
688             StringBundler sb = new StringBundler(9);
689 
690             sb.append(StringPool.OPEN_PARENTHESIS);
691             sb.append(StringPool.AMPERSAND);
692             sb.append(
693                 PrefsPropsUtil.getString(
694                     companyId,
695                     PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
696             sb.append(StringPool.OPEN_PARENTHESIS);
697             sb.append(groupMappings.getProperty("user"));
698             sb.append(StringPool.EQUAL);
699             sb.append(fullUserDN);
700             sb.append(StringPool.CLOSE_PARENTHESIS);
701             sb.append(StringPool.CLOSE_PARENTHESIS);
702 
703             byte[] cookie = new byte[0];
704 
705             while (cookie != null) {
706                 List<SearchResult> searchResults =
707                     new ArrayList<SearchResult>();
708 
709                 String groupMappingsGroupName = GetterUtil.getString(
710                     groupMappings.getProperty("groupName")).toLowerCase();
711 
712                 cookie = PortalLDAPUtil.searchLDAP(
713                     companyId, ldapContext, cookie, 0, baseDN, sb.toString(),
714                     new String[] {groupMappingsGroupName}, searchResults);
715 
716                 String[] fullGroupDNs = new String[searchResults.size()];
717 
718                 int i = 0;
719 
720                 for (SearchResult searchResult : searchResults) {
721                     String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
722                         ldapServerId, companyId, searchResult);
723 
724                     fullGroupDNs[i++] = fullGroupDN;
725                 }
726 
727                 _importGroupsAndMembershipFromLDAPUser(
728                     ldapServerId, companyId, ldapContext, user.getUserId(),
729                     fullGroupDNs);
730             }
731         }
732         else {
733             String[] fullGroupDNs = new String[userGroupAttribute.size()];
734 
735             for (int i = 0; i < userGroupAttribute.size(); i++) {
736                 fullGroupDNs[i] = (String)userGroupAttribute.get(i);
737             }
738 
739             _importGroupsAndMembershipFromLDAPUser(
740                 ldapServerId, companyId, ldapContext, user.getUserId(),
741                 fullGroupDNs);
742         }
743 
744         return user;
745     }
746 
747     private static void _importUsersAndMembershipFromLDAPGroup(
748             long ldapServerId, long companyId, LdapContext ldapContext,
749             long userGroupId, Attribute attribute)
750         throws Exception {
751 
752         List<Long> newUserIds = new ArrayList<Long>(attribute.size());
753 
754         for (int i = 0; i < attribute.size(); i++) {
755 
756             // Find user in LDAP
757 
758             String fullUserDN = (String)attribute.get(i);
759 
760             Attributes userAttributes = null;
761 
762             try {
763                 userAttributes = PortalLDAPUtil.getUserAttributes(
764                     ldapServerId, companyId, ldapContext, fullUserDN);
765             }
766             catch (NameNotFoundException nnfe) {
767                 _log.error(
768                     "LDAP user not found with fullUserDN " + fullUserDN, nnfe);
769 
770                 continue;
771             }
772 
773             User user = PortalLDAPImporter.importLDAPUser(
774                 ldapServerId, companyId, ldapContext, userAttributes,
775                 StringPool.BLANK, false);
776 
777             // Add user to user group
778 
779             if (user != null) {
780                 if (_log.isDebugEnabled()) {
781                     _log.debug(
782                         "Adding " + user.getUserId() + " to group " +
783                             userGroupId);
784                 }
785 
786                 newUserIds.add(user.getUserId());
787             }
788         }
789 
790         UserLocalServiceUtil.setUserGroupUsers(
791             userGroupId,
792             ArrayUtil.toArray(newUserIds.toArray(new Long[newUserIds.size()])));
793     }
794 
795     private static Log _log = LogFactoryUtil.getLog(PortalLDAPImporter.class);
796 
797 }