View Javadoc

    1   /*
    2    * Copyright 2002,2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    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  //import org.apache.commons.jexl.resolver.FlatResolver;
    26
    27  /***
    28   * Represents a factory of <a href="http://jakarta.apache.org/commons/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      // ExpressionFactory interface
    43      //-------------------------------------------------------------------------
    44      public Expression createExpression(String text) throws JellyException {
    45  /*
    46
    47          org.apache.commons.jexl.Expression expr =
    48              org.apache.commons.jexl.ExpressionFactory.createExpression(text);
    49
    50          if ( isSupportAntVariables() ) {
    51              expr.addPostResolver(new FlatResolver());
    52          }
    53
    54          return new JexlExpression( expr );
    55  */
    56
    57          Expression jexlExpression = null;
    58          try {
    59              // this method really does throw Exception
    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      // Properties
    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      // Implementation methods
    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             // could maybe be a bit more restrictive...
    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 }