View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.geronimo.system.configuration.condition;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.commons.jexl.Expression;
24  import org.apache.commons.jexl.ExpressionFactory;
25  import org.apache.commons.jexl.JexlContext;
26  import org.apache.commons.jexl.JexlHelper;
27  
28  import java.util.Map;
29  import java.util.HashMap;
30  import java.util.Collections;
31  
32  /**
33   * Provides a simple facility to evaluate condition expressions using the
34   * <a href="http://jakarta.apache.org/commons/jexl">Jexl</a> language.
35   *
36   * <p>
37   * This class is thread-safe.
38   * </p>
39   *
40   * @version $Rev: 454011 $ $Date: 2006-10-07 13:28:45 -0700 (Sat, 07 Oct 2006) $
41   */
42  public class JexlConditionParser
43      implements ConditionParser
44  {
45      private static final Log log = LogFactory.getLog(JexlConditionParser.class);
46  
47      private final Map vars;
48  
49      public JexlConditionParser() {
50          // Setup the default vars
51          vars = new HashMap();
52  
53          vars.put("props", Collections.unmodifiableMap(System.getProperties()));
54          vars.put("java", new JavaVariable());
55          vars.put("os", new OsVariable());
56      }
57  
58      /**
59       * Evaluate a condition expression.
60       *
61       * @param expression    The condition expression to evaluate; must not be null
62       * @return              True if the condition is satisfied
63       *
64       * @throws org.apache.geronimo.system.configuration.condition.ConditionParserException     Failed to evaluate condition expression
65       */
66      public boolean evaluate(final String expression) throws ConditionParserException {
67          if (expression == null) {
68              throw new IllegalArgumentException("Expression must not be null");
69          }
70  
71          // Empty expressions are true
72          if (expression.trim().length() == 0) {
73              log.debug("Expression is empty; skipping evaluation");
74  
75              return true;
76          }
77  
78          Object result;
79          try {
80              result = doEvaluate(expression);
81          }
82          catch (Exception e) {
83              throw new ConditionParserException("Failed to evaluate expression: " + expression, e);
84          }
85  
86          if (result instanceof Boolean) {
87              return ((Boolean)result).booleanValue();
88          }
89          else {
90              throw new ConditionParserException("Expression '" + expression + "' did not evaluate to a boolean value; found: " + result);
91          }
92      }
93  
94      private Object doEvaluate(final String expression) throws Exception {
95          assert expression != null;
96  
97          boolean debug = log.isDebugEnabled();
98  
99          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 }