/**
 * <code>ExpressionFilenameParser</code> can use any expression language supported by Mule to
 * construct a file name for the current message. Expressions can be xpath, xquery, ognl, mvel,
 * header, function and more. For more information see
 * http://www.mulesoft.org/documentation/display/MULE3USER/Using+Expressions.
 *
 * <p>For example an xpath expression can be defined to pull a message id out of an xml message and
 * use that as the file name - <code>
 * #[xpath:/message/header/@id]
 * </code>
 *
 * <p>This parser superseeds the (now removed) <code>org.mule.transport.file.SimpleFilenameParser
 * </code> which has been kept in Mule 2 for compatibility. The following demonstrates how to
 * achieve the same results when using the <code>ExpressionFilenameParser</code> over the <code>
 * SimpleFilenameParser</code>
 *
 * <ul>
 *   <li>#[DATE] : #[function:datestamp]
 *   <li>#[DATE:yy-MM-dd] : #[function:datestamp-yy-MM-dd]
 *   <li>#[SYSTIME] : #[function:systime]
 *   <li>#[UUID] : #[function:uuid]
 *   <li>#[ORIGINALNAME] : #[header:originalFilename]
 *   <li>#[COUNT] : #[function:count] - note that this is a global counter.
 *   <li>#[&lt;Message Property Name&gt;] : #[header:&lt;Message Property Name&gt;]
 * </ul>
 */
public class ExpressionFilenameParser implements FilenameParser, MuleContextAware {
  public static final String DEFAULT_DATE_FORMAT = "dd-MM-yy_HH-mm-ss.SSS";
  public static final String DEFAULT_EXPRESSION =
      MessageFormat.format(
          "{0}function:uuid{1}.dat",
          ExpressionManager.DEFAULT_EXPRESSION_PREFIX,
          ExpressionManager.DEFAULT_EXPRESSION_POSTFIX);

  private final TemplateParser wigglyMuleParser = TemplateParser.createMuleStyleParser();
  private final TemplateParser squareParser = TemplateParser.createSquareBracesStyleParser();

  protected MuleContext muleContext;

  public void setMuleContext(MuleContext context) {
    this.muleContext = context;
  }

  public String getFilename(MuleMessage message, String expression) {
    if (expression == null) {
      expression = DEFAULT_EXPRESSION;
    }

    if (expression.indexOf(ExpressionManager.DEFAULT_EXPRESSION_PREFIX) > -1) {
      return getFilename(message, expression, wigglyMuleParser);
    } else {
      return getFilename(message, expression, squareParser);
    }
  }

  protected String getFilename(
      final MuleMessage message, String expression, TemplateParser parser) {
    return parser.parse(
        new TemplateParser.TemplateCallback() {
          public Object match(String token) {
            return muleContext.getExpressionManager().evaluate(token, message);
          }
        },
        expression);
  }
}
Esempio n. 2
0
/**
 * Provides universal access for evaluating expressions embedded in Mule configurations, such as
 * Xml, Java, scripting and annotations.
 *
 * <p>Users can register or unregister {@link ExpressionEvaluator} through this interface.
 */
public class DefaultExpressionManager implements ExpressionManager {

  /** logger used by this class */
  protected static final transient Log logger = LogFactory.getLog(DefaultExpressionManager.class);

  // default style parser
  private TemplateParser parser = TemplateParser.createMuleStyleParser();

  private ConcurrentMap evaluators = new ConcurrentHashMap(8);

