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 */
24
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "memory/oopFactory.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/handles.inline.hpp"
31 #include "runtime/javaCalls.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "services/diagnosticArgument.hpp"
34 #include "services/diagnosticFramework.hpp"
35 #include "services/management.hpp"
36
37 CmdLine::CmdLine(const char* line, size_t len, bool no_command_name) {
38 assert(line != NULL, "Command line string should not be NULL");
39 const char* line_end;
40 const char* cmd_end;
41
42 _cmd = line;
43 line_end = &line[len];
44
45 // Skip whitespace in the beginning of the line.
46 while (_cmd < line_end && isspace((int) _cmd[0])) {
47 _cmd++;
48 }
49 cmd_end = _cmd;
50
51 if (no_command_name) {
52 _cmd = NULL;
53 _cmd_len = 0;
54 } else {
55 // Look for end of the command name
56 while (cmd_end < line_end && !isspace((int) cmd_end[0])) {
57 cmd_end++;
234 const size_t buflen = 256;
235 char buf[buflen];
236 GenDCmdArgument* arg = _arguments_list;
237 while (arg != NULL) {
238 if (arg->is_mandatory() && !arg->has_value()) {
239 jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
240 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
241 }
242 arg = arg->next();
243 }
244 arg = _options;
245 while (arg != NULL) {
246 if (arg->is_mandatory() && !arg->has_value()) {
247 jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
248 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
249 }
250 arg = arg->next();
251 }
252 }
253
254 void DCmdParser::print_help(outputStream* out, const char* cmd_name) {
255 out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
256 GenDCmdArgument* arg = _arguments_list;
257 while (arg != NULL) {
258 if (arg->is_mandatory()) {
259 out->print(" <%s>", arg->name());
260 } else {
261 out->print(" [<%s>]", arg->name());
262 }
263 arg = arg->next();
264 }
265 out->cr();
266 if (_arguments_list != NULL) {
267 out->print_cr("\nArguments:");
268 arg = _arguments_list;
269 while (arg != NULL) {
270 out->print("\t%s : %s %s (%s, ", arg->name(),
271 arg->is_mandatory() ? "" : "[optional]",
272 arg->description(), arg->type());
273 if (arg->has_default()) {
274 out->print("%s", arg->default_string());
306 arg = _options;
307 while (arg != NULL) {
308 arg->reset(CHECK);
309 arg = arg->next();
310 }
311 }
312
313 void DCmdParser::cleanup() {
314 GenDCmdArgument* arg = _arguments_list;
315 while (arg != NULL) {
316 arg->cleanup();
317 arg = arg->next();
318 }
319 arg = _options;
320 while (arg != NULL) {
321 arg->cleanup();
322 arg = arg->next();
323 }
324 }
325
326 int DCmdParser::num_arguments() {
327 GenDCmdArgument* arg = _arguments_list;
328 int count = 0;
329 while (arg != NULL) {
330 count++;
331 arg = arg->next();
332 }
333 arg = _options;
334 while (arg != NULL) {
335 count++;
336 arg = arg->next();
337 }
338 return count;
339 }
340
341 GrowableArray<const char *>* DCmdParser::argument_name_array() {
342 int count = num_arguments();
343 GrowableArray<const char *>* array = new GrowableArray<const char *>(count);
344 GenDCmdArgument* arg = _arguments_list;
345 while (arg != NULL) {
346 array->append(arg->name());
347 arg = arg->next();
348 }
349 arg = _options;
350 while (arg != NULL) {
351 array->append(arg->name());
352 arg = arg->next();
353 }
354 return array;
355 }
356
357 GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() {
358 int count = num_arguments();
359 GrowableArray<DCmdArgumentInfo*>* array = new GrowableArray<DCmdArgumentInfo *>(count);
360 int idx = 0;
361 GenDCmdArgument* arg = _arguments_list;
362 while (arg != NULL) {
363 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
364 arg->type(), arg->default_string(), arg->is_mandatory(),
365 false, arg->allow_multiple(), idx));
366 idx++;
367 arg = arg->next();
368 }
369 arg = _options;
370 while (arg != NULL) {
371 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
372 arg->type(), arg->default_string(), arg->is_mandatory(),
373 true, arg->allow_multiple()));
374 arg = arg->next();
375 }
376 return array;
377 }
382 void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
383 const char* cmdline, char delim, TRAPS) {
384
385 if (cmdline == NULL) return; // Nothing to do!
386 DCmdIter iter(cmdline, '\n');
387
388 int count = 0;
389 while (iter.has_next()) {
390 if(source == DCmd_Source_MBean && count > 0) {
391 // When diagnostic commands are invoked via JMX, each command line
392 // must contains one and only one command because of the Permission
393 // checks performed by the DiagnosticCommandMBean
394 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
395 "Invalid syntax");
396 }
397 CmdLine line = iter.next();
398 if (line.is_stop()) {
399 break;
400 }
401 if (line.is_executable()) {
402 DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
403 assert(command != NULL, "command error must be handled before this line");
404 DCmdMark mark(command);
405 command->parse(&line, delim, CHECK);
406 command->execute(source, CHECK);
407 }
408 count++;
409 }
410 }
411
412 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
413 _dcmdparser.parse(line, delim, CHECK);
414 }
415
416 void DCmdWithParser::print_help(const char* name) {
417 _dcmdparser.print_help(output(), name);
418 }
419
420 void DCmdWithParser::reset(TRAPS) {
421 _dcmdparser.reset(CHECK);
422 }
423
424 void DCmdWithParser::cleanup() {
425 _dcmdparser.cleanup();
426 }
427
428 GrowableArray<const char*>* DCmdWithParser::argument_name_array() {
429 return _dcmdparser.argument_name_array();
430 }
431
432 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
433 return _dcmdparser.argument_info_array();
434 }
435
436 void DCmdFactory::push_jmx_notification_request() {
437 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
438 _has_pending_jmx_notification = true;
439 Service_lock->notify_all();
440 }
441
442 void DCmdFactory::send_notification(TRAPS) {
443 DCmdFactory::send_notification_internal(THREAD);
444 // Clearing pending exception to avoid premature termination of
445 // the service thread
446 if (HAS_PENDING_EXCEPTION) {
447 CLEAR_PENDING_EXCEPTION;
448 }
449 }
450 void DCmdFactory::send_notification_internal(TRAPS) {
451 ResourceMark rm(THREAD);
452 HandleMark hm(THREAD);
500 if(factory->export_flags() & source) {
501 return factory;
502 } else {
503 return NULL;
504 }
505 }
506 factory = factory->_next;
507 }
508 return NULL;
509 }
510
511 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
512 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
513 factory->_next = _DCmdFactoryList;
514 _DCmdFactoryList = factory;
515 if (_send_jmx_notification && !factory->_hidden
516 && (factory->_export_flags & DCmd_Source_MBean)) {
517 DCmdFactory::push_jmx_notification_request();
518 }
519 return 0; // Actually, there's no checks for duplicates
520 }
521
522 DCmd* DCmdFactory::create_global_DCmd(DCmdSource source, CmdLine &line,
523 outputStream* out, TRAPS) {
524 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
525 if (f != NULL) {
526 if (f->is_enabled()) {
527 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
528 f->disabled_message());
529 }
530 return f->create_Cheap_instance(out);
531 }
532 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
533 "Unknown diagnostic command");
534 }
535
536 DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
537 outputStream* out, TRAPS) {
538 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
539 if (f != NULL) {
540 if (!f->is_enabled()) {
541 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
542 f->disabled_message());
543 }
544 return f->create_resource_instance(out);
545 }
546 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
547 "Unknown diagnostic command");
548 }
549
550 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
551 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
552 GrowableArray<const char*>* array = new GrowableArray<const char*>();
553 DCmdFactory* factory = _DCmdFactoryList;
|
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 */
24
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "memory/oopFactory.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/handles.inline.hpp"
31 #include "runtime/javaCalls.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "services/diagnosticArgument.hpp"
34 #include "services/diagnosticFramework.hpp"
35 #include "services/management.hpp"
36
37 CmdLine::CmdLine(const char* line, size_t len, bool no_command_name)
38 : _cmd(NULL)
39 , _cmd_len(0)
40 , _args(NULL)
41 , _args_len(0)
42 {
43 assert(line != NULL, "Command line string should not be NULL");
44 const char* line_end;
45 const char* cmd_end;
46
47 _cmd = line;
48 line_end = &line[len];
49
50 // Skip whitespace in the beginning of the line.
51 while (_cmd < line_end && isspace((int) _cmd[0])) {
52 _cmd++;
53 }
54 cmd_end = _cmd;
55
56 if (no_command_name) {
57 _cmd = NULL;
58 _cmd_len = 0;
59 } else {
60 // Look for end of the command name
61 while (cmd_end < line_end && !isspace((int) cmd_end[0])) {
62 cmd_end++;
239 const size_t buflen = 256;
240 char buf[buflen];
241 GenDCmdArgument* arg = _arguments_list;
242 while (arg != NULL) {
243 if (arg->is_mandatory() && !arg->has_value()) {
244 jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
245 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
246 }
247 arg = arg->next();
248 }
249 arg = _options;
250 while (arg != NULL) {
251 if (arg->is_mandatory() && !arg->has_value()) {
252 jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
253 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
254 }
255 arg = arg->next();
256 }
257 }
258
259 void DCmdParser::print_help(outputStream* out, const char* cmd_name) const {
260 out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
261 GenDCmdArgument* arg = _arguments_list;
262 while (arg != NULL) {
263 if (arg->is_mandatory()) {
264 out->print(" <%s>", arg->name());
265 } else {
266 out->print(" [<%s>]", arg->name());
267 }
268 arg = arg->next();
269 }
270 out->cr();
271 if (_arguments_list != NULL) {
272 out->print_cr("\nArguments:");
273 arg = _arguments_list;
274 while (arg != NULL) {
275 out->print("\t%s : %s %s (%s, ", arg->name(),
276 arg->is_mandatory() ? "" : "[optional]",
277 arg->description(), arg->type());
278 if (arg->has_default()) {
279 out->print("%s", arg->default_string());
311 arg = _options;
312 while (arg != NULL) {
313 arg->reset(CHECK);
314 arg = arg->next();
315 }
316 }
317
318 void DCmdParser::cleanup() {
319 GenDCmdArgument* arg = _arguments_list;
320 while (arg != NULL) {
321 arg->cleanup();
322 arg = arg->next();
323 }
324 arg = _options;
325 while (arg != NULL) {
326 arg->cleanup();
327 arg = arg->next();
328 }
329 }
330
331 int DCmdParser::num_arguments() const {
332 GenDCmdArgument* arg = _arguments_list;
333 int count = 0;
334 while (arg != NULL) {
335 count++;
336 arg = arg->next();
337 }
338 arg = _options;
339 while (arg != NULL) {
340 count++;
341 arg = arg->next();
342 }
343 return count;
344 }
345
346 GrowableArray<const char *>* DCmdParser::argument_name_array() const {
347 int count = num_arguments();
348 GrowableArray<const char *>* array = new GrowableArray<const char *>(count);
349 GenDCmdArgument* arg = _arguments_list;
350 while (arg != NULL) {
351 array->append(arg->name());
352 arg = arg->next();
353 }
354 arg = _options;
355 while (arg != NULL) {
356 array->append(arg->name());
357 arg = arg->next();
358 }
359 return array;
360 }
361
362 GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() const {
363 int count = num_arguments();
364 GrowableArray<DCmdArgumentInfo*>* array = new GrowableArray<DCmdArgumentInfo *>(count);
365 int idx = 0;
366 GenDCmdArgument* arg = _arguments_list;
367 while (arg != NULL) {
368 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
369 arg->type(), arg->default_string(), arg->is_mandatory(),
370 false, arg->allow_multiple(), idx));
371 idx++;
372 arg = arg->next();
373 }
374 arg = _options;
375 while (arg != NULL) {
376 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
377 arg->type(), arg->default_string(), arg->is_mandatory(),
378 true, arg->allow_multiple()));
379 arg = arg->next();
380 }
381 return array;
382 }
387 void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
388 const char* cmdline, char delim, TRAPS) {
389
390 if (cmdline == NULL) return; // Nothing to do!
391 DCmdIter iter(cmdline, '\n');
392
393 int count = 0;
394 while (iter.has_next()) {
395 if(source == DCmd_Source_MBean && count > 0) {
396 // When diagnostic commands are invoked via JMX, each command line
397 // must contains one and only one command because of the Permission
398 // checks performed by the DiagnosticCommandMBean
399 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
400 "Invalid syntax");
401 }
402 CmdLine line = iter.next();
403 if (line.is_stop()) {
404 break;
405 }
406 if (line.is_executable()) {
407 ResourceMark rm;
408 DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
409 assert(command != NULL, "command error must be handled before this line");
410 DCmdMark mark(command);
411 command->parse(&line, delim, CHECK);
412 command->execute(source, CHECK);
413 }
414 count++;
415 }
416 }
417
418 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
419 _dcmdparser.parse(line, delim, CHECK);
420 }
421
422 void DCmdWithParser::print_help(const char* name) const {
423 _dcmdparser.print_help(output(), name);
424 }
425
426 void DCmdWithParser::reset(TRAPS) {
427 _dcmdparser.reset(CHECK);
428 }
429
430 void DCmdWithParser::cleanup() {
431 _dcmdparser.cleanup();
432 }
433
434 GrowableArray<const char*>* DCmdWithParser::argument_name_array() const {
435 return _dcmdparser.argument_name_array();
436 }
437
438 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() const {
439 return _dcmdparser.argument_info_array();
440 }
441
442 void DCmdFactory::push_jmx_notification_request() {
443 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
444 _has_pending_jmx_notification = true;
445 Service_lock->notify_all();
446 }
447
448 void DCmdFactory::send_notification(TRAPS) {
449 DCmdFactory::send_notification_internal(THREAD);
450 // Clearing pending exception to avoid premature termination of
451 // the service thread
452 if (HAS_PENDING_EXCEPTION) {
453 CLEAR_PENDING_EXCEPTION;
454 }
455 }
456 void DCmdFactory::send_notification_internal(TRAPS) {
457 ResourceMark rm(THREAD);
458 HandleMark hm(THREAD);
506 if(factory->export_flags() & source) {
507 return factory;
508 } else {
509 return NULL;
510 }
511 }
512 factory = factory->_next;
513 }
514 return NULL;
515 }
516
517 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
518 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
519 factory->_next = _DCmdFactoryList;
520 _DCmdFactoryList = factory;
521 if (_send_jmx_notification && !factory->_hidden
522 && (factory->_export_flags & DCmd_Source_MBean)) {
523 DCmdFactory::push_jmx_notification_request();
524 }
525 return 0; // Actually, there's no checks for duplicates
526 }
527
528 DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
529 outputStream* out, TRAPS) {
530 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
531 if (f != NULL) {
532 if (!f->is_enabled()) {
533 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
534 f->disabled_message());
535 }
536 return f->create_resource_instance(out);
537 }
538 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
539 "Unknown diagnostic command");
540 }
541
542 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
543 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
544 GrowableArray<const char*>* array = new GrowableArray<const char*>();
545 DCmdFactory* factory = _DCmdFactoryList;
|