1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest; 28 29 import java.io.BufferedInputStream; 30 import java.io.BufferedOutputStream; 31 import java.io.File; 32 import java.io.FileInputStream; 33 import java.io.FileNotFoundException; 34 import java.io.FileOutputStream; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.OutputStream; 38 import java.util.*; 39 40 import com.sun.interview.ErrorQuestion; 41 import com.sun.interview.FinalQuestion; 42 import com.sun.interview.Interview; 43 import com.sun.interview.Question; 44 import com.sun.javatest.tool.CustomPropagationController; 45 import com.sun.javatest.tool.FileHistory; 46 import com.sun.javatest.util.BackupPolicy; 47 import com.sun.javatest.util.I18NResourceBundle; 48 import com.sun.javatest.util.Properties; 49 50 /** 51 * Configuration parameters provided via an interview. 52 * 53 * @since 3.0 54 */ 55 public abstract class InterviewParameters 56 extends Interview 57 implements Parameters 58 { 59 60 /** 61 * Indicates problems when accessing the work directory. 62 */ 63 public static class WorkDirFault extends Interview.Fault { 64 /** 65 * Create a fault with an internationalized message. 66 * @param i18n The bundle from which to get the string. 67 * @param s The key for getting the string to be displayed from the 68 * supplied bundle. 69 */ 70 public WorkDirFault(ResourceBundle i18n, String s) { 71 super(i18n, s); 72 } 73 74 /** 75 * Create a fault with an internationalized message. 76 * @param i18n The bundle from which to get the string. 77 * @param s The key for getting the string to be displayed from the 78 * supplied bundle. 79 * @param o Parameter to use when resolving the string from the bundle. 80 * @see java.text.MessageFormat 81 */ 82 public WorkDirFault(ResourceBundle i18n, String s, Object o) { 83 super(i18n, s, o); 84 } 85 86 /** 87 * Create a fault with an internationalized message. 88 * @param i18n The bundle from which to get the string. 89 * @param s The key for getting the string to be displayed from the 90 * supplied bundle. 91 * @param o Parameters to use when resolving the string from the bundle. 92 * @see java.text.MessageFormat 93 */ 94 public WorkDirFault(ResourceBundle i18n, String s, Object[] o) { 95 super(i18n, s, o); 96 } 97 } 98 99 /** 100 * Indicates problems when accessing the test suite. 101 */ 102 public static class TestSuiteFault extends Interview.Fault { 103 /** 104 * Create a fault with an internationalized message. 105 * @param i18n The bundle from which to get the string. 106 * @param s The key for getting the string to be displayed from the 107 * supplied bundle. 108 */ 109 public TestSuiteFault(ResourceBundle i18n, String s) { 110 super(i18n, s); 111 } 112 113 /** 114 * Create a fault with an internationalized message. 115 * @param i18n The bundle from which to get the string. 116 * @param s The key for getting the string to be displayed from the 117 * supplied bundle. 118 * @param o Parameter to use when resolving the string from the bundle. 119 * @see java.text.MessageFormat 120 */ 121 public TestSuiteFault(ResourceBundle i18n, String s, Object o) { 122 super(i18n, s, o); 123 } 124 125 /** 126 * Create a fault with an internationalized message. 127 * @param i18n The bundle from which to get the string. 128 * @param s The key for getting the string to be displayed from the 129 * supplied bundle. 130 * @param o Parameters to use when resolving the string from the bundle. 131 * @see java.text.MessageFormat 132 */ 133 public TestSuiteFault(ResourceBundle i18n, String s, Object[] o) { 134 super(i18n, s, o); 135 } 136 } 137 138 /** 139 * Indicates problems when accessing the configuration file. 140 */ 141 public static class JTIFault extends Interview.Fault { 142 /** 143 * Create a fault with an internationalized message. 144 * @param i18n The bundle from which to get the string. 145 * @param s The key for getting the string to be displayed from the 146 * supplied bundle. 147 */ 148 public JTIFault(ResourceBundle i18n, String s) { 149 super(i18n, s); 150 } 151 152 /** 153 * Create a fault with an internationalized message. 154 * @param i18n The bundle from which to get the string. 155 * @param s The key for getting the string to be displayed from the 156 * supplied bundle. 157 * @param o Parameter to use when resolving the string from the bundle. 158 * @see java.text.MessageFormat 159 */ 160 public JTIFault(ResourceBundle i18n, String s, Object o) { 161 super(i18n, s, o); 162 } 163 164 /** 165 * Create a fault with an internationalized message. 166 * @param i18n The bundle from which to get the string. 167 * @param s The key for getting the string to be displayed from the 168 * supplied bundle. 169 * @param o Parameters to use when resolving the string from the bundle. 170 * @see java.text.MessageFormat 171 */ 172 public JTIFault(ResourceBundle i18n, String s, Object[] o) { 173 super(i18n, s, o); 174 } 175 } 176 177 /** 178 * The template manager is used to change behavior of 179 * template saving, the default implementation is 180 * the context manager of corresponding test suite. 181 */ 182 public interface TemplateManager { 183 /** 184 * This method is invoked each time before saving template. 185 * The template will be saved only if this method returns true. 186 * @param file template file 187 * @return true if this operation is allowed, false otherwise 188 */ 189 public boolean canSaveTemplate(File file); 190 } 191 192 public void setPropagationController(CustomPropagationController pc) { 193 this.pc = pc; 194 } 195 196 public CustomPropagationController getPropagationController() { 197 return pc; 198 } 199 200 private TemplateManager templateManager = null; 201 /** 202 * Create an InterviewParameters object. 203 * @param tag The tag used to qualify questions in this interview 204 */ 205 protected InterviewParameters(String tag) { 206 super(tag); 207 } 208 209 /** 210 * Set the work directory to be used for this test run. 211 * @param workDir the work directory to be used for this test run. 212 * It must match the test suite to be used for this test run 213 */ 214 public abstract void setWorkDirectory(WorkDirectory workDir); 215 216 /** 217 * Set given template manager for this InterviewParameters. 218 * @param tm new template manager 219 */ 220 public void setTemplateManger(TemplateManager tm) { 221 this.templateManager = tm; 222 } 223 224 /** 225 * Return the template manager for this InterviewParameters. 226 */ 227 public TemplateManager getTemplateManger() { 228 return templateManager; 229 } 230 231 /** 232 * Initialize an InterviewParameters object. 233 * This method is called when the object is created 234 * from an entry in a .jtt file. 235 * By default, the method throws an exception if any arguments 236 * are given. It should be redefined by any test suites that wish 237 * to support this type of initialization. 238 * @param args test suite specific args with which to initialize 239 * this InterviewParameters object 240 * @throws Interview.Fault if any problems occurred while processing the arguments 241 */ 242 public void init(String[] args) throws Fault { 243 if (args != null && args.length > 0) 244 throw new Fault(i18n, "ip.unknownArgs"); 245 } 246 247 /** 248 * Clean up an InterviewParameters object. 249 * This method should be invoked at the moment InterviewParameters object 250 * becomes useless by the code, that controls it's lifecycle. For example, 251 * at the end of the method which created it's local instance. 252 * 253 * Any following invocations on this object may result in unpredictable 254 * exceptions because of object inconsistence. 255 */ 256 public void dispose() { 257 kflFiles = null; 258 backupPolicy = null; 259 cachedExcludeListFilter = null; 260 cachedKeywordsFilter = null; 261 cachedRelevantTestFilter = null; 262 cachedRelevantTestFilterEnv = null; 263 cachedStatusFilter = null; 264 cachedTestFilters = null; 265 pc = null; 266 templateManager = null; 267 } 268 269 //---------------------------------------------------------------------------- 270 271 /** 272 * Get the name for this configuration. 273 * By default and for backwards compatibility, this defaults to the 274 * name of the test environment, which means that the whole environment 275 * may need to be evaluated to get the required value. Subtypes may 276 * choose to override this method to provide a more efficient 277 * implementation. 278 * 279 * <p> Since the default implementation gets the name from the test 280 * environment, clients should not use this method to determine 281 * the name for the test environment, unless this method is redefined. 282 * The default implementation detects such a circular usage, and 283 * returns null in this case. 284 * 285 * @return the name for this configuration, or null if not known. 286 */ 287 public synchronized String getName() { 288 if (inGetName) 289 return null; 290 291 try { 292 inGetName = true; 293 294 EnvParameters eParams = getEnvParameters(); 295 if (eParams != null) { 296 // getName to get the name for the environment 297 TestEnvironment e = eParams.getEnv(); 298 if (e != null) 299 return e.getName(); 300 } 301 return null; 302 } 303 finally { 304 inGetName = false; 305 } 306 } 307 308 private boolean inGetName; 309 310 /** 311 * Get a description for this configuration. 312 * By default and for backwards compatibility, this defaults to the 313 * description entry in the test environment, which means that the 314 * whole environment may need to be evaluated to get the required value. 315 * Subtypes may choose to override this method to provide a more efficient 316 * implementation. 317 * @return a description for this configuration, or null if not known 318 */ 319 public String getDescription() { 320 EnvParameters eParams = getEnvParameters(); 321 if (eParams != null) { 322 TestEnvironment e = eParams.getEnv(); 323 if (e != null) 324 return e.getDescription(); 325 } 326 return null; 327 } 328 329 330 //---------------------------------------------------------------------------- 331 332 /** 333 * Get the next question to the asked after the initial prolog 334 * of questions. 335 * The default value is the result of getEnvFirstQuestion. 336 * @return the next question to be asked after the initial prolog 337 * of questions. 338 * @see #setFirstQuestion 339 */ 340 protected Question getPrologSuccessorQuestion() { 341 return getEnvFirstQuestion(); 342 } 343 344 //---------------------------------------------------------------------------- 345 346 347 public TestEnvironment getEnv() { 348 EnvParameters eParams = getEnvParameters(); 349 if (eParams == null) 350 throw new NullPointerException(); 351 else 352 return eParams.getEnv(); 353 } 354 355 /** 356 * Get the first question to be asked concerning the environment to be 357 * set up and used for each test to be run. If these questions are 358 * contained in an interview, this method can be simply implemented as:<br> 359 * <code>return callInterview(</code><i>envInterview</i><code>, getEnvSuccessorQuestion);</code><br> 360 * @return the first question to be asked concerning the environment to be 361 * set up and used for each test to be run. 362 * @see #getEnvSuccessorQuestion 363 */ 364 protected abstract Question getEnvFirstQuestion(); 365 366 /** 367 * Get the next question to be asked after those concerning 368 * the environment to be set up and used for each test to be run. 369 * The default value is the result of getTestsFirstQuestion. 370 * @return the next question to be asked after those concerning 371 * the environment to be set up and used for each test to be run. 372 * @see #getEnvFirstQuestion 373 */ 374 protected Question getEnvSuccessorQuestion() { 375 return getTestsFirstQuestion(); 376 } 377 378 public String[] getTests() { 379 TestsParameters iParams = getTestsParameters(); 380 return (iParams == null ? null : iParams.getTests()); 381 } 382 383 /** 384 * Get the first question to be asked concerning the set of tests 385 * and folders of tests to be run. 386 * @return the first question to be asked concerning the set of tests 387 * and folders of tests to be run. 388 * @see #getTestsSuccessorQuestion 389 */ 390 protected abstract Question getTestsFirstQuestion(); 391 392 /** 393 * Get the next question to be asked after those concerning 394 * the tests and folders of tests to be run. 395 * The default value is the result of getExcludeListFirstQuestion. 396 * @return the next question to be asked after those concerning 397 * the tests and folders of tests to be run. 398 * @see #getTestsFirstQuestion 399 */ 400 protected Question getTestsSuccessorQuestion() { 401 return getExcludeListFirstQuestion(); 402 } 403 404 public ExcludeList getExcludeList() { 405 ExcludeListParameters eParams = getExcludeListParameters(); 406 return (eParams == null ? new ExcludeList() : eParams.getExcludeList()); 407 } 408 409 /** 410 * Get the combined known failures list. 411 * Interviews expecting to use known failures lists should generally override 412 * this method and add support for users to change it. 413 * @since 4.4 414 * @see #setKnownFailureFiles(java.io.File[]) 415 * @see com.sun.javatest.interview.BasicInterviewParameters 416 * @return Current known failures list - combined from the one or more 417 * file specified by the user. 418 */ 419 public KnownFailuresList getKnownFailuresList() { 420 try { 421 if (kflFiles != null) { 422 return new KnownFailuresList(getKnownFailureFiles()); 423 } 424 else { 425 return null; 426 } 427 428 } 429 catch (IOException e){ 430 return null; 431 } 432 catch (KnownFailuresList.Fault f) { 433 // report it? 434 return null; 435 } 436 } 437 438 /** 439 * Set the set of KFL files. 440 * @since 4.4 441 * @param files The known failures list files. The array should contain 442 * one or more elements. 443 */ 444 public void setKnownFailureFiles(File[] files) { 445 kflFiles = files; 446 } 447 448 /** 449 * Get the current set of known failures list files. 450 * The default implementation will return the value in the kflFiles 451 * field, which subclasses may set. 452 * @since 4.4 453 * @see #setKnownFailureFiles(java.io.File[]) 454 * @return The list of known failure list files. Null if none. 455 */ 456 public File[] getKnownFailureFiles() { 457 return kflFiles; 458 } 459 460 /** 461 * Get the first question to be asked concerning the exclude list 462 * to be used to exclude tests from the test run. 463 * @return the first question to be asked concerning the exclude list 464 * to be used to exclude tests from the test run. 465 * @see #getExcludeListSuccessorQuestion 466 */ 467 protected abstract Question getExcludeListFirstQuestion(); 468 469 /** 470 * Get the first question to be asked concerning the exclude list 471 * to be used to exclude tests from the test run. 472 * @return the first question to be asked concerning the exclude list 473 * to be used to exclude tests from the test run 474 * @deprecated Use getExcludeListFirstQuestion(). 475 * @see #getExcludeListFirstQuestion 476 */ 477 protected Question getExcludeTableFirstQuestion() { 478 return getExcludeListFirstQuestion(); 479 } 480 481 /** 482 * Get the next question to be asked after those concerning 483 * the exclude list to be used to exclude tests from the test run. 484 * The default value is the result of getKeywordsFirstQuestion, 485 * @return the next question to be asked after those concerning 486 * the exclude list to be used to exclude tests from the test run. 487 * @see #getExcludeListFirstQuestion 488 */ 489 protected Question getExcludeListSuccessorQuestion() { 490 return getKeywordsFirstQuestion(); 491 } 492 493 /** 494 * Get the next question to be asked after those concerning 495 * the exclude list to be used to exclude tests from the test run. 496 * @return the next question to be asked after those concerning 497 * the exclude list to be used to exclude tests from the test run 498 * @deprecated Use getExcludeListFirstQuestion(). 499 * @see #getExcludeListSuccessorQuestion 500 */ 501 protected Question getExcludeTableSuccessorQuestion() { 502 return getExcludeListSuccessorQuestion(); 503 } 504 505 public Keywords getKeywords() { 506 KeywordsParameters kParams = getKeywordsParameters(); 507 return (kParams == null ? null : kParams.getKeywords()); 508 } 509 510 /** 511 * Get the first question to be asked concerning the keywords 512 * that may be used to select tests for the test run. 513 * @return the first question to be asked concerning the keywords 514 * that may be used to select tests for the test run. 515 * @see #getKeywordsSuccessorQuestion 516 */ 517 protected abstract Question getKeywordsFirstQuestion(); 518 519 /** 520 * Get the next question to be asked after those concerning 521 * the keywords that may be used to select tests for the test run. 522 * The default value is the result of getPriorStatusQuestion. 523 * @return the next question to be asked after those concerning 524 * the keywords that may be used to select tests for the test run. 525 * @see #getKeywordsFirstQuestion 526 */ 527 protected Question getKeywordsSuccessorQuestion() { 528 return getPriorStatusFirstQuestion(); 529 } 530 531 public boolean[] getPriorStatusValues() { 532 PriorStatusParameters sParams = getPriorStatusParameters(); 533 return (sParams == null ? null : sParams.getPriorStatusValues()); 534 } 535 536 /** 537 * Get the first question to be asked concerning whether tests should 538 * be selected for execution according to their prior execution status. 539 * @return the first question to be asked concerning whether tests should 540 * be selected for execution according to their prior execution status. 541 * @see #getPriorStatusSuccessorQuestion 542 */ 543 protected abstract Question getPriorStatusFirstQuestion(); 544 545 /** 546 * Get the next question to be asked after those concerning 547 * whether tests should be selected for execution according to their 548 * prior execution status. 549 * The default value is the result of getConcurrencyFirstQuestion 550 * @return the next question to be asked after those concerning 551 * whether tests should be selected for execution according to their 552 * prior execution status. 553 * @see #getPriorStatusFirstQuestion 554 */ 555 protected Question getPriorStatusSuccessorQuestion() { 556 return getConcurrencyFirstQuestion(); 557 } 558 559 public int getConcurrency() { 560 ConcurrencyParameters cParams = getConcurrencyParameters(); 561 return (cParams == null ? 1 : cParams.getConcurrency()); 562 } 563 564 /** 565 * Get the first question concerning the number of tests that 566 * may be run in parallel. 567 * @return the first question concerning the number of tests that 568 * may be run in parallel. 569 * @see #getConcurrencySuccessorQuestion 570 */ 571 protected abstract Question getConcurrencyFirstQuestion(); 572 573 /** 574 * Get the next question after those concerning the number 575 * of tests that may be run in parallel. 576 * The default is the result of getTimeoutFactorFirstQuestion 577 * @return the next question after those concerning the number 578 * of tests that may be run in parallel. 579 * @see #getConcurrencyFirstQuestion 580 */ 581 protected Question getConcurrencySuccessorQuestion() { 582 return getTimeoutFactorFirstQuestion(); 583 } 584 585 public float getTimeoutFactor() { 586 TimeoutFactorParameters tParams = getTimeoutFactorParameters(); 587 return (tParams == null ? 1 : tParams.getTimeoutFactor()); 588 } 589 590 /** 591 * Get the first question concerning the scale factor to 592 * be applied to the standard timeout for each test. 593 * @return the first question concerning the scale factor to 594 * be applied to the standard timeout for each test. 595 * @see #getTimeoutFactorSuccessorQuestion 596 */ 597 protected abstract Question getTimeoutFactorFirstQuestion(); 598 599 /** 600 * Get the next question after those concerning the scale factor to 601 * be applied to the standard timeout for each test. 602 * The default is the result of getEpilogFirstQuestion 603 * @return the next question after those concerning the scale factor to 604 * be applied to the standard timeout for each test. 605 * @see #getTimeoutFactorFirstQuestion 606 */ 607 protected Question getTimeoutFactorSuccessorQuestion() { 608 return getEpilogFirstQuestion(); 609 } 610 611 /** 612 * Get the first question of the epilog, which should be asked after 613 * all the other questions in the configuration interview have been asked. 614 * The epilog should terminate in the standard way with a FinalQuestion. 615 * @return the first question of the epilog, which should be asked after 616 * all the other questions in the configuration interview have been asked. 617 */ 618 protected abstract Question getEpilogFirstQuestion(); 619 620 //---------------------------------------------------------------------------- 621 622 /** 623 * Determine whether all the configuration values are valid, by 624 * checking if the interview has been completed. 625 * If so, the result will be true; if not, the result will be false, 626 * and getErrorMessage will provide details about at least one of the 627 * invalid values. 628 * @return true if and only if all the configuration values are valid 629 * @see #getErrorMessage 630 * @see #isFinishable 631 */ 632 public boolean isValid() { 633 return isFinishable(); 634 } 635 636 /** 637 * If there is an error in any of the configuration values, 638 * as indicated by isValid, this method will provide a detail 639 * message about the first question for which there is a problem. 640 * @return a detail message about the first question with an invalid answer, 641 * or null if none. 642 * @see #isValid 643 */ 644 public String getErrorMessage() { 645 Question[] path = getPath(); 646 Question lastQuestion = path[path.length - 1]; 647 if (lastQuestion instanceof FinalQuestion) 648 return null; 649 else if (lastQuestion instanceof ErrorQuestion) 650 return lastQuestion.getText(); 651 else { 652 String v = lastQuestion.getStringValue(); 653 return i18n.getString("ip.noAnswer", 654 new Object[] { lastQuestion.getSummary(), 655 lastQuestion.getText(), 656 lastQuestion.getTag(), 657 new Integer(v == null ? 0 : 1), 658 trim(v), 659 } ); 660 } 661 } 662 663 private String trim(String text) { 664 return (text == null ? null 665 : text.length() < 40 ? text 666 : text.substring(0, 37) + "..."); 667 } 668 669 670 //---------------------------------------------------------------------------- 671 672 /** 673 * Get a filter which will filter tests according to the result 674 * of getExcludeList(). If the result of getExcludeList is null 675 * or an empty exclude list, the result of this method will also be null. 676 * @return a filter which will filter tests according to the result 677 * of getExcludeList() 678 * @deprecated Use getExcludeListFilter(). 679 * @see #getExcludeListFilter 680 */ 681 public TestFilter getExcludeTableFilter() { 682 return getExcludeListFilter(); 683 } 684 685 public TestFilter getExcludeListFilter() { 686 ExcludeList t = getExcludeList(); 687 if (t == null) 688 cachedExcludeListFilter = null; 689 else if (cachedExcludeListFilter == null 690 || cachedExcludeListFilter.getExcludeList() != t) 691 cachedExcludeListFilter = new ExcludeListFilter(t); 692 return cachedExcludeListFilter; 693 } 694 695 private ExcludeListFilter cachedExcludeListFilter; 696 697 public TestFilter getKeywordsFilter() { 698 Keywords k = getKeywords(); 699 if (k == null) 700 cachedKeywordsFilter = null; 701 else if (cachedKeywordsFilter == null 702 || cachedKeywordsFilter.getKeywords() != k) 703 cachedKeywordsFilter = new KeywordsFilter(k); 704 return cachedKeywordsFilter; 705 } 706 707 private KeywordsFilter cachedKeywordsFilter; 708 709 public TestFilter getPriorStatusFilter() { 710 WorkDirectory wd = getWorkDirectory(); 711 TestResultTable r = (wd == null ? null : wd.getTestResultTable()); 712 boolean[] s = getPriorStatusValues(); 713 if (r == null || s == null) 714 cachedStatusFilter = null; 715 else if (cachedStatusFilter == null 716 || cachedStatusFilter.getTestResultTable() != r 717 || !equal(cachedStatusFilter.getStatusValues(), s)) 718 cachedStatusFilter = new StatusFilter(s, r); 719 // else 720 // cachedStatusFilter is OK 721 722 return cachedStatusFilter; 723 } 724 725 private StatusFilter cachedStatusFilter; 726 727 public TestFilter getRelevantTestFilter() { 728 TestSuite ts = getTestSuite(); 729 TestEnvironment env = getEnv(); 730 if (ts == null || env == null) 731 cachedRelevantTestFilter = null; 732 else if (cachedRelevantTestFilter == null || 733 ts != cachedRelevantTestFilterTestSuite || 734 env != cachedRelevantTestFilterEnv) { 735 cachedRelevantTestFilter = ts.createTestFilter(env); 736 } 737 return cachedRelevantTestFilter; 738 } 739 740 private TestFilter cachedRelevantTestFilter; 741 private TestSuite cachedRelevantTestFilterTestSuite; // do we need this? 742 private TestEnvironment cachedRelevantTestFilterEnv; 743 744 public synchronized TestFilter[] getFilters() { 745 Vector<TestFilter> v = new Vector<>(); 746 747 TestFilter excludeFilter = getExcludeListFilter(); 748 if (excludeFilter != null) { 749 v.addElement(excludeFilter); 750 } 751 752 TestFilter keywordFilter = getKeywordsFilter(); 753 if (keywordFilter != null) { 754 v.addElement(keywordFilter); 755 } 756 757 TestFilter statusFilter = getPriorStatusFilter(); 758 if (statusFilter != null) { 759 v.addElement(statusFilter); 760 } 761 762 TestFilter testSuiteFilter = null; 763 try { 764 testSuiteFilter = getRelevantTestFilter(); 765 } 766 catch (Exception e) { 767 testSuiteFilter = null; 768 } 769 if (testSuiteFilter != null) { 770 v.addElement(testSuiteFilter); 771 } 772 773 if (v.size() == 0) { 774 return null; 775 } 776 else if (equal(v, cachedTestFilters)) { 777 return cachedTestFilters; 778 } 779 else { 780 TestFilter[] filters = new TestFilter[v.size()]; 781 v.copyInto(filters); 782 return filters; 783 } 784 785 } 786 787 private static boolean equal(boolean[] b1, boolean[] b2) { 788 if (b1 == null || b2 == null) 789 return (b1 == b2); 790 791 if (b1.length != b2.length) 792 return false; 793 794 for (int i = 0; i < b1.length; i++) { 795 if (b1[i] != b2[i]) 796 return false; 797 } 798 799 return true; 800 } 801 802 private static boolean equal(Vector<TestFilter> v, TestFilter[] f) { 803 if (f == null || v.size() != f.length) 804 return false; 805 for (int i = 0; i < v.size(); i++) { 806 if (!v.elementAt(i).equals(f[i])) 807 return false; 808 } 809 return true; 810 } 811 812 private TestFilter[] cachedTestFilters; 813 814 //---------------------------------------------------------------------------- 815 816 /** 817 * Determine if the current instance is a template or not. 818 * @return true if the current instance is a template, 819 * and false otherwise 820 */ 821 public boolean isTemplate() { 822 return isTemplate; 823 } 824 825 /** 826 * Set if the current instance is a template or not. 827 * <b>For internal use only, architects should not use this.</b> 828 */ 829 public void setTemplate(boolean tm) { 830 isTemplate = tm; 831 updatePath(); 832 } 833 834 protected boolean isAutoUpdatableKey(String key) { 835 return isAutoUpdatableKey(key, null); 836 } 837 838 protected boolean isAutoUpdatableKey(String key, String subkey) { 839 return false; 840 } 841 842 protected boolean isUpdatableKey(String key) { 843 return true; 844 } 845 846 847 /** 848 * Return String path to the template file for the current instance. 849 * If the current instance is a template (isTemplate() returns true), 850 * the path to itself will be returned. 851 * @return String path to the template file, or null if the instance is 852 * not template-based 853 */ 854 public String getTemplatePath() { 855 if (isTemplate()) { 856 File f = getFile(); 857 if (f != null) { 858 return f.getPath(); 859 } 860 } 861 return templatePath; 862 } 863 864 /** 865 * Set the location of a configuration's master template. 866 * Do not change this value if this instance is a template. 867 */ 868 public void setTemplatePath(String tu) { 869 templatePath = tu; 870 } 871 872 873 874 /** 875 * Get the file associated with this interview. 876 * @return the file associated with this interview. 877 * @see #setFile 878 * @see #load 879 * @see #save 880 */ 881 public File getFile() { 882 return currFile; 883 } 884 885 /** 886 * Set the file associated with this interview. This file will be used 887 * by subsequent load and save operations. 888 * @param f The file to be associated with this interview. 889 * @see #getFile 890 * @see #load 891 * @see #save 892 */ 893 public void setFile(File f) { 894 currFile = f; 895 currFileLoaded = false; 896 if (f != null) { 897 currFileLastModified = f.lastModified(); 898 } 899 else { 900 // means: unknown; will likely a trigger a reload 901 currFileLastModified = 0; 902 } 903 } 904 905 /** 906 * Determine if the specified file is an interview file, 907 * as determined by whether its extension is .jti or not. 908 * @param f the file to be checked 909 * @return true if the specified file is an interview file, 910 * and false otherwise 911 */ 912 public static boolean isInterviewFile(File f) { 913 return (f.getName().endsWith(".jti")); 914 } 915 916 /** 917 * Create an InterviewParameters as determined by the contents of an 918 * interview file. 919 * @param file the file to be read 920 * @return an InterviewParameters as determined by the contents of an 921 * interview file. 922 * @throws IOException is there is a problem reading the file 923 * @throws Interview.Fault if there is a problem instantiating the 924 * interview 925 */ 926 public static InterviewParameters open(File file) 927 throws IOException, Fault 928 { 929 return open(file, (TestSuite) null, (WorkDirectory) null); 930 } 931 932 /** 933 * Create an InterviewParameters by populating the interview for a specified 934 * test suite with responses from a given file. 935 * @param file the file to be read 936 * @param testSuite the test suite for which to create the interview 937 * @return an InterviewParameters as determined by the test suite 938 * and the contents of an interview file 939 * @throws IOException is there is a problem reading the file 940 * @throws Interview.Fault if there is a problem instantiating the 941 * interview 942 */ 943 public static InterviewParameters open(File file, TestSuite testSuite) 944 throws IOException, Fault 945 { 946 if (testSuite == null) 947 throw new NullPointerException(); 948 949 return open(file, testSuite, null); 950 } 951 952 /** 953 * Create an InterviewParameters by populating the interview for a specified 954 * work directory with responses from a given file. 955 * @param file the file to be read 956 * @param workDir the work directory (implying the test suite) for which 957 * to create the interview 958 * @return an InterviewParameters as determined by the work directory 959 * and the contents of an interview file 960 * @throws IOException is there is a problem reading the file 961 * @throws Interview.Fault if there is a problem instantiating the 962 * interview 963 */ 964 public static InterviewParameters open(File file, WorkDirectory workDir) 965 throws IOException, Fault 966 { 967 if (workDir == null) 968 throw new NullPointerException(); 969 970 return open(file, workDir.getTestSuite(), workDir); 971 } 972 973 /** 974 * @throws WorkDirFault If there is a problem finding the work directory. 975 * @throws TestSuiteFault If there is a problem finding the test suite. 976 * @throws JTIFault If there is a problem finding the JTI file. Not thrown 977 * if the file is corrupt or incompatible though. 978 * @throws Fault If there is any other problem opening the interview params, such as 979 * problems with data in the JTI, incompatibilities between the workdir, 980 * test suite or work dir. 981 */ 982 private static InterviewParameters open(File file, TestSuite testSuite, WorkDirectory workDir) 983 throws IOException, Fault 984 { 985 // note: the additional Fault types were introduced in JT 3.2.1 986 987 // read the .jti data 988 Map<String, String> data; 989 990 try (InputStream in = new BufferedInputStream(new FileInputStream(file))) { 991 data = Properties.load(in); 992 } 993 catch (RuntimeException e) { 994 // can get IllegalArgumentException if the file is corrupt 995 throw new JTIFault(i18n, "ip.errorReadingFile", new Object[] { file, e }); 996 } 997 998 // if the test suite has not been given, set it from the .jti data 999 if (testSuite == null) { 1000 String s = data.get(TESTSUITE); 1001 if (s == null) 1002 throw new Fault(i18n, "ip.noTestSuiteInFile", file); 1003 1004 try { 1005 testSuite = TestSuite.open(new File(s)); 1006 } 1007 catch (FileNotFoundException e) { 1008 throw new TestSuiteFault(i18n, "ip.cantFindTestSuiteInFile", 1009 new Object[] { s, file }); 1010 } 1011 catch (TestSuite.Fault e) { 1012 throw new Fault(i18n, "ip.cantOpenTestSuiteInFile", 1013 new Object[] { s, file, e.getMessage() } ); 1014 } 1015 } 1016 1017 // if the work directory has not been given, 1018 // set it from the .jti data if given 1019 if (workDir == null) { 1020 String s = data.get(WORKDIR); 1021 if (s != null) { 1022 try { 1023 workDir = WorkDirectory.open(new File(s), testSuite); 1024 } 1025 catch (FileNotFoundException e) { 1026 throw new WorkDirFault(i18n, "ip.cantFindWorkDirInFile", 1027 new Object[] { s, file } ); 1028 } 1029 catch (WorkDirectory.Fault e) { 1030 throw new Fault(i18n, "ip.cantOpenWorkDirInFile", 1031 new Object[] { s, file, e.getMessage() } ); 1032 } 1033 } 1034 } 1035 1036 InterviewParameters parameters; 1037 1038 // create the parameters object 1039 try { 1040 parameters = testSuite.createInterview(); 1041 } 1042 catch (TestSuite.Fault e) { 1043 throw new Fault(i18n, "ip.cantCreateInterviewForTestSuite", 1044 new Object[] { testSuite.getPath(), e.getMessage() } ); 1045 } 1046 1047 // set the work dir in the parameters object 1048 if (workDir != null) 1049 parameters.setWorkDirectory(workDir); 1050 1051 // load the .jti data into the parameters object 1052 try { 1053 parameters.load(data, file); 1054 } 1055 catch (InterviewParameters.Fault e) { 1056 throw new Fault(i18n, "ip.cantLoadInterview", 1057 new Object[] { file, e.getMessage() }); 1058 } 1059 1060 return parameters; 1061 } 1062 1063 public void clear() { 1064 WorkDirectory wd = getWorkDirectory(); 1065 super.clear(); 1066 1067 if (wd != null && TemplateUtilities.getTemplatePath(wd) != null) { 1068 if (wd.getTestSuite() != null) { 1069 try { 1070 wd.getTestSuite().loadInterviewFromTemplate( 1071 TemplateUtilities.getTemplateFile(wd), this); 1072 } catch (TestSuite.Fault ex) { 1073 ex.printStackTrace(); 1074 } catch (IOException ex) { 1075 ex.printStackTrace(); 1076 } 1077 } 1078 } 1079 setEdited(false); 1080 currFile = null; 1081 } 1082 1083 /** 1084 * Open a a configuration file, based on paths for the configuration file, 1085 * test suite and work directory. Any, but not all, of these paths may be null. 1086 * Any non-null path must specify an appropriate existing file, otherwise 1087 * an exception will be thrown. 1088 * @param testSuitePath the path for the test suite; if not specified, 1089 * the test suite will default from the work directory (if specified) or 1090 * the configuration file. 1091 * @param workDirPath the path for the work directory; if not specified, 1092 * the work directory will the default from the config file (if specified), 1093 * or will be null if no configuration file is given 1094 * @param configFilePath the path for the configuration file; if not specified, 1095 * the result will be a blank interview as created by the test suite. 1096 * @return an InterviewParameters object created from the given arguments 1097 * @throws Interview.Fault if there is any problem creating the 1098 * result 1099 */ 1100 public static InterviewParameters open(String testSuitePath, String workDirPath, String configFilePath) 1101 throws InterviewParameters.Fault 1102 { 1103 File ts = (testSuitePath != null && testSuitePath.length() > 0 1104 ? new File(testSuitePath) : null); 1105 File wd = (workDirPath != null && workDirPath.length() > 0 1106 ? new File(workDirPath) : null); 1107 File cf = (configFilePath != null && configFilePath.length() > 0 1108 ? new File(configFilePath) : null); 1109 return open(ts, wd, cf); 1110 } 1111 1112 /** 1113 * Open a a configuration file, based on paths for the configuration file, 1114 * test suite and work directory. Any, but not all, of these paths may be null. 1115 * Any non-null path must specify an appropriate existing file, otherwise 1116 * an exception will be thrown. 1117 * @param testSuitePath the path for the test suite; if not specified, 1118 * the test suite will default from the work directory (if specified) or 1119 * the configuration file. 1120 * @param workDirPath the path for the work directory; if not specified, 1121 * the work directory will bdefault from the config file (if specified), 1122 * or will be null if no configuration file is given 1123 * @param configFilePath the path for the configuration file; if not specified, 1124 * the result will be a blank interview as created by the test suite. 1125 * @return an InterviewParameters object created from the gievn arguments 1126 * @throws Interview.Fault if there is any problem creating the 1127 * result 1128 */ 1129 public static InterviewParameters open(File testSuitePath, File workDirPath, File configFilePath) 1130 throws InterviewParameters.Fault 1131 { 1132 1133 // open test suite if specified 1134 1135 TestSuite testSuite; 1136 1137 if (testSuitePath != null) { 1138 try { 1139 testSuite = TestSuite.open(testSuitePath); 1140 } 1141 catch (FileNotFoundException e) { 1142 throw new Fault(i18n, "ip.cantFindTestSuite", testSuitePath); 1143 } 1144 catch (IOException e) { 1145 throw new Fault(i18n, "ip.cantOpenTestSuite", new Object[] { testSuitePath, e }); 1146 } 1147 catch (TestSuite.Fault e) { 1148 throw new Fault(i18n, "ip.cantOpenTestSuite", new Object[] { testSuitePath, e.getMessage() }); 1149 } 1150 } 1151 else 1152 testSuite = null; 1153 1154 // open work directory if specified, defaulting test suite if appropriate 1155 1156 WorkDirectory workDir; 1157 1158 if (workDirPath != null) { 1159 try { 1160 if (testSuite == null) { 1161 workDir = WorkDirectory.open(workDirPath); 1162 testSuite = workDir.getTestSuite(); 1163 } 1164 else 1165 workDir = WorkDirectory.open(workDirPath, testSuite); 1166 } 1167 catch (FileNotFoundException e) { 1168 throw new Fault(i18n, "ip.cantFindWorkDir", workDirPath); 1169 } 1170 catch (IOException e) { 1171 throw new Fault(i18n, "ip.cantOpenWorkDir", new Object[] { workDirPath, e }); 1172 } 1173 catch (WorkDirectory.Fault e) { 1174 throw new Fault(i18n, "ip.cantOpenWorkDir", new Object[] { workDirPath, e.getMessage() }); 1175 } 1176 } 1177 else 1178 workDir = null; 1179 1180 // open config file if specified, defaulting work dir and test suite if appropriate 1181 // default config from test suite if appropriate 1182 1183 InterviewParameters config; 1184 1185 if (configFilePath == null) { 1186 if (testSuite != null) { 1187 try { 1188 config = testSuite.createInterview(); 1189 } 1190 catch (TestSuite.Fault e) { 1191 throw new Fault(i18n, "ip.cantCreateInterviewForTestSuite", new Object[] { testSuitePath, e }); 1192 } 1193 1194 if (workDir != null) { 1195 config.setWorkDirectory(workDir); 1196 FileHistory h = FileHistory.getFileHistory(workDir, "configHistory.jtl"); 1197 File latestConfigFile = h.getLatestEntry(); 1198 1199 if (latestConfigFile != null) { 1200 try { 1201 config.load(latestConfigFile); 1202 } 1203 catch (IOException e) { 1204 // ignore? 1205 } // catch 1206 } 1207 } // workdir != null 1208 } 1209 else 1210 throw new Fault(i18n, "ip.noPaths"); 1211 } 1212 else { 1213 try { 1214 if (workDir == null) { 1215 if (testSuite == null) { 1216 config = open(configFilePath); 1217 testSuite = config.getTestSuite(); 1218 } 1219 else 1220 config = open(configFilePath, testSuite); 1221 workDir = config.getWorkDirectory(); 1222 } 1223 else 1224 config = open(configFilePath, workDir); 1225 } 1226 catch (FileNotFoundException e) { 1227 throw new Fault(i18n, "ip.cantFindConfigFile", configFilePath); 1228 } 1229 catch (IOException e) { 1230 throw new Fault(i18n, "ip.cantOpenConfigFile", new Object[] { configFilePath, e }); 1231 } 1232 } 1233 1234 // if still here, and had sufficient args, config should be open 1235 // and fully initialized 1236 return config; 1237 } 1238 1239 1240 1241 /** 1242 * Load the interview with the contents of the file associated with 1243 * the interview. If the file does not exist, the interview will be 1244 * cleared. 1245 * @throws IOException is there is a problem reading the file 1246 * @throws Interview.Fault if there is a problem loading the 1247 * interview 1248 * @return true if there was an update from template 1249 */ 1250 public boolean load() throws IOException, Fault { 1251 File f = getFile(); 1252 if (f != null && f.exists()) 1253 return load(f); 1254 else { 1255 clear(); 1256 setEdited(false); 1257 return false; 1258 } 1259 } 1260 1261 /** 1262 * Load the interview with the contents of a specified file, 1263 * which will become the default file associated with the interview. 1264 * @param file the file to be loaded 1265 * @throws FileNotFoundException if the specified file does not exist. 1266 * @throws IOException is there is a problem reading the file 1267 * @throws Interview.Fault if there is a problem loading the 1268 * interview 1269 * @return true if there was an update from template 1270 */ 1271 public boolean load(File file) throws FileNotFoundException, IOException, Fault { 1272 try (InputStream in = new BufferedInputStream(new FileInputStream(file))) { 1273 Map<String, String> data = Properties.load(in); 1274 return load(data, file); 1275 } 1276 } 1277 1278 /** 1279 * Load the interview with data that has already been read from a specified file, 1280 * which will become the default file associated with the interview. 1281 * @param data the data to be loaded 1282 * @param file the file from which the data was read 1283 * @throws Interview.Fault if there is a problem loading the interview 1284 * @return true if there was an update from template 1285 */ 1286 public boolean load(Map<String, String> data, File file) throws Fault { 1287 load(data); 1288 1289 // restore template state 1290 String tm = data.get(IS_TEMPLATE); 1291 setTemplate(tm != null && tm.equalsIgnoreCase(TRUE)); 1292 1293 setEdited(false); 1294 currFile = file; 1295 currFileLastModified = file.lastModified(); 1296 currFileLoaded = true; 1297 return checkForUpdates(); 1298 } 1299 /** 1300 * Returns true if there was update 1301 */ 1302 public boolean checkForUpdates() { 1303 InterviewPropagator prop = new InterviewPropagator(this, 1304 ignorableProps, ignorablePrefs); 1305 return prop.checkForUpdate(); 1306 } 1307 1308 public void load(Map<String, String> data, boolean checkChecksum) throws Fault { 1309 super.load(data, checkChecksum); 1310 1311 String me = data.get(MARKERS_ENABLED); 1312 setMarkersEnabled(me != null && me.equalsIgnoreCase(TRUE)); 1313 1314 String mf = data.get(MARKERS_FILTER); 1315 setMarkersFilterEnabled(mf != null && mf.equalsIgnoreCase(TRUE)); 1316 1317 String tm = data.get(IS_TEMPLATE); 1318 setTemplate(tm != null && tm.equalsIgnoreCase(TRUE)); 1319 1320 String tu = null; 1321 //if (isTemplate()) { 1322 tu = data.get(TEMPLATE_PATH); 1323 //} else { 1324 //tu = (String) data.get(TEMPLATE_PREF + TEMPLATE_PATH); 1325 //} 1326 setTemplatePath(tu); 1327 } 1328 1329 /** 1330 * Load the interview as best as possible with the data in another 1331 * Parameters object. If any of the various sub-objects as returned by 1332 * get<i>XXX</i>Parameters are not recognized, they will be ignored. 1333 * @param other The Parameters object to be copied. 1334 */ 1335 public void load(Parameters other) { 1336 loadTestsParameters(other.getTestsParameters()); 1337 loadExcludeListParameters(other.getExcludeListParameters()); 1338 loadKeywordsParameters(other.getKeywordsParameters()); 1339 loadPriorStatusParameters(other.getPriorStatusParameters()); 1340 loadEnvParameters(other.getEnvParameters()); 1341 loadConcurrencyParameters(other.getConcurrencyParameters()); 1342 loadTimeoutFactorParameters(other.getTimeoutFactorParameters()); 1343 } 1344 1345 private void loadTestsParameters(TestsParameters other) { 1346 TestsParameters tp = getTestsParameters(); 1347 if (!(tp instanceof MutableTestsParameters)) 1348 return; 1349 1350 MutableTestsParameters mtp = (MutableTestsParameters) tp; 1351 1352 if (other instanceof MutableTestsParameters) { 1353 MutableTestsParameters mop = (MutableTestsParameters) other; 1354 mtp.setTestsMode(mop.getTestsMode()); 1355 mtp.setSpecifiedTests(mop.getSpecifiedTests()); 1356 } 1357 else { 1358 String[] tests = other.getTests(); 1359 if (tests == null) { 1360 mtp.setTestsMode(MutableTestsParameters.ALL_TESTS); 1361 mtp.setSpecifiedTests(null); 1362 } 1363 else { 1364 mtp.setTestsMode(MutableTestsParameters.SPECIFIED_TESTS); 1365 mtp.setSpecifiedTests(tests); 1366 } 1367 } 1368 } 1369 1370 private void loadExcludeListParameters(ExcludeListParameters other) { 1371 ExcludeListParameters tp = getExcludeListParameters(); 1372 if (!(tp instanceof MutableExcludeListParameters)) 1373 return; 1374 1375 MutableExcludeListParameters mtp = (MutableExcludeListParameters) tp; 1376 1377 if (other instanceof MutableExcludeListParameters) { 1378 MutableExcludeListParameters mop = (MutableExcludeListParameters) other; 1379 mtp.setExcludeMode(mop.getExcludeMode()); 1380 mtp.setCustomExcludeFiles(mop.getCustomExcludeFiles()); 1381 mtp.setLatestExcludeAutoCheckEnabled(mop.isLatestExcludeAutoCheckEnabled()); 1382 mtp.setLatestExcludeAutoCheckMode(mop.getLatestExcludeAutoCheckMode()); 1383 mtp.setLatestExcludeAutoCheckInterval(mop.getLatestExcludeAutoCheckInterval()); 1384 } 1385 else { 1386 mtp.setExcludeMode(MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST); 1387 mtp.setCustomExcludeFiles(null); 1388 mtp.setLatestExcludeAutoCheckEnabled(false); 1389 mtp.setLatestExcludeAutoCheckMode(MutableExcludeListParameters.CHECK_EVERY_X_DAYS); 1390 mtp.setLatestExcludeAutoCheckInterval(0); 1391 } 1392 } 1393 1394 private void loadKeywordsParameters(KeywordsParameters other) { 1395 KeywordsParameters tp = getKeywordsParameters(); 1396 if (!(tp instanceof MutableKeywordsParameters)) 1397 return; 1398 1399 MutableKeywordsParameters mtp = (MutableKeywordsParameters) tp; 1400 1401 if (other instanceof MutableKeywordsParameters) { 1402 MutableKeywordsParameters mop = (MutableKeywordsParameters) other; 1403 mtp.setKeywordsMode(mop.getKeywordsMode()); 1404 mtp.setMatchKeywords(mop.getMatchKeywordsMode(), mop.getMatchKeywordsValue()); 1405 } 1406 else { 1407 Keywords k = other.getKeywords(); 1408 if (k == null) { 1409 mtp.setKeywordsMode(MutableKeywordsParameters.NO_KEYWORDS); 1410 mtp.setMatchKeywords(MutableKeywordsParameters.EXPR, ""); 1411 } 1412 else { 1413 mtp.setKeywordsMode(MutableKeywordsParameters.MATCH_KEYWORDS); 1414 mtp.setMatchKeywords(MutableKeywordsParameters.EXPR, k.toString()); 1415 } 1416 1417 } 1418 } 1419 1420 private void loadPriorStatusParameters(PriorStatusParameters other) { 1421 PriorStatusParameters tp = getPriorStatusParameters(); 1422 if (!(tp instanceof MutablePriorStatusParameters)) 1423 return; 1424 1425 MutablePriorStatusParameters mtp = (MutablePriorStatusParameters) tp; 1426 1427 if (other instanceof MutablePriorStatusParameters) { 1428 MutablePriorStatusParameters mop = (MutablePriorStatusParameters) other; 1429 mtp.setPriorStatusMode(mop.getPriorStatusMode()); 1430 mtp.setMatchPriorStatusValues(mop.getMatchPriorStatusValues()); 1431 } 1432 else { 1433 boolean[] b = other.getPriorStatusValues(); 1434 if (b == null) { 1435 mtp.setPriorStatusMode(MutablePriorStatusParameters.NO_PRIOR_STATUS); 1436 mtp.setMatchPriorStatusValues(new boolean[Status.NUM_STATES]); 1437 } 1438 else { 1439 mtp.setPriorStatusMode(MutablePriorStatusParameters.MATCH_PRIOR_STATUS); 1440 mtp.setMatchPriorStatusValues(b); 1441 } 1442 } 1443 } 1444 1445 private void loadEnvParameters(EnvParameters other) { 1446 EnvParameters tp = getEnvParameters(); 1447 if (!(tp instanceof LegacyEnvParameters)) 1448 return; 1449 1450 LegacyEnvParameters ltp = (LegacyEnvParameters) tp; 1451 1452 if (other instanceof LegacyEnvParameters) { 1453 LegacyEnvParameters lop = (LegacyEnvParameters) other; 1454 ltp.setEnvFiles(lop.getEnvFiles()); 1455 ltp.setEnvName(lop.getEnvName()); 1456 } 1457 } 1458 1459 private void loadConcurrencyParameters(ConcurrencyParameters other) { 1460 ConcurrencyParameters tp = getConcurrencyParameters(); 1461 if (!(tp instanceof MutableConcurrencyParameters)) 1462 return; 1463 1464 MutableConcurrencyParameters mtp = (MutableConcurrencyParameters) tp; 1465 mtp.setConcurrency(other.getConcurrency()); 1466 } 1467 1468 private void loadTimeoutFactorParameters(TimeoutFactorParameters other) { 1469 TimeoutFactorParameters tp = getTimeoutFactorParameters(); 1470 if (!(tp instanceof MutableTimeoutFactorParameters)) 1471 return; 1472 1473 MutableTimeoutFactorParameters mtp = (MutableTimeoutFactorParameters) tp; 1474 mtp.setTimeoutFactor(other.getTimeoutFactor()); 1475 } 1476 1477 /** 1478 * Save the current set of answers for the interview in the standard 1479 * file associated with the interview. 1480 * @throws IOException is there is a problem writing the file 1481 * @throws Interview.Fault if there is a problem preparing the 1482 * interview to be written 1483 * @see #getFile 1484 */ 1485 public void save() throws IOException, Fault { 1486 File f = getFile(); 1487 if (f == null) 1488 throw new IllegalStateException(); 1489 save(f); 1490 } 1491 1492 1493 /** 1494 * Save the current state of the interview in a specified file, 1495 * and make that file the new file associated with the interview. 1496 * @param file the file in which to save the state of the interview 1497 * @throws IOException is there is a problem writing the file 1498 * @throws Interview.Fault if there is a problem preparing the 1499 * interview to be written 1500 * @see #getFile 1501 */ 1502 public void save(File file) throws IOException, Fault { 1503 save(file, false); 1504 } 1505 1506 1507 1508 /** 1509 * Save the current state of the interview in a specified file, 1510 * and make that file the new file associated with the interview. 1511 * @param file the file in which to save the state of the interview 1512 * @param isTemplate 1513 * @throws IOException is there is a problem writing the file 1514 * @throws Interview.Fault if there is a problem preparing the 1515 * interview to be written 1516 * @see #getFile 1517 */ 1518 public void save(File file, boolean isTemplate) throws IOException, Fault { 1519 saveAs(file, true, true, isTemplate); 1520 1521 setEdited(false); 1522 currFile = file; 1523 currFileLastModified = file.lastModified(); 1524 currFileLoaded = true; 1525 } 1526 1527 1528 /** 1529 * Save the current state of the interview in a specified file, 1530 * including the paths for the test suite and work directory. 1531 * @param file the file in which to save the state of the interview 1532 * @throws IOException is there is a problem writing the file 1533 * @throws Interview.Fault if there is a problem preparing the 1534 * interview to be written 1535 */ 1536 public void saveAs(File file) 1537 throws IOException, Fault 1538 { 1539 saveAs(file, true, true); 1540 } 1541 1542 1543 /** 1544 * Save the current state of the interview in a specified file. 1545 * If the test suite path is not saved, the file can only be used 1546 * as a configuration template. 1547 * @param file the file in which to save the state of the interview 1548 * @param saveTestSuite if true, the test suite path will be saved 1549 * in the file. 1550 * @param saveWorkDir if true, the work directory path will be saved 1551 * in the file. 1552 * @param isTemplate True, the interview will be saved as template. 1553 * @throws IOException is there is a problem writing the file 1554 * @throws Interview.Fault if there is a problem preparing the 1555 * interview to be written 1556 */ 1557 public void saveAs(File file, boolean saveTestSuite, boolean saveWorkDir, boolean isTemplate) 1558 throws IOException, Fault 1559 { 1560 SortedMap<String, String> data = new TreeMap<>(); 1561 setTemplate(isTemplate); // dubious, why do we need to do this? 1562 1563 if (saveTestSuite) { 1564 TestSuite ts = getTestSuite(); 1565 if (ts != null) 1566 data.put(TESTSUITE, ts.getPath()); 1567 } 1568 1569 if (saveWorkDir) { 1570 WorkDirectory wd = getWorkDirectory(); 1571 if (wd != null) 1572 data.put(WORKDIR, wd.getPath()); 1573 } 1574 1575 save(data); 1576 1577 if (this.isTemplate == true ) { 1578 TemplateManager tm = this.templateManager; 1579 if (tm != null && !tm.canSaveTemplate(file)) { 1580 throw new Interview.Fault(i18n, "ip.badTmplPath"); 1581 } 1582 } 1583 1584 OutputStream out; 1585 if (backupPolicy == null) 1586 out = new BufferedOutputStream(new FileOutputStream(file)); 1587 else 1588 out = backupPolicy.backupAndOpenStream(file); 1589 1590 try { 1591 Properties.store(data, out, "JT Harness Configuration Interview"); 1592 } 1593 finally { 1594 out.close(); 1595 } 1596 } 1597 1598 1599 1600 /** 1601 * Save the current state of the interview in a specified file. 1602 * If the test suite path is not saved, the file can only be used 1603 * as a configuration template. 1604 * @param file the file in which to save the state of the interview 1605 * @param saveTestSuite if true, the test suite path will be saved 1606 * in the file. 1607 * @param saveWorkDir if true, the work directory path will be saved 1608 * in the file. 1609 * @throws IOException is there is a problem writing the file 1610 * @throws Interview.Fault if there is a problem preparing the 1611 * interview to be written 1612 */ 1613 public void saveAs(File file, boolean saveTestSuite, boolean saveWorkDir) 1614 throws IOException, Fault 1615 { 1616 saveAs(file, saveTestSuite, saveWorkDir, false); 1617 } 1618 1619 public void save(Map<String, String> data) { 1620 if (markersEnabled) 1621 data.put(MARKERS_ENABLED, TRUE); 1622 1623 if (markersFilterEnabled) 1624 data.put(MARKERS_FILTER, TRUE); 1625 1626 if (isTemplate()) { 1627 data.put(IS_TEMPLATE, TRUE); 1628 1629 storeTemplateProperties(new HashMap<String, String>()); 1630 } 1631 else { 1632 WorkDirectory wd = getWorkDirectory(); 1633 if (wd != null && TemplateUtilities.getTemplatePath(wd) != null) 1634 data.put(TEMPLATE_PATH, TemplateUtilities.getTemplatePath(wd)); 1635 } 1636 1637 String name = getName(); 1638 if (name != null) 1639 data.put(NAME, name); 1640 1641 String desc = getDescription(); 1642 if (desc != null) 1643 data.put(DESC, desc); 1644 1645 1646 super.save(data); 1647 } 1648 1649 /** 1650 * Get the backup policy to be used when saving configuration files. 1651 * @return the backup policy object to be used when saving configuration files 1652 * @see #setBackupPolicy 1653 */ 1654 public BackupPolicy getBackupPolicy() { 1655 return backupPolicy; 1656 } 1657 1658 /** 1659 * Set the backup policy to be used when saving configuration files. 1660 * @param backupPolicy the backup policy object to be used when saving configuration files 1661 * @see #getBackupPolicy 1662 */ 1663 public void setBackupPolicy(BackupPolicy backupPolicy) { 1664 this.backupPolicy = backupPolicy; 1665 } 1666 1667 /** 1668 * Check if the current file has been loaded into this interview, 1669 * or if the interview has been saved in it. 1670 * @return true if the file associated with the interview was set as a 1671 * side effect of load or save, or false if the file was just set by 1672 * setFile. 1673 */ 1674 public boolean isFileLoaded() { 1675 return currFileLoaded; 1676 } 1677 1678 /** 1679 * Determine if the file associated with this interview has been modified 1680 * on disk after the last call of load or save. 1681 * @return true if the file on disk has been modified after it was last 1682 * used by load or save. 1683 * @see #load() 1684 * @see #save() 1685 */ 1686 public boolean isFileNewer() { 1687 File f = getFile(); 1688 return (f != null && f.exists() && ((currFileLastModified == 0) 1689 || (f.lastModified() > currFileLastModified))); 1690 } 1691 1692 //---------------------------------------------------------------------------- 1693 1694 /** 1695 * Check whether or not markers should be enabled. 1696 * @return whether or not markers should be enabled 1697 * @see #setMarkersEnabled 1698 */ 1699 public boolean getMarkersEnabled() { 1700 return markersEnabled; 1701 } 1702 1703 /** 1704 * Specify whether or not markers should be enabled. 1705 * @param on whether or not markers should be enabled 1706 * @see #getMarkersEnabled 1707 */ 1708 public void setMarkersEnabled(boolean on) { 1709 if (on != markersEnabled) { 1710 markersEnabled = on; 1711 setEdited(true); 1712 } 1713 } 1714 1715 /** 1716 * Check whether or not the history list should be filtered to 1717 * just show questions which have been marked. 1718 * @return whether or not the history list should be filtered to 1719 * just show questions which have been marked 1720 * @see #setMarkersFilterEnabled 1721 */ 1722 public boolean getMarkersFilterEnabled() { 1723 return markersFilterEnabled; 1724 } 1725 1726 /** 1727 * Specify whether or not the history list should be filtered to 1728 * just show questions which have been marked. 1729 * @param on whether or not the history list should be filtered to 1730 * just show questions which have been marked 1731 * @see #getMarkersFilterEnabled 1732 */ 1733 public void setMarkersFilterEnabled(boolean on) { 1734 if (on != markersFilterEnabled) { 1735 markersFilterEnabled = on; 1736 setEdited(true); 1737 } 1738 } 1739 1740 //---------------------------------------------------------------------------- 1741 private final String [] ignorableProps = new String [] { 1742 INTERVIEW, 1743 LOCALE, TESTSUITE, WORKDIR, MARKERS, 1744 IS_TEMPLATE, TEMPLATE_PATH, QUESTION}; 1745 private final String [] ignorablePrefs = new String [] { MARKERS_PREF, EXTERNAL_PREF, TEMPLATE_PREF}; 1746 1747 private BackupPolicy backupPolicy; 1748 private boolean markersEnabled; 1749 private boolean markersFilterEnabled; 1750 1751 private File currFile; 1752 private boolean isTemplate; 1753 private String templatePath; 1754 private long currFileLastModified; 1755 private boolean currFileLoaded; 1756 protected File[] kflFiles; 1757 1758 private CustomPropagationController pc = new CustomPropagationController(); 1759 1760 static final String TESTSUITE = "TESTSUITE"; 1761 static final String WORKDIR = "WORKDIR"; 1762 static final String NAME = "NAME"; 1763 static final String DESC = "DESCRIPTION"; 1764 static final String MARKERS_ENABLED = "MARKERS.enabled"; 1765 static final String MARKERS_FILTER = "MARKERS.filter"; 1766 static final String IS_TEMPLATE = "IS_TEMPLATE"; 1767 static final String TEMPLATE_PATH = "TEMPLATE_PATH"; 1768 static final String TRUE = "true"; 1769 1770 private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(InterviewParameters.class); 1771 }