1 /*
   2  * Copyright (c) 2009, 2016, 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. 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  */
  24 
  25 package client.test.runner;
  26 
  27 import static client.test.runner.InterviewUtils.*;
  28 import client.test.runner.interview.LookAndFeelQuestion;
  29 import client.test.runner.interview.PipelineGroupQuestion;
  30 import client.util.CtrUtils;
  31 import com.sun.interview.*;
  32 import com.sun.javatest.Parameters.EnvParameters;
  33 import com.sun.javatest.TestEnvironment;
  34 import com.sun.javatest.interview.BasicInterviewParameters;
  35 import java.io.File;
  36 import java.io.IOException;
  37 import java.net.UnknownHostException;
  38 import java.util.HashMap;
  39 import java.util.Map;
  40 
  41 /**
  42  *
  43  * @author vshubov
  44  */
  45 public class BasicFXInterview extends BasicInterviewParameters
  46         implements EnvParameters {
  47 
  48     /**
  49      *
  50      */
  51     public final static String FX_SDK_HOME_PARAM_NAME = "javafx";
  52 
  53     /**
  54      *
  55      */
  56     public final static String EXTERNALOUTPUT = "externaloutput";
  57 
  58     /**
  59      *
  60      */
  61     public final static String PROXY_PARAM_NAME = "proxy";
  62 
  63     /**
  64      *
  65      */
  66     public final static String DRY_RUN_TAG = "dryrun";
  67 
  68     /**
  69      *
  70      */
  71     public final static String DRY_RUN_DURATION_TAG = "dryrun_duration";
  72 
  73     /**
  74      *
  75      */
  76     public static final String REMOTE_RUN = "remote";
  77 
  78     /**
  79      *
  80      */
  81     public static final String JAVATEST_HOSTNAME = "hostname";
  82 
  83     /**
  84      *
  85      */
  86     public static final String RUN_MODE_PARAM = "runmode";
  87 
  88     /**
  89      *
  90      */
  91     public static final String RUN_MODE_DESKTOP = "desktop";
  92 
  93     /**
  94      *
  95      */
  96     public static final String RUN_MODE_DESKTOP_SWING_INTEROPERABILITY = "swing_interoperability";
  97 
  98     /**
  99      *
 100      */
 101     public static final String RUN_MODE_DESKTOP_SWT_INTEROPERABILITY = "swt_interoperability";
 102 
 103     /**
 104      *
 105      */
 106     public static final String RUN_MODE_PLUGIN = "plugin";
 107 
 108     /**
 109      *
 110      */
 111     public static final String RUN_MODE_JNLP = "jnlp";
 112 
 113     /**
 114      *
 115      */
 116     public final static String BROWSER_PARAM_NAME = "browserPath";
 117 
 118     /**
 119      *
 120      */
 121     public final static String JAVAWS_PARAM_NAME = "javawsPath";
 122 
 123     /**
 124      *
 125      */
 126     public final static String JAVA_PARAM_NAME = "javaPath";
 127 
 128     /**
 129      *
 130      */
 131     public final static String ADD_EXPORTS_PARAM_NAME = "addExports";
 132 
 133     /**
 134      *
 135      */
 136     public final static String XPATCH_PARAM_NAME = "XPatch";
 137 
 138     /**
 139      *
 140      */
 141     public final static String ENABLE_ADD_EXPORTS_PARAM_NAME = "addExportsEnabled";
 142 
 143     /**
 144      *
 145      */
 146     public final static String VM_OPTIONS_PARAM_NAME = "vmOptions";
 147 
 148     /**
 149      *
 150      */
 151     public final static String TESTSUITE_ID = "testsuiteID";
 152 
 153     private String javaFXHome;
 154     private String extOut;
 155 
 156     /**
 157      *
 158      * @throws Fault
 159      */
 160     public BasicFXInterview() throws Fault {
 161         super(null);
 162     }
 163 
 164     /**
 165      *
 166      * @return
 167      */
 168     @Override
 169     protected Question getEnvFirstQuestion() {
 170         return qName;
 171     }
 172 
 173     /**
 174      *
 175      * @return
 176      */
 177     @Override
 178     public EnvParameters getEnvParameters() {
 179         return this;
 180     }
 181 
 182     /**
 183      *
 184      * @return
 185      */
 186     @Override
 187     public TestEnvironment getEnv() {
 188         HashMap envProps = new HashMap();
 189         export(envProps);
 190         try {
 191             String name = qName.getValue();
 192             if (name == null || name.length() == 0) {
 193                 name = "unknown";
 194             }
 195             return new TestEnvironment(name, envProps, "configuration interview");
 196         } catch (TestEnvironment.Fault e) {
 197             throw new Error("should not happen" + e);
 198         }
 199     }
 200 
 201     /**
 202      *
 203      * @param data
 204      */
 205     @Override
 206     public void export(Map data) {
 207         String id = getTestSuite().getTestSuiteInfo("id");
 208         data.put(TESTSUITE_ID, id);
 209         super.export(data);
 210     }
 211 
 212     /**
 213      *
 214      * @return
 215      */
 216     public boolean isRemoteRun() {
 217         return YesNoQuestion.YES.equals(qRemoteRun.getValue());
 218     }
 219 
 220     /**
 221      *
 222      * @return
 223      */
 224     public File getJavaPath(){
 225         return qJavaPath.getValue();
 226     }
 227 
 228     public String getXPatch() {
 229         return qXPatch.getValue();
 230     }
 231 
 232     /**
 233      *
 234      * @return
 235      */
 236     protected Question getLastQuestion(){
 237         return getEnvSuccessorQuestion();
 238     }
 239 
 240     /**
 241      *
 242      */
 243     protected StringQuestion qName = new StringQuestion(this, "name") {
 244         @Override
 245         public String getText() {
 246             return getSummary();
 247         }
 248 
 249         @Override
 250         public String getSummary() {
 251             return "Configuration name";
 252         }
 253 
 254         @Override
 255         public Question getNext() {
 256             if ("".equals(getValue()) || getValue() == null) {
 257                 return null;
 258             }
 259             return qRemoteRun;
 260         }
 261 
 262         @Override
 263         public void export(Map data) {
 264             data.put("name", value);
 265         }
 266 
 267         @Override
 268         public void load(Map data) {
 269             setValue((String) data.get("name"));
 270         }
 271     };
 272     private YesNoQuestion qRemoteRun = new YesNoQuestion(this, REMOTE_RUN, YesNoQuestion.NO) {
 273         @Override
 274         public String getText() {
 275             return "Remote test execution: please specify whether you want to run the tests on a remote host."
 276                     + "The agent should be run on that host first.";
 277         }
 278 
 279         @Override
 280         public String getSummary() {
 281             return "Remote test execution";
 282         }
 283         @Override
 284         public Question getNext() {
 285             if (YesNoQuestion.YES.equals(getValue())) {
 286                 return qHostName;
 287             }
 288             return qRunMode;
 289         }
 290 
 291         @Override
 292         public void clear() {
 293             setValue("No");
 294         }
 295 
 296         @Override
 297         protected void export(Map data) {
 298             data.put(REMOTE_RUN, getValue());
 299         }
 300     };
 301     private StringQuestion qHostName = new StringQuestion(this, JAVATEST_HOSTNAME) {
 302 
 303         @Override
 304         public String getText() {
 305             return "Enter the name of the host you are currently running Javatest harness";
 306         }
 307 
 308         @Override
 309         public String getSummary() {
 310             return "Javatest Host Name";
 311         }
 312 
 313         @Override
 314         public void clear() {
 315             String host = "localhost";
 316             try {
 317                 host = java.net.InetAddress.getLocalHost().getHostAddress();
 318             } catch (UnknownHostException ex) {
 319                 //just ignore
 320             }
 321             setValue(host);
 322         }
 323 
 324         @Override
 325         public Question getNext() {
 326             return qRunMode;
 327         }
 328 
 329         @Override
 330         public void export(Map data) {
 331             data.put(JAVATEST_HOSTNAME, value);
 332         }
 333     };
 334 
 335     private ChoiceQuestion qRunMode = new ChoiceQuestion(this, RUN_MODE_PARAM) {
 336         {
 337             setChoices(new String[]{RUN_MODE_DESKTOP, RUN_MODE_DESKTOP_SWING_INTEROPERABILITY, RUN_MODE_DESKTOP_SWT_INTEROPERABILITY, RUN_MODE_PLUGIN, RUN_MODE_JNLP}, false);
 338             clear();
 339         }
 340 
 341         @Override
 342         public Question getNext() {
 343             if (RUN_MODE_PLUGIN.equals(getValue())) {
 344                 return qBrowser;
 345             } else if (RUN_MODE_JNLP.equals(getValue())) {
 346                 return qJavawsPath;
 347             } else {
 348                 return qJavaPath;
 349             }
 350         }
 351 
 352         @Override
 353         public String getDefaultValue() {
 354             return RUN_MODE_DESKTOP;
 355         }
 356 
 357         @Override
 358         public String getText() {
 359             return "Test Run Mode: desktop or web based.\n N.B.: For web-based modes RUNTIME installed to system "
 360                     + "would be used instead SDK (javafx.home). Make sure they are of the same version.\n"
 361                     + "Run 'javaws -uninstall' before running web-mode tests.";
 362         }
 363 
 364         @Override
 365         public String getSummary() {
 366             return "Test Run Mode";
 367         }
 368 
 369         @Override
 370         public void clear() {
 371             setValue(RUN_MODE_DESKTOP);
 372         }
 373 
 374         @Override
 375         public void export(Map map) {
 376             map.put(RUN_MODE_PARAM, value);
 377         }
 378 
 379         @Override
 380         public void load(Map data) {
 381             setValue((String) data.get(RUN_MODE_PARAM));
 382         }
 383     };
 384 
 385     private FileQuestion qBrowser = new FileQuestion(this, BROWSER_PARAM_NAME) {
 386         {
 387             this.setFilter(new ExecutablesFileFilter());
 388         }
 389 
 390         @Override
 391         public String getText() {
 392             return "Choose browser executable. Please, close all instances of that browser prior to running tests.";
 393         }
 394 
 395         @Override
 396         public String getSummary() {
 397             return "Browser executable";
 398         }
 399 
 400         @Override
 401         public void export(Map data) {
 402             data.put(BROWSER_PARAM_NAME, value.getPath());
 403         }
 404 
 405         //TODO: browsers autodetection
 406         private static final String FF = "firefox";
 407 
 408         @Override
 409         protected void save(Map data) {
 410             // this is not the best place to perform this check, but javatest doesn't provide better option
 411             String path = value.getPath();
 412             if (path != null && path.contains("iexplore")) {
 413                 BasicFXInterview.ieFix.run();
 414             }
 415             super.save(data);
 416         }
 417 
 418         private final String mostCommonPaths[] = new String[]{
 419             "\\Applications\\Firefox.app\\Contents\\MacOS\\firefox",
 420             "C:/Program Files (x86)/Mozilla Firefox/firefox.exe"
 421         };
 422 
 423         @Override
 424         public void clear() {
 425             String def = FF;
 426             for (String path : mostCommonPaths) {
 427                 File f = new File(path);
 428                 if (f.isFile()) {
 429                     setValue(f.getAbsolutePath());
 430                     return;
 431                 }
 432             }
 433             setValue(def);
 434         }
 435 
 436         @Override
 437         public Question getNext() {
 438             if (!(value.isFile() || FF.equals(value.getName()))) {
 439                 return null;
 440             }
 441             return getEnvSuccessorQuestion();
 442         }
 443 
 444         @Override
 445         public void load(Map data) {
 446 
 447             String tmp = null;
 448             if (data.containsKey(BROWSER_PARAM_NAME)
 449                 && (null!=(tmp= (String)data.get(BROWSER_PARAM_NAME)))
 450                 &&  (new File(tmp)).isFile()  ) {
 451                          setValue(new File(tmp));
 452                 }
 453             else {
 454                 clear();
 455             }
 456         }
 457 
 458     };
 459 
 460     private FileQuestion qJavawsPath = new FileQuestion(this, JAVAWS_PARAM_NAME) {
 461         {
 462             this.setFilter(new ExecutablesFileFilter());
 463         }
 464 
 465         @Override
 466         public String getText() {
 467             return "Choose javaws executable location.";
 468         }
 469 
 470         @Override
 471         public String getSummary() {
 472             return "Java Web Start Executable";
 473         }
 474         private final String mostCommonPaths[] = new String[]{
 475             "C:/Program Files (x86)/Oracle/JavaFX Runtime 2.0/bin/javaws.exe",
 476             "C:/Program Files/Oracle/JavaFX Runtime 2.0/bin/javaws.exe",
 477             "C:/Program Files/Java/jdk1.8.0/jre/bin/javaws.exe",
 478             "C:/Program Files (x86)/Java/jdk1.8.0/jre/bin/javaws.exe"
 479         };
 480         private static final String JAVAWS = "javaws";
 481 
 482         @Override
 483         public void clear() { // you should not call setValue() twice here,
 484                               //  and should not ask why
 485             String def = JAVAWS;
 486             if (isWindows()) {
 487                 for (String path : mostCommonPaths) {
 488                     // debug System.out.println("try:" + path);
 489                     File f = new File(path);
 490                     if (f.isFile()) {
 491                         // debug System.out.println("Yes!" + f.getAbsolutePath());
 492                         setValue(f.getAbsolutePath());
 493                         // debug System.out.println("Yes=" + getValue());
 494                         return;
 495                     }
 496                 }
 497             }
 498             setValue(def);
 499         }
 500 
 501         @Override
 502         public Question getNext() {
 503             return qPipelineGroup;
 504         }
 505 
 506         @Override
 507         public void export(Map data) {
 508             data.put(JAVAWS_PARAM_NAME, value.getPath());
 509         }
 510 
 511         @Override
 512         public void load(Map data) {
 513 
 514             String tmp = null;
 515             if (data.containsKey(JAVAWS_PARAM_NAME)
 516                 && (null!=(tmp= (String)data.get(JAVAWS_PARAM_NAME)))
 517                 &&  (new File(tmp)).isFile()  ) {
 518                          setValue(new File(tmp));
 519                 }
 520             else {
 521                 clear();
 522             }
 523         }
 524     };
 525 
 526     private FileQuestion qJavaPath = new FileQuestion(this, JAVA_PARAM_NAME) {
 527         {
 528             this.setFilter(new ExecutablesFileFilter());
 529         }
 530 
 531         @Override
 532         public boolean isValueValid() {
 533             if(YesNoQuestion.YES.equals(qRemoteRun.getValue())) {
 534                 return true;
 535             }
 536             return super.isValueValid();
 537         }
 538 
 539         @Override
 540         public String getText() {
 541             return "Choose java executable from JDK installation.";
 542         }
 543 
 544         @Override
 545         public String getSummary() {
 546             return "Java Executable";
 547         }
 548         private final String JAVA_DEF = System.getProperty("java.home") + File.separator + "bin" + File.separator + (isWindows() ? "java.exe":"java");
 549 
 550         @Override
 551         public void clear() {
 552             setValue(JAVA_DEF);
 553         }
 554 
 555         @Override
 556         public Question getNext() {
 557             return qJavaFX;
 558         }
 559 
 560         @Override
 561         public void export(Map data) {
 562             data.put(JAVA_PARAM_NAME, value.getPath());
 563         }
 564 
 565         @Override
 566         public void load(Map data) {
 567             if (data.containsKey(JAVA_PARAM_NAME)) {
 568                 String exec = (String) data.get(JAVA_PARAM_NAME);
 569                 if (exec != null) {
 570                     setValue(new File(exec));
 571                 }
 572             }
 573         }
 574     };
 575 
 576 
 577     private FileQuestion qJavaFX = new FileQuestion(this, FX_SDK_HOME_PARAM_NAME) {
 578         {
 579             this.setFilter(new DirectoryFileFilter("JavaFX SDK containing directory"));
 580         }
 581 
 582         @Override
 583         public String getText() {
 584             return getSummary();
 585         }
 586 
 587         @Override
 588         public String getSummary() {
 589             return "JavaFX SDK Home";
 590         }
 591 
 592         @Override
 593         public boolean isValueValid() {
 594             if(YesNoQuestion.YES.equals(qRemoteRun.getValue())) {
 595                 return true;
 596             }
 597             return super.isValueValid();
 598         }
 599 
 600         @Override
 601         public void clear() {
 602             if (javaFXHome != null) {
 603                 setValue(javaFXHome);
 604             } else {
 605                 setValue("");
 606             }
 607         }
 608 
 609         @Override
 610         public Question getNext() {
 611             return qDryRun;
 612         }
 613 
 614         @Override
 615         public void export(Map data) {
 616             javaFXHome = value.getPath();
 617             data.put(FX_SDK_HOME_PARAM_NAME, javaFXHome);
 618         }
 619 
 620         @Override
 621         public void load(Map data) {
 622             if (data.containsKey(FX_SDK_HOME_PARAM_NAME)) {
 623                 javaFXHome = (String) data.get(FX_SDK_HOME_PARAM_NAME);
 624                 if (javaFXHome != null) {
 625                     setValue(new File(javaFXHome));
 626                 }
 627             }
 628         }
 629     };
 630     private YesNoQuestion qDryRun = new YesNoQuestion(this, DRY_RUN_TAG, YesNoQuestion.NO) {
 631         @Override
 632         public Question getNext() {
 633             if (getValue().toString().equals(YES)) {
 634                 return qDryRunDuration;
 635             }
 636             return qExternalOutput;
 637         }
 638 
 639         @Override
 640         public String getText() {
 641             return "During dry run no tests' instructions are shown, only tests' UI. All tests are marked as ERROR. "
 642                     + "This is artificial mode used for debugging and other purposes. Doesn't affect automated tests.";
 643         }
 644 
 645         @Override
 646         public String getSummary() {
 647             return "Perform a Dry Run";
 648         }
 649 
 650         @Override
 651         public void export(Map data) {
 652             data.put(DRY_RUN_TAG, getValue());
 653         }
 654 
 655         @Override
 656         public void load(Map data) {
 657             if (data.containsKey(DRY_RUN_TAG)) {
 658                 setValue((String) data.get(DRY_RUN_TAG));
 659             }
 660         }
 661     };
 662     static final int DRY_RUN_DEFAULT_DELAY = 5;
 663     private IntQuestion qDryRunDuration = new IntQuestion(this, DRY_RUN_DURATION_TAG, 0, 600) {
 664         {
 665             this.setDefaultValue(DRY_RUN_DEFAULT_DELAY);
 666         }
 667 
 668         @Override
 669         protected Question getNext() {
 670             return qExternalOutput;
 671         }
 672 
 673         @Override
 674         public String getText() {
 675             return "Setup duration of delay for closing test UI (in seconds)";
 676         }
 677 
 678         @Override
 679         public String getSummary() {
 680             return "Dry Run delay";
 681         }
 682 
 683         @Override
 684         public void export(Map data) {
 685             data.put(DRY_RUN_DURATION_TAG, Integer.toString(getValue()));
 686         }
 687 
 688         @Override
 689         public void load(Map data) {
 690             if (data.containsKey(DRY_RUN_DURATION_TAG)) {
 691                 try {
 692                     setValue(Integer.parseInt((String) data.get(DRY_RUN_DURATION_TAG)));
 693                 } catch (Exception e) {
 694                     // keep default
 695                 }
 696 
 697             }
 698         }
 699     };
 700     private FileQuestion qExternalOutput = new FileQuestion(this, EXTERNALOUTPUT) {
 701         @Override
 702         public boolean isValueValid() {
 703             if(YesNoQuestion.YES.equals(qRemoteRun.getValue())) {
 704                 return true;
 705             }
 706             return super.isValueValid();
 707         }
 708 
 709         @Override
 710         public Question getNext() {
 711             return qLookAndFeelGroup;
 712         }
 713 
 714         @Override
 715         public String getText() {
 716             return getSummary();
 717         }
 718 
 719         @Override
 720         public String getSummary() {
 721             return "output dir";
 722         }
 723 
 724         @Override
 725         public void export(Map data) {
 726             extOut = value.getPath();
 727             data.put(EXTERNALOUTPUT, extOut);
 728         }
 729 
 730         @Override
 731         public void load(Map data) {
 732             if (data.containsKey(EXTERNALOUTPUT)) {
 733                 extOut = (String) data.get(EXTERNALOUTPUT);
 734                 if (extOut != null) {
 735                     setValue(new File(extOut));
 736                 }
 737             }
 738         }
 739     };
 740 
 741     private StringQuestion qProxy = new StringQuestion(this, "proxy") {
 742 
 743         {
 744             clear();
 745         }
 746         @Override
 747         public void clear() {
 748             setValue("");
 749         }
 750 
 751         @Override
 752         public String getText() {
 753             return "Proxy settings in format: host:port\nE.g. proxy.example.com:80";
 754         }
 755 
 756         @Override
 757         public String getSummary() {
 758             return "Proxy settings";
 759         }
 760 
 761         @Override
 762         public Question getNext() {
 763             String val = getValue();
 764             if (val == null || val.trim().length() == 0 || CtrUtils.getProxyUrl(val) != null) {
 765                 return qXPatch;
 766             } else {
 767                 return null;
 768             }
 769         }
 770 
 771         @Override
 772         public void export(Map data) {
 773             data.put(PROXY_PARAM_NAME, value);
 774         }
 775 
 776         @Override
 777         public void load(Map data) {
 778             String v = (String) data.get(PROXY_PARAM_NAME);
 779             setValue(v != null ? v : "");
 780         }
 781     };
 782 
 783     private LookAndFeelQuestion qLookAndFeelGroup = new LookAndFeelQuestion (this, qProxy);
 784     private ChoiceQuestion qPipelineGroup = new PipelineGroupQuestion (this, getLastQuestion());
 785 
 786     private StringQuestion qXPatch = new StringQuestion(this, XPATCH_PARAM_NAME) {
 787 
 788         @Override
 789         public String getText() {
 790             return "Set -Xpatch directory for the test run. "
 791                     + "\nE.g. build/shim-modules";
 792         }
 793 
 794         @Override
 795         public String getSummary() {
 796             return "-Xpatch";
 797         }
 798 
 799         @Override
 800         public void clear() {
 801             setValue("");
 802         }
 803 
 804         @Override
 805         public Question getNext() {
 806             return qEnableAddExports;
 807         }
 808 
 809         @Override
 810         public void export(Map data) {
 811             data.put(XPATCH_PARAM_NAME, value);
 812         }
 813 
 814         @Override
 815         public void load(Map data) {
 816             String newValue = (String) data.get(XPATCH_PARAM_NAME);
 817             setValue(newValue != null ? newValue : "");
 818         }
 819     };
 820 
 821     private YesNoQuestion qEnableAddExports = new YesNoQuestion(this, ENABLE_ADD_EXPORTS_PARAM_NAME, YesNoQuestion.YES) {
 822         @Override
 823         public Question getNext() {
 824             if (getValue().equals(YES)) {
 825                 return qAddExports;
 826             }
 827             return qVmOptions;
 828         }
 829 
 830         @Override
 831         public String getText() {
 832             return "Do you wish to add -XaddExports JVM argument when running tests? "
 833                     + "\nAnswer Yes when running with JDK 9 Jigsaw."
 834                     + "\nAnswer No when running with JDK 8 and prior.";
 835         }
 836 
 837         @Override
 838         public String getSummary() {
 839             return "Add -XaddExports?";
 840         }
 841 
 842         @Override
 843         public void export(Map data) {
 844             data.put(ENABLE_ADD_EXPORTS_PARAM_NAME, getValue());
 845         }
 846 
 847         @Override
 848         public void load(Map data) {
 849             if (data.containsKey(ENABLE_ADD_EXPORTS_PARAM_NAME)) {
 850                 setValue((String) data.get(ENABLE_ADD_EXPORTS_PARAM_NAME));
 851             }
 852         }
 853     };
 854 
 855     private StringQuestion qAddExports = new StringQuestion(this, ADD_EXPORTS_PARAM_NAME) {
 856 
 857         @Override
 858         public String getText() {
 859             return "Set -XaddExports values for the test run. "
 860                     + "Individual tests can use @addExports annotation "
 861                     + "to add more specific entries to -XaddExports JVM argument."
 862                     + "\nE.g. javafx.graphics/com.sun.prism=ALL-UNNAMED,javafx.base/com.sun.javafx.runtime=ALL-UNNAMED";
 863         }
 864 
 865         @Override
 866         public String getSummary() {
 867             return "-XaddExports";
 868         }
 869 
 870         @Override
 871         public void clear() {
 872             setValue("");
 873         }
 874 
 875         @Override
 876         public Question getNext() {
 877             return qVmOptions;
 878         }
 879 
 880         @Override
 881         public void export(Map data) {
 882             data.put(ADD_EXPORTS_PARAM_NAME, value);
 883         }
 884 
 885         @Override
 886         public void load(Map data) {
 887             String newValue = (String) data.get(ADD_EXPORTS_PARAM_NAME);
 888             setValue(newValue != null ? newValue : "");
 889         }
 890     };
 891 
 892     private StringQuestion qVmOptions = new StringQuestion(this, VM_OPTIONS_PARAM_NAME) {
 893 
 894         @Override
 895         public String getText() {
 896             return "Set VM Options for test run (desktop mode only).\nE.g. -Dprism.verbose=true";
 897         }
 898 
 899         @Override
 900         public String getSummary() {
 901             return "VM Options";
 902         }
 903 
 904         @Override
 905         public void clear() {
 906             setValue("");
 907         }
 908 
 909         @Override
 910         public Question getNext() {
 911             return qPipelineGroup;//getLastQuestion();
 912         }
 913 
 914         @Override
 915         public void export(Map data) {
 916             data.put(VM_OPTIONS_PARAM_NAME, value);
 917         }
 918 
 919         @Override
 920         public void load(Map data) {
 921             String newValue = (String) data.get(VM_OPTIONS_PARAM_NAME);
 922             setValue(newValue != null ? newValue : "");
 923         }
 924     };
 925 
 926     private static Runnable ieFix = new Runnable() {
 927         @Override
 928         public void run() {
 929             if (!alreadyRun) {
 930                 alreadyRun = true; // we prefer this to be run only once but it's not big enough deal to introduce syncronization
 931                 System.out.println("NB: For internet explorer test run registry would be modified to run IE as one process and allow ActiveX from localhost.");
 932                 try {
 933                     System.out.println("'" + IE_TABS_LOCK_PATH + "\\" + IE_TABS_LOCK_KEY + "' key is being set to 0.\n");
 934                     //TODO: in the perfect world we would read current value and restore it after test run
 935                     Runtime.getRuntime().exec("reg add \"" + IE_TABS_LOCK_PATH + "\" /v " + IE_TABS_LOCK_KEY + " /t REG_DWORD /d 0 /f");
 936 
 937                     System.out.println("'" + IE_ACTIVEX_PATH + "\\" + IE_ACTIVEX_KEY + "' key is being set to 0.\n");
 938                     Runtime.getRuntime().exec("reg add \"" + IE_ACTIVEX_PATH + "\" /v " + IE_ACTIVEX_KEY + " /t REG_DWORD /d 0 /f");
 939 
 940                     System.out.println("'" + IE_ACTIVEX_LOCAL_PATH + "\\" + IE_ACTIVEX_LOCAL_KEY + "' key is being set to 0.\n");
 941                     Runtime.getRuntime().exec("reg add \"" + IE_ACTIVEX_LOCAL_PATH + "\" /v " + IE_ACTIVEX_LOCAL_KEY + " /t REG_DWORD /d 0 /f");
 942                 } catch (IOException ex) {
 943                     ex.printStackTrace();
 944                 }
 945             }
 946         }
 947         private boolean alreadyRun = false;
 948         private static final String IE_TABS_LOCK_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main";
 949         private static final String IE_TABS_LOCK_KEY = "TabProcGrowth";
 950         private static final String IE_ACTIVEX_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Safety\\ActiveXFiltering";
 951         private static final String IE_ACTIVEX_KEY = "IsEnabled";
 952         private static final String IE_ACTIVEX_LOCAL_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN";
 953         private static final String IE_ACTIVEX_LOCAL_KEY = "iexplore.exe";
 954     };
 955 
 956 }