org.jenkinsci.plugins.tokenmacro.Tokenizer.java Source code

Java tutorial

Introduction

Here is the source code for org.jenkinsci.plugins.tokenmacro.Tokenizer.java

Source

/*
 * The MIT License
 *
 * Copyright 2009- Kyle Sweeney, CloudBees, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.jenkinsci.plugins.tokenmacro;

import com.google.common.base.Supplier;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parses strings with macro references.
 *
 * @author kyle.sweeney@valtech.com
 * @author Kohsuke Kawaguchi
 */
class Tokenizer {

    private static final String tokenNameRegex = "[a-zA-Z0-9_]+";

    private static final String numberRegex = "-?[0-9]+(\\.[0-9]*)?";

    private static final String boolRegex = "(true)|(false)";
    // Sequence of (1) not \ " CR LF and (2) \ followed by non line terminator

    private static final String stringRegex = "\"([^\\\\\"\\r\\n]|(\\\\.))*\"";

    private static final String valueRegex = "(" + numberRegex + ")|(" + boolRegex + ")|(" + stringRegex + ")";

    private static final String spaceRegex = "[ \\t]*";

    private static final String argRegex = "(" + tokenNameRegex + ")" + spaceRegex + "=" + spaceRegex + "("
            + valueRegex + ")";

    private static final String argsRegex = "((" + spaceRegex + "," + spaceRegex + argRegex + ")*)";

    private static final String delimitedTokenRegex = "\\{" + spaceRegex + "(" + tokenNameRegex + ")" + argsRegex
            + spaceRegex + "\\}";

    private static final String tokenRegex = "\\$((" + tokenNameRegex + ")|(" + delimitedTokenRegex + "))";

    private static final Pattern argPattern = Pattern.compile(argRegex);

    private static final Pattern tokenPattern = Pattern.compile(tokenRegex);

    private final Matcher tokenMatcher;

    private String tokenName = null;

    private ListMultimap<String, String> args = null;

    Tokenizer(String origText) {
        tokenMatcher = tokenPattern.matcher(origText);
    }

    String getTokenName() {
        return tokenName;
    }

    ListMultimap<String, String> getArgs() {
        return args;
    }

    String group() {
        return tokenMatcher.group();
    }

    boolean find() {
        if (tokenMatcher.find()) {
            tokenName = tokenMatcher.group(2);
            if (tokenName == null) {
                tokenName = tokenMatcher.group(4);
            }
            args = Multimaps.newListMultimap(new TreeMap<String, Collection<String>>(),
                    new Supplier<List<String>>() {
                        public List<String> get() {
                            return new ArrayList<String>();
                        }
                    });
            if (tokenMatcher.group(5) != null) {
                parseArgs(tokenMatcher.group(5), args);
            }
            return true;
        } else {
            return false;
        }
    }

    static void parseArgs(String argsString, ListMultimap<String, String> args) {
        Matcher argMatcher = argPattern.matcher(argsString);
        while (argMatcher.find()) {
            String arg;
            if (argMatcher.group(3) != null) {
                // number
                arg = argMatcher.group(3);
                //                if (argMatcher.group(4) != null) {
                //                    arg = Float.valueOf();
                //                } else {
                //                    arg = Integer.valueOf(argMatcher.group(3));
                //                }
            } else if (argMatcher.group(5) != null) {
                // boolean
                if (argMatcher.group(6) != null) {
                    //                    arg = Boolean.TRUE;
                    arg = "true";
                } else {
                    //                    arg = Boolean.FALSE;
                    arg = "false";
                }
            } else { // if (argMatcher.group(8) != null) {
                // string
                arg = unescapeString(argMatcher.group(8));
            }
            args.put(argMatcher.group(1), arg);
        }
    }

    void appendReplacement(StringBuffer sb, String replacement) {
        tokenMatcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
    }

    void appendTail(StringBuffer sb) {
        tokenMatcher.appendTail(sb);
    }

    /**
     * Replaces all the printf-style escape sequences in a string
     * with the appropriate characters.
     *
     * @param escapedString the string containing escapes
     * @return the string with all the escape sequences replaced
     */
    public static String unescapeString(String escapedString) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < escapedString.length() - 1; ++i) {
            char c = escapedString.charAt(i);
            if (c == '\\') {
                ++i;
                sb.append(unescapeChar(escapedString.charAt(i)));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    private static char unescapeChar(char escapedChar) {
        switch (escapedChar) {
        case 'b':
            return '\b';
        case 't':
            return '\t';
        case 'n':
            return '\n';
        case 'f':
            return '\f';
        case 'r':
            return '\r';
        default:
            return escapedChar;
        }
    }
}