001package org.tynamo.security; 002 003import java.lang.annotation.Annotation; 004import java.util.List; 005 006import org.apache.tapestry5.model.MutableComponentModel; 007import org.apache.tapestry5.plastic.MethodAdvice; 008import org.apache.tapestry5.plastic.MethodInvocation; 009import org.apache.tapestry5.plastic.PlasticClass; 010import org.apache.tapestry5.plastic.PlasticMethod; 011import org.apache.tapestry5.services.Environment; 012import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 013import org.apache.tapestry5.services.transform.TransformationSupport; 014import org.tynamo.shiro.extension.authz.aop.AopHelper; 015import org.tynamo.shiro.extension.authz.aop.DefaultSecurityInterceptor; 016import org.tynamo.shiro.extension.authz.aop.SecurityInterceptor; 017 018 019/** 020 * Transform components based on annotation. 021 * <p/> 022 * Support annotation on method. 023 * <p/> 024 * The following rules 025 * <ul> 026 * <li>Annotations on methods are <b>not</b> inherited.</li> 027 * <li>The annotations only in target class, unlike services </li> 028 * <ul> 029 * <p/> 030 * 031 * @see org.tynamo.security.services.SecurityModule#buildSecurityFilter(org.slf4j.Logger, 032 * org.apache.tapestry5.services.ComponentEventLinkEncoder, 033 * org.apache.tapestry5.services.ComponentClassResolver, 034 * org.tynamo.security.services.ClassInterceptorsCache) 035 */ 036public class ShiroAnnotationWorker implements ComponentClassTransformWorker2 037{ 038 private final Environment environment; 039 040 public ShiroAnnotationWorker(Environment environment) 041 { 042 this.environment = environment; 043 } 044 045 @Override 046 public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model) 047 { 048 for (Class<? extends Annotation> annotationClass : AopHelper.getAutorizationAnnotationClasses()) 049 { 050 List<PlasticMethod> methodsToTransform = plasticClass.getMethodsWithAnnotation(annotationClass); 051 052 for (PlasticMethod tm : methodsToTransform) processTransform(tm, tm.getAnnotation(annotationClass)); 053 } 054 } 055 056 private void processTransform(PlasticMethod tm, Annotation annotation) 057 { 058 final SecurityInterceptor interceptor = new DefaultSecurityInterceptor(annotation); 059 060 MethodAdvice advice = new MethodAdvice() 061 { 062 public void advise(MethodInvocation invocation) 063 { 064 environment.push(MethodInvocation.class, invocation); 065 try 066 { 067 interceptor.intercept(); 068 } 069 finally 070 { 071 environment.pop(MethodInvocation.class); 072 } 073 invocation.proceed(); 074 } 075 }; 076 077 tm.addAdvice(advice); 078 079 } 080 081}