View Javadoc

1   /**
2    * 2007, Digitalis Informatica. All rights reserved. Distribuicao e Gestao de Informatica, Lda. Estrada de Paco de Arcos
3    * num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999 http://www.digitalis.pt
4    */
5   package pt.digitalis.dif.identity.ldap;
6   
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.List;
11  import java.util.Map;
12  import java.util.Map.Entry;
13  import java.util.Set;
14  
15  import javax.naming.NamingException;
16  
17  import pt.digitalis.dif.controller.security.managers.IAuthorizationManager;
18  import pt.digitalis.dif.controller.security.managers.impl.AbstractIdentityManager;
19  import pt.digitalis.dif.controller.security.objects.DIFGroupImpl;
20  import pt.digitalis.dif.controller.security.objects.DIFUserImpl;
21  import pt.digitalis.dif.controller.security.objects.IDIFGroup;
22  import pt.digitalis.dif.controller.security.objects.IDIFUser;
23  import pt.digitalis.dif.exception.security.IdentityManagerException;
24  import pt.digitalis.dif.ioc.DIFIoCRegistry;
25  import pt.digitalis.dif.utils.Pagination;
26  import pt.digitalis.dif.utils.logging.DIFLogger;
27  import pt.digitalis.utils.config.ConfigurationsPreferencesImpl;
28  import pt.digitalis.utils.config.IConfigurations;
29  import pt.digitalis.utils.ldap.ILDAPUtils;
30  import pt.digitalis.utils.ldap.LDAPConfigurations;
31  import pt.digitalis.utils.ldap.LDAPGroup;
32  import pt.digitalis.utils.ldap.LDAPUser;
33  import pt.digitalis.utils.ldap.exception.LDAPOperationException;
34  
35  /**
36   * Identity manager implementation based on LDAP.
37   * 
38   * @author Rodrigo Gonçalves <a href="mailto:rgoncalves@digitalis.pt">rgoncalves@digitalis.pt</a>
39   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
40   * @author Fábio Souto <a href="mailto:fsouto@digitalis.pt">fsouto@digitalis.pt</a><br/>
41   * @created Mar 26, 2008
42   */
43  public class IdentityManagerLDAPImpl extends AbstractIdentityManager {
44  
45      /** The authorization manager. */
46      static private IAuthorizationManager authorizationManager = DIFIoCRegistry.getRegistry().getImplementation(
47              IAuthorizationManager.class);
48  
49      /** The key used to publish the LDAP Domain Name into the users details */
50      private static String DOMAIN_NAME_USER_ATTRIBUTE = "domainName";
51  
52      /**
53       * A cache for mapping between LDAP DN group names and DIF group names: Goal is simply reduce LDAP searches for
54       * performance gain
55       */
56      static private Map<String, String> ldapGroupDNMappingCache = new HashMap<String, String>();
57  
58      /** The configurations object. */
59      private IdentityManagerLDAPConfigurations configurations = null;
60  
61      /** The ILDAPUtils current implementation (obtained from the IoC) for method execution. */
62      private ILDAPUtils ldapUtils = null;
63  
64      /**
65       * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#addGroup(pt.digitalis.dif.controller.security.objects.IDIFGroup)
66       */
67      public void addGroup(IDIFGroup newGroup) throws IdentityManagerException
68      {
69          try
70          {
71              LDAPGroup ldapGroup = convertFromDIFGroupToLDAPGroup(newGroup);
72  
73              getLDAPUtils().addGroup(ldapGroup);
74  
75              if (ldapGroup != null)
76                  // Update the cache;
77                  ldapGroupDNMappingCache.put(ldapGroup.getDistinguishedName(), newGroup.getID());
78  
79          }
80          catch (LDAPOperationException ldapOperationException)
81          {
82              throw new IdentityManagerLDAPException("Couldn't add group " + newGroup.getID() + " to LDAP server!",
83                      ldapOperationException);
84          }
85      }
86  
87      /**
88       * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#addUser(pt.digitalis.dif.controller.security.objects.IDIFUser)
89       */
90      public void addUser(IDIFUser newUser) throws IdentityManagerException
91      {
92          try
93          {
94              // If the user password is not defined, by default the password is "password"
95              if (((DIFUserImpl) newUser).getPassword() == null)
96              {
97                  newUser.setPassword("password");
98              }
99              getLDAPUtils().addUser(convertFromDIFUserToLDAPUser(newUser));
100         }
101         catch (LDAPOperationException ldapOperationException)
102         {
103             throw new IdentityManagerLDAPException("Couldn't add user to LDAP server! "
104                     + ldapOperationException.getMessage(), ldapOperationException);
105         }
106     }
107 
108     /**
109      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#addUserToGroup(java.lang.String,
110      *      java.lang.String)
111      */
112     public void addUserToGroup(String userID, String groupID) throws IdentityManagerException
113     {
114         try
115         {
116             getLDAPUtils().addUserToGroup(groupID, userID);
117         }
118         catch (LDAPOperationException ldapOperationException)
119         {
120             throw new IdentityManagerLDAPException("Coud not add user " + userID + " to group " + groupID + "!",
121                     ldapOperationException);
122         }
123     }
124 
125     /**
126      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#changePassword(java.lang.String,
127      *      java.lang.String)
128      */
129     public void changePassword(String userID, String newPassword) throws IdentityManagerException
130     {
131         try
132         {
133             getLDAPUtils().changePassword(userID, newPassword);
134         }
135         catch (LDAPOperationException ldapOperationException)
136         {
137             throw new IdentityManagerLDAPException("Could not change password for user " + userID + "!",
138                     ldapOperationException);
139         }
140     }
141 
142     /**
143      * Converts a DIF group into an LDAP group.
144      * 
145      * @param difGroup
146      *            the DIF group
147      * @return the LDAP group
148      * @throws IdentityManagerException
149      *             if a mandatory attribute is not present
150      */
151     private LDAPGroup convertFromDIFGroupToLDAPGroup(IDIFGroup difGroup) throws IdentityManagerException
152     {
153         LDAPGroup ldapGroup = new LDAPGroup();
154 
155         if (difGroup.getID() != null)
156         {
157             ldapGroup.setCommonName(difGroup.getID());
158         }
159         else
160             throw new IdentityManagerLDAPException("Group has no ID! The ID is needed to serve as LDAP cn...");
161 
162         if (difGroup.getName() != null)
163             ldapGroup.setName(difGroup.getName());
164 
165         if (difGroup.getParentGroupID() != null)
166             ldapGroup.setParentGroupDN(getParentGroupDNFromProfileID(difGroup.getParentGroupID()));
167 
168         if (difGroup.getDescription() != null)
169             ldapGroup.setDescription(difGroup.getDescription());
170 
171         return ldapGroup;
172     }
173 
174     /**
175      * Converts a DIF user into an LDAP user.
176      * 
177      * @param difUser
178      *            the user to convert
179      * @return the converted user
180      * @throws IdentityManagerException
181      *             if a mandatory attribute is not present
182      */
183     private LDAPUser convertFromDIFUserToLDAPUser(IDIFUser difUser) throws IdentityManagerException
184     {
185         LDAPUser ldapUser = new LDAPUser();
186 
187         // DIFUser#ID <-> LDAPUser#loginName
188         if (difUser.getID() != null)
189         {
190             ldapUser.setLoginName(difUser.getID());
191             ldapUser.setName(difUser.getName());
192             ldapUser.setUserName(difUser.getID());
193         }
194         else
195             throw new IdentityManagerLDAPException("User has no ID! The ID is needed to serve as LDAP login...");
196 
197         if (difUser.getProfileID() != null)
198             ldapUser.setParentGroupDN(getParentGroupDNFromProfileID(difUser.getProfileID()));
199 
200         if (difUser.getNick() != null)
201             ldapUser.setDisplayName(difUser.getNick());
202 
203         if (difUser.getName() != null)
204             ldapUser.setGivenName(difUser.getName());
205 
206         if (((DIFUserImpl) difUser).getPassword() != null)
207             ldapUser.setPassword(((DIFUserImpl) difUser).getPassword());
208 
209         if (difUser.getEmail() != null)
210             ldapUser.setEmail(difUser.getEmail());
211 
212         ldapUser.setDescription("DiF2 user");
213 
214         /* Parameters */
215         // Fetch parameters
216         Map<String, Object> attributes = difUser.getAttributes();
217 
218         // Check if there are parameters to process
219         if (attributes != null && attributes.size() > 0)
220         {
221             for (String attributeName: attributes.keySet())
222             {
223                 // ...add it to the LDAPUser parameters (K=LDAP attribute name)
224                 ldapUser.setParameter(attributeName, attributes.get(attributeName).toString());
225             }
226         }
227 
228         for (String attributeName: difUser.getAttributesToRemove())
229         {
230             ldapUser.removeParameter(attributeName);
231         }
232 
233         return ldapUser;
234     }
235 
236     /**
237      * Converts an LDAP group into a DIF group.
238      * 
239      * @param ldapGroup
240      *            the LDAP group
241      * @return the DIF group
242      * @throws IdentityManagerException
243      *             if the operation does not succeed
244      */
245     private IDIFGroup convertFromLDAPGroupToDIFGroup(LDAPGroup ldapGroup) throws IdentityManagerException
246     {
247         IDIFGroup difGroup = null;
248 
249         if (ldapGroup != null)
250         {
251             difGroup = new DIFGroupImpl();
252 
253             if (ldapGroup.getCommonName() != null)
254                 difGroup.setID(ldapGroup.getCommonName());
255 
256             if (ldapGroup.getName() != null)
257                 difGroup.setName(ldapGroup.getName());
258 
259             difGroup.setParentGroupID(N_A);
260             try
261             {
262                 if (ldapGroup.getParentGroupDN() != null && !ldapGroup.getParentGroupDN().equals(N_A))
263                     difGroup.setParentGroupID(getLDAPUtils().findGroupByDistinguishedName(ldapGroup.getParentGroupDN())
264                             .getCommonName());
265             }
266             catch (LDAPOperationException ldapOperationException)
267             {
268                 // Untestable exception: impossible to force an illegal parent group DN on the LDAP group (group is
269                 // returned by the server and is not possible, at this time, to force the illegal parent group DN
270                 // through Java).
271                 DIFLogger.getLogger().warn(
272                         "Could not access parent group \"" + ldapGroup.getParentGroupDN() + "\", of the group \""
273                                 + ldapGroup.getCommonName() + "\"! Exception: " + ldapOperationException.getMessage());
274             }
275 
276             if (ldapGroup.getDescription() != null)
277                 difGroup.setDescription(ldapGroup.getDescription());
278 
279         }
280 
281         return difGroup;
282     }
283 
284     /**
285      * Converts an LDAP user into a DIF user.
286      * 
287      * @param ldapUser
288      *            the LDAP user
289      * @return the DIF user
290      * @throws IdentityManagerException
291      *             if the operation does not succeed
292      */
293     private IDIFUser convertFromLDAPUserToDIFUser(LDAPUser ldapUser) throws IdentityManagerException
294     {
295 
296         IDIFUser difUser = null;
297 
298         if (ldapUser != null)
299         {
300             difUser = new DIFUserImpl();
301 
302             if (ldapUser.getLoginName() != null)
303                 difUser.setID(ldapUser.getLoginName());
304 
305             try
306             {
307                 if (ldapUser.getParentGroupDN() != null && !N_A.equals(ldapUser.getParentGroupDN()))
308                 {
309                     if (ldapGroupDNMappingCache.containsKey(ldapUser.getParentGroupDN()))
310                     {
311                         // Cache group, set ID
312 
313                         difUser.setProfileID(ldapGroupDNMappingCache.get(ldapUser.getParentGroupDN()));
314 
315                     }
316                     else
317                     {
318                         // Not in cache. Search it in LDAP...
319 
320                         String profileID = convertFromLDAPGroupToDIFGroup(
321                                 getLDAPUtils().findGroupByDistinguishedName(ldapUser.getParentGroupDN())).getID();
322                         difUser.setProfileID(profileID);
323 
324                         ldapGroupDNMappingCache.put(ldapUser.getParentGroupDN(), profileID);
325                     }
326                 }
327             }
328             catch (LDAPOperationException ldapOperationException)
329             {
330                 // Untestable exception: impossible to force an illegal parent group DN on the LDAP user (user is
331                 // returned by the server and is not possible, at this time, to force the illegal parent group DN
332                 // through Java).
333 
334                 // TODO: Viegas: define what to do when the profile can't be set
335             }
336 
337             if (ldapUser.getLoginName() != null)
338                 difUser.setNick(ldapUser.getLoginName());
339 
340             if (ldapUser.getGivenName() != null && !ldapUser.getGivenName().equals(ldapUtils.getNonAvailableValue()))
341                 difUser.setName(ldapUser.getGivenName());
342             else if (ldapUser.getDisplayName() != null
343                     && !ldapUser.getDisplayName().equals(ldapUtils.getNonAvailableValue()))
344                 difUser.setName(ldapUser.getDisplayName());
345 
346             // LDAP server does not return passwords.
347             // If-branch is here since this is an helper method that might be used on other operations in the future
348             if (ldapUser.getPassword() != null)
349                 difUser.setPassword(ldapUser.getPassword());
350 
351             if (ldapUser.getEmail() != null)
352                 difUser.setEmail(ldapUser.getEmail());
353 
354             /* Parameters */
355             Map<String, String> parameters = ldapUser.getParameters();
356             Map<String, Object> difAttributes = new HashMap<String, Object>();
357 
358             difAttributes.putAll(parameters);
359 
360             /* The DOMAIN_NAME_USER_ATTRIBUTE is always filled */
361             difAttributes.put(DOMAIN_NAME_USER_ATTRIBUTE, ldapUser.getDistinguishedName());
362 
363             difUser.initializeAttributes(difAttributes);
364         }
365 
366         return difUser;
367     }
368 
369     /**
370      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#countAllGroups()
371      */
372     public int countAllGroups() throws IdentityManagerException
373     {
374         try
375         {
376             return this.getLDAPUtils().countAllGroups(true);
377         }
378         catch (LDAPOperationException op)
379         {
380             throw new IdentityManagerLDAPException("Could not count all groups: ", op);
381         }
382         catch (NamingException e)
383         {
384             throw new IdentityManagerLDAPException("Could not count all groups: ", e);
385         }
386     }
387 
388     /**
389      * @see pt.digitalis.dif.controller.security.managers.impl.AbstractIdentityManager#countAllGroupsOfUser(java.lang.String)
390      */
391     public int countAllGroupsOfUser(String userId) throws IdentityManagerException
392     {
393         try
394         {
395             int result = 0;
396             // User profile
397             IDIFUser user = getUser(userId);
398 
399             if (user.getProfileID() != null)
400                 result++;
401 
402             result += getLDAPUtils().countAllGroupsOfUser(userId);
403 
404             return result;
405         }
406         catch (NamingException ne)
407         {
408             throw new IdentityManagerLDAPException("Could not retrieve information for user " + userId + "!", ne);
409         }
410         catch (LDAPOperationException ldapOperationException)
411         {
412             throw new IdentityManagerLDAPException("Could not retrieve information for user " + userId + "!",
413                     ldapOperationException);
414         }
415     }
416 
417     /**
418      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#countAllUsers()
419      */
420     public int countAllUsers() throws IdentityManagerException
421     {
422         try
423         {
424             return this.getLDAPUtils().countAllUsers();
425         }
426         catch (LDAPOperationException op)
427         {
428             throw new IdentityManagerLDAPException("Could not count all users: ", op);
429         }
430         catch (NamingException ne)
431         {
432             throw new IdentityManagerLDAPException("Could not count all users: ", ne);
433         }
434     }
435 
436     /**
437      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#countAllUsers(java.lang.String)
438      */
439     public int countAllUsers(String groupID) throws IdentityManagerException
440     {
441         try
442         {
443             return getLDAPUtils().countAllUsers(groupID);
444         }
445         catch (LDAPOperationException ldapOperationException)
446         {
447             throw new IdentityManagerLDAPException("Couldn't add user to LDAP server! "
448                     + ldapOperationException.getMessage(), ldapOperationException);
449         }
450     }
451 
452     /**
453      * @throws IdentityManagerLDAPException
454      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#countUsers(java.util.Map)
455      */
456     public int countUsers(Map<String, String> attributes) throws IdentityManagerException
457     {
458         try
459         {
460             return getLDAPUtils().countUsers(attributes);
461         }
462         catch (LDAPOperationException ldapOperationException)
463         {
464             throw new IdentityManagerLDAPException("Could not retrieve counting for users with attributes "
465                     + attributes + "!", ldapOperationException);
466         }
467     }
468 
469     /**
470      * @see pt.digitalis.dif.controller.security.managers.impl.AbstractIdentityManager#gatherManagedAttributes()
471      */
472     @Override
473     public List<String> gatherManagedAttributes()
474     {
475         LDAPConfigurations ldapconfig = DIFIoCRegistry.getRegistry().getImplementation(IConfigurations.class)
476                 .readConfiguration(LDAPConfigurations.class);
477         List<String> result = new ArrayList<String>(ldapconfig.getAttributesMapping().keySet());
478         return result;
479     }
480 
481     /**
482      * @throws IdentityManagerLDAPException
483      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getAllGroups()
484      */
485     public Set<IDIFGroup> getAllGroups() throws IdentityManagerException
486     {
487         Set<LDAPGroup> ldapGroups = null;
488         Set<IDIFGroup> result = null;
489 
490         try
491         {
492             ldapGroups = getLDAPUtils().findAllGroups();
493             result = new HashSet<IDIFGroup>();
494 
495             // convert from LDAPGroup to IDIFGroup, for returning
496             for (LDAPGroup g: ldapGroups)
497             {
498                 result.add(this.convertFromLDAPGroupToDIFGroup(g));
499 
500             }
501 
502             return result;
503         }
504         catch (LDAPOperationException ldapOperationException)
505         {
506             throw new IdentityManagerLDAPException("Could not get all groups from LDAP: ", ldapOperationException);
507         }
508     }
509 
510     /**
511      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getAllUsers()
512      */
513     public Set<IDIFUser> getAllUsers() throws IdentityManagerException
514     {
515         Set<LDAPUser> ldapUsers = null;
516         Set<IDIFUser> result = null;
517 
518         try
519         {
520             ldapUsers = getLDAPUtils().findAllUsers();
521             result = new HashSet<IDIFUser>();
522 
523             // convert from LDAPUser to IDIFUser, for returning
524             for (LDAPUser u: ldapUsers)
525                 result.add(this.convertFromLDAPUserToDIFUser(u));
526             return result;
527         }
528         catch (LDAPOperationException ldapOperationException)
529         {
530             throw new IdentityManagerLDAPException("Could not get all users from LDAP: ", ldapOperationException);
531         }
532 
533     }
534 
535     /**
536      * Configurations accessor.
537      * 
538      * @return the configurations
539      */
540     protected IdentityManagerLDAPConfigurations getConfigurations()
541     {
542         if (this.configurations == null)
543             configurations = new ConfigurationsPreferencesImpl()
544                     .readConfiguration(IdentityManagerLDAPConfigurations.class);
545 
546         return this.configurations;
547 
548     }
549 
550     /**
551      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getExclusionCharaters()
552      */
553     public String getExclusionCharaters()
554     {
555         return this.getLDAPUtils().getConfigurations().getExclusionCharaters();
556     }
557 
558     /**
559      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getGroup(java.lang.String)
560      */
561     public IDIFGroup getGroup(String groupID) throws IdentityManagerException
562     {
563 
564         if (groupID == null || N_A.equals(groupID))
565             return null;
566 
567         try
568         {
569             LDAPGroup ldapGroup = getLDAPUtils().findGroupByCommonName(groupID);
570             IDIFGroup difGroup = convertFromLDAPGroupToDIFGroup(ldapGroup);
571 
572             if (difGroup != null)
573                 // Update the cache;
574                 ldapGroupDNMappingCache.put(ldapGroup.getDistinguishedName(), difGroup.getID());
575 
576             return difGroup;
577 
578         }
579         catch (LDAPOperationException ldapOperationException)
580         {
581             throw new IdentityManagerLDAPException("Could not fetch data for group " + groupID + "!",
582                     ldapOperationException);
583         }
584     }
585 
586     /**
587      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getGroupAttributeName()
588      */
589     public String getGroupAttributeName()
590     {
591         return getLDAPUtils().getGroupAttributeName();
592     }
593 
594     /**
595      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getGroupGroups(java.lang.String)
596      */
597     public Map<String, IDIFGroup> getGroupGroups(String parentGroupID) throws IdentityManagerException
598     {
599 
600         Set<LDAPGroup> childGroups = null;
601 
602         try
603         {
604             childGroups = getLDAPUtils().getChildGroupsByDN(getParentGroupDNFromProfileID(parentGroupID));
605         }
606         catch (LDAPOperationException ldapOperationException)
607         {
608             // Untestable exception: getChildGroupsByDN never throws the LDAPOperationException since passing an invalid
609             // parentGroupID will yield an IdentityManagerException
610             throw new IdentityManagerLDAPException(
611                     "Could not access LDAP server to find child groups of group with ID: " + parentGroupID + "!",
612                     ldapOperationException);
613         }
614 
615         Map<String, IDIFGroup> childGroupsMap = new HashMap<String, IDIFGroup>(childGroups.size());
616 
617         for (LDAPGroup group: childGroups)
618         {
619             IDIFGroup difGroup = convertFromLDAPGroupToDIFGroup(group);
620 
621             childGroupsMap.put(difGroup.getID(), difGroup);
622         }
623 
624         return childGroupsMap;
625     }
626 
627     /**
628      * @throws IdentityManagerException
629      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getGroups(Pagination)
630      */
631     public Set<IDIFGroup> getGroups(Pagination page) throws IdentityManagerException
632     {
633         Set<LDAPGroup> ldapGroups = null;
634         Set<IDIFGroup> result = null;
635 
636         try
637         {
638             ldapGroups = getLDAPUtils().findGroups(page.getRowsPerPage(), page.getPage());
639             result = new HashSet<IDIFGroup>();
640 
641             // convert from LDAPGroup to IDIFGroup, for returning
642             for (LDAPGroup g: ldapGroups)
643                 result.add(this.convertFromLDAPGroupToDIFGroup(g));
644             return result;
645         }
646         catch (LDAPOperationException ldapOperationException)
647         {
648             throw new IdentityManagerLDAPException("Could not retrieve subset of groups (" + page.getRowsPerPage()
649                     + " rows per page, " + page.getPage() + " page)", ldapOperationException);
650         }
651     }
652 
653     /**
654      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getGroupUsers(java.lang.String)
655      */
656     public Map<String, IDIFUser> getGroupUsers(String groupID) throws IdentityManagerException
657     {
658         Map<String, IDIFUser> difUsers = new HashMap<String, IDIFUser>();
659 
660         Map<String, LDAPUser> ldapUsers = null;
661         try
662         {
663             ldapUsers = getLDAPUtils().findUsersInGroup(groupID);
664         }
665         catch (LDAPOperationException ldapOperationException)
666         {
667             throw new IdentityManagerLDAPException(ldapOperationException);
668         }
669 
670         for (String userID: ldapUsers.keySet())
671             difUsers.put(userID, convertFromLDAPUserToDIFUser(ldapUsers.get(userID)));
672 
673         return difUsers;
674     }
675 
676     /**
677      * Returns the active LDAP Utils implementation. Uses lazy-loading to instantiate the configured implementation.
678      * 
679      * @return the active LDAP Utils implementation
680      */
681     public ILDAPUtils getLDAPUtils()
682     {
683         if (this.ldapUtils == null)
684         {
685             if (LDAPUtilsImplementation.AD.equals(getConfigurations().getLdapUtilsImplementation()))
686                 this.ldapUtils = DIFIoCRegistry.getRegistry().getImplementation(ILDAPUtils.class,
687                         LDAPUtilsImplementation.AD.getIdTag());
688             else if (LDAPUtilsImplementation.OPEN_LDAP.equals(getConfigurations().getLdapUtilsImplementation()))
689                 this.ldapUtils = DIFIoCRegistry.getRegistry().getImplementation(ILDAPUtils.class,
690                         LDAPUtilsImplementation.OPEN_LDAP.getIdTag());
691             else if (LDAPUtilsImplementation.OID.equals(getConfigurations().getLdapUtilsImplementation()))
692                 throw new RuntimeException("Oracle OID LDAP Utils implementation is not supported on this version! ");
693         }
694 
695         ldapUtils.setLogger(DIFLogger.getLogger());
696         return ldapUtils;
697     }
698 
699     /**
700      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getMailAttributeName()
701      */
702     public String getMailAttributeName()
703     {
704         return getLDAPUtils().getMailAttributeName();
705 
706     }
707 
708     /**
709      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getNameAttributeName()
710      */
711     public String getNameAttributeName()
712     {
713         return getLDAPUtils().getNameAttributeName();
714     }
715 
716     /**
717      * Gets the parent group DN from the profile ID.
718      * 
719      * @param profileID
720      *            the profile ID
721      * @return the parent group DN
722      * @throws IdentityManagerException
723      *             if the parent group can't be accessed
724      */
725     final private String getParentGroupDNFromProfileID(String profileID) throws IdentityManagerException
726     {
727         String result = null;
728         try
729         {
730             LDAPGroup group = getLDAPUtils().findGroupByCommonName(profileID);
731             if (group != null)
732             {
733                 result = group.getDistinguishedName();
734             }
735         }
736         catch (LDAPOperationException ldapOperationException)
737         {
738             throw new IdentityManagerLDAPException("Could not fetch parent group for profile ID: " + profileID,
739                     ldapOperationException);
740         }
741         return result;
742     }
743 
744     /**
745      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUser(java.lang.String)
746      */
747     public IDIFUser getUser(String userID) throws IdentityManagerException
748     {
749         try
750         {
751             return convertFromLDAPUserToDIFUser(getLDAPUtils().findUserByLogin(userID));
752         }
753         catch (LDAPOperationException ldapOperationException)
754         {
755             throw new IdentityManagerLDAPException("Could not fetch data for user " + userID + "!",
756                     ldapOperationException);
757         }
758     }
759 
760     /**
761      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserGroups(java.lang.String)
762      */
763     public Map<String, IDIFGroup> getUserGroups(String userID) throws IdentityManagerException
764     {
765         Map<String, IDIFGroup> groupsOfUser = new HashMap<String, IDIFGroup>();
766 
767         IDIFGroup difGroup = null;
768 
769         try
770         {
771             // User profile
772             IDIFUser user = getUser(userID);
773             IDIFGroup profile = getGroup(user.getProfileID());
774 
775             if (profile != null)
776                 groupsOfUser.put(profile.getID(), profile);
777 
778             // Groups of user
779             for (LDAPGroup ldapGroup: getLDAPUtils().findGroupsOfUser(userID))
780             {
781                 difGroup = convertFromLDAPGroupToDIFGroup(ldapGroup);
782 
783                 if (difGroup != null)
784                 {
785                     groupsOfUser.put(difGroup.getID(), difGroup);
786 
787                     // Update the cache;
788                     ldapGroupDNMappingCache.put(ldapGroup.getDistinguishedName(), difGroup.getID());
789                 }
790             }
791         }
792         catch (LDAPOperationException ldapOperationException)
793         {
794             throw new IdentityManagerLDAPException("Could not get groups of user " + userID, ldapOperationException);
795         }
796 
797         return groupsOfUser;
798     }
799 
800     /**
801      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserGroupsIDs(java.lang.String)
802      */
803     public Set<String> getUserGroupsIDs(String userID) throws IdentityManagerException
804     {
805         return getUserGroups(userID).keySet();
806     }
807 
808     /**
809      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserGroupsPagination(java.lang.String,
810      *      pt.digitalis.dif.utils.Pagination)
811      */
812     public Map<String, IDIFGroup> getUserGroupsPagination(String userID, Pagination page)
813             throws IdentityManagerException
814     {
815         Map<String, IDIFGroup> groupsOfUser = new HashMap<String, IDIFGroup>();
816 
817         IDIFGroup difGroup = null;
818 
819         try
820         {
821 
822             int rowsPerPage = page.getRowsPerPage();
823 
824             // Groups of user
825             for (LDAPGroup ldapGroup: getLDAPUtils().findGroupsOfUserPagination(userID, rowsPerPage, page.getPage()))
826             {
827                 difGroup = convertFromLDAPGroupToDIFGroup(ldapGroup);
828 
829                 if (difGroup != null)
830                 {
831                     groupsOfUser.put(difGroup.getID(), difGroup);
832 
833                     // Update the cache;
834                     ldapGroupDNMappingCache.put(ldapGroup.getDistinguishedName(), difGroup.getID());
835                 }
836             }
837         }
838         catch (LDAPOperationException ldapOperationException)
839         {
840             throw new IdentityManagerLDAPException("Could not get groups of user " + userID, ldapOperationException);
841         }
842 
843         return groupsOfUser;
844     }
845 
846     /**
847      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserIDsInGroup(java.lang.String)
848      */
849     public Set<String> getUserIDsInGroup(String groupID) throws IdentityManagerException
850     {
851         return getGroupUsers(groupID).keySet();
852     }
853 
854     /**
855      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserLoginAttributeName()
856      */
857     public String getUserLoginAttributeName()
858     {
859         return getLDAPUtils().getUserLoginAttributeName();
860 
861     }
862 
863     /**
864      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUserParentGroupAttributeName()
865      */
866     public String getUserParentGroupAttributeName()
867     {
868         return getLDAPUtils().getUserParentGroupAttributeName();
869     }
870 
871     /**
872      * @throws IdentityManagerException
873      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUsers(Pagination)
874      */
875     public Set<IDIFUser> getUsers(Pagination page) throws IdentityManagerException
876     {
877         Set<LDAPUser> ldapUsers = null;
878         Set<IDIFUser> result = null;
879 
880         try
881         {
882             // add 1 to the page to return, since findUsers starts counting from 1 instead of 0
883             ldapUsers = getLDAPUtils().findUsers(page.getRowsPerPage(), page.getPage() + 1);
884             result = new HashSet<IDIFUser>();
885 
886             // convert from LDAPUser to IDIFUser, for returning
887             for (LDAPUser u: ldapUsers)
888                 result.add(this.convertFromLDAPUserToDIFUser(u));
889             return result;
890         }
891         catch (LDAPOperationException ldapOperationException)
892         {
893             throw new IdentityManagerLDAPException("Could not get all users from LDAP: ", ldapOperationException);
894         }
895     }
896 
897     /**
898      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUsersByAttribute(java.lang.String,
899      *      java.lang.String)
900      */
901     public Set<IDIFUser> getUsersByAttribute(String attribute, String value) throws IdentityManagerException
902     {
903         // Replace all * syntax (LDAP notation) to SQL like syntax
904         value = value.replaceAll("\\%", "*");
905 
906         Set<IDIFUser> difUsers = new HashSet<IDIFUser>();
907         try
908         {
909             for (LDAPUser ldapUser: getLDAPUtils().findUsersByAttribute(attribute, value))
910                 difUsers.add(convertFromLDAPUserToDIFUser(ldapUser));
911             return difUsers;
912         }
913         catch (LDAPOperationException ldapOperationException)
914         {
915             throw new IdentityManagerLDAPException("Could not fetch data for users!", ldapOperationException);
916         }
917     }
918 
919     /**
920      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUsersByAttributes(java.util.Map)
921      */
922     public Set<IDIFUser> getUsersByAttributes(Map<String, String> attributes) throws IdentityManagerException
923     {
924         // Replace all * syntax (LDAP notation) to SQL like syntax
925         for (Entry<String, String> entry: attributes.entrySet())
926             attributes.put(entry.getKey(), entry.getValue().replaceAll("\\%", "*"));
927 
928         Set<LDAPUser> ldapUsers = null;
929         Set<IDIFUser> result = null;
930         try
931         {
932             // add 1 to the page to return, since findUsers starts counting from 1 instead of 0
933             ldapUsers = this.getLDAPUtils().findUsersByAttributes(attributes);
934             result = new HashSet<IDIFUser>();
935 
936             // convert from LDAPUser to IDIFUser, for returning
937             for (LDAPUser u: ldapUsers)
938                 result.add(this.convertFromLDAPUserToDIFUser(u));
939             return result;
940         }
941         catch (LDAPOperationException ldapOperationException)
942         {
943             throw new IdentityManagerLDAPException("Could not get all users from LDAP: ", ldapOperationException);
944         }
945     }
946 
947     /**
948      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUsersByAttributes(java.util.Map,
949      *      Pagination)
950      */
951     public Set<IDIFUser> getUsersByAttributes(Map<String, String> attributes, Pagination page)
952             throws IdentityManagerException
953     {
954         // Replace all * syntax (LDAP notation) to SQL like syntax
955         for (Entry<String, String> entry: attributes.entrySet())
956             attributes.put(entry.getKey(), entry.getValue().replaceAll("\\%", "*"));
957 
958         Set<LDAPUser> ldapUsers = null;
959         Set<IDIFUser> result = null;
960 
961         try
962         {
963             // add 1 to the page to return, since findUsers starts counting from 1 instead of 0
964             ldapUsers = this.getLDAPUtils()
965                     .findUsersByAttributes(attributes, page.getRowsPerPage(), page.getPage() + 1);
966             result = new HashSet<IDIFUser>();
967 
968             // convert from LDAPUser to IDIFUser, for returning
969             for (LDAPUser u: ldapUsers)
970                 result.add(this.convertFromLDAPUserToDIFUser(u));
971             return result;
972         }
973         catch (LDAPOperationException ldapOperationException)
974         {
975             throw new IdentityManagerLDAPException("Could not get all users from LDAP: ", ldapOperationException);
976         }
977     }
978 
979     /**
980      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#getUsersByEmail(java.lang.String)
981      */
982     public Set<IDIFUser> getUsersByEmail(String value) throws IdentityManagerException
983     {
984         return getUsersByAttribute(getLDAPUtils().getMailAttributeName(), value);
985     }
986 
987     /**
988      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#groupExists(java.lang.String)
989      */
990     public boolean groupExists(String groupID) throws IdentityManagerException
991     {
992         try
993         {
994             return getLDAPUtils().groupExists(groupID);
995         }
996         catch (LDAPOperationException ldapOperationException)
997         {
998             throw new IdentityManagerLDAPException("Could not retrieve information for group " + groupID + "!",
999                     ldapOperationException);
1000         }
1001     }
1002 
1003     /**
1004      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#isIdentityValid(java.lang.String,
1005      *      java.lang.String)
1006      */
1007     public boolean isIdentityValid(String userID, String suppliedPassword) throws IdentityManagerException
1008     {
1009         try
1010         {
1011             return getLDAPUtils().isIdentityValid(userID, suppliedPassword);
1012         }
1013         catch (LDAPOperationException ldapOperationException)
1014         {
1015             throw new IdentityManagerLDAPException("Could not verify identity of user " + userID + "!",
1016                     ldapOperationException);
1017         }
1018     }
1019 
1020     /**
1021      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#isReadOnly()
1022      */
1023     public boolean isReadOnly()
1024     {
1025         return this.getLDAPUtils().isReadOnly();
1026     }
1027 
1028     /**
1029      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#isUserInGroup(java.lang.String,
1030      *      java.lang.String)
1031      */
1032     public boolean isUserInGroup(String userID, String groupID) throws IdentityManagerException
1033     {
1034         try
1035         {
1036             return getLDAPUtils().isUserInGroup(groupID, userID);
1037         }
1038         catch (LDAPOperationException ldapOperationException)
1039         {
1040             throw new IdentityManagerLDAPException("Could not check if user " + userID + " belongs to group " + groupID
1041                     + "!", ldapOperationException);
1042         }
1043     }
1044 
1045     /**
1046      * @see pt.digitalis.dif.controller.security.managers.IIdentityManagerPrivate#persistUserAttribute(java.lang.String,
1047      *      java.lang.String, java.lang.Object)
1048      */
1049     synchronized public void persistUserAttribute(String userID, String attributeID, Object attributeValue)
1050             throws IdentityManagerException
1051     {
1052         /* Never saves the attribute DOMAIN_NAME_USER_ATTRIBUTE, there no need to persist it. */
1053         if (!DOMAIN_NAME_USER_ATTRIBUTE.equals(attributeID))
1054         {
1055             try
1056             {
1057                 // ...add it to the LDAPUser parameters (K=LDAP attribute name)
1058                 getLDAPUtils().setUserAttribute(userID, attributeID, attributeValue.toString());
1059             }
1060             catch (LDAPOperationException ldapOperationException)
1061             {
1062                 throw new IdentityManagerLDAPException("Could not update attribute with ID: " + attributeID
1063                         + " with value : " + attributeValue + " for user with ID: " + userID + "!",
1064                         ldapOperationException);
1065             }
1066         }
1067 
1068     }
1069 
1070     /**
1071      * @see pt.digitalis.dif.controller.security.managers.IIdentityManagerPrivate#persistUserAttributes(java.lang.String,
1072      *      java.util.Map)
1073      */
1074     public void persistUserAttributes(String userID, Map<String, Object> attributes) throws IdentityManagerException
1075     {
1076 
1077         for (String attributeID: attributes.keySet())
1078         {
1079             updateUserAttribute(userID, attributeID, attributes.get(attributeID));
1080         }
1081 
1082     }
1083 
1084     /**
1085      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#removeGroup(java.lang.String)
1086      */
1087     public void removeGroup(String groupID) throws IdentityManagerException
1088     {
1089         try
1090         {
1091             LDAPGroup ldapGroup = getLDAPUtils().findGroupByCommonName(groupID);
1092 
1093             if (ldapGroup != null)
1094             {
1095 
1096                 getLDAPUtils().removeGroup(groupID);
1097                 authorizationManager.revokeAllAccessFromGroup(groupID);
1098 
1099                 // Update the cache;
1100                 ldapGroupDNMappingCache.remove(ldapGroup.getDistinguishedName());
1101             }
1102         }
1103         catch (LDAPOperationException ldapOperationException)
1104         {
1105             throw new IdentityManagerLDAPException("Could not remove group " + groupID + "!", ldapOperationException);
1106         }
1107     }
1108 
1109     /**
1110      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#removeUser(java.lang.String)
1111      */
1112     public void removeUser(String userID) throws IdentityManagerException
1113     {
1114         try
1115         {
1116             getLDAPUtils().removeUser(userID);
1117             authorizationManager.revokeAllAccessFromUser(userID);
1118         }
1119         catch (LDAPOperationException ldapOperationException)
1120         {
1121             throw new IdentityManagerLDAPException("Could not remove user " + userID + "!", ldapOperationException);
1122         }
1123     }
1124 
1125     /**
1126      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#removeUserFromGroup(java.lang.String,
1127      *      java.lang.String)
1128      */
1129     public void removeUserFromGroup(String userID, String groupID) throws IdentityManagerException
1130     {
1131         try
1132         {
1133             getLDAPUtils().removeUserFromGroup(groupID, userID);
1134         }
1135         catch (LDAPOperationException ldapOperationException)
1136         {
1137             throw new IdentityManagerLDAPException("Could not remove user " + userID + " from group " + groupID + "!",
1138                     ldapOperationException);
1139         }
1140     }
1141 
1142     /**
1143      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#resetIdentityManager() Forces LDAPUtils
1144      *      re-instantiation (when the LDAP utils changes in runtime, e.g. unit tests) and configurations reloading.
1145      */
1146     public void resetIdentityManager()
1147     {
1148         if (this.ldapUtils != null)
1149         {
1150             this.ldapUtils.resetConfigurations();
1151         }
1152         this.configurations = null;
1153         this.ldapUtils = null;
1154     }
1155 
1156     /**
1157      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#updateGroup(pt.digitalis.dif.controller.security.objects.IDIFGroup)
1158      */
1159     public void updateGroup(IDIFGroup existingGroup) throws IdentityManagerException
1160     {
1161         try
1162         {
1163             getLDAPUtils().updateGroup(convertFromDIFGroupToLDAPGroup(existingGroup), existingGroup.getID());
1164         }
1165         catch (LDAPOperationException ldapOperationException)
1166         {
1167             throw new IdentityManagerLDAPException("Could not update group " + existingGroup.getID() + "!",
1168                     ldapOperationException);
1169         }
1170     }
1171 
1172     /**
1173      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#updateUser(pt.digitalis.dif.controller.security.objects.IDIFUser,
1174      *      java.lang.String)
1175      */
1176     public void updateUser(IDIFUser existingUser, String userID) throws IdentityManagerException
1177     {
1178         try
1179         {
1180             existingUser.cleanCache();
1181 
1182             getLDAPUtils().updateUser(this.convertFromDIFUserToLDAPUser(existingUser), userID);
1183             existingUser.refresh();
1184 
1185         }
1186         catch (LDAPOperationException ldapOperationException)
1187         {
1188             throw new IdentityManagerLDAPException("Could not update user " + existingUser.getID() + "!",
1189                     ldapOperationException);
1190         }
1191     }
1192 
1193     /**
1194      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#updateUserAttribute(java.lang.String,
1195      *      java.lang.String, java.lang.Object)
1196      */
1197     synchronized public void updateUserAttribute(String userID, String attributeID, Object attributeValue)
1198             throws IdentityManagerException
1199     {
1200         persistUserAttribute(userID, attributeID, attributeValue);
1201     }
1202 
1203     /**
1204      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#updateUserAttributes(java.lang.String,
1205      *      java.util.Map)
1206      */
1207     synchronized public void updateUserAttributes(String userID, Map<String, Object> attributes)
1208             throws IdentityManagerException
1209     {
1210         this.persistUserAttributes(userID, attributes);
1211     }
1212 
1213     /**
1214      * @see pt.digitalis.dif.controller.security.managers.IIdentityManager#userExists(java.lang.String)
1215      */
1216     public boolean userExists(String userID) throws IdentityManagerException
1217     {
1218         try
1219         {
1220             return (userID == null ? false : getLDAPUtils().userExists(userID));
1221         }
1222         catch (LDAPOperationException ldapOperationException)
1223         {
1224             throw new IdentityManagerLDAPException("Could not retrieve information for user " + userID + "!",
1225                     ldapOperationException);
1226         }
1227     }
1228 
1229 }