001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.system.configuration.condition;
018
019 import java.util.Map;
020
021 import org.apache.commons.jexl.Expression;
022 import org.apache.commons.jexl.ExpressionFactory;
023 import org.apache.commons.jexl.JexlContext;
024 import org.apache.commons.jexl.JexlHelper;
025 import org.apache.commons.jexl.resolver.FlatResolver;
026 import org.apache.commons.logging.Log;
027 import org.apache.commons.logging.LogFactory;
028
029 /**
030 * Parses expressions using <a href="http://jakarta.apache.org/commons/jexl/">Commons Jexl</a>.
031 *
032 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
033 */
034 public class JexlExpressionParser {
035 private static final Log log = LogFactory.getLog(JexlExpressionParser.class);
036
037 protected JexlContext context;
038
039 public JexlExpressionParser(final Map vars) {
040 if (vars == null) {
041 throw new IllegalArgumentException("vars");
042 }
043
044 context = JexlHelper.createContext();
045 context.setVars(vars);
046
047 if (log.isTraceEnabled()) {
048 log.trace("Using variables: " + context.getVars());
049 }
050 }
051
052 public JexlExpressionParser() {
053 this(System.getProperties());
054 }
055
056 public Map getVariables() {
057 return context.getVars();
058 }
059
060 public Object getVariable(final Object name) {
061 if (name == null) {
062 throw new IllegalArgumentException("name");
063 }
064
065 return getVariables().get(name);
066 }
067
068 public Object setVariable(final Object name, final Object value) {
069 if (name == null) {
070 throw new IllegalArgumentException("name");
071 }
072
073 return getVariables().put(name, value);
074 }
075
076 public Object unsetVariable(final Object name) {
077 if (name == null) {
078 throw new IllegalArgumentException("name");
079 }
080
081 return getVariables().remove(name);
082 }
083
084 public void addVariables(final Map map) {
085 if (map == null) {
086 throw new IllegalArgumentException("map");
087 }
088
089 getVariables().putAll(map);
090 }
091
092 public void setVariables(final Map map) {
093 if (map == null) {
094 throw new IllegalArgumentException("map");
095 }
096 context.setVars(map);
097 }
098
099 private FlatResolver resolver = new FlatResolver(true);
100
101 protected Expression createExpression(final String expression) throws Exception {
102 // assert expression != null;
103
104 Expression expr = ExpressionFactory.createExpression(expression);
105 expr.addPreResolver(resolver);
106
107 return expr;
108 }
109
110 public Object evaluate(final String expression) throws Exception {
111 if (expression == null) {
112 throw new IllegalArgumentException("expression");
113 }
114
115 boolean trace = log.isTraceEnabled();
116 if (trace) {
117 log.trace("Evaluating expression: " + expression);
118 }
119
120 Expression expr = createExpression(expression);
121 Object obj = expr.evaluate(context);
122 if (trace) {
123 log.trace("Result: " + obj);
124 }
125
126 return obj;
127 }
128
129 public String parse(final String input) {
130 if (input == null) {
131 throw new IllegalArgumentException("input");
132 }
133
134 boolean trace = log.isTraceEnabled();
135 if (trace) {
136 log.trace("Parsing input: " + input);
137 }
138
139 StringBuffer buff = new StringBuffer();
140
141 int cur = 0;
142 int prefixLoc;
143 int suffixLoc;
144
145 while (cur < input.length()) {
146 prefixLoc = input.indexOf("${", cur);
147
148 if (prefixLoc < 0) {
149 break;
150 }
151
152 suffixLoc = findBlockEnd(prefixLoc + 2, input);
153 if (suffixLoc < 0) {
154 throw new RuntimeException("Missing '}': " + input);
155 }
156
157 String expr = input.substring(prefixLoc + 2, suffixLoc);
158 buff.append(input.substring(cur, prefixLoc));
159
160 try {
161 buff.append(evaluate(expr));
162 }
163 catch (Exception e) {
164 throw new RuntimeException("Failed to evaluate: " + expr, e);
165 }
166
167 cur = suffixLoc + 1;
168 }
169
170 buff.append(input.substring(cur));
171
172 if (trace) {
173 log.trace("Parsed result: " + buff);
174 }
175
176 return buff.toString();
177 }
178
179 private int findBlockEnd(int pos, String input) {
180 int nested = 0;
181 while (pos < input.length()) {
182 char ch = input.charAt(pos);
183 if (ch == '{') {
184 nested++;
185 } else if (ch == '}') {
186 if (nested == 0) {
187 return pos;
188 } else {
189 nested--;
190 }
191 }
192 pos++;
193 }
194 return -1;
195 }
196
197 public String parse(final String input, final boolean trim) {
198 String output = parse(input);
199 if (trim && output != null) {
200 output = output.trim();
201 }
202
203 return output;
204 }
205 }