All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.util.OgnlHelper Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Helper for Camel OGNL (Object-Graph Navigation Language) expressions.
 */
public final class OgnlHelper {

    private static final Pattern INDEX_PATTERN = Pattern.compile("^(.*)\\[(.*)\\]$");

    private OgnlHelper() {
    }

    /**
     * Tests whether or not the given String is a Camel OGNL expression.
     * 

* An expression is considered an OGNL expression when it contains either one of the following chars: . or [ * * @param expression the String * @return true if a Camel OGNL expression, otherwise false. */ public static boolean isValidOgnlExpression(String expression) { if (expression == null || expression.isEmpty()) { return false; } // the brackets should come in a pair int bracketBegin = StringHelper.countChar(expression, '['); int bracketEnd = StringHelper.countChar(expression, ']'); if (bracketBegin > 0 && bracketEnd > 0) { return bracketBegin == bracketEnd; } return expression.contains("."); } public static boolean isInvalidValidOgnlExpression(String expression) { if (expression == null) { return false; } if (expression.indexOf('.') == -1 && expression.indexOf('[') == -1 && expression.indexOf(']') == -1) { return false; } // the brackets should come in pair int bracketBegin = StringHelper.countChar(expression, '['); int bracketEnd = StringHelper.countChar(expression, ']'); if (bracketBegin > 0 || bracketEnd > 0) { return bracketBegin != bracketEnd; } // check for double dots if (expression.contains("..")) { return true; } return false; } /** * Validates whether the method name is using valid java identifiers in the name Will throw * {@link IllegalArgumentException} if the method name is invalid. */ public static void validateMethodName(String method) { for (int i = 0; i < method.length(); i++) { char ch = method.charAt(i); if (i == 0 && '.' == ch) { // its a dot before a method name continue; } if (ch == '(' || ch == '[' || ch == '.' || ch == '?') { // break when method name ends and sub method or arguments begin break; } if (i == 0 && !Character.isJavaIdentifierStart(ch)) { throw new IllegalArgumentException( "Method name must start with a valid java identifier at position: 0 in method: " + method); } else if (!Character.isJavaIdentifierPart(ch)) { throw new IllegalArgumentException( "Method name must be valid java identifier at position: " + i + " in method: " + method); } } } /** * Tests whether or not the given Camel OGNL expression is using the null safe operator or not. * * @param ognlExpression the Camel OGNL expression * @return true if the null safe operator is used, otherwise false. */ public static boolean isNullSafeOperator(String ognlExpression) { return ognlExpression.startsWith("?"); } /** * Removes any leading operators from the Camel OGNL expression. *

* Will remove any leading of the following chars: ? or . * * @param ognlExpression the Camel OGNL expression * @return the Camel OGNL expression without any leading operators. */ public static String removeLeadingOperators(String ognlExpression) { if (ognlExpression.startsWith("?")) { ognlExpression = ognlExpression.substring(1); } if (ognlExpression.startsWith(".")) { ognlExpression = ognlExpression.substring(1); } return ognlExpression; } /** * Removes any trailing operators from the Camel OGNL expression. * * @param ognlExpression the Camel OGNL expression * @return the Camel OGNL expression without any trailing operators. */ public static String removeTrailingOperators(String ognlExpression) { return StringHelper.before(ognlExpression, "[", ognlExpression); } public static String removeOperators(String ognlExpression) { return removeLeadingOperators(removeTrailingOperators(ognlExpression)); } public static KeyValueHolder isOgnlIndex(String ognlExpression) { Matcher matcher = INDEX_PATTERN.matcher(ognlExpression); if (matcher.matches()) { // to avoid empty strings as we want key/value to be null in such cases String key = matcher.group(1); if (key != null && key.isEmpty()) { key = null; } // to avoid empty strings as we want key/value to be null in such cases String value = matcher.group(2); if (value != null && value.isEmpty()) { value = null; } return new KeyValueHolder<>(key, value); } return null; } /** * Regular expression with repeating groups is a pain to get right and then nobody understands the reg exp * afterwards. So we use a bit ugly/low-level Java code to split the OGNL into methods. * * @param ognl the ognl expression * @return a list of methods, will return an empty list, if ognl expression has no methods * @throws IllegalArgumentException if the last method has a missing ending parenthesis */ public static List splitOgnl(String ognl) { // return an empty list if ognl is empty if (ognl == null || ognl.isBlank()) { return Collections.emptyList(); } List methods = new ArrayList<>(4); StringBuilder sb = new StringBuilder(256); int j = 0; // j is used as counter per method int squareBracketCnt = 0; // special to keep track if and how deep we are inside a square bracket block, eg: [foo] int parenthesisBracketCnt = 0; // special to keep track if and how deep we are inside a parenthesis block, eg: bar(${body}, ${header.foo}) boolean singleQuoted = false; boolean doubleQuoted = false; for (int i = 0; i < ognl.length(); i++) { char ch = ognl.charAt(i); if (!doubleQuoted && ch == '\'') { singleQuoted = !singleQuoted; } else if (!singleQuoted && ch == '\"') { doubleQuoted = !doubleQuoted; } if (singleQuoted || doubleQuoted) { // quoted text so append as literal text sb.append(ch); continue; } // special for starting a new method if (j == 0 || j == 1 && ognl.charAt(i - 1) == '?' || ch != '.' && ch != '?' && ch != ']') { sb.append(ch); // special if we are doing square bracket if (ch == '[' && parenthesisBracketCnt == 0) { squareBracketCnt++; } else if (ch == '(') { parenthesisBracketCnt++; } else if (ch == ')') { parenthesisBracketCnt--; } j++; // advance } else { if (ch == '.' && squareBracketCnt == 0 && parenthesisBracketCnt == 0) { // only treat dot as a method separator if not inside a square bracket block // as dots can be used in key names when accessing maps // a dit denotes end of this method and a new method is to be invoked String s = sb.toString(); // reset sb sb.setLength(0); // pass over ? to the new method if (s.endsWith("?")) { sb.append("?"); s = s.substring(0, s.length() - 1); } // add the method methods.add(s); // reset j to begin a new method j = 0; } else if (ch == ']' && parenthesisBracketCnt == 0) { // append ending ] to method name sb.append(ch); String s = sb.toString(); // reset sb sb.setLength(0); // add the method methods.add(s); // reset j to begin a new method j = 0; // no more square bracket squareBracketCnt--; } // and don't lose the char if its not an ] end marker (as we already added that) if (ch != ']' || parenthesisBracketCnt > 0) { sb.append(ch); } // only advance if already begun on the new method if (j > 0) { j++; } } } // add remainder in buffer when reached end of data if (!sb.isEmpty()) { methods.add(sb.toString()); } String last = methods.isEmpty() ? null : methods.get(methods.size() - 1); if (parenthesisBracketCnt > 0 && last != null) { // there is an unclosed parenthesis bracket on the last method, so it should end with a parenthesis if (last.contains("(") && !last.endsWith(")")) { throw new IllegalArgumentException("Method should end with parenthesis, was " + last); } } return methods; } public static String methodAsDoubleQuotes(String ognl) { StringBuilder sb = new StringBuilder(ognl.length() + 32); int singleBracketCnt = 0; int doubleBracketCnt = 0; for (int i = 0; i < ognl.length(); i++) { char ch = ognl.charAt(i); char next = i < ognl.length() - 1 ? ognl.charAt(i + 1) : 0; if (ch == '\\' && next == '\'') { if (singleBracketCnt % 2 != 0) { // its an escaped single quote inside an existing quote // then unescape it sb.append('\''); // and skip over to next i++; continue; } } if (doubleBracketCnt % 2 == 0 && ch == '\'') { singleBracketCnt++; sb.append('"'); } else if (singleBracketCnt % 2 == 0 && ch == '"') { doubleBracketCnt++; sb.append('"'); } else { sb.append(ch); } } return sb.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy