Coverage Report - org.trails.security.DescriptorSecurity
 
Classes in this File Line Coverage Branch Coverage Complexity
DescriptorSecurity
79% 
73% 
0
 
 1  
 package org.trails.security;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.HashMap;
 5  
 import java.util.List;
 6  
 import java.util.Map;
 7  
 
 8  
 import org.acegisecurity.context.SecurityContext;
 9  
 import org.acegisecurity.context.SecurityContextHolder;
 10  
 import org.acegisecurity.ui.session.HttpSessionApplicationEvent;
 11  
 import org.acegisecurity.ui.session.HttpSessionCreatedEvent;
 12  
 import org.acegisecurity.ui.session.HttpSessionDestroyedEvent;
 13  
 import org.apache.commons.logging.Log;
 14  
 import org.apache.commons.logging.LogFactory;
 15  
 import org.aspectj.lang.ProceedingJoinPoint;
 16  
 import org.aspectj.lang.annotation.Around;
 17  
 import org.aspectj.lang.annotation.Aspect;
 18  
 import org.springframework.context.ApplicationEvent;
 19  
 import org.springframework.context.ApplicationListener;
 20  
 import org.trails.descriptor.IClassDescriptor;
 21  
 import org.trails.descriptor.TrailsClassDescriptor;
 22  
 
 23  
 @Aspect
 24  27
 public class DescriptorSecurity implements ApplicationListener
 25  
 {
 26  3
         private static final Log log = LogFactory.getLog(DescriptorSecurity.class);
 27  
         // Only used to log a warning each time an element is added to cache when no session events have been published
 28  3
         private static boolean sessionCreationDetected = false;
 29  
 
 30  
         private SecurityService securityService;
 31  27
         Map<String, Map<String,IClassDescriptor>> perUserClassDescriptorCache = new HashMap<String, Map<String,IClassDescriptor>>();
 32  
 
 33  
         @Around(
 34  
                 "execution(public org.trails.descriptor.IClassDescriptor org.trails.descriptor.DescriptorService+.getClassDescriptor(Class))")
 35  
         public Object classDescriptorSecurity(ProceedingJoinPoint pjp) throws Throwable
 36  
         {
 37  132
                 IClassDescriptor desc = (IClassDescriptor) pjp.proceed();
 38  132
                 if (desc != null) {
 39  132
                         SecurityContext context = SecurityContextHolder.getContext();
 40  132
                         if (context == null || context.getAuthentication() == null) return desc;
 41  15
                         return applyRestrictions(desc, context);
 42  
                 } 
 43  0
                 else return null;
 44  
         }
 45  
 
 46  
         @Around("execution(public java.util.List org.trails.descriptor.DescriptorService+.getAllDescriptors())")
 47  
         public Object getAllClassDescriptorSecurity(ProceedingJoinPoint pjp) throws Throwable
 48  
         {
 49  66
                 List<IClassDescriptor> descriptors = (List<IClassDescriptor>) pjp.proceed();
 50  66
                 if (descriptors == null) return null;
 51  
 
 52  66
                 SecurityContext context = SecurityContextHolder.getContext();
 53  66
                 if (context == null || context.getAuthentication() == null) return descriptors;
 54  
 
 55  21
                 List<IClassDescriptor> cloneDescriptors = new ArrayList<IClassDescriptor>(descriptors.size());
 56  21
                 for (IClassDescriptor descriptor : descriptors) cloneDescriptors.add(applyRestrictions(descriptor, context) );
 57  21
                 return cloneDescriptors;
 58  
         }
 59  
 
 60  
         protected IClassDescriptor applyRestrictions(IClassDescriptor descriptor, SecurityContext context)
 61  
         {
 62  
                 // Return a clone specific to this user rather than modify the shared original
 63  
                 // See if the class descriptor for this user is already cached, otherwise cache
 64  120
                 Map<String,IClassDescriptor> cachedDescriptors = perUserClassDescriptorCache.get(context.getAuthentication().getName());
 65  120
                 IClassDescriptor cloneDescriptor = null;
 66  120
                 if (cachedDescriptors != null) cloneDescriptor = cachedDescriptors.get(descriptor.getType().getSimpleName());
 67  
                 else {
 68  27
                         cachedDescriptors = new HashMap<String,IClassDescriptor>();
 69  27
                         perUserClassDescriptorCache.put(context.getAuthentication().getName(), cachedDescriptors);
 70  27
                         if (!sessionCreationDetected) log.warn("This implementation caches security-enhanced class descriptors for each user\n "
 71  
                                         + "but no session events are detected. Descriptors for expired sessions cannot be removed from the cache\n"
 72  
                                         + "Check that you have configured <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>?\n");
 73  
                 }
 74  
                 
 75  120
                 if (cloneDescriptor != null) return cloneDescriptor;
 76  
 
 77  87
                 cloneDescriptor = new TrailsClassDescriptor(descriptor);
 78  87
                 cachedDescriptors.put(descriptor.getType().getSimpleName(), cloneDescriptor);
 79  
                 
 80  87
                 List<SecurityRestriction> restrictions = securityService.findRestrictions(descriptor);
 81  87
                 if (restrictions != null)
 82  
                 {
 83  87
                         for (SecurityRestriction restriction : restrictions)
 84  
                         {
 85  123
                                 restriction.restrict(context.getAuthentication().getAuthorities(), cloneDescriptor);
 86  
                         }
 87  
                 }
 88  87
                 return cloneDescriptor;
 89  
         }
 90  
 
 91  
         public void setSecurityService(SecurityService securityService)
 92  
         {
 93  27
                 this.securityService = securityService;
 94  27
         }
 95  
 
 96  
         public void onApplicationEvent(ApplicationEvent event) {
 97  32
                 if (!(event instanceof HttpSessionApplicationEvent)) return;
 98  
                 
 99  0
                 if (event instanceof HttpSessionDestroyedEvent) {
 100  0
                         SecurityContext context = SecurityContextHolder.getContext();
 101  
                         // Do nothing if security context wasn't available
 102  0
                         if (context == null || context.getAuthentication() == null) return;
 103  0
                         Object object = perUserClassDescriptorCache.remove(context.getAuthentication().getName());
 104  0
                         if (object != null && log.isDebugEnabled()) log.debug("Removing cached descriptors for user " + context.getAuthentication().getName());
 105  0
                 }
 106  0
                 else if (event instanceof HttpSessionCreatedEvent) sessionCreationDetected = true;
 107  0
         }
 108  
 }