This project has retired. For details please refer to its Attic page.
LdapRbacManager xref
View Javadoc

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