package com.wooki.services.security; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.apache.tapestry5.EventConstants; import org.apache.tapestry5.EventContext; import org.apache.tapestry5.annotations.OnEvent; import org.apache.tapestry5.internal.EmptyEventContext; /** * Object used to store the information related to activation context for a given page. * * @author ccordenier */ public class ActivationContextDefinition { static final String OBJECT_ARRAY_TYPE = "java.lang.Object[]"; static final String EVENT_CONTEXT_TYPE = EventContext.class.getName(); static final String LIST_TYPE = List.class.getName(); private final static int ANY_NUMBER_OF_PARAMETERS = -1; /** * The list of method definition for activation context for this class. */ private List<Class[]> authorizedActivationContext = new ArrayList<Class[]>(); /** * Tag this page as unsecured */ private boolean unsecured; /** * Create the activation context definition for the given class. * * @param clazz */ public ActivationContextDefinition(Class clazz) { Method[] methods = clazz.getMethods(); for (Method method : methods) { OnEvent eventHandler = method.getAnnotation(OnEvent.class); if ((eventHandler != null && EventConstants.ACTIVATE.equals(eventHandler.value())) || ("on" + EventConstants.ACTIVATE).equalsIgnoreCase(method.getName())) { // Check parameters Class[] parameterType = method.getParameterTypes(); int count = getParameterCount(parameterType); if (ANY_NUMBER_OF_PARAMETERS == count) { this.unsecured = true; this.authorizedActivationContext.clear(); break; } this.authorizedActivationContext.add(parameterType); } } } /** * This method must be called to check if the activation context of the current request * correspond to an existing matching method. * * @param pageName * @param ctx * @return */ public boolean findMatchingMethod(String pageName, EventContext ctx) { // First check unsecure flag if (unsecured) { return true; } // No activation context method inside class if (this.authorizedActivationContext.size() == 0) { return EmptyEventContext.class .equals(ctx.getClass()); } // Check the list of parameter types arrays for (Class[] parameterType : this.authorizedActivationContext) { if (parameterType.length == ctx.getCount()) { // If no parameter to check return true if (ctx.getCount() == 0) { return true; } for (int i = 0; i < parameterType.length; i++) { Class type = parameterType[i]; try { ctx.get(type, i); if (i == parameterType.length - 1) { return true; } } catch (RuntimeException re) { break; } } } } return false; } private int getParameterCount(Class[] types) { if (types.length == 0) return 0; if (types.length == 1) { String soloType = types[0].getName(); if (soloType.equals(OBJECT_ARRAY_TYPE) || soloType.equals(EVENT_CONTEXT_TYPE) || soloType.equals(LIST_TYPE)) return ANY_NUMBER_OF_PARAMETERS; } return types.length; } }