001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.geronimo.system.configuration.condition;
020
021 import org.apache.commons.logging.Log;
022 import org.apache.commons.logging.LogFactory;
023 import org.apache.commons.jexl.Expression;
024 import org.apache.commons.jexl.ExpressionFactory;
025 import org.apache.commons.jexl.JexlContext;
026 import org.apache.commons.jexl.JexlHelper;
027
028 import java.util.Map;
029 import java.util.HashMap;
030 import java.util.Collections;
031
032 /**
033 * Provides a simple facility to evaluate condition expressions using the
034 * <a href="http://jakarta.apache.org/commons/jexl">Jexl</a> language.
035 *
036 * <p>
037 * This class is thread-safe.
038 * </p>
039 *
040 * @version $Rev: 454011 $ $Date: 2006-10-07 13:28:45 -0700 (Sat, 07 Oct 2006) $
041 */
042 public class JexlConditionParser
043 implements ConditionParser
044 {
045 private static final Log log = LogFactory.getLog(JexlConditionParser.class);
046
047 private final Map vars;
048
049 public JexlConditionParser() {
050 // Setup the default vars
051 vars = new HashMap();
052
053 vars.put("props", Collections.unmodifiableMap(System.getProperties()));
054 vars.put("java", new JavaVariable());
055 vars.put("os", new OsVariable());
056 }
057
058 /**
059 * Evaluate a condition expression.
060 *
061 * @param expression The condition expression to evaluate; must not be null
062 * @return True if the condition is satisfied
063 *
064 * @throws org.apache.geronimo.system.configuration.condition.ConditionParserException Failed to evaluate condition expression
065 */
066 public boolean evaluate(final String expression) throws ConditionParserException {
067 if (expression == null) {
068 throw new IllegalArgumentException("Expression must not be null");
069 }
070
071 // Empty expressions are true
072 if (expression.trim().length() == 0) {
073 log.debug("Expression is empty; skipping evaluation");
074
075 return true;
076 }
077
078 Object result;
079 try {
080 result = doEvaluate(expression);
081 }
082 catch (Exception e) {
083 throw new ConditionParserException("Failed to evaluate expression: " + expression, e);
084 }
085
086 if (result instanceof Boolean) {
087 return ((Boolean)result).booleanValue();
088 }
089 else {
090 throw new ConditionParserException("Expression '" + expression + "' did not evaluate to a boolean value; found: " + result);
091 }
092 }
093
094 private Object doEvaluate(final String expression) throws Exception {
095 assert expression != null;
096
097 boolean debug = log.isDebugEnabled();
098
099 if (debug) {
100 log.debug("Evaluating expression: " + expression);
101 }
102
103 Expression expr = ExpressionFactory.createExpression(expression);
104
105 JexlContext ctx = JexlHelper.createContext();
106 ctx.setVars(vars);
107
108 Object result = expr.evaluate(ctx);
109 if (debug) {
110 log.debug("Result: " + result);
111 }
112
113 return result;
114 }
115 }