Path: blob/master/test/functional/cmdline_options_tester/src/Tokenizer.java
6004 views
/*******************************************************************************1* Copyright (c) 2013, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21import java.util.ArrayList;22import java.util.List;232425/**26* <br/>The Tokenizer class converts a command string into a command array with arguments split up in it.27* <br/>In this case, all parts of the command line would be scanned for purpose of splitting.28* <br/>29* <br/>The main operations includes:30* <br/>1) A well-quoted classpath is treated as a single argument (e.g. "/FOOPATH/.../foo.jar" or "/FOOPATH/"foo1.jar:"/FOOPATH/"foo2.jar)31* <br/>2) White spaces between arguments of command are ignored when scanning the command string.32* <br/>3) Arguments without white spaces involved would be filled into the command array eventually without further processing.33* <br/>34* <br/>Error condition:35* <br/>If open/close double-quotes are missing in the command line, an error message prompting tester with the error36* <br/>would be thrown out as an exception to the test framework.37* <br/>38* <br/>NOTE:39* <br/>1) Only double-quotes(") are accepted in Tokenizer and single-quotes(') cannot be used as delimiters.40* <br/>1) Non-quoted and quoted portions of an argument would be concatenated as long as they are part of the same argument.41* <br/>1) A quote(") itself would not be included in any argument of the command array.42* <br/>2) An well-quoted empty argument (e.g. "/FOOPATH/" expanding to "") is possible for tester but would be ignored eventually in the command array.43* <br/>3) No support of escapes or nested quoted strings.44* <br/>4) Escape characters (e.g. \b, \n, \t) in the classpath would be interpreted into two individual characters if detected.45*46* @author Cheng Jin and Francis Bogsanyi47* @version 1.048*/49class Tokenizer {5051private int index = 0;52private final String buffer;5354/**55* Accepts a command string56* @param b a command string passed in for splitting57*/58private Tokenizer(String b) {59buffer = b;60}6162/**63* Ignore the white spaces between arguments in the command string.64*/65private void skipWhitespace() {66while ((index < buffer.length()) && Character.isWhitespace(buffer.charAt(index))) {67index++;68}69}7071/**72* Extract double-quoted classpaths from the command string to form a single argument if spotted.73*/74private String token() throws Exception {75String tok = "";76skipWhitespace();7778/**79* The external while loop begins once a non-white-space character is encountered for the first time;80* otherwise it will ends up returning an empty argument to be ignored in forming the command array.81*82* Three cases are taken into account in the while loop:83* 1) Strings in double-quotes/single-quotes (an argument starting with double-quotes(") or single-quotes(')) are completely extracted from the command string,84* whether white spaces in the argument exist or not. Double-quotes/single-quotes themselves are discarded after extraction when scanning forward.85* 2) Normal arguments (no double-quotes/single-quotes occur in the argument) are split up and extracted with white spaces between arguments.86* 3) Following the original order of the command line, non-quoted portions of an argument would be extracted in case 2)87* and concatenated to quoted portions of the argument extracted in case 1) within the external while loop.88*/89while ((index < buffer.length()) && !Character.isWhitespace(buffer.charAt(index))) {9091/**92* Case 1: Expect a double-quoted or single-quoted string once either is detected93*/94char delim = buffer.charAt(index);95if ((delim == '"') || (delim == '\'')) {96index++;97int i = index;9899/**100* search for the closing quote since they appear in pairs.101*/102while ((i < buffer.length()) && (buffer.charAt(i) != delim)) {103i++;104}105106/**107* Throw out an exception if either of the quotes pair is missing108*/109if (i == buffer.length()) {110throw new Exception("TEST CMD FORMAT ERROR: Quote is missing in the path of .jar file: " + buffer);111}112113tok += buffer.substring(index, i);114115/**116* In quoted case, it will move forward by one character because the current character is known as a quote(" or ')117* or the end of command string.118*/119index = i + 1;120} else {121122/**123* Case 2: normal arguments or non-quoted portions of an argument are scanned124*/125int i = index;126127while ((i < buffer.length()) && (buffer.charAt(i) != '"') && !Character.isWhitespace(buffer.charAt(i))) {128i++;129}130131tok += buffer.substring(index, i);132133/**134* In non-quoted case, the current character will be judged later by the external while loop135* as well as the if-statement in Case 1 if required. Whether it is a white space, a double-quote(")136* or the end of command string has not yet be decided at this point.137* Thus, the current character has to be counted in for the later judgment and can't be skipper over.138*/139index = i;140}141}142143return tok;144}145146/**147* Convert a command string to a command array with all arguments split in it.148* @param buffer a command string passed in for splitting149* @return command a command array after splitting-up150*/151public static String[] tokenize(String buffer) throws Exception {152153List<String> result = new ArrayList<String>();154Tokenizer t = new Tokenizer(buffer);155while (t.index < buffer.length()) {156String token = t.token();157if (!token.isEmpty()) {158result.add(token);159}160}161162String[] command = new String[result.size()];163result.toArray(command);164165return command;166}167}168169170