  public void registerEvaluator(ExpressionEvaluator evaluator) {
    if (evaluator == null) {
      throw new IllegalArgumentException(CoreMessages.objectIsNull("evaluator").getMessage());
    }

    final String name = evaluator.getName();
    // TODO MULE-3809 Eliminate duplicate evaluators registration
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Evaluators already contain an object named '"
              + name
              + "'.  The previous object will be overwritten.");
    }
    evaluators.put(evaluator.getName(), evaluator);
  }

  /**
   * Checks whether an evaluator is registered with the manager
   *
   * @param name the name of the expression evaluator
   * @return true if the evaluator is registered with the manager, false otherwise
   */
  public boolean isEvaluatorRegistered(String name) {
    return evaluators.containsKey(name);
  }

  /**
   * Removes the evaluator with the given name
   *
   * @param name the name of the evaluator to remove
   */
  public ExpressionEvaluator unregisterEvaluator(String name) {
    if (name == null) {
      return null;
    }

    ExpressionEvaluator evaluator = (ExpressionEvaluator) evaluators.remove(name);
    if (evaluator instanceof Disposable) {
      ((Disposable) evaluator).dispose();
    }
    return evaluator;
  }

  /**
   * Evaluates the given expression. The expression should be a single expression definition with or
   * without enclosing braces. i.e. "mule:serviceName" and "#[mule:serviceName]" are both valid. For
   * situations where one or more expressions need to be parsed within a single text, the {@link
   * org.mule.api.expression.ExpressionManager#parse(String,org.mule.api.MuleMessage,boolean)}
   * method should be used since it will iterate through all expressions in a string.
   *
   * @param expression a single expression i.e. xpath://foo
   * @param message the current message to process. The expression will evaluata on the message.
   * @return the result of the evaluation. Expressions that return collection will return an empty
   *     collection, not null.
   * @throws ExpressionRuntimeException if the expression is invalid, or a null is found for the
   *     expression and 'failIfNull is set to true.
   */
  public Object evaluate(String expression, MuleMessage message) throws ExpressionRuntimeException {
    return evaluate(expression, message, false);
  }

  /**
   * Evaluates the given expression. The expression should be a single expression definition with or
   * without enclosing braces. i.e. "mule:serviceName" and "#[mule:serviceName]" are both valid. For
   * situations where one or more expressions need to be parsed within a single text, the {@link
   * org.mule.api.expression.ExpressionManager#parse(String,org.mule.api.MuleMessage,boolean)}
   * method should be used since it will iterate through all expressions in a string.
   *
   * @param expression a single expression i.e. xpath://foo
   * @param message the current message to process. The expression will evaluata on the message.
   * @param failIfNull determines if an exception should be thrown if expression could not be
   *     evaluated or returns null.
   * @return the result of the evaluation. Expressions that return collection will return an empty
   *     collection, not null.
   * @throws ExpressionRuntimeException if the expression is invalid, or a null is found for the
   *     expression and 'failIfNull is set to true.
   */
  public Object evaluate(String expression, MuleMessage message, boolean failIfNull)
      throws ExpressionRuntimeException {
    String name;

    if (expression == null) {
      throw new IllegalArgumentException(CoreMessages.objectIsNull("expression").getMessage());
    }
    if (expression.startsWith(DEFAULT_EXPRESSION_PREFIX)) {
      expression = expression.substring(2, expression.length() - 1);
    }
    int i = expression.indexOf(":");
    if (i > -1) {
      name = expression.substring(0, i);
      expression = expression.substring(i + DEFAULT_EXPRESSION_POSTFIX.length());
    } else {
      name = expression;
      expression = null;
    }
    return evaluate(expression, name, message, failIfNull);
  }

  /**
   * Evaluates the given expression. The expression should be a single expression definition with or
   * without enclosing braces. i.e. "mule:serviceName" and "#[mule:serviceName]" are both valid. For
   * situations where one or more expressions need to be parsed within a single text, the {@link
   * org.mule.api.expression.ExpressionManager#parse(String,org.mule.api.MuleMessage,boolean)}
   * method should be used since it will iterate through all expressions in a string.
   *
   * @param expression a single expression i.e. xpath://foo
   * @param evaluator the evaluator to use when executing the expression
   * @param message the current message to process. The expression will evaluata on the message.
   * @param failIfNull determines if an exception should be thrown if expression could not be
   *     evaluated or returns null or if an exception should be thrown if an empty collection is
   *     returned.
   * @return the result of the evaluation. Expressions that return collection will return an empty
   *     collection, not null.
   * @throws ExpressionRuntimeException if the expression is invalid, or a null is found for the
   *     expression and 'failIfNull is set to true.
   */
  public Object evaluate(
      String expression, String evaluator, MuleMessage message, boolean failIfNull)
      throws ExpressionRuntimeException {
    ExpressionEvaluator extractor = (ExpressionEvaluator) evaluators.get(evaluator);
    if (extractor == null) {
      throw new IllegalArgumentException(
          CoreMessages.expressionEvaluatorNotRegistered(evaluator).getMessage());
    }
    Object result = extractor.evaluate(expression, message);
    // TODO Handle empty collections || (result instanceof Collection &&
    // ((Collection)result).size()==0)
    if (failIfNull && (result == null)) {
      throw new ExpressionRuntimeException(
          CoreMessages.expressionEvaluatorReturnedNull(evaluator, expression));
    }
    if (logger.isDebugEnabled()) {
      logger.debug(
          MessageFormat.format(
              "Result of expression: {0}:{1} is: {2}", evaluator, expression, result));
    }
    return result;
  }

  /**
   * Evaluates expressions in a given string. This method will iterate through each expression and
   * evaluate it. If a user needs to evaluate a single expression they can use {@link
   * org.mule.api.expression.ExpressionManager#evaluate(String,org.mule.api.MuleMessage,boolean)}.
   *
   * @param expression a single expression i.e. xpath://foo
   * @param message the current message to process. The expression will evaluata on the message.
   * @return the result of the evaluation. Expressions that return collection will return an empty
   *     collection, not null.
   * @throws org.mule.api.expression.ExpressionRuntimeException if the expression is invalid, or a
   *     null is found for the expression and 'failIfNull is set to true.
   */
  public String parse(String expression, MuleMessage message) throws ExpressionRuntimeException {
    return parse(expression, message, false);
  }

  /**
   * Evaluates expressions in a given string. This method will iterate through each expression and
   * evaluate it. If a user needs to evaluate a single expression they can use {@link
   * org.mule.api.expression.ExpressionManager#evaluate(String,org.mule.api.MuleMessage,boolean)}.
   *
   * @param expression a single expression i.e. xpath://foo
   * @param message the current message to process. The expression will evaluata on the message.
   * @param failIfNull determines if an exception should be thrown if expression could not be
   *     evaluated or returns null.
   * @return the result of the evaluation. Expressions that return collection will return an empty
   *     collection, not null.
   * @throws ExpressionRuntimeException if the expression is invalid, or a null is found for the
   *     expression and 'failIfNull is set to true.
   */
  public String parse(final String expression, final MuleMessage message, final boolean failIfNull)
      throws ExpressionRuntimeException {
    return parser.parse(
        new TemplateParser.TemplateCallback() {
          public Object match(String token) {
            return evaluate(token, message, failIfNull);
          }
        },
        expression);
  }

  /** Clears all registered evaluators from the manager. */
  public synchronized void clearEvaluators() {
    for (Iterator iterator = evaluators.values().iterator(); iterator.hasNext(); ) {
      ExpressionEvaluator evaluator = (ExpressionEvaluator) iterator.next();
      if (evaluator instanceof Disposable) {
        ((Disposable) evaluator).dispose();
      }
    }
    evaluators.clear();
  }

  /**
   * Determines if the expression is valid or not. This method will validate a single expression or
   * expressions embedded in a string. the expression must be well formed i.e. #[bean:user]
   *
   * @param expression the expression to validate
   * @return true if the expression evaluator is recognised
   */
  public boolean isValidExpression(String expression) {
    final AtomicBoolean valid = new AtomicBoolean(true);
    final AtomicBoolean match = new AtomicBoolean(false);
    final StringBuffer message = new StringBuffer();
    parser.parse(
        new TemplateParser.TemplateCallback() {
          public Object match(String token) {
            match.set(true);
            if (token.indexOf(":") == -1) {
              if (valid.get()) {
                valid.compareAndSet(true, false);
              }
              message.append(token).append(" is malformed\n");
            }
            return null;
          }
        },
        expression);

    if (message.length() > 0) {
      logger.warn("Expression " + expression + " is malformed: " + message.toString());
    }
    return match.get() && valid.get();
  }
}
 public GetMentionsDefinitionParser() {
   patternInfo = TemplateParser.createMuleStyleParser().getStyle();
 }