Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/test/functional/cmdline_options_tester/src/Tokenizer.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2013, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
import java.util.ArrayList;
23
import java.util.List;
24
25
26
/**
27
* <br/>The Tokenizer class converts a command string into a command array with arguments split up in it.
28
* <br/>In this case, all parts of the command line would be scanned for purpose of splitting.
29
* <br/>
30
* <br/>The main operations includes:
31
* <br/>1) A well-quoted classpath is treated as a single argument (e.g. "/FOOPATH/.../foo.jar" or "/FOOPATH/"foo1.jar:"/FOOPATH/"foo2.jar)
32
* <br/>2) White spaces between arguments of command are ignored when scanning the command string.
33
* <br/>3) Arguments without white spaces involved would be filled into the command array eventually without further processing.
34
* <br/>
35
* <br/>Error condition:
36
* <br/>If open/close double-quotes are missing in the command line, an error message prompting tester with the error
37
* <br/>would be thrown out as an exception to the test framework.
38
* <br/>
39
* <br/>NOTE:
40
* <br/>1) Only double-quotes(") are accepted in Tokenizer and single-quotes(') cannot be used as delimiters.
41
* <br/>1) Non-quoted and quoted portions of an argument would be concatenated as long as they are part of the same argument.
42
* <br/>1) A quote(") itself would not be included in any argument of the command array.
43
* <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.
44
* <br/>3) No support of escapes or nested quoted strings.
45
* <br/>4) Escape characters (e.g. \b, \n, \t) in the classpath would be interpreted into two individual characters if detected.
46
*
47
* @author Cheng Jin and Francis Bogsanyi
48
* @version 1.0
49
*/
50
class Tokenizer {
51
52
private int index = 0;
53
private final String buffer;
54
55
/**
56
* Accepts a command string
57
* @param b a command string passed in for splitting
58
*/
59
private Tokenizer(String b) {
60
buffer = b;
61
}
62
63
/**
64
* Ignore the white spaces between arguments in the command string.
65
*/
66
private void skipWhitespace() {
67
while ((index < buffer.length()) && Character.isWhitespace(buffer.charAt(index))) {
68
index++;
69
}
70
}
71
72
/**
73
* Extract double-quoted classpaths from the command string to form a single argument if spotted.
74
*/
75
private String token() throws Exception {
76
String tok = "";
77
skipWhitespace();
78
79
/**
80
* The external while loop begins once a non-white-space character is encountered for the first time;
81
* otherwise it will ends up returning an empty argument to be ignored in forming the command array.
82
*
83
* Three cases are taken into account in the while loop:
84
* 1) Strings in double-quotes/single-quotes (an argument starting with double-quotes(") or single-quotes(')) are completely extracted from the command string,
85
* whether white spaces in the argument exist or not. Double-quotes/single-quotes themselves are discarded after extraction when scanning forward.
86
* 2) Normal arguments (no double-quotes/single-quotes occur in the argument) are split up and extracted with white spaces between arguments.
87
* 3) Following the original order of the command line, non-quoted portions of an argument would be extracted in case 2)
88
* and concatenated to quoted portions of the argument extracted in case 1) within the external while loop.
89
*/
90
while ((index < buffer.length()) && !Character.isWhitespace(buffer.charAt(index))) {
91
92
/**
93
* Case 1: Expect a double-quoted or single-quoted string once either is detected
94
*/
95
char delim = buffer.charAt(index);
96
if ((delim == '"') || (delim == '\'')) {
97
index++;
98
int i = index;
99
100
/**
101
* search for the closing quote since they appear in pairs.
102
*/
103
while ((i < buffer.length()) && (buffer.charAt(i) != delim)) {
104
i++;
105
}
106
107
/**
108
* Throw out an exception if either of the quotes pair is missing
109
*/
110
if (i == buffer.length()) {
111
throw new Exception("TEST CMD FORMAT ERROR: Quote is missing in the path of .jar file: " + buffer);
112
}
113
114
tok += buffer.substring(index, i);
115
116
/**
117
* In quoted case, it will move forward by one character because the current character is known as a quote(" or ')
118
* or the end of command string.
119
*/
120
index = i + 1;
121
} else {
122
123
/**
124
* Case 2: normal arguments or non-quoted portions of an argument are scanned
125
*/
126
int i = index;
127
128
while ((i < buffer.length()) && (buffer.charAt(i) != '"') && !Character.isWhitespace(buffer.charAt(i))) {
129
i++;
130
}
131
132
tok += buffer.substring(index, i);
133
134
/**
135
* In non-quoted case, the current character will be judged later by the external while loop
136
* as well as the if-statement in Case 1 if required. Whether it is a white space, a double-quote(")
137
* or the end of command string has not yet be decided at this point.
138
* Thus, the current character has to be counted in for the later judgment and can't be skipper over.
139
*/
140
index = i;
141
}
142
}
143
144
return tok;
145
}
146
147
/**
148
* Convert a command string to a command array with all arguments split in it.
149
* @param buffer a command string passed in for splitting
150
* @return command a command array after splitting-up
151
*/
152
public static String[] tokenize(String buffer) throws Exception {
153
154
List<String> result = new ArrayList<String>();
155
Tokenizer t = new Tokenizer(buffer);
156
while (t.index < buffer.length()) {
157
String token = t.token();
158
if (!token.isEmpty()) {
159
result.add(token);
160
}
161
}
162
163
String[] command = new String[result.size()];
164
result.toArray(command);
165
166
return command;
167
}
168
}
169
170