Another lovely day with Tapestry! Inspired by Taha's blog entry on
Tapestry Magic, our app instead of this mess:

public class OrderHistoryPage extends AuthenticatedPage

looks sexy like never before with this:

@RequiresLogin(ssoClass= UserUiBean.class, pageClass= Login.class)
public class OrderHistoryPage extends BasePage

Here are the pieces:

Custom Annotation
/**
 * Tells Tapestry that a page requires authenticated user. If a page is
 * annotated with this, and user is not logged in, that page shall redirect
 * to a login screen instead of rendering itself.
 *
 * @author Adam Zimowski
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequiresLogin {
        
        /**
         * Class whose instance lives in session and represents authenticated 
user.
         */
        Class<?> ssoClass();
        
        /**
         * Page class to which Tapestry should redirect guests instead of
         * displaying secured page
         */
        Class<? extends BasePage> pageClass();
}

Annotation Worker
/**
 * Transforms page classes annotated with {@link RequiresLogin} adding advice
 * which tests if the user is logged in, then redirects to login page if user
 * is guest.
 *
 * @author Adam Zimowski
 */
public class RequiresLoginAnnotationWorker implements
ComponentClassTransformWorker {

        private final TransformMethodSignature ONACTIVATE_SIGNATURE =
                new TransformMethodSignature(
                        0, "java.lang.Object", "onActivate", null, null);
        
        private Logger log =
                LoggerFactory.getLogger(RequiresLoginAnnotationWorker.class);

        private ApplicationStateManager asm;
        
        
        public RequiresLoginAnnotationWorker(ApplicationStateManager aAsm) {
                asm = aAsm;
        }
        
        @Override
        public void transform(ClassTransformation aTransformation,
                        MutableComponentModel aModel) {

                RequiresLogin annotation = aTransformation
                                .getAnnotation(RequiresLogin.class);

                if (annotation == null) {
                        return;
                }
                
                final Class<?> ssoClass = annotation.ssoClass();
                final Class<?> pageClass = annotation.pageClass();
                
                if(log.isDebugEnabled()) {
                        log.debug(".. transforming {} ..", 
aTransformation.getClassName());
                }

                TransformMethod methodTransformer = null;
                try {
                        methodTransformer =
                                
aTransformation.getOrCreateMethod(ONACTIVATE_SIGNATURE);
                }
                catch(Throwable t) {
                        throw new 
RuntimeException(RequiresLogin.class.getSimpleName() +
                                " annotation requires package scope " +
                                "[ Object onActivate() ] method.", t);
                }
                
                methodTransformer.addAdvice(
                                new ComponentMethodAdvice() {
                                        public void 
advise(ComponentMethodInvocation invocation) {
                                                invocation.proceed();
                                                if(!asm.exists(ssoClass)) {
                                                        
if(log.isDebugEnabled()) {
                                                                log.debug(
                                                                                
"redirecting to {} page ...",
                                                                                
pageClass.getSimpleName());
                                                        }
                                                        
invocation.overrideResult(pageClass);
                                                }
                                        }
                                }
                );
        }
}

Service Contribution
        @Contribute(ComponentClassTransformWorker.class)
        public void contributeComponentClassTransformWorker(
                        OrderedConfiguration<ComponentClassTransformWorker> 
aWorkers) {

                aWorkers.addInstance(
                                RequiresLogin.class.getSimpleName(),
                                RequiresLoginAnnotationWorker.class,
                                "before:OnEvent");
        }

Page class usage:

@RequiresLogin(ssoClass = UserUiBean.class, pageClass = Login.class)
public class UserProfilePage extends BasePage { ...


Feel free to re-use! Para-Ta-Ta-Taaaaa ........... I'M LOVIN' IT !!!!!

Adam

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to