001package com.randomnoun.common.security.impl;
002
003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
005 */
006
007import java.io.StringReader;
008import java.util.*;
009
010import com.randomnoun.common.jexl.ast.TopLevelExpression;
011import com.randomnoun.common.jexl.eval.EvalContext;
012import com.randomnoun.common.jexl.eval.EvalFunction;
013import com.randomnoun.common.jexl.eval.Evaluator;
014import com.randomnoun.common.jexl.parser.ExpressionParser;
015import com.randomnoun.common.jexl.parser.ParseException;
016import com.randomnoun.common.jexl.parser.TokenMgrError;
017/*
018import com.randomnoun.common.jexl.sql.function.AggregateFunction;
019import com.randomnoun.common.jexl.sql.function.BetweenFunction;
020import com.randomnoun.common.jexl.sql.function.EndsWithFunction;
021import com.randomnoun.common.jexl.sql.function.IsInFunction;
022import com.randomnoun.common.jexl.sql.function.IsNullFunction;
023import com.randomnoun.common.jexl.sql.function.LikeFunction;
024import com.randomnoun.common.jexl.sql.function.PromptFunction;
025import com.randomnoun.common.jexl.sql.function.StartsWithFunction;
026*/
027import com.randomnoun.common.security.ResourceCriteria;
028
029/**
030 * Implements the ResourceCriteria interface, using JEXL strings to represent
031 * {@link com.randomnoun.common.jexl.ast.TopLevelExpression} objects,
032 * which are then used to determine matches a given criteria context.
033 *
034 * 
035 * @author knoxg
036 */
037public class ResourceCriteriaImpl extends ResourceCriteria
038{
039    
040    /** generated serialVerisonUID */
041        private static final long serialVersionUID = -8307206866854674839L;
042        
043        /** The expression used to evaluate a criteria context. */
044    private TopLevelExpression expression;
045
046    /**
047     * Construct a new ResourceCriteriaImpl object. The criteria is parsed using
048     * an EditableTranslator to convert it into a EditableCriteria object,
049     * and from there into an Expression object.
050     *
051     * @param criteriaString The JEX expression used to define this criteria.
052     *
053     * @throws CriteriaException if the underlying EditableTranslator throws
054     *   an exception during initialisation, deserialisation or conversion.
055     */
056    public ResourceCriteriaImpl(String criteriaString)
057    {
058        super(criteriaString);
059
060        if (criteriaString != null && !"".equals(criteriaString)) {
061            try {
062                expression = stringToExpression(criteriaString);
063            } catch (java.text.ParseException pe) {
064                throw new RuntimeException(
065                    "Illegal expression found in security table: '" + criteriaString +
066                    "', Error: " + pe.getMessage());
067            }
068        }
069    }
070    
071    /** Convert Java expression String to a TopLevelExpression */
072    public static TopLevelExpression stringToExpression(String expressionString)
073        throws java.text.ParseException
074    {
075        StringReader reader = new StringReader(expressionString);
076        ExpressionParser parser = new ExpressionParser(reader);
077        TopLevelExpression root = null;
078
079        try {
080                root = parser.TopLevelExpression();
081        } catch (ParseException pe) {
082            throw new java.text.ParseException(pe.getMessage(), -1);
083        } catch (TokenMgrError tme) {
084            throw new java.text.ParseException(tme.getMessage(), -1);
085        }
086
087        return root;
088    }
089    
090
091    /**
092     * Evaluates the supplied criteria context against the criteria expression
093     * stored in this object.
094     *
095     * {@inheritdoc}
096     *
097     * @param criteriaContext {@inheritdoc}
098     *
099     * @return {@inheritdoc}
100     */
101    public boolean evaluate(Map<String, Object> criteriaContext)
102    {
103        EvalContext evalContext = new EvalContext();
104
105        Map<String, EvalFunction> functions = new HashMap<String, EvalFunction>();
106        /*
107        functions.put("all", new AggregateFunction("all", "AND", false, false));
108        functions.put("anyTrue", new AggregateFunction("anyTrue", "OR", false, false));        
109        functions.put("anyFalse", new AggregateFunction("anyFalse", "OR", false, true));
110        functions.put("none", new AggregateFunction("none", "AND", true, false));
111        functions.put("like", new LikeFunction());
112        functions.put("startsWith", new StartsWithFunction());
113        functions.put("endsWith", new EndsWithFunction());
114        functions.put("prompt", new PromptFunction());
115        functions.put("between", new BetweenFunction());
116        functions.put("isNull", new IsNullFunction());
117        functions.put("isIn", new IsInFunction());
118        */
119        evalContext.setFunctions(functions);
120
121        // put security-specific resources, functions, etc... in here
122        evalContext.setVariables(criteriaContext);
123
124        if (expression == null) {
125            // always return true for null expressions
126            return true;
127        }
128        
129        Evaluator evaluator = new Evaluator();
130        Object result = evaluator.visit(expression, evalContext);
131        return ((Boolean) result).booleanValue();
132        // return ExpressionUtils.evaluateBooleanExpression(expression, evalContext);
133    }
134}