package org.jboss.seam.el;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.el.FunctionMapper;
import org.jboss.el.lang.ExtendedFunctionMapper;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.security.SecurityFunctions;
/**
* Resolves Seam Security EL functions, s:hasRole() and s:hasPermission()
* by decorating a delegate Unified EL FunctionMapper
*
* @author Shane Bryzak
*/
public class SeamFunctionMapper extends ExtendedFunctionMapper
{
private static Map<String,List<Method>> methodCache = new HashMap<String,List<Method>>();
private static final LogProvider log = Logging.getLogProvider(SeamFunctionMapper.class);
private FunctionMapper functionMapper;
public SeamFunctionMapper(FunctionMapper functionMapper)
{
this.functionMapper = functionMapper;
}
static
{
cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission",
new Class[] {String.class, String.class, Object.class});
cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission",
new Class[] {Object.class, String.class});
cacheMethod("hasRole", SecurityFunctions.class, "hasRole",
new Class[] { String.class });
}
@Override
public Method resolveFunction(String prefix, String localName)
{
if ( "s".equals(prefix) )
{
List<Method> methods = methodCache.get(localName);
return methods != null ? methods.get(0) : null;
}
else if (functionMapper != null)
{
return functionMapper.resolveFunction(prefix, localName);
}
else
{
return null;
}
}
@Override
public Method resolveFunction(String prefix, String localName, int paramCount)
{
if ( "s".equals(prefix) )
{
List<Method> methods = methodCache.get(localName);
if (methods != null)
{
for (Method m : methods)
{
if (m.getParameterTypes().length == paramCount) return m;
}
}
return null;
}
else if (functionMapper != null)
{
return functionMapper.resolveFunction(prefix, localName);
}
else
{
return null;
}
}
private static void cacheMethod(String localName, Class cls, String name, Class[] params)
{
try
{
Method m = cls.getMethod(name, params);
List<Method> methods;
if (methodCache.containsKey(localName))
{
methods = methodCache.get(localName);
}
else
{
methods = new ArrayList<Method>();
methodCache.put(localName, methods);
}
methods.add(m);
}
catch (NoSuchMethodException ex)
{
log.warn(String.format("Method %s.%s could not be cached", cls.getName(), name));
}
}
}