| 
 | 1 | +package com.github.eirslett.maven.plugins.frontend.lib;  | 
 | 2 | + | 
 | 3 | +import java.util.ArrayList;  | 
 | 4 | +import java.util.Collections;  | 
 | 5 | +import java.util.LinkedList;  | 
 | 6 | +import java.util.List;  | 
 | 7 | + | 
 | 8 | +class YarnArgumentsParser {  | 
 | 9 | + | 
 | 10 | +  private final List<String> additionalArguments;  | 
 | 11 | + | 
 | 12 | +  YarnArgumentsParser() {  | 
 | 13 | +    this(Collections.<String>emptyList());  | 
 | 14 | +  }  | 
 | 15 | + | 
 | 16 | +  YarnArgumentsParser(List<String> additionalArguments) {  | 
 | 17 | +    this.additionalArguments = additionalArguments;  | 
 | 18 | +  }  | 
 | 19 | + | 
 | 20 | +  /**  | 
 | 21 | +   * Parses a given string of arguments, splitting it by characters that are whitespaces according to {@link Character#isWhitespace(char)}.  | 
 | 22 | +   * <p>  | 
 | 23 | +   * This method respects quoted arguments. Meaning that whitespaces appearing phrases that are enclosed by an opening  | 
 | 24 | +   * single or double quote and a closing single or double quote or the end of the string will not be considered.  | 
 | 25 | +   * <p>  | 
 | 26 | +   * All characters excluding whitespaces considered for splitting stay in place.  | 
 | 27 | +   * <p>  | 
 | 28 | +   * Examples:  | 
 | 29 | +   * "foo bar" will be split to ["foo", "bar"]  | 
 | 30 | +   * "foo \"bar foobar\"" will be split to ["foo", "\"bar foobar\""]  | 
 | 31 | +   * "foo 'bar" will be split to ["foo", "'bar"]  | 
 | 32 | +   *  | 
 | 33 | +   * @param args a string of arguments  | 
 | 34 | +   * @return an mutable copy of the list of all arguments  | 
 | 35 | +   */  | 
 | 36 | +  List<String> parse(String args) {  | 
 | 37 | +    if (args == null || "null".equals(args) || args.isEmpty()) {  | 
 | 38 | +      return Collections.emptyList();  | 
 | 39 | +    }  | 
 | 40 | + | 
 | 41 | +    final List<String> arguments = new LinkedList<>();  | 
 | 42 | + | 
 | 43 | +    for (String argument : this.additionalArguments) {  | 
 | 44 | +      ArgumentsParser.addArgument(argument, arguments);  | 
 | 45 | +    }  | 
 | 46 | + | 
 | 47 | +    final StringBuilder argumentBuilder = new StringBuilder();  | 
 | 48 | +    Character quote = null;  | 
 | 49 | + | 
 | 50 | +    for (int i = 0, l = args.length(); i < l; i++) {  | 
 | 51 | +      char c = args.charAt(i);  | 
 | 52 | + | 
 | 53 | +      if (Character.isWhitespace(c) && quote == null) {  | 
 | 54 | +        ArgumentsParser.addArgument(argumentBuilder, arguments);  | 
 | 55 | +        continue;  | 
 | 56 | +      } else if (c == '"' || c == '\'') {  | 
 | 57 | +        // explicit boxing allows us to use object caching of the Character class  | 
 | 58 | +        Character currentQuote = Character.valueOf(c);  | 
 | 59 | +        if (quote == null) {  | 
 | 60 | +          quote = currentQuote;  | 
 | 61 | +        } else if (quote.equals(currentQuote)){  | 
 | 62 | +          quote = null;  | 
 | 63 | +        } // else  | 
 | 64 | +        // we ignore the case when a quoted argument contains the other kind of quote  | 
 | 65 | +      }  | 
 | 66 | + | 
 | 67 | +      argumentBuilder.append(c);  | 
 | 68 | +    }  | 
 | 69 | + | 
 | 70 | +    ArgumentsParser.addArgument(argumentBuilder, arguments);  | 
 | 71 | + | 
 | 72 | +    return new ArrayList<>(arguments);  | 
 | 73 | +  }  | 
 | 74 | +}  | 
0 commit comments