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