19fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann/******************************************************************************* 2b9d1b54e300318b470d9fedccc69d75187016444Evgeny Mandrikov * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors 39fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * All rights reserved. This program and the accompanying materials 49fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * are made available under the terms of the Eclipse Public License v1.0 59fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * which accompanies this distribution, and is available at 69fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * http://www.eclipse.org/legal/epl-v10.html 79fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * 89fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Contributors: 99fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Marc R. Hoffmann - initial API and implementation 109fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * 119fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann *******************************************************************************/ 129fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmannpackage org.jacoco.core.runtime; 139fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 149fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmannimport java.util.ArrayList; 159fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmannimport java.util.List; 169fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 179fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann/** 189fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Internal utility to parse and create command lines arguments. 199fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann */ 209fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmannfinal class CommandLineSupport { 219fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 229fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final char BLANK = ' '; 239fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final char QUOTE = '"'; 249fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final char SLASH = '\\'; 259fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 269fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann /** 279fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Quotes a single command line argument if necessary. 289fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * 299fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @param arg 309fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * command line argument 319fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @return quoted argument 329fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann */ 339fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann static String quote(final String arg) { 349fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann final StringBuilder escaped = new StringBuilder(); 359fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann for (final char c : arg.toCharArray()) { 369fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (c == QUOTE || c == SLASH) { 379fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann escaped.append(SLASH); 389fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 399fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann escaped.append(c); 409fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 419fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (arg.indexOf(BLANK) != -1 || arg.indexOf(QUOTE) != -1) { 429fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann escaped.insert(0, QUOTE).append(QUOTE); 439fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 449fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann return escaped.toString(); 459fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 469fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 479fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann /** 489fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Builds a single command line string from the given argument list. 499fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Arguments are quoted when necessary. 509fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * 519fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @param args 529fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * command line arguments 539fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @return combined command line 549fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann */ 559fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann static String quote(final List<String> args) { 569fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann final StringBuilder result = new StringBuilder(); 579fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann boolean seperate = false; 589fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann for (final String arg : args) { 599fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (seperate) { 609fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann result.append(BLANK); 619fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 629fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann result.append(quote(arg)); 639fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann seperate = true; 649fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 659fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann return result.toString(); 669fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 679fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 689fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann /** 699fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * Splits a command line into single arguments and removes quotes if 709fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * present. 719fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * 729fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @param commandline 739fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * combinded command line 749fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann * @return list of arguments 759fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann */ 769fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann static List<String> split(final String commandline) { 779fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (commandline == null || commandline.length() == 0) { 789fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann return new ArrayList<String>(); 799fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 809fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann final List<String> args = new ArrayList<String>(); 819fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann final StringBuilder current = new StringBuilder(); 829fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann int mode = M_STRIPWHITESPACE; 839fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann int endChar = BLANK; 849fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann for (final char c : commandline.toCharArray()) { 859fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann switch (mode) { 869fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann case M_STRIPWHITESPACE: 879fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (!Character.isWhitespace(c)) { 889fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (c == QUOTE) { 899fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann endChar = QUOTE; 909fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } else { 919fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.append(c); 929fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann endChar = BLANK; 939fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 949fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann mode = M_PARSEARGUMENT; 959fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 969fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann break; 979fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann case M_PARSEARGUMENT: 989fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (c == endChar) { 999fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann addArgument(args, current); 1009fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann mode = M_STRIPWHITESPACE; 1019fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } else if (c == SLASH) { 1029fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.append(SLASH); 1039fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann mode = M_ESCAPED; 1049fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } else { 1059fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.append(c); 1069fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1079fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann break; 1089fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann case M_ESCAPED: 1099fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (c == QUOTE || c == SLASH) { 1109fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.setCharAt(current.length() - 1, c); 1119fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } else if (c == endChar) { 1129fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann addArgument(args, current); 1139fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann mode = M_STRIPWHITESPACE; 1149fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } else { 1159fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.append(c); 1169fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1179fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann mode = M_PARSEARGUMENT; 118e35a34adcc3a47eac6723533e811e52c288d4dd5Mirko Friedenhagen break; 1199fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1209fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1219fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann addArgument(args, current); 1229fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann return args; 1239fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1249fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 1259fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static void addArgument(final List<String> args, 1269fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann final StringBuilder current) { 1279fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann if (current.length() > 0) { 1289fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann args.add(current.toString()); 1299fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann current.setLength(0); 1309fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1319fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1329fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 1339fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final int M_STRIPWHITESPACE = 0; 1349fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final int M_PARSEARGUMENT = 1; 1359fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private static final int M_ESCAPED = 2; 1369fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann 1379fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann private CommandLineSupport() { 1389fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann // no instances 1399fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann } 1409fdd14bd5cf0ad765135c8466dcaa9921c72c74bMarc R. Hoffmann} 141