001: /*
002: * Copyright 2002,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.commons.jelly.expression.jexl;
018:
019: import org.apache.commons.jelly.JellyContext;
020: import org.apache.commons.jelly.JellyException;
021: import org.apache.commons.jelly.expression.Expression;
022: import org.apache.commons.jelly.expression.ExpressionSupport;
023: import org.apache.commons.jelly.expression.ExpressionFactory;
024:
025: //import org.apache.commons.jexl.resolver.FlatResolver;
026:
027: /**
028: * Represents a factory of <a href="http://jakarta.apache.org/commons/jexl.html">Jexl</a>
029: * expression which fully supports the Expression Language in JSTL and JSP.
030: * In addition this ExpressionFactory can also support Ant style variable
031: * names, where '.' is used inside variable names.
032: *
033: * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
034: * @version $Revision: 155420 $
035: */
036:
037: public class JexlExpressionFactory implements ExpressionFactory {
038:
039: /** whether we should allow Ant-style expresssions, using dots as part of variable name */
040: private boolean supportAntVariables = true;
041:
042: // ExpressionFactory interface
043: //-------------------------------------------------------------------------
044: public Expression createExpression(String text)
045: throws JellyException {
046: /*
047:
048: org.apache.commons.jexl.Expression expr =
049: org.apache.commons.jexl.ExpressionFactory.createExpression(text);
050:
051: if ( isSupportAntVariables() ) {
052: expr.addPostResolver(new FlatResolver());
053: }
054:
055: return new JexlExpression( expr );
056: */
057:
058: Expression jexlExpression = null;
059: try {
060: // this method really does throw Exception
061: jexlExpression = new JexlExpression(
062: org.apache.commons.jexl.ExpressionFactory
063: .createExpression(text));
064: } catch (Exception e) {
065: throw new JellyException("Unable to create expression: "
066: + text, e);
067: }
068:
069: if (isSupportAntVariables() && isValidAntVariableName(text)) {
070: return new ExpressionSupportLocal(jexlExpression, text);
071: }
072: return jexlExpression;
073: }
074:
075: // Properties
076: //-------------------------------------------------------------------------
077:
078: /**
079: * @return whether we should allow Ant-style expresssions, using dots as
080: * part of variable name
081: */
082: public boolean isSupportAntVariables() {
083: return supportAntVariables;
084: }
085:
086: /**
087: * Sets whether we should allow Ant-style expresssions, using dots as
088: * part of variable name
089: */
090: public void setSupportAntVariables(boolean supportAntVariables) {
091: this .supportAntVariables = supportAntVariables;
092: }
093:
094: // Implementation methods
095: //-------------------------------------------------------------------------
096:
097: /**
098: * @return true if the given string is a valid Ant variable name,
099: * typically thats alphanumeric text with '.' etc.
100: */
101: protected boolean isValidAntVariableName(String text) {
102: char[] chars = text.toCharArray();
103: for (int i = 0, size = chars.length; i < size; i++) {
104: char ch = chars[i];
105: // could maybe be a bit more restrictive...
106: if (Character.isWhitespace(ch) || ch == '[' || ch == ']'
107: || ch == '(' || ch == ')') {
108: return false;
109: }
110: }
111: return true;
112: }
113:
114: private class ExpressionSupportLocal extends ExpressionSupport {
115:
116: protected Expression jexlExpression = null;
117: protected String text = null;
118:
119: public ExpressionSupportLocal(Expression jexlExpression,
120: String text) {
121: this .jexlExpression = jexlExpression;
122: this .text = text;
123: }
124:
125: public Object evaluate(JellyContext context) {
126: Object answer = jexlExpression.evaluate(context);
127:
128: if (answer == null) {
129: answer = context.getVariable(text);
130: }
131:
132: return answer;
133: }
134:
135: public String getExpressionText() {
136: return "${" + text + "}";
137: }
138:
139: public String toString() {
140: return super .toString() + "[expression:" + text + "]";
141: }
142: }
143:
144: }
|