]> source.dussan.org Git - archiva.git/blob
230091bbf7e9a25223631eb6b060d103b43fe9b4
[archiva.git] /
1 package org.apache.archiva.redback.rbac.ldap;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import com.google.common.base.Function;
23 import com.google.common.collect.Lists;
24 import org.apache.archiva.redback.common.ldap.MappingException;
25 import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
26 import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
27 import org.apache.archiva.redback.common.ldap.connection.LdapException;
28 import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
29 import org.apache.archiva.redback.components.cache.Cache;
30 import org.apache.archiva.redback.configuration.UserConfiguration;
31 import org.apache.archiva.redback.configuration.UserConfigurationKeys;
32 import org.apache.archiva.redback.rbac.AbstractRBACManager;
33 import org.apache.archiva.redback.rbac.AbstractRole;
34 import org.apache.archiva.redback.rbac.Operation;
35 import org.apache.archiva.redback.rbac.Permission;
36 import org.apache.archiva.redback.rbac.RBACManager;
37 import org.apache.archiva.redback.rbac.RBACManagerListener;
38 import org.apache.archiva.redback.rbac.RBACObjectAssertions;
39 import org.apache.archiva.redback.rbac.RbacManagerException;
40 import org.apache.archiva.redback.rbac.RbacObjectInvalidException;
41 import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
42 import org.apache.archiva.redback.rbac.RbacPermanentException;
43 import org.apache.archiva.redback.rbac.Resource;
44 import org.apache.archiva.redback.rbac.Role;
45 import org.apache.archiva.redback.rbac.UserAssignment;
46 import org.apache.archiva.redback.users.User;
47 import org.apache.archiva.redback.users.UserManager;
48 import org.apache.archiva.redback.users.UserManagerException;
49 import org.apache.archiva.redback.users.ldap.ctl.LdapController;
50 import org.apache.archiva.redback.users.ldap.ctl.LdapControllerException;
51 import org.apache.commons.lang.StringUtils;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.stereotype.Service;
55
56 import javax.annotation.PostConstruct;
57 import javax.inject.Inject;
58 import javax.inject.Named;
59 import javax.naming.NamingException;
60 import javax.naming.directory.DirContext;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.Collections;
64 import java.util.HashSet;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Set;
68
69 /**
70  * LdapRbacManager will read datas from ldap for mapping groups to role.
71  * Write operations will delegate to cached implementation.
72  *
73  * @author Olivier Lamy
74  */
75 @Service( "rbacManager#ldap" )
76 public class LdapRbacManager
77     extends AbstractRBACManager
78     implements RBACManager, RBACManagerListener
79 {
80
81     private Logger log = LoggerFactory.getLogger( getClass() );
82
83     @Inject
84     @Named( value = "rbacManager#cached" )
85     private RBACManager rbacImpl;
86
87     @Inject
88     @Named( value = "ldapRoleMapper#default" )
89     private LdapRoleMapper ldapRoleMapper;
90
91     @Inject
92     @Named( value = "userConfiguration#default" )
93     private UserConfiguration userConf;
94
95     @Inject
96     @Named( value = "userManager#ldap" )
97     private UserManager userManager;
98
99     @Inject
100     private LdapConnectionFactory ldapConnectionFactory;
101
102     @Inject
103     private LdapController ldapController;
104
105     @Inject
106     @Named( value = "cache#ldapRoles" )
107     private Cache<String, Role> rolesCache;
108
109     private boolean writableLdap = false;
110
111
112     @PostConstruct
113     public void initialize()
114     {
115         this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
116     }
117
118
119     public void addChildRole( Role role, Role childRole )
120         throws RbacObjectInvalidException, RbacManagerException
121     {
122         this.rbacImpl.addChildRole( role, childRole );
123     }
124
125     public void addListener( RBACManagerListener listener )
126     {
127         super.addListener( listener );
128         this.rbacImpl.addListener( listener );
129     }
130
131     public Operation createOperation( String name )
132         throws RbacManagerException
133     {
134         return this.rbacImpl.createOperation( name );
135     }
136
137     public Permission createPermission( String name )
138         throws RbacManagerException
139     {
140         return this.rbacImpl.createPermission( name );
141     }
142
143     public Permission createPermission( String name, String operationName, String resourceIdentifier )
144         throws RbacManagerException
145     {
146         return this.rbacImpl.createPermission( name, operationName, resourceIdentifier );
147     }
148
149     public Resource createResource( String identifier )
150         throws RbacManagerException
151     {
152         return this.rbacImpl.createResource( identifier );
153     }
154
155     public Role createRole( String name )
156     {
157         return this.rbacImpl.createRole( name );
158     }
159
160     public UserAssignment createUserAssignment( String username )
161         throws RbacManagerException
162     {
163         // TODO ldap cannot or isWritable ldap ?
164         return this.rbacImpl.createUserAssignment( username );
165     }
166
167     public void eraseDatabase()
168     {
169         if ( writableLdap )
170         {
171             LdapConnection ldapConnection = null;
172             DirContext context = null;
173             try
174             {
175                 ldapConnection = ldapConnectionFactory.getConnection();
176                 context = ldapConnection.getDirContext();
177                 ldapRoleMapper.removeAllRoles( context );
178             }
179             catch ( MappingException e )
180             {
181                 log.warn( "skip error removing all roles {}", e.getMessage() );
182             }
183             catch ( LdapException e )
184             {
185                 log.warn( "skip error removing all roles {}", e.getMessage() );
186             }
187             finally
188             {
189                 closeContext( context );
190                 closeLdapConnection( ldapConnection );
191             }
192         }
193         this.rbacImpl.eraseDatabase();
194     }
195
196     /**
197      * @see org.apache.archiva.redback.rbac.RBACManager#getAllAssignableRoles()
198      */
199     public List<Role> getAllAssignableRoles()
200         throws RbacManagerException
201     {
202         try
203         {
204             Collection<Collection<String>> roleNames = ldapRoleMapper.getLdapGroupMappings().values();
205
206             Set<Role> roles = new HashSet<Role>();
207
208             for ( Collection<String> names : roleNames )
209             {
210                 for ( String name : names )
211                 {
212                     roles.add( new RoleImpl( name ) );
213                 }
214             }
215
216             return new ArrayList<Role>( roles );
217         }
218         catch ( MappingException e )
219         {
220             throw new RbacManagerException( e.getMessage(), e );
221         }
222     }
223
224     public List<Operation> getAllOperations()
225         throws RbacManagerException
226     {
227         return this.rbacImpl.getAllOperations();
228     }
229
230     public List<Permission> getAllPermissions()
231         throws RbacManagerException
232     {
233         return this.rbacImpl.getAllPermissions();
234     }
235
236     public List<Resource> getAllResources()
237         throws RbacManagerException
238     {
239         return this.rbacImpl.getAllResources();
240     }
241
242     public List<Role> getAllRoles()
243         throws RbacManagerException
244     {
245         LdapConnection ldapConnection = null;
246         DirContext context = null;
247         try
248         {
249             ldapConnection = ldapConnectionFactory.getConnection();
250             context = ldapConnection.getDirContext();
251
252             List<String> groups = ldapRoleMapper.getAllGroups( context );
253             return mapToRoles( groups );
254         }
255         catch ( MappingException e )
256         {
257             throw new RbacManagerException( e.getMessage(), e );
258         }
259         catch ( LdapException e )
260         {
261             throw new RbacManagerException( e.getMessage(), e );
262         }
263         finally
264         {
265             closeContext( context );
266             closeLdapConnection( ldapConnection );
267         }
268         //return this.rbacImpl.getAllRoles();
269     }
270
271
272     public List<UserAssignment> getAllUserAssignments()
273         throws RbacManagerException
274     {
275         LdapConnection ldapConnection = null;
276         DirContext context = null;
277         try
278         {
279             ldapConnection = ldapConnectionFactory.getConnection();
280             context = ldapConnection.getDirContext();
281             Map<String, Collection<String>> usersWithRoles = ldapController.findUsersWithRoles( context );
282             List<UserAssignment> userAssignments = new ArrayList<UserAssignment>( usersWithRoles.size() );
283
284             for ( Map.Entry<String, Collection<String>> entry : usersWithRoles.entrySet() )
285             {
286                 UserAssignment userAssignment = new UserAssignmentImpl( entry.getKey(), entry.getValue() );
287                 userAssignments.add( userAssignment );
288             }
289
290             return userAssignments;
291         }
292         catch ( LdapControllerException e )
293         {
294             throw new RbacManagerException( e.getMessage(), e );
295         }
296         catch ( LdapException e )
297         {
298             throw new RbacManagerException( e.getMessage(), e );
299         }
300         finally
301         {
302             closeContext( context );
303             closeLdapConnection( ldapConnection );
304         }
305     }
306
307     protected void closeLdapConnection( LdapConnection ldapConnection )
308     {
309         if ( ldapConnection != null )
310         {
311             ldapConnection.close();
312         }
313     }
314
315     protected void closeContext( DirContext context )
316     {
317         if ( context != null )
318         {
319             try
320             {
321                 context.close();
322             }
323             catch ( NamingException e )
324             {
325                 log.warn( "skip issue closing context: {}", e.getMessage() );
326             }
327         }
328     }
329
330     /**
331      * public Map<String, List<Permission>> getAssignedPermissionMap( String username )
332      * throws RbacManagerException
333      * {
334      * return this.rbacImpl.getAssignedPermissionMap( username );
335      * }*
336      */
337
338     /*public Set<Permission> getAssignedPermissions( String username )
339         throws RbacObjectNotFoundException, RbacManagerException
340     {
341         // TODO here !!
342         return this.rbacImpl.getAssignedPermissions( username );
343     }*/
344     private List<Role> mapToRoles( List<String> groups )
345         throws MappingException, RbacManagerException
346     {
347         if ( groups == null || groups.isEmpty() )
348         {
349             return Collections.emptyList();
350         }
351
352         List<Role> roles = new ArrayList<Role>( groups.size() );
353         Map<String, Collection<String>> mappedGroups = ldapRoleMapper.getLdapGroupMappings();
354         for ( String group : groups )
355         {
356             Collection<String> roleNames = mappedGroups.get( group );
357             if ( roleNames != null )
358             {
359                 for ( String roleName : roleNames )
360                 {
361                     Role role = getRole( roleName );
362                     if ( role != null )
363                     {
364                         roles.add( role );
365                     }
366                 }
367             }
368         }
369         return roles;
370
371     }
372
373     public Collection<Role> getAssignedRoles( String username )
374         throws RbacManagerException
375     {
376
377         LdapConnection ldapConnection = null;
378         DirContext context = null;
379
380         try
381         {
382
383             ldapConnection = ldapConnectionFactory.getConnection();
384             context = ldapConnection.getDirContext();
385             List<String> roleNames = ldapRoleMapper.getRoles( username, context );
386
387             if ( roleNames.isEmpty() )
388             {
389                 return Collections.emptyList();
390             }
391
392             List<Role> roles = new ArrayList<Role>( roleNames.size() );
393
394             for ( String name : roleNames )
395             {
396                 roles.add( this.rbacImpl.getRole( name ) );// new RoleImpl( name ) );
397             }
398
399             return roles;
400         }
401         catch ( MappingException e )
402         {
403             throw new RbacManagerException( e.getMessage(), e );
404         }
405         catch ( LdapException e )
406         {
407             throw new RbacManagerException( e.getMessage(), e );
408         }
409     }
410
411     public Collection<Role> getAssignedRoles( UserAssignment userAssignment )
412         throws RbacManagerException
413     {
414         return getAssignedRoles( userAssignment.getPrincipal() );
415     }
416
417     public Map<String, Role> getChildRoles( Role role )
418         throws RbacManagerException
419     {
420         return this.rbacImpl.getChildRoles( role );
421     }
422
423     public Map<String, Role> getParentRoles( Role role )
424         throws RbacManagerException
425     {
426         return this.rbacImpl.getParentRoles( role );
427     }
428
429     /**
430      public Collection<Role> getEffectivelyAssignedRoles( String username )
431      throws RbacManagerException
432      {
433      // TODO here !!
434      return this.rbacImpl.getEffectivelyAssignedRoles( username );
435      }**/
436
437     /**
438      * public Collection<Role> getEffectivelyUnassignedRoles( String username )
439      * throws RbacManagerException
440      * {
441      * // TODO here !!
442      * return this.rbacImpl.getEffectivelyUnassignedRoles( username );
443      * }*
444      */
445
446     public Set<Role> getEffectiveRoles( Role role )
447         throws RbacManagerException
448     {
449         return this.rbacImpl.getEffectiveRoles( role );
450     }
451
452     public Resource getGlobalResource()
453         throws RbacManagerException
454     {
455         return this.rbacImpl.getGlobalResource();
456     }
457
458     public Operation getOperation( String operationName )
459         throws RbacManagerException
460     {
461         return this.rbacImpl.getOperation( operationName );
462     }
463
464     public Permission getPermission( String permissionName )
465         throws RbacManagerException
466     {
467         return this.rbacImpl.getPermission( permissionName );
468     }
469
470     public Resource getResource( String resourceIdentifier )
471         throws RbacManagerException
472     {
473         return this.rbacImpl.getResource( resourceIdentifier );
474     }
475
476     public Role getRole( String roleName )
477         throws RbacManagerException
478     {
479
480         Role role = rolesCache.get( roleName );
481         if ( role != null )
482         {
483             return role;
484         }
485         LdapConnection ldapConnection = null;
486         DirContext context = null;
487         //verify it's a ldap group
488         try
489         {
490             ldapConnection = ldapConnectionFactory.getConnection();
491             context = ldapConnection.getDirContext();
492             if ( !ldapRoleMapper.hasRole( context, roleName ) )
493             {
494                 return null;
495             }
496         }
497         catch ( MappingException e )
498         {
499             throw new RbacManagerException( e.getMessage(), e );
500         }
501         catch ( LdapException e )
502         {
503             throw new RbacManagerException( e.getMessage(), e );
504         }
505         role = this.rbacImpl.getRole( roleName );
506         role = ( role == null ) ? new RoleImpl( roleName ) : role;
507
508         rolesCache.put( roleName, role );
509
510         return role;
511     }
512
513     public Map<String, Role> getRoles( Collection<String> roleNames )
514         throws RbacManagerException
515     {
516         return this.rbacImpl.getRoles( roleNames );
517     }
518
519     public Collection<Role> getUnassignedRoles( String username )
520         throws RbacManagerException
521     {
522         LdapConnection ldapConnection = null;
523
524         DirContext context = null;
525
526         try
527         {
528
529             ldapConnection = ldapConnectionFactory.getConnection();
530
531             context = ldapConnection.getDirContext();
532
533             List<String> allRoles = ldapRoleMapper.getAllRoles( context );
534             final List<String> userRoles = ldapRoleMapper.getRoles( username, context );
535
536             List<Role> unassignedRoles = new ArrayList<Role>();
537
538             for ( String roleName : allRoles )
539             {
540                 if ( !userRoles.contains( roleName ) )
541                 {
542                     unassignedRoles.add( rbacImpl.getRole( roleName ) );
543                 }
544             }
545             return unassignedRoles;
546         }
547         catch ( MappingException e )
548         {
549             throw new RbacManagerException( e.getMessage(), e );
550         }
551         catch ( LdapException e )
552         {
553             throw new RbacManagerException( e.getMessage(), e );
554         }
555         finally
556         {
557             closeContext( context );
558             closeLdapConnection( ldapConnection );
559         }
560     }
561
562     public UserAssignment getUserAssignment( String username )
563         throws RbacManagerException
564     {
565         LdapConnection ldapConnection = null;
566         DirContext context = null;
567         try
568         {
569             ldapConnection = ldapConnectionFactory.getConnection();
570             context = ldapConnection.getDirContext();
571             List<String> roles = ldapRoleMapper.getRoles( username, context );
572
573             return new UserAssignmentImpl( username, roles );
574         }
575         catch ( MappingException e )
576         {
577             throw new RbacManagerException( e.getMessage(), e );
578         }
579         catch ( LdapException e )
580         {
581             throw new RbacManagerException( e.getMessage(), e );
582         }
583         finally
584         {
585             closeContext( context );
586             closeLdapConnection( ldapConnection );
587         }
588
589         //return this.rbacImpl.getUserAssignment( username );
590     }
591
592     public List<UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
593         throws RbacManagerException
594     {
595         // TODO from ldap
596         return this.rbacImpl.getUserAssignmentsForRoles( roleNames );
597     }
598
599     public boolean operationExists( Operation operation )
600     {
601         return this.rbacImpl.operationExists( operation );
602     }
603
604     public boolean operationExists( String name )
605     {
606         return this.rbacImpl.operationExists( name );
607     }
608
609     public boolean permissionExists( Permission permission )
610     {
611         return this.rbacImpl.permissionExists( permission );
612     }
613
614     public boolean permissionExists( String name )
615     {
616         return this.rbacImpl.permissionExists( name );
617     }
618
619     public void rbacInit( boolean freshdb )
620     {
621         if ( rbacImpl instanceof RBACManagerListener )
622         {
623             ( (RBACManagerListener) this.rbacImpl ).rbacInit( freshdb );
624         }
625     }
626
627     public void rbacPermissionRemoved( Permission permission )
628     {
629         if ( rbacImpl instanceof RBACManagerListener )
630         {
631             ( (RBACManagerListener) this.rbacImpl ).rbacPermissionRemoved( permission );
632         }
633
634     }
635
636     public void rbacPermissionSaved( Permission permission )
637     {
638         if ( rbacImpl instanceof RBACManagerListener )
639         {
640             ( (RBACManagerListener) this.rbacImpl ).rbacPermissionSaved( permission );
641         }
642
643     }
644
645     public void rbacRoleRemoved( Role role )
646     {
647         if ( rbacImpl instanceof RBACManagerListener )
648         {
649             ( (RBACManagerListener) this.rbacImpl ).rbacRoleRemoved( role );
650         }
651
652     }
653
654     public void rbacRoleSaved( Role role )
655     {
656         if ( rbacImpl instanceof RBACManagerListener )
657         {
658             ( (RBACManagerListener) this.rbacImpl ).rbacRoleSaved( role );
659         }
660
661     }
662
663     public void rbacUserAssignmentRemoved( UserAssignment userAssignment )
664     {
665         if ( rbacImpl instanceof RBACManagerListener )
666         {
667             ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentRemoved( userAssignment );
668         }
669
670     }
671
672     public void rbacUserAssignmentSaved( UserAssignment userAssignment )
673     {
674         if ( rbacImpl instanceof RBACManagerListener )
675         {
676             ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentSaved( userAssignment );
677         }
678
679     }
680
681     public void removeListener( RBACManagerListener listener )
682     {
683         this.rbacImpl.removeListener( listener );
684     }
685
686     public void removeOperation( Operation operation )
687         throws RbacManagerException
688     {
689         this.rbacImpl.removeOperation( operation );
690     }
691
692     public void removeOperation( String operationName )
693         throws RbacManagerException
694     {
695         this.rbacImpl.removeOperation( operationName );
696     }
697
698     public void removePermission( Permission permission )
699         throws RbacManagerException
700     {
701         this.rbacImpl.removePermission( permission );
702     }
703
704     public void removePermission( String permissionName )
705         throws RbacManagerException
706     {
707         this.rbacImpl.removePermission( permissionName );
708     }
709
710     public void removeResource( Resource resource )
711         throws RbacManagerException
712     {
713         this.rbacImpl.removeResource( resource );
714     }
715
716     public void removeResource( String resourceIdentifier )
717         throws RbacManagerException
718     {
719         this.rbacImpl.removeResource( resourceIdentifier );
720     }
721
722     public void removeRole( Role role )
723         throws RbacManagerException
724     {
725         RBACObjectAssertions.assertValid( role );
726
727         if ( role.isPermanent() )
728         {
729             throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
730         }
731         rolesCache.remove( role.getName() );
732         if ( writableLdap )
733         {
734             LdapConnection ldapConnection = null;
735             DirContext context = null;
736             try
737             {
738                 ldapConnection = ldapConnectionFactory.getConnection();
739                 context = ldapConnection.getDirContext();
740                 ldapRoleMapper.removeRole( role.getName(), context );
741             }
742             catch ( MappingException e )
743             {
744                 throw new RbacManagerException( e.getMessage(), e );
745             }
746             catch ( LdapException e )
747             {
748                 throw new RbacManagerException( e.getMessage(), e );
749             }
750             fireRbacRoleRemoved( role );
751         }
752     }
753
754     public void removeRole( String roleName )
755         throws RbacManagerException
756     {
757         if ( roleName == null )
758         {
759             return;
760         }
761         removeRole( new RoleImpl( roleName ) );
762     }
763
764     public void removeUserAssignment( String username )
765         throws RbacManagerException
766     {
767         // TODO ldap cannot or isWritable ldap ?
768         this.rbacImpl.removeUserAssignment( username );
769     }
770
771     public void removeUserAssignment( UserAssignment userAssignment )
772         throws RbacManagerException
773     {
774         // TODO ldap cannot or isWritable ldap ?
775         this.rbacImpl.removeUserAssignment( userAssignment );
776     }
777
778     public boolean resourceExists( Resource resource )
779     {
780         return this.rbacImpl.resourceExists( resource );
781     }
782
783     public boolean resourceExists( String identifier )
784     {
785         return this.rbacImpl.resourceExists( identifier );
786     }
787
788     @Override
789     public boolean roleExists( Role role )
790         throws RbacManagerException
791     {
792         if ( role == null )
793         {
794             return false;
795         }
796         return roleExists( role.getName() );
797     }
798
799     @Override
800     public boolean roleExists( String name )
801         throws RbacManagerException
802     {
803         if ( StringUtils.isEmpty( name ) )
804         {
805             return false;
806         }
807         if ( rolesCache.get( name ) != null )
808         {
809             return true;
810         }
811         LdapConnection ldapConnection = null;
812         DirContext context = null;
813         try
814         {
815             ldapConnection = ldapConnectionFactory.getConnection();
816             context = ldapConnection.getDirContext();
817             if ( rolesCache.hasKey( name ) )
818             {
819                 return true;
820             }
821             return ldapRoleMapper.hasRole( context, name );
822         }
823         catch ( MappingException e )
824         {
825             throw new RbacManagerException( e.getMessage(), e );
826         }
827         catch ( LdapException e )
828         {
829             throw new RbacManagerException( e.getMessage(), e );
830         }
831         finally
832         {
833             closeContext( context );
834             closeLdapConnection( ldapConnection );
835         }
836     }
837
838     public Operation saveOperation( Operation operation )
839         throws RbacManagerException
840     {
841         return this.rbacImpl.saveOperation( operation );
842     }
843
844     public Permission savePermission( Permission permission )
845         throws RbacManagerException
846     {
847         return this.rbacImpl.savePermission( permission );
848     }
849
850     public Resource saveResource( Resource resource )
851         throws RbacManagerException
852     {
853         return this.rbacImpl.saveResource( resource );
854     }
855
856     public synchronized Role saveRole( Role role )
857         throws RbacManagerException
858     {
859         if ( writableLdap )
860         {
861             LdapConnection ldapConnection = null;
862             DirContext context = null;
863             try
864             {
865                 ldapConnection = ldapConnectionFactory.getConnection();
866                 context = ldapConnection.getDirContext();
867                 ldapRoleMapper.saveRole( role.getName(), context );
868
869                 if ( !role.getChildRoleNames().isEmpty() )
870                 {
871                     for ( String roleName : role.getChildRoleNames() )
872                     {
873                         ldapRoleMapper.saveRole( roleName, context );
874                     }
875                 }
876                 fireRbacRoleSaved( role );
877             }
878             catch ( MappingException e )
879             {
880                 throw new RbacManagerException( e.getMessage(), e );
881             }
882             catch ( LdapException e )
883             {
884                 throw new RbacManagerException( e.getMessage(), e );
885             }
886         }
887         role = this.rbacImpl.saveRole( role );
888         rolesCache.put( role.getName(), role );
889
890         return role;
891         //return new RoleImpl( role.getName(), role.getPermissions() );
892     }
893
894     public synchronized void saveRoles( Collection<Role> roles )
895         throws RbacManagerException
896     {
897         if ( writableLdap )
898         {
899             LdapConnection ldapConnection = null;
900             DirContext context = null;
901             try
902             {
903
904                 ldapConnection = ldapConnectionFactory.getConnection();
905                 context = ldapConnection.getDirContext();
906                 for ( Role role : roles )
907                 {
908                     ldapRoleMapper.saveRole( role.getName(), context );
909                     fireRbacRoleSaved( role );
910                 }
911             }
912             catch ( MappingException e )
913             {
914                 throw new RbacManagerException( e.getMessage(), e );
915             }
916             catch ( LdapException e )
917             {
918                 throw new RbacManagerException( e.getMessage(), e );
919             }
920         }
921         this.rbacImpl.saveRoles( roles );
922
923     }
924
925     public UserAssignment saveUserAssignment( UserAssignment userAssignment )
926         throws RbacManagerException
927     {
928         LdapConnection ldapConnection = null;
929         DirContext context = null;
930         try
931         {
932             if ( !userManager.userExists( userAssignment.getPrincipal() ) )
933             {
934                 User user = userManager.createUser( userAssignment.getPrincipal(), null, null );
935                 userManager.addUser( user );
936             }
937             ldapConnection = ldapConnectionFactory.getConnection();
938             context = ldapConnection.getDirContext();
939             List<String> allRoles = ldapRoleMapper.getAllRoles( context );
940
941             List<String> currentUserRoles = ldapRoleMapper.getRoles( userAssignment.getPrincipal(), context );
942
943             for ( String role : userAssignment.getRoleNames() )
944             {
945                 if ( !currentUserRoles.contains( role ) && writableLdap )
946                 {
947                     // role exists in ldap ?
948                     if ( !allRoles.contains( role ) )
949                     {
950                         ldapRoleMapper.saveRole( role, context );
951                         allRoles.add( role );
952                     }
953                     ldapRoleMapper.saveUserRole( role, userAssignment.getPrincipal(), context );
954                     currentUserRoles.add( role );
955                 }
956             }
957
958             for ( String role : currentUserRoles )
959             {
960                 if ( !userAssignment.getRoleNames().contains( role ) && writableLdap )
961                 {
962                     ldapRoleMapper.removeUserRole( role, userAssignment.getPrincipal(), context );
963                 }
964             }
965
966             return userAssignment;
967         }
968         catch ( UserManagerException e )
969         {
970             throw new RbacManagerException( e.getMessage(), e );
971         }
972         catch ( MappingException e )
973         {
974             throw new RbacManagerException( e.getMessage(), e );
975         }
976         catch ( LdapException e )
977         {
978             throw new RbacManagerException( e.getMessage(), e );
979         }
980         finally
981         {
982             closeContext( context );
983             closeLdapConnection( ldapConnection );
984         }
985     }
986
987     public boolean userAssignmentExists( String principal )
988     {
989         LdapConnection ldapConnection = null;
990         DirContext context = null;
991         try
992         {
993             ldapConnection = ldapConnectionFactory.getConnection();
994             context = ldapConnection.getDirContext();
995             List<String> roles = ldapRoleMapper.getRoles( principal, context );
996             if ( roles == null || roles.isEmpty() )
997             {
998                 return false;
999             }
1000             return true;
1001         }
1002         catch ( LdapException e )
1003         {
1004             log.warn( "fail to call userAssignmentExists: {}", e.getMessage() );
1005         }
1006         catch ( MappingException e )
1007         {
1008             log.warn( "fail to call userAssignmentExists: {}", e.getMessage() );
1009         }
1010         finally
1011         {
1012             closeContext( context );
1013             closeLdapConnection( ldapConnection );
1014         }
1015         return false;
1016     }
1017
1018     public boolean userAssignmentExists( UserAssignment assignment )
1019     {
1020         if ( assignment == null )
1021         {
1022             return false;
1023         }
1024         return this.userAssignmentExists( assignment.getPrincipal() );
1025     }
1026
1027     public RBACManager getRbacImpl()
1028     {
1029         return rbacImpl;
1030     }
1031
1032     public void setRbacImpl( RBACManager rbacImpl )
1033     {
1034         this.rbacImpl = rbacImpl;
1035     }
1036
1037     public boolean isWritableLdap()
1038     {
1039         return writableLdap;
1040     }
1041
1042     public void setWritableLdap( boolean writableLdap )
1043     {
1044         this.writableLdap = writableLdap;
1045     }
1046
1047     public LdapRoleMapper getLdapRoleMapper()
1048     {
1049         return ldapRoleMapper;
1050     }
1051
1052     public void setLdapRoleMapper( LdapRoleMapper ldapRoleMapper )
1053     {
1054         this.ldapRoleMapper = ldapRoleMapper;
1055     }
1056
1057     private static class RoleImpl
1058         extends AbstractRole
1059     {
1060         private String name;
1061
1062         private String description;
1063
1064         private List<Permission> permissions = new ArrayList<Permission>();
1065
1066         private List<String> childRoleNames = new ArrayList<String>();
1067
1068         private RoleImpl( String name )
1069         {
1070             this.name = name;
1071         }
1072
1073         private RoleImpl( String name, List<Permission> permissions )
1074         {
1075             this.name = name;
1076             this.permissions = permissions;
1077         }
1078
1079         public void addPermission( Permission permission )
1080         {
1081             this.permissions.add( permission );
1082         }
1083
1084         public void addChildRoleName( String name )
1085         {
1086             this.childRoleNames.add( name );
1087         }
1088
1089         public List<String> getChildRoleNames()
1090         {
1091             return this.childRoleNames;
1092         }
1093
1094         public String getDescription()
1095         {
1096             return this.description;
1097         }
1098
1099         public String getName()
1100         {
1101             return this.name;
1102         }
1103
1104         public List<Permission> getPermissions()
1105         {
1106             return this.permissions;
1107         }
1108
1109         public boolean isAssignable()
1110         {
1111             return true;
1112         }
1113
1114         public void removePermission( Permission permission )
1115         {
1116             this.permissions.remove( permission );
1117         }
1118
1119         public void setAssignable( boolean assignable )
1120         {
1121             // no op
1122         }
1123
1124         public void setChildRoleNames( List<String> names )
1125         {
1126             this.childRoleNames = names;
1127         }
1128
1129         public void setDescription( String description )
1130         {
1131             this.description = description;
1132         }
1133
1134         public void setName( String name )
1135         {
1136             this.name = name;
1137         }
1138
1139         public void setPermissions( List<Permission> permissions )
1140         {
1141             this.permissions = permissions;
1142         }
1143
1144         public boolean isPermanent()
1145         {
1146             return true;
1147         }
1148
1149         public void setPermanent( boolean permanent )
1150         {
1151             // no op
1152         }
1153
1154         @Override
1155         public String toString()
1156         {
1157             final StringBuilder sb = new StringBuilder();
1158             sb.append( "RoleImpl" );
1159             sb.append( "{name='" ).append( name ).append( '\'' );
1160             sb.append( '}' );
1161             return sb.toString();
1162         }
1163
1164         @Override
1165         public boolean equals( Object o )
1166         {
1167             if ( this == o )
1168             {
1169                 return true;
1170             }
1171             if ( o == null || getClass() != o.getClass() )
1172             {
1173                 return false;
1174             }
1175
1176             RoleImpl role = (RoleImpl) o;
1177
1178             if ( name != null ? !name.equals( role.name ) : role.name != null )
1179             {
1180                 return false;
1181             }
1182
1183             return true;
1184         }
1185
1186         @Override
1187         public int hashCode()
1188         {
1189             return name != null ? name.hashCode() : 0;
1190         }
1191     }
1192
1193     private static class UserAssignmentImpl
1194         implements UserAssignment
1195     {
1196         private String username;
1197
1198         private List<String> roleNames;
1199
1200         private boolean permanent;
1201
1202         private UserAssignmentImpl( String username, Collection<String> roleNames )
1203         {
1204             this.username = username;
1205
1206             if ( roleNames == null )
1207             {
1208                 this.roleNames = new ArrayList<String>();
1209             }
1210             else
1211             {
1212                 this.roleNames = new ArrayList<String>( roleNames );
1213             }
1214         }
1215
1216         public String getPrincipal()
1217         {
1218             return this.username;
1219         }
1220
1221         public List<String> getRoleNames()
1222         {
1223             return this.roleNames;
1224         }
1225
1226         public void addRoleName( Role role )
1227         {
1228             if ( role == null )
1229             {
1230                 return;
1231             }
1232             this.roleNames.add( role.getName() );
1233         }
1234
1235         public void addRoleName( String roleName )
1236         {
1237             if ( roleName == null )
1238             {
1239                 return;
1240             }
1241             this.roleNames.add( roleName );
1242         }
1243
1244         public void removeRoleName( Role role )
1245         {
1246             if ( role == null )
1247             {
1248                 return;
1249             }
1250             this.roleNames.remove( role.getName() );
1251         }
1252
1253         public void removeRoleName( String roleName )
1254         {
1255             if ( roleName == null )
1256             {
1257                 return;
1258             }
1259             this.roleNames.remove( roleName );
1260         }
1261
1262         public void setPrincipal( String principal )
1263         {
1264             this.username = principal;
1265         }
1266
1267         public void setRoleNames( List<String> roles )
1268         {
1269             this.roleNames = roles;
1270         }
1271
1272         public boolean isPermanent()
1273         {
1274             return this.permanent;
1275         }
1276
1277         public void setPermanent( boolean permanent )
1278         {
1279             this.permanent = permanent;
1280         }
1281
1282         @Override
1283         public String toString()
1284         {
1285             final StringBuilder sb = new StringBuilder();
1286             sb.append( "UserAssignmentImpl" );
1287             sb.append( "{username='" ).append( username ).append( '\'' );
1288             sb.append( ", roleNames=" ).append( roleNames );
1289             sb.append( ", permanent=" ).append( permanent );
1290             sb.append( '}' );
1291             return sb.toString();
1292         }
1293     }
1294 }