1 /* 2 * Copyright (c) 2001, 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 24 package nsk.share.jpda; 25 26 import nsk.share.*; 27 28 import java.io.*; 29 import java.net.ServerSocket; 30 31 /** 32 * Parser for JPDA test's launching and connection arguments. 33 * <p> 34 * <Code>DebugeeArgumentHandler</code> handles specific JDI/JDWP/JDB tests 35 * command line arguments related to launching and connection parameters 36 * for debugee VM in addition to general arguments recognized by 37 * <code>ArgumentParser</code>. 38 * <p> 39 * Following is the list of specific options for 40 * <code>DebugeeAgrumentHandler</code>: 41 * <ul> 42 * <li> <code>-test.host=</code><<i>host</i>> - 43 * address of a host where test executes 44 * <li> <code>-debugee.host=</code><<i>host</i>> - 45 * address of a host where debugee VM executes 46 * <li> <code>-connector=[attaching|listening]</code> - 47 * connector type to connect to debugee VM 48 * <li> <code>-transport=[socket|shmem]</code> - 49 * transport type to connect to debugee VM 50 * <li> <code>-transport.port=</code><<i>port</i>> - 51 * port number for <code>socket</code> transport 52 * <li> <code>-transport.shname=</code><<i>name</i>> - 53 * shared memory name for <code>shmem</code> transport 54 * <li> <code>-transport.address=</code><<i>dynamic</i>> - 55 * use dynamically allocated unique transport address for JDWP connection 56 * ignoring settings for <code>-transport.port</code> and <code>-transport.shname</code> 57 * (this works only with <code>-connector=listening</code> and <code>-transport=socket</code>) 58 * <li> <code>-debugee.suspend=[yes|no|default]</code> - 59 * should debugee start in suspend mode or not 60 * <li> <code>-debugee.launch=[local|remote|manual]</code> - 61 * launch and bind to debugee VM locally, remotely (via BindSever) or manually 62 * <li> <code>-debugee.vmhome=</code><<i>path</i>> - 63 * path to JDK used for launching debugee VM 64 * <li> <code>-debugee.vmkind=</code><<i>name</i>> - 65 * name of debugee VM launcher executable 66 * <li> <code>-debugee.vmkeys=</code><<i>string</i>> - 67 * additional options for launching debugee VM 68 * <li> <code>-jvmdi.strict=[yes|no|default]</code> - 69 * using JVMDI strict mode 70 * <li> <code>-pipe.port=</code><<i>port</i>> - 71 * port number for internal IOPipe connection 72 * <li> <code>-bind.port=</code><<i>port</i>> - 73 * port number for BindServer connection 74 * </ul> 75 * <p> 76 * See also list of basic options recognized by 77 * <code>ArgumentParser</code>. 78 * <p> 79 * See also comments to <code>ArgumentParser</code> for list of general 80 * recognized options and how to work with command line arguments and options. 81 * 82 * @see ArgumentParser 83 * @see nsk.share.jdi.ArgumentHandler 84 * @see nsk.share.jdwp.ArgumentHandler 85 */ 86 public class DebugeeArgumentHandler extends ArgumentParser { 87 88 public static final String DEFAULT_PIPE_PORT = "7123"; 89 public static final String DEFAULT_TRANSPORT_PORT = "8123"; 90 public static final String DEFAULT_BIND_PORT = "9123"; 91 92 93 /** 94 * Keep a copy of raw command-line arguments and parse them; 95 * but throw an exception on parsing error. 96 * 97 * @param args Array of the raw command-line arguments. 98 * 99 * @throws BadOption If unknown option or illegal 100 * option value found 101 * 102 * @see #setRawArguments(String[]) 103 */ DebugeeArgumentHandler(String args[])104 public DebugeeArgumentHandler(String args[]) { 105 super(args); 106 } 107 108 /** 109 * Return name of the host where test executes, specified by 110 * <code>-test.host</code> command line option or 111 * "<i>localhost</i>" string by default. 112 * 113 * @see #setRawArguments(String[]) 114 */ getTestHost()115 public String getTestHost() { 116 return options.getProperty("test.host", "localhost"); 117 } 118 119 /** 120 * Return name of host where the debugee VM is executed, specified by 121 * <code>-debugee.host</code> command line option or value of 122 * getTestHost() by default. 123 * 124 * @see #getTestHost() 125 * @see #setRawArguments(String[]) 126 */ getDebugeeHost()127 public String getDebugeeHost() { 128 return options.getProperty("debugee.host", getTestHost()); 129 } 130 131 private boolean transportPortInited = false; 132 /** 133 * Return string representation of port number for socket transport, 134 * specified by <code>-tranport.port</code> command line option or 135 * "<code>DEFAULT_TRANSPORT_PORT</code>" string by default. 136 * 137 * @see #getTransportPortIfNotDynamic() 138 * @see #getTransportPortNumber() 139 * @see #setTransportPortNumber(int) 140 * @see #setRawArguments(String[]) 141 */ getTransportPort()142 synchronized public String getTransportPort() { 143 String port = options.getProperty("transport.port"); 144 if (port == null) { 145 if (!transportPortInited) { 146 port = findFreePort(); 147 if (port == null) { 148 port = DEFAULT_TRANSPORT_PORT; 149 } 150 options.setProperty("transport.port", port); 151 transportPortInited = true; 152 } 153 } 154 return port; 155 } 156 157 /** 158 * Return string representation of port number for socket transport, 159 * specified by <code>-tranport.port</code> command line option or 160 * "<code>DEFAULT_TRANSPORT_PORT</code>" string by default in case transport address is 161 * not dynamic. 162 * Otherwise null is returned. 163 * 164 * @see #getTransportPort() 165 * @see #getTransportPortNumber() 166 * @see #setTransportPortNumber(int) 167 * @see #setRawArguments(String[]) 168 */ getTransportPortIfNotDynamic()169 public String getTransportPortIfNotDynamic() { 170 return ( isTransportAddressDynamic() ? 171 null : getTransportPort() ); 172 } 173 174 /** 175 * Return string port number for socket transport, 176 * specified by <code>-debugee.port</code> command line option or 177 * <code>DEFAULT_TRANSPORT_PORT</code> port number by default. 178 * 179 * @see #getTransportPort() 180 * @see #getTransportPortIfNotDynamic() 181 * @see #setTransportPortNumber(int) 182 * @see #setRawArguments(String[]) 183 */ getTransportPortNumber()184 public int getTransportPortNumber() { 185 String value = getTransportPort(); 186 try { 187 return Integer.parseInt(value); 188 } catch (NumberFormatException e) { 189 throw new TestBug("Not integer value of \"-transport.port\" argument: " + value); 190 } 191 } 192 193 /** 194 * Add or replace value of option <code>-transport.port</code> in options list 195 * with the specified port number. 196 * 197 * @see #getTransportPortNumber() 198 * @see #setRawArguments(String[]) 199 */ setTransportPortNumber(int port)200 public void setTransportPortNumber(int port) { 201 String value = Integer.toString(port); 202 setOption("-", "transport.port", value); 203 } 204 205 /** 206 * Return shared name for shmem transport, specified by 207 * <code>-transport.shname</code> command line option, or 208 * "<i>nskjpdatestchannel</i>" + a process unique string by default. 209 * 210 * @see #setTransportSharedName(String) 211 * @see #setRawArguments(String[]) 212 */ 213 // Use a unique id for this process by default. This makes sure that 214 // tests running concurrently do not use the same shared name. 215 private static String defaultTransportSharedName 216 = "nskjpdatestchannel" + ProcessHandle.current().pid(); getTransportSharedName()217 public String getTransportSharedName() { 218 return options.getProperty("transport.shname", defaultTransportSharedName); 219 } 220 221 /** 222 * Add or replace value of option <code>-transport.shname</code> in options list 223 * with the specified name. 224 * 225 * @see #getTransportSharedName() 226 * @see #setRawArguments(String[]) 227 */ setTransportSharedName(String name)228 public void setTransportSharedName(String name) { 229 setOption("-", "transport.shname", name); 230 } 231 232 /** 233 * Return <i>true</i> if <code>-transport.address=dynamic</code> command line option 234 * is specified. 235 * 236 * @see #setRawArguments(String[]) 237 */ isTransportAddressDynamic()238 public boolean isTransportAddressDynamic() { 239 String value = options.getProperty("transport.address", null); 240 if (value != null && value.equals("dynamic")) 241 return true; 242 return false; 243 } 244 245 /** 246 * Return suspend mode for launching debugee VM, specified by 247 * <code>-debugee.suspend</code> command line option, or 248 * "<i>default</i>" string by default. 249 * 250 * @see #isDefaultDebugeeSuspendMode() 251 * @see #willDebugeeSuspended() 252 * @see #setRawArguments(String[]) 253 */ getDebugeeSuspendMode()254 public String getDebugeeSuspendMode() { 255 return options.getProperty("debugee.suspend", "default"); 256 } 257 258 /** 259 * Return <i>true</i> if default suspend mode is used 260 * for launching debugee VM. 261 * 262 * @see #getDebugeeSuspendMode() 263 * @see #willDebugeeSuspended() 264 */ isDefaultDebugeeSuspendMode()265 public boolean isDefaultDebugeeSuspendMode() { 266 String mode = getDebugeeSuspendMode(); 267 return mode.equals("default"); 268 } 269 270 /** 271 * Return <i>true</i> if debugee VM will be suspended after launching, 272 * either according to specified suspend mode or by default. 273 * 274 * @see #getDebugeeSuspendMode() 275 * @see #isDefaultDebugeeSuspendMode() 276 */ willDebugeeSuspended()277 public boolean willDebugeeSuspended() { 278 if (isLaunchedLocally()) { 279 String mode = getDebugeeSuspendMode(); 280 return mode.equals("no"); 281 } 282 return true; 283 } 284 285 private boolean pipePortInited = false; 286 /** 287 * Return string representation of the port number for IOPipe connection, 288 * specified by <code>-pipe.port</code> command line option, or 289 * "<i>DEFAULT_PIPE_PORT</i>" string by default. 290 * 291 * @see #getPipePortNumber() 292 * @see #setPipePortNumber(int) 293 * @see #setRawArguments(String[]) 294 */ getPipePort()295 synchronized public String getPipePort() { 296 String port = options.getProperty("pipe.port"); 297 if (port == null) { 298 if (!pipePortInited) { 299 port = findFreePort(); 300 if (port == null) { 301 port = DEFAULT_PIPE_PORT; 302 } 303 pipePortInited = true; 304 options.setProperty("pipe.port", port); 305 } 306 } 307 return port; 308 } 309 310 /** 311 * Return port number for IOPipe connection, 312 * specified by <code>-pipe.port</code> command line option, or 313 * <i>DEFAULT_PIPE_PORT</i> port number by default. 314 * 315 * @see #getPipePort() 316 * @see #setPipePortNumber(int) 317 * @see #setRawArguments(String[]) 318 */ getPipePortNumber()319 public int getPipePortNumber() { 320 String value = getPipePort(); 321 try { 322 return Integer.parseInt(value); 323 } catch (NumberFormatException e) { 324 throw new TestBug("Not integer value of \"-pipe.port\" argument: " + value); 325 } 326 } 327 328 /** 329 * Add or replace value of option <code>-pipe.port</code> in options list 330 * with the specified port number. 331 * 332 * @see #getPipePortNumber() 333 * @see #setRawArguments(String[]) 334 */ setPipePortNumber(int port)335 public void setPipePortNumber(int port) { 336 String value = Integer.toString(port); 337 setOption("-", "pipe.port", value); 338 } 339 340 /** 341 * Return debugee VM launching mode, specified by 342 * <code>-launch.mode</code> command line option, or 343 * "<i>local</i>" string by default. 344 * 345 * Possible values for this option are: 346 * <ul> 347 * <li> "<code>local</code>" 348 * <li> "<code>remote</code>" 349 * <li> "<code>manual</code>" 350 * </ul> 351 * 352 * @see #isLaunchedLocally() 353 * @see #isLaunchedRemotely() 354 * @see #isLaunchedManually() 355 * @see #setRawArguments(String[]) 356 */ getLaunchMode()357 public String getLaunchMode() { 358 return options.getProperty("debugee.launch", "local"); 359 } 360 361 /** 362 * Return <i>true</i> if debugee should be launched locally. 363 * 364 * @see #getLaunchMode() 365 */ isLaunchedLocally()366 public boolean isLaunchedLocally() { 367 return getLaunchMode().equals("local"); 368 } 369 370 /** 371 * Return <i>true</i> if debugee should be launched remotely via 372 * BindServer. 373 * 374 * @see #getLaunchMode() 375 */ isLaunchedRemotely()376 public boolean isLaunchedRemotely() { 377 return getLaunchMode().equals("remote"); 378 } 379 380 /** 381 * Return <i>true</i> if debugee should be launched manually by user. 382 * 383 * @see #getLaunchMode() 384 */ isLaunchedManually()385 public boolean isLaunchedManually() { 386 return getLaunchMode().equals("manual"); 387 } 388 389 /** 390 * Return additional options for launching debugee VM, specified by 391 * <code>-launch.options</code> command line option, or 392 * empty string by default. 393 * 394 * @see #setRawArguments(String[]) 395 */ getLaunchOptions()396 public String getLaunchOptions() { 397 String result = options.getProperty("debugee.vmkeys", "").trim(); 398 if (result.startsWith("\"") && result.endsWith("\"")) { 399 result = result.substring(1, result.length() - 1); 400 } 401 return result; 402 } 403 404 /** 405 * Return name of debugee VM launcher executable, specified by 406 * <code>-launch.vmexec</code> command line option, or 407 * "<i>java</i>" string by default. 408 * 409 * @see #setRawArguments(String[]) 410 */ getLaunchExecName()411 public String getLaunchExecName() { 412 return options.getProperty("debugee.vmkind", "java"); 413 } 414 415 /** 416 * Return full path to debugee VM launcher executable. 417 * 418 * @see #getLaunchExecName() 419 * @see #getLaunchExecPath(String) 420 * @see #getDebugeeJavaHome() 421 */ getLaunchExecPath()422 public String getLaunchExecPath() { 423 String java_home = getDebugeeJavaHome(); 424 return getLaunchExecPath(java_home); 425 } 426 427 /** 428 * Return full path to VM launcher executable using givet JAVA_HOME path. 429 * 430 * @see #getLaunchExecName() 431 */ getLaunchExecPath(String java_home)432 public String getLaunchExecPath(String java_home) { 433 String filesep = System.getProperty("file.separator"); 434 return java_home + filesep + "bin" + filesep + getLaunchExecName(); 435 } 436 437 /** 438 * Return full JAVA_HOME path for debugee VM. 439 * 440 * @see #getLaunchExecName() 441 */ getDebugeeJavaHome()442 public String getDebugeeJavaHome() { 443 String java_home = System.getProperty("java.home"); 444 return options.getProperty("debugee.vmhome", java_home); 445 } 446 447 /** 448 * Return true if default debuggee VM launcher executable is used. 449 * 450 * @see #getLaunchExecName() 451 */ isDefaultLaunchExecName()452 public boolean isDefaultLaunchExecName() { 453 String vmkind = options.getProperty("debugee.vmkind", null); 454 return (vmkind == null); 455 } 456 457 /** 458 * Return true if default JAVA_HOME path for debuggee VM is used. 459 * 460 * @see #getDebugeeJavaHome() 461 */ isDefaultDebugeeJavaHome()462 public boolean isDefaultDebugeeJavaHome() { 463 String java_home = options.getProperty("debugee.vmhome", null); 464 return (java_home == null); 465 } 466 467 private boolean bindPortInited = false; 468 /** 469 * Return string representation of the port number for BindServer connection, 470 * specified by <code>-bind.port</code> command line option, or 471 * "<i>DEFAULT_BIND_PORT</i>" string by default. 472 * 473 * @see #getBindPortNumber() 474 * @see #setRawArguments(String[]) 475 */ getBindPort()476 public String getBindPort() { 477 String port = options.getProperty("bind.port"); 478 if (port == null) { 479 if (!bindPortInited) { 480 port = findFreePort(); 481 if (port == null) { 482 port = DEFAULT_BIND_PORT; 483 } 484 options.setProperty("bind.port", port); 485 bindPortInited = true; 486 } 487 } 488 return port; 489 } 490 491 /** 492 * Return port number for BindServer connection, 493 * specified by <code>-bind.port</code> command line option, or 494 * "<i>DEFAULT_BIND_PORT</i>" port number by default. 495 * 496 * @see #getBindPort() 497 * @see #setRawArguments(String[]) 498 */ getBindPortNumber()499 public int getBindPortNumber() { 500 String value = getBindPort(); 501 try { 502 return Integer.parseInt(value); 503 } catch (NumberFormatException e) { 504 throw new TestBug("Not integer value of \"bind.port\" argument: " + value); 505 } 506 } 507 508 /** 509 * Return JVMDI strict mode for launching debugee VM, specified by. 510 * <code>-jvmdi.strict</code> command line option, or 511 * "<i>default</i>" string by default. 512 * 513 * Possible values for this option are: 514 * <ul> 515 * <li> "<code>yes</code>" 516 * <li> "<code>no</code>" 517 * <li> "<code>default</code>" 518 * </ul> 519 * 520 * @see #setRawArguments(String[]) 521 */ getJVMDIStrictMode()522 public String getJVMDIStrictMode() { 523 return options.getProperty("jvmdi.strict", "default"); 524 } 525 526 /** 527 * Return <i>true</i> if JVMDI strict mode for launching debugeeVM is used^ 528 * either by specifying in command line or by default. 529 * 530 * @see #getJVMDIStrictMode() 531 * @see #isDefaultJVMDIStrictMode() 532 * @see #setRawArguments(String[]) 533 */ isJVMDIStrictMode()534 public boolean isJVMDIStrictMode() { 535 String mode = getJVMDIStrictMode(); 536 return mode.equals("yes"); 537 } 538 539 /** 540 * Return <i>true</i> if JVMDI default strict mode for launching debugee VM is used. 541 * 542 * @see #getJVMDIStrictMode() 543 * @see #isJVMDIStrictMode() 544 * @see #setRawArguments(String[]) 545 */ isDefaultJVMDIStrictMode()546 public boolean isDefaultJVMDIStrictMode() { 547 String mode = getJVMDIStrictMode(); 548 return mode.equals("default"); 549 } 550 551 /** 552 * Return type of JDI connector used for connecting to debugee VM, specified by 553 * <code>-connector</code> command line option, or 554 * "<i>listening</i>" string by default. 555 * 556 * Possible values for this option are: 557 * <ul> 558 * <li> "<code>attaching</code>" 559 * <li> "<code>listening</code>" 560 * </ul> 561 * 562 * @see #isAttachingConnector() 563 * @see #isListeningConnector() 564 * @see #setRawArguments(String[]) 565 */ getConnectorType()566 public String getConnectorType() { 567 return options.getProperty("connector", "listening"); 568 } 569 570 /** 571 * Return <i>true</i> if type of the used JDI connector is <code>attaching</code>. 572 * 573 * @see #getConnectorType() 574 */ isAttachingConnector()575 public boolean isAttachingConnector() { 576 return getConnectorType().equals("attaching"); 577 } 578 579 /** 580 * Return <i>true</i> if type of the used JDI connector is <code>listening</code>. 581 * 582 * @see #getConnectorType() 583 */ isListeningConnector()584 public boolean isListeningConnector() { 585 return getConnectorType().equals("listening"); 586 } 587 588 /** 589 * Return <i>true</i> if connector type is not actually specified. 590 * In this case getConnectorType() returns some default connector type. 591 * 592 * @see #getConnectorType() 593 */ isDefaultConnector()594 public boolean isDefaultConnector() { 595 return options.getProperty("connector") == null; 596 } 597 598 /** 599 * Return type of JDWP transport for connecting to debugee VM, specified by 600 * <code>-transport</code> command line option, or 601 * "<i>socket</i>" string by default. 602 * 603 * Possible values for this option are: 604 * <ul> 605 * <li> "<code>socket</code>" 606 * <li> "<code>shmem</code>" 607 * </ul> 608 * 609 * @see #getTransportName() 610 * @see #isSocketTransport() 611 * @see #isShmemTransport() 612 * @see #setRawArguments(String[]) 613 */ getTransportType()614 public String getTransportType() { 615 return options.getProperty("transport", "socket"); 616 } 617 618 /** 619 * Return transport name corresponding to the used JDWP transport type. 620 * 621 * @see #getTransportType() 622 */ getTransportName()623 public String getTransportName() { 624 if (isSocketTransport()) { 625 return "dt_socket"; 626 } else if (isShmemTransport()) { 627 return "dt_shmem"; 628 } else { 629 throw new TestBug("Undefined transport type"); 630 } 631 } 632 633 /** 634 * Return <i>true</i> if the used JDWP transport type is <code>socket</code>, 635 * either by specifying in command line or as a platform default transport. 636 * 637 * @see #getTransportType() 638 */ isSocketTransport()639 public boolean isSocketTransport() { 640 String transport = getTransportType(); 641 return transport.equals("socket"); 642 } 643 644 /** 645 * Return <i>true</i> if the used JDWP transport type is <code>shmem</code>, 646 * either by specifying in command line or as a platform default transport. 647 * 648 * @see #getTransportType() 649 */ isShmemTransport()650 public boolean isShmemTransport() { 651 String transport = getTransportType(); 652 return transport.equals("shmem"); 653 } 654 655 /** 656 * Return <i>true</i> if transport type is not actually specified. 657 * In this case getTransportType() returns some default transport kind. 658 * 659 * @see #getTransportType() 660 */ isDefaultTransport()661 public boolean isDefaultTransport() { 662 return options.getProperty("transport") == null; 663 } 664 665 /** 666 * Create <code>Log</code> for debugee application using command line options. 667 */ createDebugeeLog()668 public Log createDebugeeLog() { 669 return new Log(System.err, this); 670 }; 671 672 /** 673 * Create IOPipe for debugee application using command line options. 674 */ createDebugeeIOPipe()675 public IOPipe createDebugeeIOPipe() { 676 return createDebugeeIOPipe(createDebugeeLog()); 677 }; 678 679 /** 680 * Create IOPipe for debugee application using connection 681 * parameters from the command line and specify Log. 682 */ createDebugeeIOPipe(Log log)683 public IOPipe createDebugeeIOPipe(Log log) { 684 return new IOPipe(this, log); 685 }; 686 687 /** 688 * Check if an option is aloowed and has proper value. 689 * This method is invoked by <code>parseArgumentss()</code> 690 * 691 * @param option option name 692 * @param value string representation of value 693 * (could be an empty string too) 694 * null if this option has no value 695 * @return <i>true</i> if option is allowed and has proper value 696 * <i>false</i> if otion is not admissible 697 * 698 * @throws <i>BadOption</i> if option has an illegal value 699 * 700 * @see #parseArguments() 701 */ checkOption(String option, String value)702 protected boolean checkOption(String option, String value) { 703 704 if(option.equals("traceAll")) 705 return true; 706 707 // option with any string value 708 if (option.equals("debugee.vmkeys")) { 709 return true; 710 } 711 712 // option with any nonempty string value 713 if (option.equals("test.host") 714 || option.equals("debugee.host") 715 || option.equals("debugee.vmkind") 716 || option.equals("debugee.vmhome") 717 || option.equals("transport.shname")) { 718 if (value.length() <= 0) { 719 throw new BadOption(option + ": cannot be an empty string"); 720 } 721 return true; 722 } 723 724 // option with positive integer port value 725 if (option.equals("transport.port") 726 || option.equals("bind.port") 727 || option.equals("pipe.port")) { 728 try { 729 int number = Integer.parseInt(value); 730 if (number < 0) { 731 throw new BadOption(option + ": must be a positive integer"); 732 } 733 } catch (NumberFormatException e) { 734 throw new BadOption(option + ": must be an integer"); 735 } 736 return true; 737 } 738 739 // options with enumerated values 740 741 if (option.equals("debugee.suspend")) { 742 if ((!value.equals("yes")) 743 && (!value.equals("no")) 744 && (!value.equals("default"))) { 745 throw new BadOption(option + ": must be one of: " 746 + "yes, no, default"); 747 } 748 return true; 749 } 750 751 if (option.equals("debugee.launch")) { 752 if ((!value.equals("local")) 753 && (!value.equals("remote")) 754 && (!value.equals("manual"))) { 755 throw new BadOption(option + ": must be one of: " 756 + "local, remote, manual " + value); 757 } 758 return true; 759 } 760 761 if (option.equals("jvmdi.strict")) { 762 if ((!value.equals("yes")) 763 && (!value.equals("no")) 764 && (!value.equals("default"))) { 765 throw new BadOption(option + ": must be one of: " 766 + "yes, no, default"); 767 } 768 return true; 769 } 770 771 if (option.equals("transport")) { 772 if ((!value.equals("socket")) 773 && (!value.equals("shmem"))) { 774 throw new BadOption(option + ": must be one of: " 775 + "socket, shmem"); 776 } 777 return true; 778 } 779 780 if (option.equals("connector")) { 781 if ((!value.equals("attaching")) 782 && (!value.equals("listening"))) { 783 throw new BadOption(option + ": value must be one of: " 784 + "attaching, listening"); 785 } 786 return true; 787 } 788 789 if (option.equals("transport.address")) { 790 if (!value.equals("dynamic")) { 791 throw new BadOption(option + ": must be only: " 792 + "dynamic"); 793 } 794 return true; 795 } 796 797 return super.checkOption(option, value); 798 } 799 800 /** 801 * Check if the values of all options are consistent. 802 * This method is invoked by <code>parseArguments()</code> 803 * 804 * @throws <i>BadOption</i> if options have inconsistent values 805 * 806 * @see #parseArguments() 807 */ checkOptions()808 protected void checkOptions() { 809 super.checkOptions(); 810 } 811 findFreePort()812 private String findFreePort() { 813 ServerSocket ss = null; 814 try { 815 ss = new ServerSocket(0); 816 return String.valueOf(ss.getLocalPort()); 817 } catch (IOException e) { 818 return null; 819 } finally { 820 try { 821 ss.close(); 822 } catch (Throwable t) { 823 // ignore 824 } 825 } 826 } 827 828 } // DebugeeArgumentHandler 829