Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionsSetup.java
41155 views
1
/*
2
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
package vm.share.options;
24
25
import java.util.Map;
26
import java.util.LinkedHashMap;
27
import java.util.List;
28
import java.util.ArrayList;
29
import java.util.LinkedList;
30
import java.util.Iterator;
31
import java.lang.reflect.Field;
32
import java.lang.reflect.Modifier;
33
import java.io.PrintStream;
34
import nsk.share.TestBug;
35
import nsk.share.log.LogSupport;
36
37
class OptionsSetup {
38
private LogSupport log = new LogSupport();
39
private boolean verbose = true;
40
private Object test;
41
private String[] args;
42
private OptionHandler unknownOptionHandler;
43
44
private int argIndex = 0;
45
private Map<String, OptionDefinition> optionDefs = new LinkedHashMap<String, OptionDefinition>(); // Use LinkedHashMap to ensure order of options
46
private List<OptionDefinition> unconfiguredOptionsList = new ArrayList<OptionDefinition>();
47
private List<OptionDefinition> unconfiguredOptionList = new ArrayList<OptionDefinition>();
48
private Map<String, Object> optionValues = new LinkedHashMap<String, Object>();
49
50
public OptionsSetup(Object test, String[] args, OptionHandler unknownOptionHandler) {
51
this.test = test;
52
this.args = args;
53
this.unknownOptionHandler = unknownOptionHandler;
54
log.setDebugEnabled(verbose);
55
}
56
57
public void run() {
58
searchAnnotations(test, null);
59
while (argIndex < args.length) {
60
process1Arg();
61
}
62
setDefaultValues();
63
checkMandatoryOptions();
64
if (unconfiguredOptionsList.size() > 0) {
65
for (OptionDefinition optDef : unconfiguredOptionsList)
66
log.info("Unconfigured option: " + optDef);
67
throw new TestBug("Some options are unconfigured");
68
}
69
}
70
71
private void checkMandatoryOptions() {
72
for (Map.Entry<String, OptionDefinition> e : optionDefs.entrySet()) {
73
String name = e.getKey();
74
OptionDefinition optDef = e.getValue();
75
if (optDef.getDefaultValue() == null && !optionValues.containsKey(name))
76
throw new TestBug("Mandatory option is not specified: -" + name);
77
}
78
}
79
80
private void setDefaultValues() {
81
for (Iterator<OptionDefinition> it = unconfiguredOptionList.iterator(); it.hasNext(); ) {
82
OptionDefinition optDef = it.next();
83
String value = optDef.getDefaultValue();
84
if (value == null)
85
continue;
86
setOptionValue(optDef, value);
87
it.remove();
88
if (unconfiguredOptionsList.contains(optDef))
89
unconfiguredOptionsList.remove(optDef);
90
}
91
92
for (Iterator<OptionDefinition> it = unconfiguredOptionsList.iterator(); it.hasNext(); ) {
93
OptionDefinition optDef = it.next();
94
if (optionsAnnotation(optDef.getOwner(), optDef.getField(), null, optDef, true))
95
it.remove();
96
}
97
}
98
99
private void process1Arg() {
100
String arg = args[argIndex++];
101
//log.debug("Processing argument: " + arg);
102
if (!arg.startsWith("-")) {
103
processUnknownArg(arg);
104
return;
105
}
106
String opt = arg.substring(1);
107
String value = null;
108
int i = opt.indexOf('=');
109
if (i != -1) {
110
value = opt.substring(i + 1);
111
opt = opt.substring(0, i);
112
}
113
if (opt.equals("help")) {
114
printHelp();
115
throw new TestBug("-help was specified");
116
}
117
if (!optionDefs.containsKey(opt)) {
118
if (value == null && argIndex < args.length)
119
value = args[argIndex++];
120
// We need to try to resolve default values of all unconfigured fields because one of them may potentially have this option
121
setDefaultValues();
122
if (!optionDefs.containsKey(opt)) {
123
processUnknownOpt(opt, value);
124
return;
125
}
126
}
127
OptionDefinition optDef = optionDefs.get(opt);
128
Field f = optDef.getField();
129
// Handle boolean omitted value
130
if (value == null && (argIndex >= args.length || args[argIndex].startsWith("-"))) {
131
if (f.getType() == boolean.class || f.getType() == Boolean.class) {
132
value = "true";
133
}
134
}
135
if (value == null) {
136
if (argIndex >= args.length)
137
throw new TestBug("Missing value for option -" + opt);
138
value = args[argIndex++];
139
}
140
setOptionValue(optDef, value);
141
if (unconfiguredOptionList.contains(optDef)){
142
unconfiguredOptionList.remove(optDef);
143
}
144
}
145
146
private void setOptionValue(OptionDefinition optDef, String value) {
147
Object ovalue = null;
148
if (optDef.hasFactory()) {
149
ovalue = optDef.getFactory().getObject(value);
150
} else {
151
ovalue = PrimitiveParser.parse(value, optDef.getField().getType());
152
}
153
optionValues.put(optDef.getName(), ovalue);
154
try {
155
Field f = optDef.getField();
156
Object o = optDef.getOwner();
157
f.set(o, ovalue);
158
if (f.isAnnotationPresent(Options.class)) {
159
if (!optionsAnnotation(o, f, optDef.getPrefix(), optDef, false))
160
throw new TestBug("Unexpected (bug in framework?): optionsAnnotation returned null: " + optDef);
161
if (unconfiguredOptionsList.contains(optDef))
162
unconfiguredOptionsList.remove(optDef);
163
}
164
} catch (IllegalArgumentException e) {
165
throw new TestBug("Exception setting field value for option " + optDef.getName(), e);
166
} catch (IllegalAccessException e) {
167
throw new TestBug("Exception setting field value for option " + optDef.getName(), e);
168
}
169
}
170
171
private void processUnknownArg(String arg) {
172
if (unknownOptionHandler != null)
173
unknownOptionHandler.argument(arg);
174
else
175
throw new TestBug("Invalid argument: " + arg);
176
}
177
178
private void processUnknownOpt(String opt, String value) {
179
if (unknownOptionHandler != null)
180
unknownOptionHandler.option(opt, value);
181
else
182
throw new TestBug("Invalid option: '" + opt + "', value: '" + value + "'");
183
}
184
185
private void searchAnnotations(Object o, String prefix) {
186
Class<?> cl0 = o.getClass();
187
//log.debug("Looking for annotations for object " + o + ", class " + cl0);
188
List<Class> classes = new LinkedList<Class>();
189
while (cl0.getSuperclass() != null) {
190
classes.add(0, cl0); // Add to the beginning to ensure the option order is from superclass to subclass
191
cl0 = cl0.getSuperclass();
192
}
193
for (Class<?> cl : classes) {
194
for (Field f : cl.getDeclaredFields()) {
195
OptionDefinition optDef = null;
196
if (f.isAnnotationPresent(Option.class)) {
197
optDef = optionAnnotation(o, f, prefix);
198
if (optDef != null) {
199
unconfiguredOptionList.add(optDef);
200
}
201
}
202
if (f.isAnnotationPresent(Options.class)) {
203
if (!optionsAnnotation(o, f, prefix, optDef, false)) {
204
if (!unconfiguredOptionsList.contains(optDef))
205
unconfiguredOptionsList.add(optDef);
206
}
207
}
208
}
209
}
210
}
211
212
private boolean optionsAnnotation(Object o, Field f, String prefix, OptionDefinition optDef, boolean useDefault) {
213
if (Modifier.isStatic(f.getModifiers()))
214
throw new OptionError("@Options annotation is not allowed at static field", optDef);
215
if (!Object.class.isAssignableFrom(f.getDeclaringClass()))
216
throw new OptionError("@Options annotation is only allowed on object types", optDef);
217
//log.debug("Processing @Options annotation: object " + o + ", field " + f + ", prefix " + prefix);
218
Object v = null;
219
try {
220
f.setAccessible(true);
221
v = f.get(o);
222
} catch (IllegalAccessException e) {
223
throw new OptionError("Exception getting value of field ", e, optDef);
224
}
225
if (v == null) {
226
if (optDef == null)
227
throw new OptionError("Value of field is null and no @Option annotation is present", optDef);
228
if (!optDef.hasFactory())
229
throw new OptionError("Value of field is null and no @Option annotation does not have factory", optDef);
230
if (useDefault) {
231
setOptionValue(optDef, optDef.getDefaultValue());
232
try {
233
v = f.get(o);
234
} catch (IllegalAccessException e) {
235
throw new OptionError("Exception getting value of field ", e, optDef);
236
}
237
}
238
if (v == null) {
239
// We cannot setup it right away, so it is stored until value is set
240
return false;
241
} else
242
return true; // setOption Value already searched annotations
243
}
244
Options opts = f.getAnnotation(Options.class);
245
String vprefix = opts.prefix();
246
if (vprefix.equals(Options.defPrefix))
247
vprefix = null;
248
if (vprefix != null) {
249
if (prefix != null)
250
prefix = prefix + "." + vprefix;
251
else
252
prefix = vprefix;
253
}
254
searchAnnotations(v, prefix);
255
return true;
256
}
257
258
private OptionDefinition optionAnnotation(Object o, Field f, String prefix) {
259
//log.debug("Processing @Option annotation: object " + o + ", field " + f + ", prefix " + prefix);
260
f.setAccessible(true);
261
Option opt = f.getAnnotation(Option.class);
262
String name = opt.name();
263
if (name.equals(Option.defName))
264
name = f.getName(); // option name defaults to field name
265
if (prefix != null)
266
name = prefix + "." + name;
267
if (optionDefs.containsKey(name))
268
throw new TestBug("Option is already defined: " + name);
269
String defaultValue = opt.default_value();
270
if (defaultValue.equals(Option.defDefaultValue))
271
defaultValue = null; // default value defaults to null
272
String description = opt.description();
273
if (description.equals(Option.defDescription))
274
description = null;
275
if (description == null) {
276
if (name.equals("log") || name.endsWith(".log")) {
277
try {
278
f.set(o, log);
279
} catch (IllegalAccessException e) {
280
throw new TestBug("Exception setting log field of " + o, e);
281
}
282
return null;
283
} else
284
throw new TestBug("@Option annotation should always have description set: " + name + ", field: " + f);
285
}
286
Class<? extends OptionObjectFactory> factory = opt.factory();
287
//log.debug("Factory: " + factory);
288
if (factory.equals(OptionObjectFactory.class))
289
factory = null;
290
OptionDefinition optDef = new OptionDefinition(
291
prefix,
292
name,
293
description,
294
defaultValue,
295
factory,
296
f,
297
o
298
);
299
optionDefs.put(name, optDef);
300
//log.debug("Added option definition: " + optDef);
301
return optDef;
302
}
303
304
private void printHelp() {
305
PrintStream out = System.out;
306
out.println(" Supported options:");
307
out.println(" -help");
308
out.println(" Show this help screen");
309
for (Map.Entry<String, OptionDefinition> entry : optionDefs.entrySet()) {
310
String opt = entry.getKey();
311
OptionDefinition optDef = entry.getValue();
312
out.println(" -" + opt + " <" + optDef.getPlaceHolder() + ">");
313
out.print(" " + optDef.getDescription() + " ");
314
if (optDef.getDefaultValue() != null) {
315
out.println("(default: " + optDef.getDefaultValue() + ")");
316
} else {
317
out.println("(mandatory)");
318
}
319
if (optDef.hasFactory()) {
320
OptionObjectFactory factory = optDef.getFactory();
321
for (String key : factory.getPossibleValues()) {
322
out.println(" " + key + ": " + factory.getParameterDescription(key));
323
}
324
}
325
}
326
}
327
}
328
329