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  package org.apache.commons.jexl;
    17
    18  import java.io.StringReader;
    19
    20  import org.apache.commons.jexl.parser.ASTExpressionExpression;
    21  import org.apache.commons.jexl.parser.ASTReferenceExpression;
    22  import org.apache.commons.jexl.parser.Parser;
    23  import org.apache.commons.jexl.parser.SimpleNode;
    24  import org.apache.commons.logging.Log;
    25  import org.apache.commons.logging.LogFactory;
    26
    27  /***
    28   * <p>
    29   * Creates Expression objects.  To create a JEXL Expression object, pass
    30   * valid JEXL syntax to the static createExpression() method:
    31   * </p>
    32   *
    33   * <pre>
    34   * String jexl = "array[1]";
    35   * Expression expression = ExpressionFactory.createExpression( jexl );
    36   * </pre>
    37   *
    38   * <p>
    39   * When an {@link Expression} object is created, the JEXL syntax is
    40   * parsed and verified.  If the supplied expression is neither an
    41   * expression not a reference, an exception is thrown from createException().
    42   * </p>
    43   * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
    44   * @version $Id: ExpressionFactory.java,v 1.7 2004/08/23 13:50:00 dion Exp $
    45   */
    46  public class ExpressionFactory
    47  {
    48      /***
    49       * The Log to which all ExpressionFactory messages will be logged.
    50       */
    51      protected static Log log =
    52          LogFactory.getLog("org.apache.commons.jexl.ExpressionFactory");
    53
    54      /***
    55       * The singleton ExpressionFactory also holds a single instance of {@link Parser}.
    56       * When parsing expressions, ExpressionFactory synchronizes on Parser.
    57       */
    58      protected static Parser parser = new Parser(new StringReader(";")); //$NON-NLS-1$
    59
    60      /***
    61       * ExpressionFactory is a single and this is the private
    62       * status instance fufilling that pattern.
    63       */
    64      protected static ExpressionFactory ef = new ExpressionFactory();
    65
    66      /***
    67       * Private constructor, the single instance is always obtained
    68       * with a call to getInstance().
    69       */
    70      private ExpressionFactory(){}
    71
    72      /***
    73       * Returns the single instance of ExpressionFactory.
    74       * @return the instance of ExpressionFactory.
    75       */
    76      protected static  ExpressionFactory getInstance()
    77      {
    78          return ef;
    79      }
    80
    81      /***
    82       * Creates an Expression from a String containing valid
    83       * JEXL syntax.  This method parses the expression which
    84       * must contain either a reference or an expression.
    85       * @param expression A String containing valid JEXL syntax
    86       * @return An Expression object which can be evaluated with a JexlContext
    87       * @throws Exception An exception can be thrown if there is a problem parsing
    88       *                   his expression, or if the expression is neither an
    89       *                   expression or a reference.
    90       */
    91      public static Expression createExpression(String expression)
    92          throws Exception
    93      {
    94          return getInstance().createNewExpression(expression);
    95      }
    96
    97
    98      /***
    99       *  Creates a new Expression based on the expression string.
    100      *
    101      *  @param expression valid Jexl expression
    102      *  @return Expression
    103      *  @throws Exception for a variety of reasons - mostly malformed
    104      *          Jexl expression
    105      */
    106     protected Expression createNewExpression(String expression)
    107         throws Exception {
    108
    109         String expr = cleanExpression(expression);
    110
    111         // Parse the Expression
    112         SimpleNode tree;
    113         synchronized(parser)
    114         {
    115             log.debug( "Parsing expression: " + expr );
    116             tree = parser.parse(new StringReader(expr));
    117         }
    118
    119         // Must be a simple reference or expression, otherwise
    120         // throw an exception.
    121         SimpleNode node = (SimpleNode) tree.jjtGetChild(0);
    122
    123         if( (node instanceof ASTReferenceExpression) ||
    124             (node instanceof ASTExpressionExpression) )
    125         {
    126             node = (SimpleNode) node.jjtGetChild(0);
    127             Expression e = new ExpressionImpl(expression, node);
    128
    129             return e;
    130         }
    131         else
    132         {
    133             log.error( "Invalid Expression, node of type: " + node.getClass().getName() );
    134             throw new Exception("Invalid Expression: neither Reference nor Expression");
    135         }
    136     }
    137
    138     /***
    139      * Trims the expression and adds a semi-colon if missing.
    140      * @param expression to clean
    141      * @return trimmed expression ending in a semi-colon
    142      */
    143     private String cleanExpression(String expression) {
    144         String expr = expression.trim();
    145         if (!expr.endsWith(";"))
    146         {
    147             expr += ";";
    148         }
    149         return expr;
    150     }
    151 }