001    package org.apache.turbine.services.security.ldap;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.Hashtable;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Vector;
026    import javax.naming.NameAlreadyBoundException;
027    import javax.naming.NamingEnumeration;
028    import javax.naming.NamingException;
029    import javax.naming.directory.Attribute;
030    import javax.naming.directory.Attributes;
031    import javax.naming.directory.BasicAttribute;
032    import javax.naming.directory.BasicAttributes;
033    import javax.naming.directory.DirContext;
034    import javax.naming.directory.SearchControls;
035    import javax.naming.directory.SearchResult;
036    
037    import org.apache.commons.logging.Log;
038    import org.apache.commons.logging.LogFactory;
039    import org.apache.turbine.om.security.Group;
040    import org.apache.turbine.om.security.Permission;
041    import org.apache.turbine.om.security.Role;
042    import org.apache.turbine.om.security.TurbineGroup;
043    import org.apache.turbine.om.security.TurbinePermission;
044    import org.apache.turbine.om.security.TurbineRole;
045    import org.apache.turbine.om.security.User;
046    import org.apache.turbine.services.security.BaseSecurityService;
047    import org.apache.turbine.services.security.TurbineSecurity;
048    import org.apache.turbine.util.security.AccessControlList;
049    import org.apache.turbine.util.security.DataBackendException;
050    import org.apache.turbine.util.security.EntityExistsException;
051    import org.apache.turbine.util.security.GroupSet;
052    import org.apache.turbine.util.security.PermissionSet;
053    import org.apache.turbine.util.security.RoleSet;
054    import org.apache.turbine.util.security.UnknownEntityException;
055    
056    /**
057     * An implementation of SecurityService that uses LDAP as a backend.
058     *
059     * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
060     * @author <a href="mailto:tadewunmi@gluecode.com">Tracy M. Adewunmi </a>
061     * @author <a href="mailto:lflournoy@gluecode.com">Leonard J. Flournoy </a>
062     * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
063     * @author <a href="mailto:marco@intermeta.de">Marco Kn&uuml;ttel</a>
064     * @author <a href="mailto:hhernandez@itweb.com.mx">Humberto Hernandez</a>
065     * @version $Id: LDAPSecurityService.java 1096130 2011-04-23 10:37:19Z ludwig $
066     */
067    public class LDAPSecurityService extends BaseSecurityService
068    {
069    
070        /** Logging */
071        private static Log log = LogFactory.getLog(LDAPSecurityService.class);
072    
073        /*
074         * -----------------------------------------------------------------------
075         *  C R E A T I O N  O F  A C C E S S  C O N T R O L  L I S T
076         * -----------------------------------------------------------------------
077         */
078    
079        /**
080         * Constructs an AccessControlList for a specific user.
081         *
082         * This method creates a snapshot of the state of security information
083         * concerning this user, at the moment of invocation and stores it
084         * into an AccessControlList object.
085         *
086         * @param user the user for whom the AccessControlList are to be retrieved
087         * @throws DataBackendException if there was an error accessing the backend.
088         * @throws UnknownEntityException if user account is not present.
089         * @return an AccessControlList for a specific user.
090         */
091        public AccessControlList getACL(User user)
092                throws DataBackendException, UnknownEntityException
093        {
094            if (!TurbineSecurity.accountExists(user))
095            {
096                throw new UnknownEntityException("The account '"
097                        + user.getName() + "' does not exist");
098            }
099            try
100            {
101                Hashtable roles = new Hashtable();
102                Hashtable permissions = new Hashtable();
103    
104                // notify the state modifiers (writers) that we want to create
105                // the snapshot.
106                lockShared();
107    
108                // construct the snapshot:
109                // foreach group in the system
110                Iterator groupsIterator = getAllGroups().iterator();
111    
112                while (groupsIterator.hasNext())
113                {
114                    Group group = (Group) groupsIterator.next();
115    
116                    // get roles of user in the group
117                    RoleSet groupRoles = getRoles(user, group);
118    
119                    // put the Set into roles(group)
120                    roles.put(group, groupRoles);
121                    // collect all permissoins in this group
122                    PermissionSet groupPermissions = new PermissionSet();
123                    // foreach role in Set
124                    Iterator rolesIterator = groupRoles.iterator();
125    
126                    while (rolesIterator.hasNext())
127                    {
128                        Role role = (Role) rolesIterator.next();
129                        // get permissions of the role
130                        PermissionSet rolePermissions = getPermissions(role);
131    
132                        groupPermissions.add(rolePermissions);
133                    }
134                    // put the Set into permissions(group)
135                    permissions.put(group, groupPermissions);
136                }
137                return getAclInstance(roles, permissions);
138            }
139            catch (Exception e)
140            {
141                throw new DataBackendException("Failed to build ACL for user '"
142                        + user.getName() + "'", e);
143            }
144            finally
145            {
146                // notify the state modifiers that we are done creating
147                // the snapshot.
148                unlockShared();
149            }
150        }
151    
152        /*
153         * -----------------------------------------------------------------------
154         * S E C U R I T Y  M A N A G E M E N T
155         * -----------------------------------------------------------------------
156         */
157    
158        /**
159         * Grant an User a Role in a Group.
160         *
161         * @param user the user.
162         * @param group the group.
163         * @param role the role.
164         * @throws DataBackendException if there was an error accessing the backend.
165         * @throws UnknownEntityException if user account, group or role
166         *         is not present.
167         */
168        public synchronized void grant(User user, Group group, Role role)
169                throws DataBackendException, UnknownEntityException
170        {
171            try
172            {
173                lockExclusive();
174    
175                String userName = user.getName();
176                String roleName = role.getName();
177                String groupName = group.getName();
178    
179                if (!accountExists(user))
180                {
181                    throw new UnknownEntityException(
182                            "User '" + userName + "' does not exist");
183                }
184    
185                if (!checkExists(role))
186                {
187                    throw new UnknownEntityException(
188                            "Role '" + roleName + "' does not exist");
189                }
190    
191                if (!checkExists(group))
192                {
193                    throw new UnknownEntityException(
194                            "Group '" + groupName + "' does not exist");
195                }
196    
197                // Make the distinguished name.
198                String dn = "turbineGroupName=" + groupName + ","
199                        + LDAPSecurityConstants.getNameAttribute()
200                        + "=" + userName + ","
201                        + LDAPSecurityConstants.getBaseSearch();
202    
203    
204                // Connect to LDAP.
205                DirContext ctx = LDAPUserManager.bindAsAdmin();
206    
207                // Make the attributes.
208                Attributes attrs = new BasicAttributes();
209    
210                attrs.put(new BasicAttribute("turbineRoleName", roleName));
211                attrs.put(new BasicAttribute("objectClass", "turbineUserGroup"));
212                attrs.put(new BasicAttribute("turbineUserUniqueId", userName));
213                try
214                {
215                    // Add the turbineUserGroup.
216                    ctx.bind(dn, null, attrs);
217                }
218                catch (NameAlreadyBoundException ex)
219                {
220                    // Since turbineUserGroup had already been created
221                    // then just add the role name attribute.
222                    attrs = new BasicAttributes();
223                    attrs.put(new BasicAttribute("turbineRoleName", roleName));
224                    ctx.modifyAttributes(dn, DirContext.ADD_ATTRIBUTE, attrs);
225                }
226    
227            }
228            catch (NamingException ex)
229            {
230                throw new DataBackendException("NamingException caught", ex);
231            }
232            finally
233            {
234                unlockExclusive();
235            }
236        }
237    
238        /**
239         * Revoke a Role in a Group from an User.
240         *
241         * @param user the user.
242         * @param group the group.
243         * @param role the role.
244         * @throws DataBackendException if there was an error accessing the backend.
245         * @throws UnknownEntityException if user account, group or role is
246         *         not present.
247         */
248        public synchronized void revoke(User user, Group group, Role role)
249                throws DataBackendException, UnknownEntityException
250        {
251            try
252            {
253                lockExclusive();
254    
255                String userName = user.getName();
256                String roleName = role.getName();
257                String groupName = group.getName();
258    
259                if (!accountExists(user))
260                {
261                    throw new UnknownEntityException(
262                            "User '" + userName + "' does not exist");
263                }
264    
265                if (!checkExists(role))
266                {
267                    throw new UnknownEntityException(
268                            "Role '" + roleName + "' does not exist");
269                }
270    
271                if (!checkExists(group))
272                {
273                    throw new UnknownEntityException(
274                            "Group '" + groupName + "' does not exist");
275                }
276    
277                // Make the distinguished name.
278                String dn = "turbineGroupName=" + groupName + ","
279                        + LDAPSecurityConstants.getNameAttribute()
280                        + "=" + userName + ","
281                        + LDAPSecurityConstants.getBaseSearch();
282    
283                // Make the attributes.
284                Attributes attrs = new BasicAttributes();
285    
286                attrs.put(new BasicAttribute("turbineRoleName", roleName));
287    
288                // Connect to LDAP.
289                DirContext ctx = LDAPUserManager.bindAsAdmin();
290    
291                // Remove the role.
292                ctx.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, attrs);
293    
294            }
295            catch (NamingException ex)
296            {
297                throw new DataBackendException("NamingException caught", ex);
298            }
299            finally
300            {
301                unlockExclusive();
302            }
303        }
304    
305        /**
306         * Grants a Role a Permission
307         *
308         * @param role the Role.
309         * @param permission the Permission.
310         * @throws DataBackendException if there was an error accessing the backend.
311         * @throws UnknownEntityException if role or permission is not present.
312         */
313        public synchronized void grant(Role role, Permission permission)
314                throws DataBackendException, UnknownEntityException
315        {
316            try
317            {
318                lockExclusive();
319    
320                String roleName = role.getName();
321                String permName = permission.getName();
322    
323                if (!checkExists(role))
324                {
325                    throw new UnknownEntityException(
326                            "Role '" + roleName + "' does not exist");
327                }
328    
329                if (!checkExists(permission))
330                {
331                    throw new UnknownEntityException(
332                            "Permission '" + permName + "' does not exist");
333                }
334    
335                // Make the distinguished name.
336                String dn = "turbineRoleName=" + roleName + ","
337                        + LDAPSecurityConstants.getBaseSearch();
338    
339                // Make the attributes.
340                Attributes attrs = new BasicAttributes();
341    
342                attrs.put(new BasicAttribute("turbinePermissionName", permName));
343    
344                // Connect to LDAP.
345                DirContext ctx = LDAPUserManager.bindAsAdmin();
346    
347                // Add the permission.
348                ctx.modifyAttributes(dn, DirContext.ADD_ATTRIBUTE, attrs);
349    
350            }
351            catch (NamingException ex)
352            {
353                throw new DataBackendException("NamingException caught", ex);
354            }
355            finally
356            {
357                unlockExclusive();
358            }
359        }
360    
361        /**
362         * Revokes a Permission from a Role.
363         *
364         * @param role the Role.
365         * @param permission the Permission.
366         * @throws DataBackendException if there was an error accessing the backend.
367         * @throws UnknownEntityException if role or permission is not present.
368         */
369        public synchronized void revoke(Role role, Permission permission)
370                throws DataBackendException, UnknownEntityException
371        {
372            try
373            {
374                lockExclusive();
375    
376                String roleName = role.getName();
377                String permName = permission.getName();
378    
379                if (!checkExists(role))
380                {
381                    throw new UnknownEntityException(
382                            "Role '" + roleName + "' does not exist");
383                }
384    
385                if (!checkExists(permission))
386                {
387                    throw new UnknownEntityException(
388                            "Permission '" + permName + "' does not exist");
389                }
390    
391                // Make the distinguished name.
392                String dn = "turbineRoleName=" + roleName + ","
393                        + LDAPSecurityConstants.getBaseSearch();
394    
395                // Make the attributes.
396                Attributes attrs = new BasicAttributes();
397    
398                attrs.put(new BasicAttribute("turbinePermissionName", permName));
399    
400                // Connect to LDAP.
401                DirContext ctx = LDAPUserManager.bindAsAdmin();
402    
403                // Remove the permission.
404                ctx.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, attrs);
405    
406            }
407            catch (NamingException ex)
408            {
409                throw new DataBackendException("NamingException caught", ex);
410            }
411            finally
412            {
413                unlockExclusive();
414            }
415        }
416    
417        /*
418         * -----------------------------------------------------------------------
419         * G R O U P / R O L E / P E R M I S S I O N  M A N A G E M E N T
420         * -----------------------------------------------------------------------
421         */
422    
423        /**
424         * Retrieves a new Group. It creates
425         * a new Group based on the Services Group implementation. It does not
426         * create a new Group in the system though. Use addGroup for that.
427         * <strong>Not implemented</strong>
428         *
429         * @param groupName The name of the Group to be retrieved.
430         * @return a Group.
431         */
432        public Group getNewGroup(String groupName)
433        {
434            return (Group) new TurbineGroup(groupName);
435        }
436    
437        /**
438         * Retrieves a new Role. It creates
439         * a new Role based on the Services Role implementation. It does not
440         * create a new Role in the system though. Use addRole for that.
441         * <strong>Not implemented</strong>
442         *
443         * @param roleName The name of the Group to be retrieved.
444         * @return a Role.
445         */
446        public Role getNewRole(String roleName)
447        {
448            return (Role) new TurbineRole(roleName);
449        }
450    
451        /**
452         * Retrieves a new Permission. It creates
453         * a new Permission based on the Services Permission implementation. It
454         * does not create a new Permission in the system though. Use create for
455         * that.
456         * <strong>Not implemented</strong>
457         *
458         * @param permissionName The name of the Permission to be retrieved.
459         * @return a Permission
460         */
461        public Permission getNewPermission(String permissionName)
462        {
463            return (Permission) new TurbinePermission(permissionName);
464        }
465    
466        /**
467         * Retrieve a set of Groups that meet the specified Criteria.
468         *
469         * @param criteria Criteria of Group selection.
470         * @return a set of Groups that meet the specified Criteria.
471         * @throws DataBackendException if there is problem with the Backend.
472         */
473        public GroupSet getGroups(Object criteria)
474                throws DataBackendException
475        {
476            Vector groups = new Vector();
477    
478            try
479            {
480                DirContext ctx = LDAPUserManager.bindAsAdmin();
481    
482                String baseSearch = LDAPSecurityConstants.getBaseSearch();
483                String filter = "(objectclass=turbineGroup)";
484    
485                /*
486                 * Create the default search controls.
487                 */
488                SearchControls ctls = new SearchControls();
489    
490                NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
491    
492                while (answer.hasMore())
493                {
494                    SearchResult sr = (SearchResult) answer.next();
495                    Attributes attribs = sr.getAttributes();
496                    Attribute attr = attribs.get("turbineGroupName");
497    
498                    if (attr != null && attr.get() != null)
499                    {
500                        Group group = getNewGroup(attr.get().toString());
501    
502                        groups.add(group);
503                    }
504                }
505            }
506            catch (NamingException ex)
507            {
508                throw new DataBackendException("NamingException caught", ex);
509            }
510            return new GroupSet(groups);
511        }
512    
513        /** Get the Roles that a user belongs in a specific group.
514         * @param user The user.
515         * @param group The group
516         * @throws DataBackendException if there is a problem with
517         *     the LDAP service.
518         * @return a RoleSet.
519         */
520        private RoleSet getRoles(User user, Group group)
521                throws DataBackendException
522        {
523            Vector roles = new Vector(0);
524    
525            try
526            {
527                DirContext ctx = LDAPUserManager.bindAsAdmin();
528    
529                String baseSearch = LDAPSecurityConstants.getBaseSearch();
530                String filter = "(& ";
531    
532                filter += "(objectclass=turbineUserGroup)";
533                filter += "(turbineUserUniqueId=" + user.getName() + ")";
534                filter += "(turbineGroupName=" + group.getName() + ")";
535                filter += ")";
536    
537                /*
538                 * Create the default search controls.
539                 */
540                SearchControls ctls = new SearchControls();
541    
542                ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
543    
544                NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
545    
546                while (answer.hasMore())
547                {
548                    SearchResult sr = (SearchResult) answer.next();
549                    Attributes attribs = sr.getAttributes();
550                    Attribute attr = attribs.get("turbineRoleName");
551    
552                    if (attr != null)
553                    {
554                        NamingEnumeration values = attr.getAll();
555    
556                        while (values.hasMore())
557                        {
558                            Role role = getNewRole(values.next().toString());
559    
560                            roles.add(role);
561                        }
562                    }
563                    else
564                    {
565                        log.error("Role doesn't have a name");
566                    }
567                }
568            }
569            catch (NamingException ex)
570            {
571                throw new DataBackendException(
572                        "NamingException caught:", ex);
573            }
574    
575            return new RoleSet(roles);
576        }
577    
578        /**
579         * Retrieve a set of Roles that meet the specified Criteria.
580         *
581         * @param criteria Criteria of Roles selection.
582         * @return a set of Roles that meet the specified Criteria.
583         * @throws DataBackendException if there is a problem with the Backend.
584         */
585        public RoleSet getRoles(Object criteria) throws DataBackendException
586        {
587            Vector roles = new Vector(0);
588    
589            try
590            {
591                DirContext ctx = LDAPUserManager.bindAsAdmin();
592    
593                String baseSearch = LDAPSecurityConstants.getBaseSearch();
594                String filter = "(objectclass=turbineRole)";
595    
596                /*
597                 * Create the default search controls.
598                 */
599                SearchControls ctls = new SearchControls();
600    
601                NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
602    
603                while (answer.hasMore())
604                {
605                    SearchResult sr = (SearchResult) answer.next();
606                    Attributes attribs = sr.getAttributes();
607                    Attribute attr = attribs.get("turbineRoleName");
608    
609                    if (attr != null && attr.get() != null)
610                    {
611                        Role role = getNewRole(attr.get().toString());
612    
613                        roles.add(role);
614                    }
615                    else
616                    {
617                        log.error("Role doesn't have a name");
618                    }
619                }
620            }
621            catch (NamingException ex)
622            {
623                throw new DataBackendException("NamingException caught", ex);
624            }
625    
626            return new RoleSet(roles);
627        }
628    
629        /**
630         * Retrieve a set of Permissions that meet the specified Criteria.
631         *
632         * @param criteria Criteria of Permissions selection.
633         * @return a set of Permissions that meet the specified Criteria.
634         * @throws DataBackendException if there is a problem with the Backend.
635         */
636        public PermissionSet getPermissions(Object criteria)
637                throws DataBackendException
638        {
639            Vector permissions = new Vector();
640    
641            try
642            {
643                DirContext ctx = LDAPUserManager.bindAsAdmin();
644    
645                String baseSearch = LDAPSecurityConstants.getBaseSearch();
646                String filter = "(objectClass=turbinePermission)";
647    
648                /*
649                 * Create the default search controls.
650                 */
651                SearchControls ctls = new SearchControls();
652    
653                NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
654    
655                while (answer.hasMore())
656                {
657                    SearchResult sr = (SearchResult) answer.next();
658                    Attributes attribs = sr.getAttributes();
659                    Attribute attr = attribs.get("turbinePermissionName");
660    
661                    if (attr != null && attr.get() != null)
662                    {
663                        Permission perm = getNewPermission(attr.get().toString());
664    
665                        permissions.add(perm);
666                    }
667                    else
668                    {
669                        log.error("Permission doesn't have a name");
670                    }
671                }
672            }
673            catch (NamingException ex)
674            {
675                throw new DataBackendException(
676                        "The LDAP server specified is unavailable", ex);
677            }
678            return new PermissionSet(permissions);
679        }
680    
681        /**
682         * Retrieves all permissions associated with a role.
683         *
684         * @param role the role name, for which the permissions are to be retrieved.
685         * @throws DataBackendException if there was an error accessing the backend.
686         * @throws UnknownEntityException if the role is not present.
687         * @return a PermissionSet.
688         */
689        public PermissionSet getPermissions(Role role)
690                throws DataBackendException, UnknownEntityException
691        {
692            Hashtable permissions = new Hashtable();
693    
694            try
695            {
696                DirContext ctx = LDAPUserManager.bindAsAdmin();
697    
698                String baseSearch = LDAPSecurityConstants.getBaseSearch();
699                String filter = "(& ";
700    
701                filter += "(objectClass=turbineRole)";
702                filter += "(turbineRoleName=" + role.getName() + ")";
703                filter += ")";
704    
705                /*
706                 * Create the default search controls.
707                 */
708                SearchControls ctls = new SearchControls();
709    
710                NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
711    
712                while (answer.hasMore())
713                {
714                    SearchResult sr = (SearchResult) answer.next();
715                    Attributes attribs = sr.getAttributes();
716                    Attribute attr = attribs.get("turbinePermissionName");
717    
718                    if (attr != null)
719                    {
720                        NamingEnumeration values = attr.getAll();
721    
722                        while (values.hasMore())
723                        {
724                            String permName = values.next().toString();
725                            Permission perm = getNewPermission(permName);
726    
727                            permissions.put(perm.getName(), perm);
728                        }
729                    }
730                }
731            }
732            catch (NamingException ex)
733            {
734                throw new DataBackendException(
735                        "The LDAP server specified is unavailable", ex);
736            }
737            return new PermissionSet(permissions.values());
738        }
739    
740        /**
741         * Stores Group's attributes. The Groups is required to exist in the system.
742         *
743         * @param group The Group to be stored.
744         * @throws DataBackendException if there was an error accessing the backend.
745         * @throws UnknownEntityException if the group does not exist.
746         */
747        public void saveGroup(Group group) throws DataBackendException,
748                UnknownEntityException
749        {
750            // Not implemented yet.
751        }
752    
753        /**
754         * Stores Role's attributes. The Roles is required to exist in the system.
755         *
756         * @param role The Role to be stored.
757         * @throws DataBackendException if there was an error accessing the backend.
758         * @throws UnknownEntityException if the role does not exist.
759         */
760        public void saveRole(Role role) throws DataBackendException,
761                UnknownEntityException
762        {
763            // Not implemented yet.
764        }
765    
766        /**
767         * Stores Permission's attributes. The Permissions is required to exist in
768         * the system.
769         *
770         * @param permission The Permission to be stored.
771         * @throws DataBackendException if there was an error accessing the backend.
772         * @throws UnknownEntityException if the permission does not exist.
773         */
774        public void savePermission(Permission permission)
775                throws DataBackendException, UnknownEntityException
776        {
777            // Not implemented yet.
778        }
779    
780        /**
781         * Creates a new group with specified attributes.
782         * <strong>Not implemented</strong>
783         *
784         * @param group the object describing the group to be created.
785         * @return a new Group object that has id set up properly.
786         * @throws DataBackendException if there was an error accessing the backend.
787         * @throws EntityExistsException if the group already exists.
788         */
789        public synchronized Group addGroup(Group group)
790                throws DataBackendException, EntityExistsException
791        {
792            try
793            {
794                lockExclusive();
795    
796                String groupName = group.getName();
797    
798                if (checkExists(group))
799                {
800                    throw new EntityExistsException(
801                            "Group '" + groupName + "' already exists");
802                }
803    
804                // Make the distinguished name.
805                String dn = "turbineGroupName=" + groupName + ","
806                        + LDAPSecurityConstants.getBaseSearch();
807    
808                // Make the attributes.
809                Attributes attrs = new BasicAttributes();
810    
811                attrs.put(new BasicAttribute("objectClass", "turbineGroup"));
812                attrs.put(new BasicAttribute("turbineGroupName", groupName));
813    
814                // Connect to LDAP.
815                DirContext ctx = LDAPUserManager.bindAsAdmin();
816    
817                // Add the group in LDAP.
818                ctx.bind(dn, null, attrs);
819    
820                // Add the group to system-wide cache.
821                getAllGroups().add(group);
822    
823                return group;
824            }
825            catch (NamingException ex)
826            {
827                throw new DataBackendException("NamingException caught", ex);
828            }
829            finally
830            {
831                unlockExclusive();
832            }
833        }
834    
835        /**
836         * Creates a new role with specified attributes.
837         *
838         * @param role the object describing the role to be created.
839         * @return a new Role object that has id set up properly.
840         * @throws DataBackendException if there was an error accessing the backend.
841         * @throws EntityExistsException if the role already exists.
842         */
843        public synchronized Role addRole(Role role)
844                throws DataBackendException, EntityExistsException
845        {
846            try
847            {
848                lockExclusive();
849    
850                String roleName = role.getName();
851    
852                if (checkExists(role))
853                {
854                    throw new EntityExistsException(
855                            "Role '" + roleName + "' already exists");
856                }
857    
858                // Make the distinguished name.
859                String dn = "turbineRoleName=" + roleName + ","
860                        + LDAPSecurityConstants.getBaseSearch();
861    
862                // Make the attributes.
863                Attributes attrs = new BasicAttributes();
864    
865                attrs.put(new BasicAttribute("objectClass", "turbineRole"));
866                attrs.put(new BasicAttribute("turbineRoleName", roleName));
867    
868                // Connect to LDAP.
869                DirContext ctx = LDAPUserManager.bindAsAdmin();
870    
871                // Add the role in LDAP.
872                ctx.bind(dn, null, attrs);
873    
874                // Add the role to system-wide cache.
875                getAllRoles().add(role);
876    
877                return role;
878            }
879            catch (NamingException ex)
880            {
881                throw new DataBackendException("NamingException caught", ex);
882            }
883            finally
884            {
885                unlockExclusive();
886            }
887        }
888    
889        /**
890         * Creates a new permission with specified attributes.
891         * <strong>Not implemented</strong>
892         *
893         * @param permission the object describing the permission to be created.
894         * @return a new Permission object that has id set up properly.
895         * @throws DataBackendException if there was an error accessing the backend.
896         * @throws EntityExistsException if the permission already exists.
897         */
898        public synchronized Permission addPermission(Permission permission)
899                throws DataBackendException, EntityExistsException
900        {
901            try
902            {
903                lockExclusive();
904    
905                String permName = permission.getName();
906    
907                if (checkExists(permission))
908                {
909                    throw new EntityExistsException(
910                            "Permission '" + permName + "' already exists");
911                }
912    
913                // Make the distinguished name.
914                String dn = "turbinePermissionName=" + permName + ","
915                        + LDAPSecurityConstants.getBaseSearch();
916    
917                // Make the attributes.
918                Attributes attrs = new BasicAttributes();
919    
920                attrs.put(new BasicAttribute("objectClass", "turbinePermission"));
921                attrs.put(new BasicAttribute("turbinePermissionName", permName));
922    
923                DirContext ctx = LDAPUserManager.bindAsAdmin();
924    
925                // Add the permission in LDAP.
926                ctx.bind(dn, null, attrs);
927    
928                // add the permission to system-wide cache
929                getAllPermissions().add(permission);
930    
931                return permission;
932            }
933            catch (NamingException ex)
934            {
935                throw new DataBackendException("NamingException caught", ex);
936            }
937            finally
938            {
939                unlockExclusive();
940            }
941        }
942    
943        /**
944         * Removes a Group from the system.
945         *
946         * @param group object describing group to be removed.
947         * @throws DataBackendException if there was an error accessing the backend.
948         * @throws UnknownEntityException if the group does not exist.
949         */
950        public synchronized void removeGroup(Group group)
951                throws DataBackendException, UnknownEntityException
952        {
953            try
954            {
955                lockExclusive();
956    
957                String groupName = group.getName();
958    
959                if (!checkExists(group))
960                {
961                    throw new UnknownEntityException(
962                            "Group '" + groupName + "' does not exist");
963                }
964    
965                // Make the distinguished name.
966                String dn = "turbineGroupName=" + groupName + ","
967                        + LDAPSecurityConstants.getBaseSearch();
968    
969                DirContext ctx = LDAPUserManager.bindAsAdmin();
970    
971                // Remove the group from LDAP.
972                ctx.unbind(dn);
973    
974                // Remove the group from system-wide cache.
975                getAllGroups().remove(group);
976            }
977            catch (NamingException ex)
978            {
979                throw new DataBackendException("NamingException caught", ex);
980            }
981            finally
982            {
983                unlockExclusive();
984            }
985        }
986    
987        /**
988         * Removes a Role from the system.
989         *
990         * @param role object describing role to be removed.
991         * @throws DataBackendException if there was an error accessing the backend.
992         * @throws UnknownEntityException if the role does not exist.
993         */
994        public synchronized void removeRole(Role role)
995                throws DataBackendException, UnknownEntityException
996        {
997            try
998            {
999                lockExclusive();
1000    
1001                String roleName = role.getName();
1002    
1003                if (!checkExists(role))
1004                {
1005                    throw new UnknownEntityException(
1006                            "Role '" + roleName + "' does not exist");
1007                }
1008    
1009                // Make the distinguished name.
1010                String dn = "turbineRoleName=" + roleName + ","
1011                        + LDAPSecurityConstants.getBaseSearch();
1012    
1013                DirContext ctx = LDAPUserManager.bindAsAdmin();
1014    
1015                // Remove the role from LDAP.
1016                ctx.unbind(dn);
1017    
1018                // Remove the role from system-wide cache.
1019                getAllRoles().remove(role);
1020            }
1021            catch (NamingException ex)
1022            {
1023                throw new DataBackendException("NamingException caught", ex);
1024            }
1025            finally
1026            {
1027                unlockExclusive();
1028            }
1029        }
1030    
1031        /**
1032         * Removes a Permission from the system.
1033         *
1034         * @param permission object describing permission to be removed.
1035         * @throws DataBackendException if there was an error accessing the backend.
1036         * @throws UnknownEntityException if the permission does not exist.
1037         */
1038        public synchronized void removePermission(Permission permission)
1039                throws DataBackendException, UnknownEntityException
1040        {
1041            try
1042            {
1043                lockExclusive();
1044    
1045                String permName = permission.getName();
1046    
1047                if (!checkExists(permission))
1048                {
1049                    throw new UnknownEntityException(
1050                            "Permission '" + permName + "' does not exist");
1051                }
1052    
1053                // Make the distinguished name.
1054                String dn = "turbinePermissionName=" + permName + ","
1055                        + LDAPSecurityConstants.getBaseSearch();
1056    
1057                DirContext ctx = LDAPUserManager.bindAsAdmin();
1058    
1059                // Remove the permission in LDAP.
1060                ctx.unbind(dn);
1061    
1062                // Remove the permission from system-wide cache.
1063                getAllPermissions().remove(permission);
1064            }
1065            catch (NamingException ex)
1066            {
1067                throw new DataBackendException("NamingException caught", ex);
1068            }
1069            finally
1070            {
1071                unlockExclusive();
1072            }
1073        }
1074    
1075        /**
1076         * Renames an existing Group.
1077         *
1078         * @param group object describing the group to be renamed.
1079         * @param name the new name for the group.
1080         * @throws DataBackendException if there was an error accessing the backend.
1081         * @throws UnknownEntityException if the group does not exist.
1082         */
1083        public synchronized void renameGroup(Group group, String name)
1084                throws DataBackendException, UnknownEntityException
1085        {
1086            // Not implemented yet.
1087        }
1088    
1089        /**
1090         * Renames an existing Role.
1091         *
1092         * @param role object describing the role to be renamed.
1093         * @param name the new name for the role.
1094         * @throws DataBackendException if there was an error accessing the backend.
1095         * @throws UnknownEntityException if the role does not exist.
1096         */
1097        public synchronized void renameRole(Role role, String name)
1098                throws DataBackendException, UnknownEntityException
1099        {
1100            // Not implemented yet.
1101        }
1102    
1103        /**
1104         * Renames an existing Permission.
1105         *
1106         * @param permission object describing the permission to be renamed.
1107         * @param name the new name for the permission.
1108         * @throws DataBackendException if there was an error accessing the backend.
1109         * @throws UnknownEntityException if the permission does not exist.
1110         */
1111        public synchronized void renamePermission(Permission permission,
1112                                                  String name)
1113                throws DataBackendException, UnknownEntityException
1114        {
1115            // Not implemented yet.
1116        }
1117    
1118        /**
1119         * Revoke all the roles to a user
1120         * @param user the user.
1121         * @throws DataBackendException if there is an error with the data backend.
1122         * @throws UnkownEntityException if the role or a permission is not found.
1123         */
1124        public void revokeAll(User user)
1125                throws DataBackendException, UnknownEntityException
1126        {
1127            Iterator groupsIterator = getAllGroups().iterator();
1128            while (groupsIterator.hasNext())
1129            {
1130                Group group = (Group) groupsIterator.next();
1131                Iterator rolesIterator = getRoles(user, group).iterator();
1132                while (rolesIterator.hasNext())
1133                {
1134                    Role role = (Role) rolesIterator.next();
1135                    revoke(user, group, role);
1136                }
1137            }
1138        }
1139    
1140        /**
1141         * Revoke all the permissions to a role.
1142         * @param role the role.
1143         * @throws DataBackendException if there is an error with the data backend.
1144         * @throws UnkownEntityException if the role or a permission is not found.
1145         */
1146        public void revokeAll(Role role)
1147                throws DataBackendException, UnknownEntityException
1148        {
1149            PermissionSet permissions = getPermissions(role);
1150            Iterator permIterator = permissions.iterator();
1151            while (permIterator.hasNext())
1152            {
1153                Permission perm = (Permission) permIterator.next();
1154                revoke(role, perm);
1155            }
1156        }
1157    
1158        /**
1159         * Revoke all the roles to a group.
1160         * @param group the group.
1161         * @throws DataBackendException if there is an error with the data backend.
1162         * @throws UnkownEntityException if the role or a permission is not found.
1163         */
1164        public void revokeAll(Group group)
1165                throws DataBackendException, UnknownEntityException
1166        {
1167            for (Iterator it = getUserList(new Object()).iterator();
1168                 it.hasNext();)
1169            {
1170                User user = (User) it.next();
1171                for (Iterator rolesIterator = getRoles(user, group).iterator();
1172                     rolesIterator.hasNext();)
1173                {
1174                    Role role = (Role) rolesIterator.next();
1175                    revoke(user, group, role);
1176                }
1177            }
1178        }
1179    
1180        /**
1181         * Determines if the <code>Role</code> exists in the security system.
1182         *
1183         * @param role a <code>Role</code> value
1184         * @return true if the role exists in the system, false otherwise
1185         * @throws DataBackendException if there is an error with LDAP
1186         */
1187        public boolean checkExists(Role role)
1188                throws DataBackendException
1189        {
1190            RoleSet roleSet = getRoles(new Object());
1191    
1192            return roleSet.contains(role);
1193        }
1194    
1195        /**
1196         * Determines if the <code>Group</code> exists in the security system.
1197         *
1198         * @param group a <code>Group</code> value
1199         * @return true if the group exists in the system, false otherwise
1200         * @throws DataBackendException if there is an error with LDAP
1201         */
1202        public boolean checkExists(Group group)
1203                throws DataBackendException
1204        {
1205            GroupSet groupSet = getGroups(new Object());
1206    
1207            return groupSet.contains(group);
1208        }
1209    
1210        /**
1211         * Determines if the <code>Permission</code> exists in the security system.
1212         *
1213         * @param permission a <code>Permission</code> value
1214         * @return true if the permission exists in the system, false otherwise
1215         * @throws DataBackendException if there is an error with LDAP
1216         */
1217        public boolean checkExists(Permission permission)
1218                throws DataBackendException
1219        {
1220            PermissionSet permissionSet = getPermissions(new Object());
1221    
1222            return permissionSet.contains(permission);
1223        }
1224    
1225    
1226        /* (non-Javadoc)
1227         * @see org.apache.turbine.services.security.SecurityService#getAllGroups()
1228         */
1229        public GroupSet getAllGroups() throws DataBackendException {
1230            // TODO Auto-generated method stub
1231            return null;
1232        }
1233        /* (non-Javadoc)
1234         * @see org.apache.turbine.services.security.SecurityService#getAllPermissions()
1235         */
1236        public PermissionSet getAllPermissions() throws DataBackendException {
1237            // TODO Auto-generated method stub
1238            return null;
1239        }
1240        /* (non-Javadoc)
1241         * @see org.apache.turbine.services.security.SecurityService#getAllRoles()
1242         */
1243        public RoleSet getAllRoles() throws DataBackendException {
1244            // TODO Auto-generated method stub
1245            return null;
1246        }
1247        /* (non-Javadoc)
1248         * @see org.apache.turbine.services.security.SecurityService#getUserList(java.lang.Object)
1249         */
1250        public List getUserList(Object criteria) throws DataBackendException {
1251            // TODO Auto-generated method stub
1252            return null;
1253        }
1254    }