001package org.apache.archiva.redback.rbac.cached;
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
022import org.apache.archiva.components.cache.Cache;
023import org.apache.archiva.redback.rbac.Operation;
024import org.apache.archiva.redback.rbac.Permission;
025import org.apache.archiva.redback.rbac.RBACManager;
026import org.apache.archiva.redback.rbac.RBACManagerListener;
027import org.apache.archiva.redback.rbac.RbacManagerException;
028import org.apache.archiva.redback.rbac.RbacObjectInvalidException;
029import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
030import org.apache.archiva.redback.rbac.Resource;
031import org.apache.archiva.redback.rbac.Role;
032import org.apache.archiva.redback.rbac.UserAssignment;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035import org.springframework.stereotype.Service;
036
037import javax.annotation.PreDestroy;
038import javax.inject.Inject;
039import javax.inject.Named;
040import java.util.Collection;
041import java.util.List;
042import java.util.Map;
043import java.util.Set;
044
045/**
046 * CachedRbacManager is a wrapped RBACManager with caching.
047 *
048 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
049 */
050@Service( "rbacManager#cached" )
051public class CachedRbacManager
052    implements RBACManager, RBACManagerListener
053{
054
055    private Logger log = LoggerFactory.getLogger( getClass() );
056
057    @Inject
058    @Named( value = "rbacManager#jpa" )
059    private RBACManager rbacImpl;
060
061    @Inject
062    @Named( value = "cache#operations" )
063    private Cache<String, Operation> operationsCache;
064
065    @Inject
066    @Named( value = "cache#permissions" )
067    private Cache<String, Permission> permissionsCache;
068
069    @Inject
070    @Named( value = "cache#resources" )
071    private Cache<String, Resource> resourcesCache;
072
073    @Inject
074    @Named( value = "cache#roles" )
075    private Cache<String, Role> rolesCache;
076
077    @Inject
078    @Named( value = "cache#rolesById" )
079    private Cache<String, Role> rolesByIdCache;
080
081    @Inject
082    @Named( value = "cache#userAssignments" )
083    private Cache<String, UserAssignment> userAssignmentsCache;
084
085    @Inject
086    @Named( value = "cache#userPermissions" )
087    private Cache<String, Map<String, List<? extends Permission>>> userPermissionsCache;
088
089    @Inject
090    @Named( value = "cache#effectiveRoleSet" )
091    private Cache<String, Set<? extends Role>> effectiveRoleSetCache;
092
093    @Override
094    public void initialize()
095    {
096        // no op
097    }
098
099    @Override
100    public void addChildRole( Role role, Role childRole )
101        throws RbacObjectInvalidException, RbacManagerException
102    {
103        try
104        {
105            this.rbacImpl.addChildRole( role, childRole );
106        }
107        finally
108        {
109            invalidateCachedRole( role );
110            invalidateCachedRole( childRole );
111        }
112    }
113
114    @Override
115    public void addListener( RBACManagerListener listener )
116    {
117        this.rbacImpl.addListener( listener );
118    }
119
120    @Override
121    public Operation createOperation( String name )
122        throws RbacManagerException
123    {
124        operationsCache.remove( name );
125        return this.rbacImpl.createOperation( name );
126    }
127
128    @Override
129    public Permission createPermission( String name )
130        throws RbacManagerException
131    {
132        permissionsCache.remove( name );
133        return this.rbacImpl.createPermission( name );
134    }
135
136    @Override
137    public Permission createPermission( String name, String operationName, String resourceIdentifier )
138        throws RbacManagerException
139    {
140        permissionsCache.remove( name );
141        return this.rbacImpl.createPermission( name, operationName, resourceIdentifier );
142    }
143
144    @Override
145    public Resource createResource( String identifier )
146        throws RbacManagerException
147    {
148        resourcesCache.remove( identifier );
149        return this.rbacImpl.createResource( identifier );
150    }
151
152    @Override
153    public Role createRole( String name )
154    {
155        if (rolesCache.hasKey( name ))
156        {
157            Role role = rolesCache.remove( name );
158            rolesByIdCache.remove( role.getId( ) );
159        }
160        return this.rbacImpl.createRole( name );
161    }
162
163    @Override
164    public Role createRole( String id, String name )
165    {
166        if (rolesByIdCache.hasKey( id ))
167        {
168            Role role = rolesByIdCache.remove( id );
169            rolesCache.remove( role.getName( ) );
170        }
171        return this.rbacImpl.createRole( id, name );
172    }
173
174    @Override
175    public UserAssignment createUserAssignment( String principal )
176        throws RbacManagerException
177    {
178        invalidateCachedUserAssignment( principal );
179        return this.rbacImpl.createUserAssignment( principal );
180    }
181
182    @Override
183    public void eraseDatabase()
184    {
185        try
186        {
187            this.rbacImpl.eraseDatabase();
188        }
189        finally
190        {
191            clearCache();
192        }
193    }
194
195    /**
196     * @see org.apache.archiva.redback.rbac.RBACManager#getAllAssignableRoles()
197     */
198    @Override
199    public List<? extends Role> getAllAssignableRoles()
200        throws RbacManagerException, RbacObjectNotFoundException
201    {
202        log.debug( "NOT CACHED - .getAllAssignableRoles()" );
203        return this.rbacImpl.getAllAssignableRoles();
204    }
205
206    @Override
207    public List<? extends Operation> getAllOperations()
208        throws RbacManagerException
209    {
210        log.debug( "NOT CACHED - .getAllOperations()" );
211        return this.rbacImpl.getAllOperations();
212    }
213
214    @Override
215    public List<? extends Permission> getAllPermissions()
216        throws RbacManagerException
217    {
218        log.debug( "NOT CACHED - .getAllPermissions()" );
219        return this.rbacImpl.getAllPermissions();
220    }
221
222    @Override
223    public List<? extends Resource> getAllResources()
224        throws RbacManagerException
225    {
226        log.debug( "NOT CACHED - .getAllResources()" );
227        return this.rbacImpl.getAllResources();
228    }
229
230    @Override
231    public List<? extends Role> getAllRoles()
232        throws RbacManagerException
233    {
234        log.debug( "NOT CACHED - .getAllRoles()" );
235        return this.rbacImpl.getAllRoles();
236    }
237
238    @Override
239    public List<? extends UserAssignment> getAllUserAssignments()
240        throws RbacManagerException
241    {
242        log.debug( "NOT CACHED - .getAllUserAssignments()" );
243        return this.rbacImpl.getAllUserAssignments();
244    }
245
246    /**
247     * @see org.apache.archiva.redback.rbac.RBACManager#getAssignedPermissionMap(java.lang.String)
248     */
249    @Override
250    @SuppressWarnings( "unchecked" )
251    public Map<String, List<? extends Permission>> getAssignedPermissionMap( String principal )
252        throws RbacObjectNotFoundException, RbacManagerException
253    {
254        Map<String, List<? extends Permission>> el = userPermissionsCache.get( principal );
255
256        if ( el != null )
257        {
258            log.debug( "using cached user permission map" );
259            return el;
260        }
261
262        log.debug( "building user permission map" );
263        Map<String, List<? extends Permission>> userPermMap = this.rbacImpl.getAssignedPermissionMap( principal );
264        userPermissionsCache.put( principal, userPermMap );
265        return userPermMap;
266
267    }
268
269    @Override
270    public Set<? extends Permission> getAssignedPermissions( String principal )
271        throws RbacObjectNotFoundException, RbacManagerException
272    {
273        log.debug( "NOT CACHED - .getAssignedPermissions(String)" );
274        return this.rbacImpl.getAssignedPermissions( principal );
275    }
276
277    @Override
278    public Collection<? extends Role> getAssignedRoles( String principal )
279        throws RbacObjectNotFoundException, RbacManagerException
280    {
281        log.debug( "NOT CACHED - .getAssignedRoles(String)" );
282        return this.rbacImpl.getAssignedRoles( principal );
283    }
284
285    @Override
286    public Collection<? extends Role> getAssignedRoles( UserAssignment userAssignment )
287        throws RbacObjectNotFoundException, RbacManagerException
288    {
289        log.debug( "NOT CACHED - .getAssignedRoles(UserAssignment)" );
290        return this.rbacImpl.getAssignedRoles( userAssignment );
291    }
292
293    @Override
294    public Map<String, ? extends Role> getChildRoleNames( Role role )
295        throws RbacManagerException
296    {
297        log.debug( "NOT CACHED - .getChildRoles(Role)" );
298        return this.rbacImpl.getChildRoleNames( role );
299    }
300
301    @Override
302    public Map<String, ? extends Role> getChildRoleIds( Role role ) throws RbacManagerException
303    {
304        log.debug( "NOT CACHED - .getChildRoles(Role)" );
305        return this.rbacImpl.getChildRoleIds( role );
306    }
307
308    @Override
309    public Map<String, ? extends Role> getParentRoleNames( Role role )
310        throws RbacManagerException
311    {
312        log.debug( "NOT CACHED - .getParentRoles(Role)" );
313        return this.rbacImpl.getParentRoleNames( role );
314    }
315
316    @Override
317    public Map<String, ? extends Role> getParentRoleIds( Role role ) throws RbacManagerException
318    {
319        log.debug( "NOT CACHED - .getParentRoles(Role)" );
320        return this.rbacImpl.getParentRoleIds( role );
321    }
322
323    @Override
324    public Collection<? extends Role> getEffectivelyAssignedRoles( String principal )
325        throws RbacObjectNotFoundException, RbacManagerException
326    {
327        log.debug( "NOT CACHED - .getEffectivelyAssignedRoles(String)" );
328        return this.rbacImpl.getEffectivelyAssignedRoles( principal );
329    }
330
331    @Override
332    public Collection<? extends Role> getEffectivelyUnassignedRoles( String principal )
333        throws RbacManagerException, RbacObjectNotFoundException
334    {
335        log.debug( "NOT CACHED - .getEffectivelyUnassignedRoles(String)" );
336        return this.rbacImpl.getEffectivelyUnassignedRoles( principal );
337    }
338
339    @Override
340    @SuppressWarnings( "unchecked" )
341    public Set<? extends Role> getEffectiveRoles( Role role )
342        throws RbacObjectNotFoundException, RbacManagerException
343    {
344        Set<? extends Role> el = effectiveRoleSetCache.get( role.getName() );
345
346        if ( el != null )
347        {
348            log.debug( "using cached effective role set" );
349            return el;
350        }
351        else
352        {
353            log.debug( "building effective role set" );
354            Set<? extends Role> effectiveRoleSet = this.rbacImpl.getEffectiveRoles( role );
355            effectiveRoleSetCache.put( role.getName(), effectiveRoleSet );
356            return effectiveRoleSet;
357        }
358    }
359
360    @Override
361    public Resource getGlobalResource()
362        throws RbacManagerException
363    {
364        /* this is very light */
365        log.debug( "NOT CACHED - .getGlobalResource()" );
366        return this.rbacImpl.getGlobalResource();
367    }
368
369    @Override
370    public Operation getOperation( String operationName )
371        throws RbacObjectNotFoundException, RbacManagerException
372    {
373        Operation el = operationsCache.get( operationName );
374        if ( el != null )
375        {
376            return el;
377        }
378        else
379        {
380            Operation operation = this.rbacImpl.getOperation( operationName );
381            operationsCache.put( operationName, operation );
382            return operation;
383        }
384    }
385
386    @Override
387    public Permission getPermission( String permissionName )
388        throws RbacObjectNotFoundException, RbacManagerException
389    {
390        Permission el = permissionsCache.get( permissionName );
391        if ( el != null )
392        {
393            return el;
394        }
395        else
396        {
397            Permission permission = this.rbacImpl.getPermission( permissionName );
398            permissionsCache.put( permissionName, permission );
399            return permission;
400        }
401    }
402
403    @Override
404    public Resource getResource( String resourceIdentifier )
405        throws RbacObjectNotFoundException, RbacManagerException
406    {
407        Resource el = resourcesCache.get( resourceIdentifier );
408        if ( el != null )
409        {
410            return el;
411        }
412        else
413        {
414            Resource resource = this.rbacImpl.getResource( resourceIdentifier );
415            resourcesCache.put( resourceIdentifier, resource );
416            return resource;
417        }
418    }
419
420    @Override
421    public Role getRole( String roleName )
422        throws RbacObjectNotFoundException, RbacManagerException
423    {
424        Role el = rolesCache.get( roleName );
425        if ( el != null )
426        {
427            return el;
428        }
429        else
430        {
431            Role role = this.rbacImpl.getRole( roleName );
432            rolesCache.put( roleName, role );
433            rolesByIdCache.put( role.getId( ), role );
434            return role;
435        }
436    }
437
438    @Override
439    public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
440    {
441        if (rolesByIdCache.hasKey( id )) {
442            return rolesByIdCache.get( id );
443        } else {
444            return this.rbacImpl.getRoleById( id );
445        }
446    }
447
448    @Override
449    public Map<String, ? extends Role> getRoles( Collection<String> roleNames )
450        throws RbacObjectNotFoundException, RbacManagerException
451    {
452        log.debug( "NOT CACHED - .getRoles(Collection)" );
453        return this.rbacImpl.getRoles( roleNames );
454    }
455
456    @Override
457    public Collection<? extends Role> getUnassignedRoles( String principal )
458        throws RbacManagerException, RbacObjectNotFoundException
459    {
460        log.debug( "NOT CACHED - .getUnassignedRoles(String)" );
461        return this.rbacImpl.getUnassignedRoles( principal );
462    }
463
464    @Override
465    public UserAssignment getUserAssignment( String principal )
466        throws RbacObjectNotFoundException, RbacManagerException
467    {
468        UserAssignment el = userAssignmentsCache.get( principal );
469        if ( el != null )
470        {
471            return el;
472        }
473        else
474        {
475            UserAssignment userAssignment = this.rbacImpl.getUserAssignment( principal );
476            userAssignmentsCache.put( principal, userAssignment );
477            return userAssignment;
478        }
479    }
480
481    @Override
482    public List<? extends UserAssignment> getUserAssignmentsForRoles( Collection<String> roleIds )
483        throws RbacManagerException
484    {
485        log.debug( "NOT CACHED - .getUserAssignmentsForRoles(Collection)" );
486        return this.rbacImpl.getUserAssignmentsForRoles( roleIds );
487    }
488
489    @Override
490    public boolean operationExists( Operation operation )
491    {
492        if ( operation == null )
493        {
494            return false;
495        }
496
497        if ( operationsCache.hasKey( operation.getName() ) )
498        {
499            return true;
500        }
501
502        return this.rbacImpl.operationExists( operation );
503    }
504
505    @Override
506    public boolean operationExists( String name )
507    {
508        if ( operationsCache.hasKey( name ) )
509        {
510            return true;
511        }
512
513        return this.rbacImpl.operationExists( name );
514    }
515
516    @Override
517    public boolean permissionExists( Permission permission )
518    {
519        if ( permission == null )
520        {
521            return false;
522        }
523
524        if ( permissionsCache.hasKey( permission.getName() ) )
525        {
526            return true;
527        }
528
529        return this.rbacImpl.permissionExists( permission );
530    }
531
532    @Override
533    public boolean permissionExists( String name )
534    {
535        if ( permissionsCache.hasKey( name ) )
536        {
537            return true;
538        }
539
540        return this.rbacImpl.permissionExists( name );
541    }
542
543    @Override
544    public void rbacInit( boolean freshdb )
545    {
546        if ( rbacImpl instanceof RBACManagerListener )
547        {
548            ( (RBACManagerListener) this.rbacImpl ).rbacInit( freshdb );
549        }
550        // lookup all Cache and clear all ?
551        clearCache( );
552    }
553
554    public void clearCache( )
555    {
556        this.resourcesCache.clear();
557        this.operationsCache.clear();
558        this.permissionsCache.clear();
559        this.rolesCache.clear();
560        this.rolesByIdCache.clear();
561        this.userAssignmentsCache.clear();
562        this.userPermissionsCache.clear();
563    }
564
565    @Override
566    public void rbacPermissionRemoved( Permission permission )
567    {
568        if ( rbacImpl instanceof RBACManagerListener )
569        {
570            ( (RBACManagerListener) this.rbacImpl ).rbacPermissionRemoved( permission );
571        }
572
573        invalidateCachedPermission( permission );
574    }
575
576    @Override
577    public void rbacPermissionSaved( Permission permission )
578    {
579        if ( rbacImpl instanceof RBACManagerListener )
580        {
581            ( (RBACManagerListener) this.rbacImpl ).rbacPermissionSaved( permission );
582        }
583
584        invalidateCachedPermission( permission );
585    }
586
587    @Override
588    public void rbacRoleRemoved( Role role )
589    {
590        if ( rbacImpl instanceof RBACManagerListener )
591        {
592            ( (RBACManagerListener) this.rbacImpl ).rbacRoleRemoved( role );
593        }
594
595        invalidateCachedRole( role );
596    }
597
598    @Override
599    public void rbacRoleSaved( Role role )
600    {
601        if ( rbacImpl instanceof RBACManagerListener )
602        {
603            ( (RBACManagerListener) this.rbacImpl ).rbacRoleSaved( role );
604        }
605
606        invalidateCachedRole( role );
607    }
608
609    @Override
610    public void rbacUserAssignmentRemoved( UserAssignment userAssignment )
611    {
612        if ( rbacImpl instanceof RBACManagerListener )
613        {
614            ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentRemoved( userAssignment );
615        }
616
617        invalidateCachedUserAssignment( userAssignment );
618    }
619
620    @Override
621    public void rbacUserAssignmentSaved( UserAssignment userAssignment )
622    {
623        if ( rbacImpl instanceof RBACManagerListener )
624        {
625            ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentSaved( userAssignment );
626        }
627
628        invalidateCachedUserAssignment( userAssignment );
629    }
630
631    @Override
632    public void removeListener( RBACManagerListener listener )
633    {
634        this.rbacImpl.removeListener( listener );
635    }
636
637    @Override
638    public void removeOperation( Operation operation )
639        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
640    {
641        invalidateCachedOperation( operation );
642        this.rbacImpl.removeOperation( operation );
643    }
644
645    @Override
646    public void removeOperation( String operationName )
647        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
648    {
649        operationsCache.remove( operationName );
650        this.rbacImpl.removeOperation( operationName );
651    }
652
653    @Override
654    public void removePermission( Permission permission )
655        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
656    {
657        invalidateCachedPermission( permission );
658        this.rbacImpl.removePermission( permission );
659    }
660
661    @Override
662    public void removePermission( String permissionName )
663        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
664    {
665        permissionsCache.remove( permissionName );
666        this.rbacImpl.removePermission( permissionName );
667    }
668
669    @Override
670    public void removeResource( Resource resource )
671        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
672    {
673        invalidateCachedResource( resource );
674        this.rbacImpl.removeResource( resource );
675    }
676
677    @Override
678    public void removeResource( String resourceIdentifier )
679        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
680    {
681        resourcesCache.remove( resourceIdentifier );
682        this.rbacImpl.removeResource( resourceIdentifier );
683    }
684
685    @Override
686    public void removeRole( Role role )
687        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
688    {
689        invalidateCachedRole( role );
690        this.rbacImpl.removeRole( role );
691    }
692
693    @Override
694    public void removeRole( String roleName )
695        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
696    {
697        Role role = rolesCache.remove( roleName );
698        if (role!=null) {
699            rolesByIdCache.remove( role.getId( ) );
700        }
701        this.rbacImpl.removeRole( roleName );
702    }
703
704    @Override
705    public void removeRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
706    {
707        Role role = rolesByIdCache.remove( id );
708        if (role!=null) {
709            rolesCache.remove( role.getName( ) );
710        }
711        this.rbacImpl.removeRoleById( id );
712    }
713
714    @Override
715    public void removeUserAssignment( String principal )
716        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
717    {
718        invalidateCachedUserAssignment( principal );
719        this.rbacImpl.removeUserAssignment( principal );
720    }
721
722    @Override
723    public void removeUserAssignment( UserAssignment userAssignment )
724        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
725    {
726        invalidateCachedUserAssignment( userAssignment );
727        this.rbacImpl.removeUserAssignment( userAssignment );
728    }
729
730    @Override
731    public boolean resourceExists( Resource resource )
732    {
733        if ( resourcesCache.hasKey( resource.getIdentifier() ) )
734        {
735            return true;
736        }
737
738        return this.rbacImpl.resourceExists( resource );
739    }
740
741    @Override
742    public boolean resourceExists( String identifier )
743    {
744        if ( resourcesCache.hasKey( identifier ) )
745        {
746            return true;
747        }
748
749        return this.rbacImpl.resourceExists( identifier );
750    }
751
752    @Override
753    public boolean roleExists( Role role )
754        throws RbacManagerException
755    {
756        if ( rolesByIdCache.hasKey( role.getId() ) )
757        {
758            return true;
759        }
760
761        return this.rbacImpl.roleExists( role );
762    }
763
764    @Override
765    public boolean roleExists( String name )
766        throws RbacManagerException
767    {
768        if ( rolesCache.hasKey( name ) )
769        {
770            return true;
771        }
772
773        return this.rbacImpl.roleExists( name );
774    }
775
776    @Override
777    public boolean roleExistsById( String id ) throws RbacManagerException
778    {
779        if (rolesByIdCache.hasKey( id )) {
780            return true;
781        } else {
782            return this.rbacImpl.roleExistsById( id );
783        }
784    }
785
786    @Override
787    public Operation saveOperation( Operation operation )
788        throws RbacObjectInvalidException, RbacManagerException
789    {
790        invalidateCachedOperation( operation );
791        return this.rbacImpl.saveOperation( operation );
792    }
793
794    @Override
795    public Permission savePermission( Permission permission )
796        throws RbacObjectInvalidException, RbacManagerException
797    {
798        invalidateCachedPermission( permission );
799        return this.rbacImpl.savePermission( permission );
800    }
801
802    @Override
803    public Resource saveResource( Resource resource )
804        throws RbacObjectInvalidException, RbacManagerException
805    {
806        invalidateCachedResource( resource );
807        return this.rbacImpl.saveResource( resource );
808    }
809
810    @Override
811    public synchronized Role saveRole( Role role )
812        throws RbacObjectInvalidException, RbacManagerException
813    {
814        /*
815        List assignments = this.rbacImpl.getUserAssignmentsForRoles( Collections.singletonList( role.getName() ) );
816
817        for ( Iterator i = assignments.iterator(); i.hasNext();  )
818        {
819            log.debug( "invalidating user assignment with role " + role.getName() );
820            invalidateCachedUserAssignment( (UserAssignment)i.next() );
821        }
822        */
823
824        /*
825        the above commented out section would try and invalidate just that user caches that are effected by
826        changes in the users permissions map due to role changes.
827
828        however the implementations of those do not take into account child role hierarchies so wipe all
829        user caches on role saving...which is a heavy handed way to solve the problem, but not going to
830        happen frequently for current applications so not a huge deal.
831         */
832        invalidateAllCachedUserAssignments();
833        invalidateCachedRole( role );
834        return this.rbacImpl.saveRole( role );
835    }
836
837    @Override
838    public synchronized void saveRoles( Collection<Role> roles )
839        throws RbacObjectInvalidException, RbacManagerException
840    {
841
842        for ( Role role : roles )
843        {
844            invalidateCachedRole( role );
845        }
846
847        /*
848        List assignments = this.rbacImpl.getUserAssignmentsForRoles( roles );
849
850        for ( Iterator i = assignments.iterator(); i.hasNext();  )
851        {
852            log.debug( "invalidating user assignment with roles" );
853            invalidateCachedUserAssignment( (UserAssignment)i.next() );
854        }
855        */
856        invalidateAllCachedUserAssignments();
857        this.rbacImpl.saveRoles( roles );
858    }
859
860    @Override
861    public UserAssignment saveUserAssignment( UserAssignment userAssignment )
862        throws RbacObjectInvalidException, RbacManagerException
863    {
864        invalidateCachedUserAssignment( userAssignment );
865        return this.rbacImpl.saveUserAssignment( userAssignment );
866    }
867
868    @Override
869    public boolean userAssignmentExists( String principal )
870    {
871        if ( userAssignmentsCache.hasKey( principal ) )
872        {
873            return true;
874        }
875
876        return this.rbacImpl.userAssignmentExists( principal );
877    }
878
879    @Override
880    public boolean userAssignmentExists( UserAssignment assignment )
881    {
882        if ( userAssignmentsCache.hasKey( assignment.getPrincipal() ) )
883        {
884            return true;
885        }
886
887        return this.rbacImpl.userAssignmentExists( assignment );
888    }
889
890    private void invalidateCachedRole( Role role )
891    {
892        if ( role != null )
893        {
894            rolesCache.remove( role.getName() );
895            rolesByIdCache.remove( role.getId( ) );
896            // if a role changes we need to invalidate the entire effective role set cache
897            // since we have no concept of the heirarchy involved in the role sets
898            effectiveRoleSetCache.clear();
899        }
900
901    }
902
903    private void invalidateCachedOperation( Operation operation )
904    {
905        if ( operation != null )
906        {
907            operationsCache.remove( operation.getName() );
908        }
909    }
910
911    private void invalidateCachedPermission( Permission permission )
912    {
913        if ( permission != null )
914        {
915            permissionsCache.remove( permission.getName() );
916        }
917    }
918
919    private void invalidateCachedResource( Resource resource )
920    {
921        if ( resource != null )
922        {
923            resourcesCache.remove( resource.getIdentifier() );
924        }
925    }
926
927    private void invalidateCachedUserAssignment( UserAssignment userAssignment )
928    {
929        if ( userAssignment != null )
930        {
931            userAssignmentsCache.remove( userAssignment.getPrincipal() );
932            userPermissionsCache.remove( userAssignment.getPrincipal() );
933        }
934    }
935
936    private void invalidateCachedUserAssignment( String principal )
937    {
938        userAssignmentsCache.remove( principal );
939        userPermissionsCache.remove( principal );
940    }
941
942    private void invalidateAllCachedUserAssignments()
943    {
944        userAssignmentsCache.clear();
945        userPermissionsCache.clear();
946    }
947
948    public Cache<String, ? extends Operation> getOperationsCache()
949    {
950        return operationsCache;
951    }
952
953    @SuppressWarnings( "unchecked" )
954    public void setOperationsCache( Cache<String, ? extends Operation> operationsCache )
955    {
956        this.operationsCache = (Cache<String, Operation>) operationsCache;
957    }
958
959    public Cache<String, ? extends Permission> getPermissionsCache()
960    {
961        return permissionsCache;
962    }
963
964    @SuppressWarnings( "unchecked" )
965    public void setPermissionsCache( Cache<String, ? extends Permission> permissionsCache )
966    {
967        this.permissionsCache = (Cache<String, Permission>) permissionsCache;
968    }
969
970    public Cache<String, ? extends Resource> getResourcesCache()
971    {
972        return resourcesCache;
973    }
974
975    @SuppressWarnings( "unchecked" )
976    public void setResourcesCache( Cache<String, ? extends Resource> resourcesCache )
977    {
978        this.resourcesCache = (Cache<String, Resource>) resourcesCache;
979    }
980
981    public Cache<String, ? extends Role> getRolesCache()
982    {
983        return rolesCache;
984    }
985
986
987    @SuppressWarnings( "unchecked" )
988    public void setRolesCache( Cache<String, ? extends Role> rolesCache )
989    {
990        this.rolesCache = (Cache<String, Role>) rolesCache;
991    }
992
993    public Cache<String, ? extends Role> getRolesByIdCache( )
994    {
995        return rolesByIdCache;
996    }
997
998    public void setRolesByIdCache( Cache<String, ? extends Role> rolesByIdCache )
999    {
1000        this.rolesByIdCache = (Cache<String, Role>) rolesByIdCache;
1001    }
1002
1003    public Cache<String, ? extends UserAssignment> getUserAssignmentsCache()
1004    {
1005        return userAssignmentsCache;
1006    }
1007
1008    @SuppressWarnings( "unchecked" )
1009    public void setUserAssignmentsCache( Cache<String, ? extends UserAssignment> userAssignmentsCache )
1010    {
1011        this.userAssignmentsCache = (Cache<String, UserAssignment>) userAssignmentsCache;
1012    }
1013
1014    public Cache<String, Map<String, List<? extends Permission>>> getUserPermissionsCache()
1015    {
1016        return userPermissionsCache;
1017    }
1018
1019    public void setUserPermissionsCache( Cache<String, Map<String, List<? extends Permission>>> userPermissionsCache )
1020    {
1021        this.userPermissionsCache = userPermissionsCache;
1022    }
1023
1024    public Cache<String, Set<? extends Role>> getEffectiveRoleSetCache()
1025    {
1026        return effectiveRoleSetCache;
1027    }
1028
1029    public void setEffectiveRoleSetCache( Cache<String, Set<? extends Role>> effectiveRoleSetCache )
1030    {
1031        this.effectiveRoleSetCache = effectiveRoleSetCache;
1032    }
1033
1034    public RBACManager getRbacImpl()
1035    {
1036        return rbacImpl;
1037    }
1038
1039    public void setRbacImpl( RBACManager rbacImpl )
1040    {
1041        this.rbacImpl = rbacImpl;
1042    }
1043
1044
1045    @Override
1046    public boolean isFinalImplementation()
1047    {
1048        return false;
1049    }
1050
1051    @Override
1052    public String getDescriptionKey()
1053    {
1054        return "archiva.redback.rbacmanager.cached";
1055    }
1056
1057    @Override
1058    public boolean isReadOnly()
1059    {
1060        return false;
1061    }
1062
1063    @PreDestroy
1064    void shutdown() {
1065        clearCache( );
1066    }
1067}