author | sundar |
Mon, 27 May 2013 20:41:34 +0530 | |
changeset 17776 | 59fb7b69846d |
parent 17749 | 0f0fad887be7 |
child 19459 | 79e75274df99 |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 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. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.runtime.options; |
|
27 |
||
28 |
import java.io.PrintWriter; |
|
29 |
import java.security.AccessController; |
|
30 |
import java.security.PrivilegedAction; |
|
31 |
import java.text.MessageFormat; |
|
32 |
import java.util.ArrayList; |
|
33 |
import java.util.Collection; |
|
34 |
import java.util.Collections; |
|
35 |
import java.util.Enumeration; |
|
36 |
import java.util.HashMap; |
|
37 |
import java.util.LinkedList; |
|
38 |
import java.util.List; |
|
39 |
import java.util.Locale; |
|
40 |
import java.util.Map; |
|
41 |
import java.util.MissingResourceException; |
|
42 |
import java.util.ResourceBundle; |
|
43 |
import java.util.StringTokenizer; |
|
44 |
import java.util.TimeZone; |
|
45 |
import java.util.TreeMap; |
|
46 |
import java.util.TreeSet; |
|
47 |
import jdk.nashorn.internal.runtime.Logging; |
|
48 |
import jdk.nashorn.internal.runtime.QuotedStringTokenizer; |
|
49 |
||
50 |
/** |
|
51 |
* Manages global runtime options. |
|
52 |
*/ |
|
53 |
public final class Options { |
|
54 |
/** Resource tag. */ |
|
55 |
private final String resource; |
|
56 |
||
57 |
/** Error writer. */ |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
58 |
private final PrintWriter err; |
16147 | 59 |
|
60 |
/** File list. */ |
|
61 |
private final List<String> files; |
|
62 |
||
63 |
/** Arguments list */ |
|
64 |
private final List<String> arguments; |
|
65 |
||
66 |
/** The options map of enabled options */ |
|
67 |
private final TreeMap<String, Option<?>> options; |
|
68 |
||
16533
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
69 |
/** System property that can be used for command line option propagation */ |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
70 |
private static final String NASHORN_ARGS_PROPERTY = "nashorn.args"; |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
71 |
|
16147 | 72 |
/** |
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
73 |
* Constructor |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
74 |
* |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
75 |
* Options will use System.err as the output stream for any errors |
16147 | 76 |
* |
77 |
* @param resource resource prefix for options e.g. "nashorn" |
|
78 |
*/ |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
79 |
public Options(final String resource) { |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
80 |
this(resource, new PrintWriter(System.err, true)); |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
81 |
} |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
82 |
|
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
83 |
/** |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
84 |
* Constructor |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
85 |
* |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
86 |
* @param resource resource prefix for options e.g. "nashorn" |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
87 |
* @param err error stream for reporting parse errors |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
88 |
*/ |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
89 |
public Options(final String resource, final PrintWriter err) { |
16147 | 90 |
this.resource = resource; |
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
91 |
this.err = err; |
16147 | 92 |
this.files = new ArrayList<>(); |
93 |
this.arguments = new ArrayList<>(); |
|
94 |
this.options = new TreeMap<>(); |
|
95 |
||
96 |
// set all default values |
|
97 |
for (final OptionTemplate t : Options.validOptions) { |
|
98 |
if (t.getDefaultValue() != null) { |
|
99 |
// populate from system properties |
|
100 |
final String v = getStringProperty(t.getKey(), null); |
|
101 |
if (v != null) { |
|
102 |
set(t.getKey(), createOption(t, v)); |
|
103 |
} else if (t.getDefaultValue() != null) { |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
104 |
set(t.getKey(), createOption(t, t.getDefaultValue())); |
16147 | 105 |
} |
106 |
} |
|
107 |
} |
|
108 |
} |
|
109 |
||
110 |
/** |
|
111 |
* Get the resource for this Options set, e.g. "nashorn" |
|
112 |
* @return the resource |
|
113 |
*/ |
|
114 |
public String getResource() { |
|
115 |
return resource; |
|
116 |
} |
|
117 |
||
118 |
@Override |
|
119 |
public String toString() { |
|
120 |
return options.toString(); |
|
121 |
} |
|
122 |
||
123 |
/** |
|
124 |
* Convenience function for getting system properties in a safe way |
|
125 |
||
126 |
* @param name of boolean property |
|
127 |
* @return true if set to true, false if unset or set to false |
|
128 |
*/ |
|
129 |
public static boolean getBooleanProperty(final String name) { |
|
130 |
name.getClass(); // null check |
|
131 |
if (!name.startsWith("nashorn.")) { |
|
132 |
throw new IllegalArgumentException(name); |
|
133 |
} |
|
134 |
||
135 |
return AccessController.doPrivileged( |
|
136 |
new PrivilegedAction<Boolean>() { |
|
137 |
@Override |
|
138 |
public Boolean run() { |
|
139 |
try { |
|
140 |
final String property = System.getProperty(name); |
|
141 |
return property != null && !"false".equalsIgnoreCase(property); |
|
142 |
} catch (final SecurityException e) { |
|
143 |
// if no permission to read, assume false |
|
144 |
return false; |
|
145 |
} |
|
146 |
} |
|
147 |
}); |
|
148 |
} |
|
149 |
||
150 |
/** |
|
151 |
* Convenience function for getting system properties in a safe way |
|
152 |
* |
|
153 |
* @param name of string property |
|
154 |
* @param defValue the default value if unset |
|
155 |
* @return string property if set or default value |
|
156 |
*/ |
|
157 |
public static String getStringProperty(final String name, final String defValue) { |
|
158 |
name.getClass(); // null check |
|
159 |
if (! name.startsWith("nashorn.")) { |
|
160 |
throw new IllegalArgumentException(name); |
|
161 |
} |
|
162 |
||
163 |
return AccessController.doPrivileged( |
|
164 |
new PrivilegedAction<String>() { |
|
165 |
@Override |
|
166 |
public String run() { |
|
167 |
try { |
|
168 |
return System.getProperty(name, defValue); |
|
169 |
} catch (final SecurityException e) { |
|
170 |
// if no permission to read, assume the default value |
|
171 |
return defValue; |
|
172 |
} |
|
173 |
} |
|
174 |
}); |
|
175 |
} |
|
176 |
||
177 |
/** |
|
178 |
* Convenience function for getting system properties in a safe way |
|
179 |
* |
|
180 |
* @param name of integer property |
|
181 |
* @param defValue the default value if unset |
|
182 |
* @return integer property if set or default value |
|
183 |
*/ |
|
184 |
public static int getIntProperty(final String name, final int defValue) { |
|
185 |
name.getClass(); // null check |
|
186 |
if (! name.startsWith("nashorn.")) { |
|
187 |
throw new IllegalArgumentException(name); |
|
188 |
} |
|
189 |
||
190 |
return AccessController.doPrivileged( |
|
191 |
new PrivilegedAction<Integer>() { |
|
192 |
@Override |
|
193 |
public Integer run() { |
|
194 |
try { |
|
195 |
return Integer.getInteger(name, defValue); |
|
196 |
} catch (final SecurityException e) { |
|
197 |
// if no permission to read, assume the default value |
|
198 |
return defValue; |
|
199 |
} |
|
200 |
} |
|
201 |
}); |
|
202 |
} |
|
203 |
||
204 |
/** |
|
205 |
* Return an option given its resource key. If the key doesn't begin with |
|
16272 | 206 |
* {@literal <resource>}.option it will be completed using the resource from this |
16147 | 207 |
* instance |
208 |
* |
|
209 |
* @param key key for option |
|
210 |
* @return an option value |
|
211 |
*/ |
|
212 |
public Option<?> get(final String key) { |
|
213 |
return options.get(key(key)); |
|
214 |
} |
|
215 |
||
216 |
/** |
|
217 |
* Return an option as a boolean |
|
218 |
* |
|
219 |
* @param key key for option |
|
220 |
* @return an option value |
|
221 |
*/ |
|
222 |
public boolean getBoolean(final String key) { |
|
223 |
final Option<?> option = get(key); |
|
224 |
return option != null ? (Boolean)option.getValue() : false; |
|
225 |
} |
|
226 |
||
227 |
/** |
|
228 |
* Return an option as a integer |
|
229 |
* |
|
230 |
* @param key key for option |
|
231 |
* @return an option value |
|
232 |
*/ |
|
233 |
public int getInteger(final String key) { |
|
234 |
final Option<?> option = get(key); |
|
235 |
return option != null ? (Integer)option.getValue() : 0; |
|
236 |
} |
|
237 |
||
238 |
/** |
|
239 |
* Return an option as a String |
|
240 |
* |
|
241 |
* @param key key for option |
|
242 |
* @return an option value |
|
243 |
*/ |
|
244 |
public String getString(final String key) { |
|
245 |
final Option<?> option = get(key); |
|
17519
19c9d2553e35
8013871: mem usage histograms enabled with compiler logging level set to more specific than or equals to info when --print-mem-usage flag is used
lagergren
parents:
17257
diff
changeset
|
246 |
if (option != null) { |
17257
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
247 |
final String value = (String)option.getValue(); |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
248 |
if(value != null) { |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
249 |
return value.intern(); |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
250 |
} |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
251 |
} |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
16533
diff
changeset
|
252 |
return null; |
16147 | 253 |
} |
254 |
||
255 |
/** |
|
256 |
* Set an option, overwriting an existing state if one exists |
|
257 |
* |
|
258 |
* @param key option key |
|
259 |
* @param option option |
|
260 |
*/ |
|
261 |
public void set(final String key, final Option<?> option) { |
|
262 |
options.put(key(key), option); |
|
263 |
} |
|
264 |
||
265 |
/** |
|
266 |
* Set an option as a boolean value, overwriting an existing state if one exists |
|
267 |
* |
|
268 |
* @param key option key |
|
269 |
* @param option option |
|
270 |
*/ |
|
271 |
public void set(final String key, final boolean option) { |
|
272 |
set(key, new Option<>(option)); |
|
273 |
} |
|
274 |
||
275 |
/** |
|
276 |
* Set an option as a String value, overwriting an existing state if one exists |
|
277 |
* |
|
278 |
* @param key option key |
|
279 |
* @param option option |
|
280 |
*/ |
|
281 |
public void set(final String key, final String option) { |
|
282 |
set(key, new Option<>(option)); |
|
283 |
} |
|
284 |
||
285 |
/** |
|
286 |
* Return the user arguments to the program, i.e. those trailing "--" after |
|
287 |
* the filename |
|
288 |
* |
|
289 |
* @return a list of user arguments |
|
290 |
*/ |
|
291 |
public List<String> getArguments() { |
|
292 |
return Collections.unmodifiableList(this.arguments); |
|
293 |
} |
|
294 |
||
295 |
/** |
|
296 |
* Return the JavaScript files passed to the program |
|
297 |
* |
|
298 |
* @return a list of files |
|
299 |
*/ |
|
300 |
public List<String> getFiles() { |
|
301 |
return Collections.unmodifiableList(files); |
|
302 |
} |
|
303 |
||
304 |
/** |
|
305 |
* Return the option templates for all the valid option supported. |
|
306 |
* |
|
307 |
* @return a collection of OptionTemplate objects. |
|
308 |
*/ |
|
309 |
public static Collection<OptionTemplate> getValidOptions() { |
|
310 |
return Collections.unmodifiableCollection(validOptions); |
|
311 |
} |
|
312 |
||
313 |
/** |
|
314 |
* Make sure a key is fully qualified for table lookups |
|
315 |
* |
|
316 |
* @param shortKey key for option |
|
317 |
* @return fully qualified key |
|
318 |
*/ |
|
319 |
private String key(final String shortKey) { |
|
320 |
String key = shortKey; |
|
321 |
while (key.startsWith("-")) { |
|
322 |
key = key.substring(1, key.length()); |
|
323 |
} |
|
324 |
key = key.replace("-", "."); |
|
325 |
final String keyPrefix = this.resource + ".option."; |
|
326 |
if (key.startsWith(keyPrefix)) { |
|
327 |
return key; |
|
328 |
} |
|
329 |
return keyPrefix + key; |
|
330 |
} |
|
331 |
||
332 |
static String getMsg(final String msgId, final String... args) { |
|
333 |
try { |
|
334 |
final String msg = Options.bundle.getString(msgId); |
|
335 |
if (args.length == 0) { |
|
336 |
return msg; |
|
337 |
} |
|
338 |
return new MessageFormat(msg).format(args); |
|
339 |
} catch (final MissingResourceException e) { |
|
340 |
throw new IllegalArgumentException(e); |
|
341 |
} |
|
342 |
} |
|
343 |
||
344 |
/** |
|
345 |
* Display context sensitive help |
|
346 |
* |
|
347 |
* @param e exception that caused a parse error |
|
348 |
*/ |
|
349 |
public void displayHelp(final IllegalArgumentException e) { |
|
350 |
if (e instanceof IllegalOptionException) { |
|
351 |
final OptionTemplate template = ((IllegalOptionException)e).getTemplate(); |
|
352 |
if (template.isXHelp()) { |
|
353 |
// display extended help information |
|
354 |
displayHelp(true); |
|
355 |
} else { |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
356 |
err.println(((IllegalOptionException)e).getTemplate()); |
16147 | 357 |
} |
358 |
return; |
|
359 |
} |
|
360 |
||
361 |
if (e != null && e.getMessage() != null) { |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
362 |
err.println(getMsg("option.error.invalid.option", |
16147 | 363 |
e.getMessage(), |
364 |
helpOptionTemplate.getShortName(), |
|
365 |
helpOptionTemplate.getName())); |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
366 |
err.println(); |
16147 | 367 |
return; |
368 |
} |
|
369 |
||
370 |
displayHelp(false); |
|
371 |
} |
|
372 |
||
373 |
/** |
|
374 |
* Display full help |
|
375 |
* |
|
376 |
* @param extended show the extended help for all options, including undocumented ones |
|
377 |
*/ |
|
378 |
public void displayHelp(final boolean extended) { |
|
379 |
for (final OptionTemplate t : Options.validOptions) { |
|
380 |
if ((extended || !t.isUndocumented()) && t.getResource().equals(resource)) { |
|
16155
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
381 |
err.println(t); |
a8ab83cbaa49
8005788: Loggers and their corresponding system properties not working correctly
lagergren
parents:
16152
diff
changeset
|
382 |
err.println(); |
16147 | 383 |
} |
384 |
} |
|
385 |
} |
|
386 |
||
387 |
/** |
|
388 |
* Processes the arguments and stores their information. Throws |
|
389 |
* IllegalArgumentException on error. The message can be analyzed by the |
|
390 |
* displayHelp function to become more context sensitive |
|
391 |
* |
|
392 |
* @param args arguments from command line |
|
393 |
*/ |
|
394 |
public void process(final String[] args) { |
|
395 |
final LinkedList<String> argList = new LinkedList<>(); |
|
396 |
Collections.addAll(argList, args); |
|
397 |
||
16533
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
398 |
final String extra = getStringProperty(NASHORN_ARGS_PROPERTY, null); |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
399 |
if (extra != null) { |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
400 |
final StringTokenizer st = new StringTokenizer(extra); |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
401 |
while (st.hasMoreTokens()) { |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
402 |
argList.add(st.nextToken()); |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
403 |
} |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
404 |
} |
6ae708677f92
8010706: -Dnashorn.args system property to create command lines to wrapped nashorn.jar:s
lagergren
parents:
16272
diff
changeset
|
405 |
|
16147 | 406 |
while (!argList.isEmpty()) { |
407 |
final String arg = argList.remove(0); |
|
408 |
||
409 |
// skip empty args |
|
410 |
if (arg.isEmpty()) { |
|
411 |
continue; |
|
412 |
} |
|
413 |
||
414 |
// user arguments to the script |
|
415 |
if ("--".equals(arg)) { |
|
416 |
arguments.addAll(argList); |
|
417 |
argList.clear(); |
|
418 |
continue; |
|
419 |
} |
|
420 |
||
421 |
// if it doesn't start with -, it's a file |
|
422 |
if (!arg.startsWith("-")) { |
|
423 |
files.add(arg); |
|
424 |
continue; |
|
425 |
} |
|
426 |
||
427 |
if (arg.startsWith(definePropPrefix)) { |
|
428 |
final String value = arg.substring(definePropPrefix.length()); |
|
429 |
final int eq = value.indexOf('='); |
|
430 |
if (eq != -1) { |
|
431 |
// -Dfoo=bar Set System property "foo" with value "bar" |
|
432 |
System.setProperty(value.substring(0, eq), value.substring(eq + 1)); |
|
433 |
} else { |
|
434 |
// -Dfoo is fine. Set System property "foo" with "" as it's value |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16155
diff
changeset
|
435 |
if (!value.isEmpty()) { |
16147 | 436 |
System.setProperty(value, ""); |
437 |
} else { |
|
438 |
// do not allow empty property name |
|
439 |
throw new IllegalOptionException(definePropTemplate); |
|
440 |
} |
|
441 |
} |
|
442 |
continue; |
|
443 |
} |
|
444 |
||
445 |
// it is an argument, it and assign key, value and template |
|
446 |
final ParsedArg parg = new ParsedArg(arg); |
|
447 |
||
448 |
// check if the value of this option is passed as next argument |
|
449 |
if (parg.template.isValueNextArg()) { |
|
450 |
if (argList.isEmpty()) { |
|
451 |
throw new IllegalOptionException(parg.template); |
|
452 |
} |
|
453 |
parg.value = argList.remove(0); |
|
454 |
} |
|
455 |
||
456 |
// -h [args...] |
|
457 |
if (parg.template.isHelp()) { |
|
458 |
// check if someone wants help on an explicit arg |
|
459 |
if (!argList.isEmpty()) { |
|
460 |
try { |
|
461 |
final OptionTemplate t = new ParsedArg(argList.get(0)).template; |
|
462 |
throw new IllegalOptionException(t); |
|
463 |
} catch (final IllegalArgumentException e) { |
|
464 |
throw e; |
|
465 |
} |
|
466 |
} |
|
467 |
throw new IllegalArgumentException(); // show help for |
|
468 |
// everything |
|
469 |
} |
|
470 |
||
471 |
if (parg.template.isXHelp()) { |
|
472 |
throw new IllegalOptionException(parg.template); |
|
473 |
} |
|
474 |
||
475 |
set(parg.template.getKey(), createOption(parg.template, parg.value)); |
|
476 |
||
477 |
// Arg may have a dependency to set other args, e.g. |
|
478 |
// scripting->anon.functions |
|
479 |
if (parg.template.getDependency() != null) { |
|
480 |
argList.addFirst(parg.template.getDependency()); |
|
481 |
} |
|
482 |
} |
|
483 |
} |
|
484 |
||
485 |
private static OptionTemplate getOptionTemplate(final String key) { |
|
486 |
for (final OptionTemplate t : Options.validOptions) { |
|
487 |
if (t.matches(key)) { |
|
488 |
return t; |
|
489 |
} |
|
490 |
} |
|
491 |
return null; |
|
492 |
} |
|
493 |
||
494 |
private static Option<?> createOption(final OptionTemplate t, final String value) { |
|
495 |
switch (t.getType()) { |
|
496 |
case "string": |
|
497 |
// default value null |
|
498 |
return new Option<>(value); |
|
499 |
case "timezone": |
|
500 |
// default value "TimeZone.getDefault()" |
|
501 |
return new Option<>(TimeZone.getTimeZone(value)); |
|
17776
59fb7b69846d
8015352: "i".toUpperCase() => currently returns "İ", but should be "I" (with Turkish locale)
sundar
parents:
17749
diff
changeset
|
502 |
case "locale": |
59fb7b69846d
8015352: "i".toUpperCase() => currently returns "İ", but should be "I" (with Turkish locale)
sundar
parents:
17749
diff
changeset
|
503 |
return new Option<>(Locale.forLanguageTag(value)); |
16147 | 504 |
case "keyvalues": |
505 |
return new KeyValueOption(value); |
|
506 |
case "log": |
|
507 |
final KeyValueOption kv = new KeyValueOption(value); |
|
508 |
Logging.initialize(kv.getValues()); |
|
509 |
return kv; |
|
510 |
case "boolean": |
|
511 |
return new Option<>(value != null && Boolean.parseBoolean(value)); |
|
512 |
case "integer": |
|
513 |
try { |
|
16152
ea430b83d74d
8005789: Forgot to document -Dnashorn.unstable.relink.threshold
lagergren
parents:
16151
diff
changeset
|
514 |
return new Option<>((value == null) ? 0 : Integer.parseInt(value)); |
16147 | 515 |
} catch (final NumberFormatException nfe) { |
516 |
throw new IllegalOptionException(t); |
|
517 |
} |
|
518 |
case "properties": |
|
519 |
//swallow the properties and set them |
|
520 |
initProps(new KeyValueOption(value)); |
|
521 |
return null; |
|
522 |
default: |
|
523 |
break; |
|
524 |
} |
|
525 |
throw new IllegalArgumentException(value); |
|
526 |
} |
|
527 |
||
528 |
private static void initProps(final KeyValueOption kv) { |
|
529 |
for (final Map.Entry<String, String> entry : kv.getValues().entrySet()) { |
|
530 |
System.setProperty(entry.getKey(), entry.getValue()); |
|
531 |
} |
|
532 |
} |
|
533 |
||
534 |
/** |
|
535 |
* Resource name for properties file |
|
536 |
*/ |
|
537 |
private static final String MESSAGES_RESOURCE = "jdk.nashorn.internal.runtime.resources.Options"; |
|
538 |
||
539 |
/** |
|
540 |
* Resource bundle for properties file |
|
541 |
*/ |
|
542 |
private static ResourceBundle bundle; |
|
543 |
||
544 |
/** |
|
545 |
* Usages per resource from properties file |
|
546 |
*/ |
|
547 |
private static HashMap<Object, Object> usage; |
|
548 |
||
549 |
/** |
|
550 |
* Valid options from templates in properties files |
|
551 |
*/ |
|
552 |
private static Collection<OptionTemplate> validOptions; |
|
553 |
||
554 |
/** |
|
555 |
* Help option |
|
556 |
*/ |
|
557 |
private static OptionTemplate helpOptionTemplate; |
|
558 |
||
559 |
/** |
|
560 |
* Define property option template. |
|
561 |
*/ |
|
562 |
private static OptionTemplate definePropTemplate; |
|
563 |
||
564 |
/** |
|
565 |
* Prefix of "define property" option. |
|
566 |
*/ |
|
567 |
private static String definePropPrefix; |
|
568 |
||
569 |
static { |
|
570 |
// Without do privileged, under security manager messages can not be |
|
571 |
// loaded. |
|
572 |
Options.bundle = AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() { |
|
573 |
@Override |
|
574 |
public ResourceBundle run() { |
|
575 |
return ResourceBundle.getBundle(Options.MESSAGES_RESOURCE, Locale.getDefault()); |
|
576 |
} |
|
577 |
}); |
|
578 |
||
579 |
Options.validOptions = new TreeSet<>(); |
|
580 |
Options.usage = new HashMap<>(); |
|
581 |
||
582 |
for (final Enumeration<String> keys = Options.bundle.getKeys(); keys.hasMoreElements(); ) { |
|
583 |
final String key = keys.nextElement(); |
|
584 |
final StringTokenizer st = new StringTokenizer(key, "."); |
|
585 |
String resource = null; |
|
586 |
String type = null; |
|
587 |
||
588 |
if (st.countTokens() > 0) { |
|
589 |
resource = st.nextToken(); // e.g. "nashorn" |
|
590 |
} |
|
591 |
||
592 |
if (st.countTokens() > 0) { |
|
593 |
type = st.nextToken(); // e.g. "option" |
|
594 |
} |
|
595 |
||
596 |
if ("option".equals(type)) { |
|
597 |
String helpKey = null; |
|
598 |
String xhelpKey = null; |
|
599 |
String definePropKey = null; |
|
600 |
try { |
|
601 |
helpKey = Options.bundle.getString(resource + ".options.help.key"); |
|
602 |
xhelpKey = Options.bundle.getString(resource + ".options.xhelp.key"); |
|
603 |
definePropKey = Options.bundle.getString(resource + ".options.D.key"); |
|
604 |
} catch (final MissingResourceException e) { |
|
605 |
//ignored: no help |
|
606 |
} |
|
607 |
final boolean isHelp = key.equals(helpKey); |
|
608 |
final boolean isXHelp = key.equals(xhelpKey); |
|
609 |
final OptionTemplate t = new OptionTemplate(resource, key, Options.bundle.getString(key), isHelp, isXHelp); |
|
610 |
||
611 |
Options.validOptions.add(t); |
|
612 |
if (isHelp) { |
|
613 |
helpOptionTemplate = t; |
|
614 |
} |
|
615 |
||
616 |
if (key.equals(definePropKey)) { |
|
617 |
definePropPrefix = t.getName(); |
|
618 |
definePropTemplate = t; |
|
619 |
} |
|
620 |
} else if (resource != null && "options".equals(type)) { |
|
621 |
Options.usage.put(resource, Options.bundle.getObject(key)); |
|
622 |
} |
|
623 |
} |
|
624 |
} |
|
625 |
||
626 |
@SuppressWarnings("serial") |
|
627 |
private static class IllegalOptionException extends IllegalArgumentException { |
|
628 |
private final OptionTemplate template; |
|
629 |
||
630 |
IllegalOptionException(final OptionTemplate t) { |
|
631 |
super(); |
|
632 |
this.template = t; |
|
633 |
} |
|
634 |
||
635 |
OptionTemplate getTemplate() { |
|
636 |
return this.template; |
|
637 |
} |
|
638 |
} |
|
639 |
||
640 |
/** |
|
641 |
* This is a resolved argument of the form key=value |
|
642 |
*/ |
|
643 |
private static class ParsedArg { |
|
644 |
/** The resolved option template this argument corresponds to */ |
|
645 |
OptionTemplate template; |
|
646 |
||
647 |
/** The value of the argument */ |
|
648 |
String value; |
|
649 |
||
650 |
ParsedArg(final String argument) { |
|
651 |
final QuotedStringTokenizer st = new QuotedStringTokenizer(argument, "="); |
|
652 |
if (!st.hasMoreTokens()) { |
|
653 |
throw new IllegalArgumentException(); |
|
654 |
} |
|
655 |
||
656 |
final String token = st.nextToken(); |
|
657 |
this.template = Options.getOptionTemplate(token); |
|
658 |
if (this.template == null) { |
|
659 |
throw new IllegalArgumentException(argument); |
|
660 |
} |
|
661 |
||
662 |
value = ""; |
|
663 |
if (st.hasMoreTokens()) { |
|
664 |
while (st.hasMoreTokens()) { |
|
665 |
value += st.nextToken(); |
|
666 |
if (st.hasMoreTokens()) { |
|
667 |
value += ':'; |
|
668 |
} |
|
669 |
} |
|
670 |
} else if ("boolean".equals(this.template.getType())) { |
|
671 |
value = "true"; |
|
672 |
} |
|
673 |
} |
|
674 |
} |
|
675 |
} |