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

org.jolokia.util.EscapeUtil Maven / Gradle / Ivy

There is a newer version: 1.7.2
Show newest version
package org.jolokia.util;

/*
 * Copyright 2009-2013 Roland Huss
 *
 * Licensed 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.
 */

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Utility class for handling escaping of strings and paths.
 *
 * @author roland
 * @since 15.03.11
 */
public final class EscapeUtil {

    /**
     * Escape character used for path escaping as it can be used
     * in a regexp
     */
    public static final String PATH_ESCAPE = "!";

    /**
     * Escape character for escaping CSV type string as it can be used in a
     * regexp. E.g. a backslash (\ or "\\") must be doubled (\\ or "\\\\")
     */
    public static final String CSV_ESCAPE = "\\\\";
    
    // Compile patterns in advance and cache them
    static final Map SPLIT_PATTERNS = new HashMap();
    static {
        for (String param[] : new String[][] {
                { PATH_ESCAPE, "/"} ,
                { CSV_ESCAPE, ","},
                { CSV_ESCAPE, "="}
        }) {
            String esc = param[0];
            String del = param[1];
            SPLIT_PATTERNS.put(esc + del, createSplitPatterns(esc, del));
        }
    }

    private EscapeUtil() {}

    /**
     * Combine a list of strings to a single path with proper escaping.
     *
     * @param pParts parts to combine
     * @return the combined path
     */
    public static String combineToPath(List pParts) {
        if (pParts != null && pParts.size() > 0) {
            StringBuilder buf = new StringBuilder();
            Iterator it = pParts.iterator();
            while (it.hasNext()) {
                String part = it.next();
                buf.append(escapePart(part != null ? part : "*"));
                if (it.hasNext()) {
                    buf.append("/");
                }
            }
            return buf.toString();
        } else {
            return null;
        }
    }

    /**
     * Parse a string path and return a list of split up parts.
     *
     * @param pPath the path to parse. Can be null
     * @return list of path elements or null if the initial path is null.
     */
    public static List parsePath(String pPath) {
        // Special cases which simply implies 'no path'
        if (pPath == null || pPath.equals("") || pPath.equals("/")) {
            return null;
        }
        return replaceWildcardsWithNull(split(pPath, PATH_ESCAPE, "/"));
    }

    /**
     * Get the path as a reverse stack with the first element of the path on top
     *
     * @param pPath path to parse
     * @return stack of arguments in reverse order or an empty stack if path was null or empty
     */
    public static Stack extractElementsFromPath(String pPath) {
        return reversePath(parsePath(pPath));
    }

    /**
     * Reverse path and return as a stack. First path element is on top
     * of the stack.
     *
     * @param pathParts path to reverse
     * @return reversed path or an empty stack if no path parts are given. Never return null.
     */
    public static Stack reversePath(List pathParts) {
        Stack pathStack = new Stack();
        if (pathParts != null) {
            // Needs first extra argument at top of the stack
            for (int i = pathParts.size() - 1;i >=0;i--) {
                pathStack.push(pathParts.get(i));
            }
        }
        return pathStack;
    }

    /**
     * Split a string on a delimiter, respecting escaping with an escape char. Assuming
     * that a backslash (\) is used as escape char, then the following
     * replacement rules apply:
     *
     * 
    *
  • * \delimiter for the delimiter as literal *
  • *
  • * \\ for backslashes *
  • *
  • * \(everything else) is the same as (everything else). *
  • * * @param pArg argument to split * @param pEscape escape pattern as it can be used in a regular expression. * @param pDelimiter delimiter to use * @return the split string as list or an empty array if the argument was null */ public static List split(String pArg, String pEscape, String pDelimiter) { if (pArg != null) { ArrayList ret = new ArrayList(); Pattern[] pattern = SPLIT_PATTERNS.get(pEscape + pDelimiter); if (pattern == null) { pattern = createSplitPatterns(pEscape, pDelimiter); SPLIT_PATTERNS.put(pEscape + pDelimiter,pattern); } final Matcher m = pattern[0].matcher(pArg); while (m.find() && m.start(1) != pArg.length()) { // Finally unescape all escaped parts. Trailing escapes are captured before the delimiter applies String trailingEscapes = m.group(2); ret.add(pattern[1].matcher(m.group(1) + (trailingEscapes != null ? trailingEscapes : "")).replaceAll("$1")); } return ret; } else { return null; } } /** * Split but return an array which is never null (but might be empty) * * @param pArg argument to split * @param pEscape single character used for escaping * @param pDelimiter delimiter to use * @return the splitted string as list or an empty array if the argument was null */ public static String[] splitAsArray(String pArg, String pEscape, String pDelimiter) { if (pArg != null) { List elements = split(pArg, pEscape, pDelimiter); return elements.toArray(new String[elements.size()]); } else { return new String[0]; } } /** * Escape the delimiter in an argument with the given escape char. * * @param pArg string to add escapes to * @param pEscape the escape character (e.g. '\') * @param pDelimiter the delimiter to escape (e.g. ',') * @return the escaped char */ public static String escape(String pArg, String pEscape, String pDelimiter) { return pArg.replaceAll(pEscape, pEscape + pEscape).replaceAll(pDelimiter, pEscape + pDelimiter); } // =================================================================================== // Create a split pattern for a given delimiter private static Pattern[] createSplitPatterns(String pEscape, String pDel) { return new Pattern[] { // Escape ($1: Everything before the delimiter, $2: Trailing escaped values (optional) Pattern.compile("(.*?)" + // Any chars "(?:" + // The delimiter not preceded by an escape (but pairs of escape & value can be in // are allowed before nevertheless). A negative-look-before (? replaceWildcardsWithNull(List pParts) { if (pParts == null) { return null; } List ret = new ArrayList(pParts.size()); for (String part : pParts) { ret.add("*".equals(part) ? null : part); } return ret; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy