1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jelly.expression.jexl;
18
19 import org.apache.commons.jelly.JellyContext;
20 import org.apache.commons.jelly.JellyException;
21 import org.apache.commons.jelly.expression.Expression;
22 import org.apache.commons.jelly.expression.ExpressionSupport;
23 import org.apache.commons.jelly.expression.ExpressionFactory;
24
25
26
27 /***
28 * Represents a factory of <a href="http://commons.apache.org/jexl.html">Jexl</a>
29 * expression which fully supports the Expression Language in JSTL and JSP.
30 * In addition this ExpressionFactory can also support Ant style variable
31 * names, where '.' is used inside variable names.
32 *
33 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
34 * @version $Revision: 155420 $
35 */
36
37 public class JexlExpressionFactory implements ExpressionFactory {
38
39 /*** whether we should allow Ant-style expresssions, using dots as part of variable name */
40 private boolean supportAntVariables = true;
41
42
43
44 public Expression createExpression(String text) throws JellyException {
45
46
47
48
49
50
51
52
53
54
55
56
57 Expression jexlExpression = null;
58 try {
59
60 jexlExpression = new JexlExpression(
61 org.apache.commons.jexl.ExpressionFactory.createExpression(text)
62 );
63 } catch (Exception e) {
64 throw new JellyException("Unable to create expression: " + text, e);
65 }
66
67 if ( isSupportAntVariables() && isValidAntVariableName(text) ) {
68 return new ExpressionSupportLocal(jexlExpression,text);
69 }
70 return jexlExpression;
71 }
72
73
74
75
76 /***
77 * @return whether we should allow Ant-style expresssions, using dots as
78 * part of variable name
79 */
80 public boolean isSupportAntVariables() {
81 return supportAntVariables;
82 }
83
84 /***
85 * Sets whether we should allow Ant-style expresssions, using dots as
86 * part of variable name
87 */
88 public void setSupportAntVariables(boolean supportAntVariables) {
89 this.supportAntVariables = supportAntVariables;
90 }
91
92
93
94
95 /***
96 * @return true if the given string is a valid Ant variable name,
97 * typically thats alphanumeric text with '.' etc.
98 */
99 protected boolean isValidAntVariableName(String text) {
100 char[] chars = text.toCharArray();
101 for (int i = 0, size = chars.length; i < size; i++ ) {
102 char ch = chars[i];
103
104 if ( Character.isWhitespace(ch) || ch == '[' || ch == ']' || ch == '(' || ch == ')') {
105 return false;
106 }
107 }
108 return true;
109 }
110
111 private class ExpressionSupportLocal extends ExpressionSupport {
112
113 protected Expression jexlExpression = null;
114 protected String text = null;
115
116 public ExpressionSupportLocal(Expression jexlExpression, String text) {
117 this.jexlExpression = jexlExpression;
118 this.text = text;
119 }
120
121 public Object evaluate(JellyContext context) {
122 Object answer = jexlExpression.evaluate(context);
123
124 if ( answer == null ) {
125 answer = context.getVariable(text);
126 }
127
128 return answer;
129 }
130
131 public String getExpressionText() {
132 return "${" + text + "}";
133 }
134
135 public String toString() {
136 return super.toString() + "[expression:" + text + "]";
137 }
138 }
139
140 }