1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2004, 2011, 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.tool; 28 29 import java.io.BufferedInputStream; 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.net.URL; 36 import java.net.URLClassLoader; 37 import java.text.NumberFormat; 38 import java.text.ParsePosition; 39 import java.util.Iterator; 40 import java.util.ListIterator; 41 import java.util.Locale; 42 import java.util.Map; 43 import java.util.MissingResourceException; 44 import java.util.Properties; 45 import java.util.ResourceBundle; 46 import java.util.Set; 47 import java.util.Vector; 48 49 import com.sun.interview.Interview; 50 import com.sun.interview.NullQuestion; 51 import com.sun.interview.CompositeQuestion; 52 import com.sun.interview.Question; 53 import com.sun.javatest.FileParameters; 54 import com.sun.javatest.InterviewParameters; 55 import com.sun.javatest.Parameters; 56 import com.sun.javatest.Status; 57 import com.sun.javatest.TestSuite; 58 import com.sun.javatest.WorkDirectory; 59 import com.sun.javatest.util.DirectoryClassLoader; 60 //import com.sun.javatest.util.PathClassLoader; 61 import com.sun.javatest.util.HelpTree; 62 import com.sun.javatest.util.I18NResourceBundle; 63 import java.util.HashMap; 64 import java.util.Map.Entry; 65 66 /** 67 * A manager for all the various configuration commands. 68 */ 69 public class ConfigManager 70 extends CommandManager 71 { 72 public HelpTree.Node getHelp() { 73 Object[] childData = { 74 ConcurrencyCommand.getName(), 75 ConfigCommand.getName(), 76 EnvCommand.getName(), 77 EnvFilesCommand.getNames(), 78 ExcludeListCommand.getName(), 79 KeywordsCommand.getName(), 80 KflCommand.getName(), 81 OpenCommand.getName(), 82 ParamsCommand.getHelp(), 83 PriorStatusCommand.getName(), 84 SetCommand.getName(), 85 TestsCommand.getName(), 86 TestSuiteCommand.getNames(), 87 TimeoutFactorCommand.getName(), 88 WorkDirectoryCommand.getNames(), 89 WriteConfigCommand.getName() 90 }; 91 92 return getHelp(i18n, "cnfg", childData); 93 } 94 95 HelpTree.Node getHelp(I18NResourceBundle i18n, String prefix, Object[] childData) { 96 Vector<HelpTree.Node> v = new Vector<>(); 97 for (int i = 0; i < childData.length; i++) { 98 Object data = childData[i]; 99 if (data instanceof HelpTree.Node) 100 v.add((HelpTree.Node)data); 101 else if (data instanceof String) 102 v.add(new HelpTree.Node(i18n, prefix + "." + data)); 103 else if (data instanceof String[]) { 104 String[] names = (String[]) data; 105 for (int j = 0; j < names.length; j++) 106 v.add(new HelpTree.Node(i18n, prefix + "." + names[j])); 107 } 108 else 109 throw new IllegalArgumentException(); 110 } 111 HelpTree.Node[] childNodes = new HelpTree.Node[v.size()]; 112 v.copyInto(childNodes); 113 return new HelpTree.Node(i18n, prefix, childNodes); 114 } 115 116 public boolean parseCommand(String cmd, ListIterator<String> argIter, CommandContext ctx) 117 throws Command.Fault 118 { 119 if (isMatch(cmd, ConcurrencyCommand.getName())) { 120 ctx.addCommand(new ConcurrencyCommand(argIter)); 121 return true; 122 } 123 124 if (isMatch(cmd, ConfigCommand.getName())) { 125 ctx.addCommand(new ConfigCommand(argIter)); 126 return true; 127 } 128 129 if (isMatch(cmd, EnvCommand.getName())) { 130 ctx.addCommand(new EnvCommand(argIter)); 131 return true; 132 } 133 134 if (isMatch(cmd, EnvFilesCommand.getNames())) { 135 ctx.addCommand(new EnvFilesCommand(argIter)); 136 return true; 137 } 138 139 if (isMatch(cmd, ExcludeListCommand.getName())) { 140 ctx.addCommand(new ExcludeListCommand(argIter)); 141 return true; 142 } 143 144 if (isMatch(cmd, OpenCommand.getName())) { 145 ctx.addCommand(new OpenCommand(argIter)); 146 return true; 147 } 148 149 if (isMatch(cmd, KeywordsCommand.getName())) { 150 ctx.addCommand(new KeywordsCommand(argIter)); 151 return true; 152 } 153 154 if (isMatch(cmd, KflCommand.getName())) { 155 ctx.addCommand(new KflCommand(argIter)); 156 return true; 157 } 158 159 if (isMatch(cmd, ParamsCommand.getName())) { 160 ctx.addCommand(new ParamsCommand(argIter)); 161 return true; 162 } 163 164 if (isMatch(cmd, PriorStatusCommand.getName())) { 165 ctx.addCommand(new PriorStatusCommand(argIter)); 166 return true; 167 } 168 169 if (isMatch(cmd, SetCommand.getName())) { 170 ctx.addCommand(new SetCommand(argIter)); 171 return true; 172 } 173 174 if (isMatch(cmd, SetXCommand.getName())) { 175 ctx.addCommand(new SetXCommand(argIter)); 176 return true; 177 } 178 179 if (isMatch(cmd, TestsCommand.getName())) { 180 ctx.addCommand(new TestsCommand(argIter)); 181 return true; 182 } 183 184 if (isMatch(cmd, TestSuiteCommand.getNames())) { 185 ctx.addCommand(new TestSuiteCommand(argIter)); 186 return true; 187 } 188 189 if (isMatch(cmd, TimeoutFactorCommand.getName())) { 190 ctx.addCommand(new TimeoutFactorCommand(argIter)); 191 return true; 192 } 193 194 if (isMatch(cmd, WorkDirectoryCommand.getNames())) { 195 ctx.addCommand(new WorkDirectoryCommand(argIter)); 196 return true; 197 } 198 199 if (isMatch(cmd, WriteConfigCommand.getName())) { 200 ctx.addCommand(new WriteConfigCommand(argIter)); 201 return true; 202 } 203 204 205 return false; 206 } 207 208 static Command getOpenCommand(File file) 209 throws Command.Fault 210 { 211 return new OpenCommand(file); 212 } 213 214 private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(ConfigManager.class); 215 216 //-------------------------------------------------------------------------- 217 218 private static class ConcurrencyCommand extends Command 219 { 220 static String getName() { 221 return "concurrency"; 222 } 223 224 ConcurrencyCommand(ListIterator<String> argIter) throws Fault { 225 super(getName()); 226 227 if (!argIter.hasNext()) 228 throw new Fault(i18n, "cnfg.conc.missingArg"); 229 230 String arg = nextArg(argIter); 231 232 NumberFormat fmt = NumberFormat.getIntegerInstance(); // will be locale-specific 233 ParsePosition pos = new ParsePosition(0); 234 Number num = fmt.parse(arg, pos); 235 if (num != null && (pos.getIndex() == arg.length())) { 236 value = num.intValue(); 237 if (value < Parameters.ConcurrencyParameters.MIN_CONCURRENCY 238 || value > Parameters.ConcurrencyParameters.MAX_CONCURRENCY) { 239 throw new Fault(i18n, "cnfg.conc.badRange", 240 new Object[] { 241 arg, 242 new Integer(Parameters.ConcurrencyParameters.MIN_CONCURRENCY), 243 new Integer(Parameters.ConcurrencyParameters.MAX_CONCURRENCY) }); 244 } 245 } 246 else 247 throw new Fault(i18n, "cnfg.conc.badValue", arg); 248 } 249 250 public void run(CommandContext ctx) throws Fault { 251 InterviewParameters p = getConfig(ctx); 252 if (p.getConcurrencyParameters() instanceof Parameters.MutableConcurrencyParameters) { 253 Parameters.MutableConcurrencyParameters cParams = 254 (Parameters.MutableConcurrencyParameters) (p.getConcurrencyParameters()); 255 cParams.setConcurrency(value); 256 } 257 else 258 throw new Fault(i18n, "cnfg.conc.notEditable"); 259 } 260 261 private int value; 262 } 263 264 265 //-------------------------------------------------------------------------- 266 267 private static class ConfigCommand extends Command 268 { 269 static String getName() { 270 return "config"; 271 } 272 273 ConfigCommand(ListIterator<String> argIter) throws Fault { 274 super(getName()); 275 276 if (!argIter.hasNext()) 277 throw new Fault(i18n, "cnfg.conf.missingArg"); 278 279 path = new File(nextArg(argIter)); 280 } 281 282 ConfigCommand(File path) { 283 super(path.getPath()); 284 285 this.path = path; 286 } 287 288 public void run(CommandContext ctx) throws Fault { 289 /*OLD 290 try { 291 InterviewParameters p = getConfig(ctx); 292 if (p == null) 293 ctx.setInterviewParameters(InterviewParameters.open(path)); 294 else { 295 // should check for compatibility? 296 p.load(path); 297 } 298 299 if (ctx.getWorkDirectory() == null) 300 ctx.setWorkDirectory(p.getWorkDirectory()); 301 302 ctx.setAutoRunReportDir(null); 303 } 304 catch (TestSuite.Fault e) { 305 throw new Fault(i18n, "cnfg.cantSetParameters", e.getMessage()); 306 } 307 catch (FileNotFoundException e) { 308 throw new Fault(i18n, "cnfg.cantFindFile", path); 309 } 310 catch (IOException e) { 311 throw new Fault(i18n, "cnfg.cantReadFile", new Object[] { path, e} ); 312 } 313 catch (InterviewParameters.Fault e) { 314 throw new Fault(i18n, "cnfg.cantOpenConfig", new Object[] { path, e} ); 315 } 316 */ 317 318 try { 319 ctx.setConfig(path); 320 ctx.setAutoRunReportDir(null); 321 } 322 catch (CommandContext.Fault e) { 323 throw new Fault(e); 324 } 325 } 326 327 private File path; 328 } 329 330 //-------------------------------------------------------------------------- 331 332 private static class WriteConfigCommand extends Command 333 { 334 static String getName() { 335 return "writeConfig"; 336 } 337 338 WriteConfigCommand(ListIterator<String> argIter) throws Fault { 339 super(getName()); 340 341 if (!argIter.hasNext()) 342 throw new Fault(i18n, "cnfg.conf.missingArg"); 343 // XXX could provide a better error message, perhaps including the value of 344 // getName(), because the missingArg error message is general purpose 345 // EX: throw new Fault(i18n, "cnfg.conf.missingArg", getName()); 346 347 path = new File(nextArg(argIter)); 348 } 349 350 WriteConfigCommand(File path) { 351 super(path.getPath()); 352 353 this.path = path; 354 } 355 356 public void run(CommandContext ctx) throws Fault { 357 try { 358 InterviewParameters p = getConfig(ctx); 359 p.saveAs(path, true, true); 360 } 361 catch (IOException e) { 362 if (!path.canWrite()) 363 throw new Fault(i18n, "cnfg.writeConfig.cantWrite", path.getPath()); 364 else 365 throw new Fault(i18n, "cnfg.writeConfig.writeErr", new Object[] { path, e } ); 366 } 367 catch (Interview.Fault e) { 368 throw new Fault(i18n, "cnfg.writeConfig.badConfig", new Object[] { path, e.getMessage() } ); 369 } // catch 370 } 371 372 private File path; 373 } 374 375 //-------------------------------------------------------------------------- 376 377 private static class EnvCommand extends Command 378 { 379 static String getName() { 380 return "env"; 381 } 382 383 EnvCommand(ListIterator<String> argIter) throws Fault { 384 super(getName()); 385 386 if (!argIter.hasNext()) 387 throw new Fault(i18n, "cnfg.env.missingArg"); 388 389 name = nextArg(argIter); 390 } 391 392 public void run(CommandContext ctx) throws Fault { 393 InterviewParameters p = getConfig(ctx); 394 if (p.getEnvParameters() instanceof Parameters.LegacyEnvParameters) { 395 Parameters.LegacyEnvParameters eParams = 396 (Parameters.LegacyEnvParameters) (p.getEnvParameters()); 397 eParams.setEnvName(name); 398 } 399 else 400 throw new Fault(i18n, "cnfg.env.notEditable"); 401 } 402 403 private String name; 404 } 405 406 //-------------------------------------------------------------------------- 407 408 private static class EnvFilesCommand extends Command 409 { 410 static String[] getNames() { 411 return new String[] { "envfile", "envfiles" }; 412 } 413 414 EnvFilesCommand(ListIterator<String> argIter) throws Fault { 415 super(getNames()[0]); 416 417 Vector<File> v = new Vector<>(); 418 419 while (argIter.hasNext()) { 420 String arg = nextArg(argIter); 421 if (arg.startsWith("-")) { 422 putbackArg(argIter); 423 break; 424 } 425 else 426 v.add(new File(arg)); 427 } 428 429 if (v.size() == 0) 430 throw new Fault(i18n, "cnfg.envFiles.noFiles"); 431 432 files = new File[v.size()]; 433 v.toArray(files); 434 } 435 436 public void run(CommandContext ctx) throws Fault { 437 InterviewParameters p = getConfig(ctx); 438 if (p.getEnvParameters() instanceof Parameters.LegacyEnvParameters) { 439 Parameters.LegacyEnvParameters eParams = 440 (Parameters.LegacyEnvParameters) (p.getEnvParameters()); 441 eParams.setEnvFiles(files); 442 } 443 else 444 throw new Fault(i18n, "cnfg.envFiles.notEditable"); 445 } 446 447 private File[] files; 448 } 449 450 //-------------------------------------------------------------------------- 451 452 private static class ExcludeListCommand extends Command 453 { 454 static String getName() { 455 return "excludeList"; 456 } 457 458 ExcludeListCommand(ListIterator<String> argIter) throws Fault { 459 super(getName()); 460 461 // in time, we should support -none, -default, -latest etc 462 Vector<File> v = new Vector<>(); 463 464 while (argIter.hasNext()) { 465 String arg = nextArg(argIter); 466 if (arg.startsWith("-")) { 467 putbackArg(argIter); 468 break; 469 } 470 else 471 v.add(new File(arg)); 472 } 473 474 if (v.size() == 0) 475 throw new Fault(i18n, "cnfg.excl.noFiles"); 476 477 files = new File[v.size()]; 478 v.toArray(files); 479 } 480 481 public void run(CommandContext ctx) throws Fault { 482 InterviewParameters p = getConfig(ctx); 483 if (p.getExcludeListParameters() instanceof Parameters.MutableExcludeListParameters) { 484 Parameters.MutableExcludeListParameters eParams = 485 (Parameters.MutableExcludeListParameters) (p.getExcludeListParameters()); 486 eParams.setExcludeMode(Parameters.MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST); 487 eParams.setCustomExcludeFiles(files); 488 } 489 else 490 throw new Fault(i18n, "cnfg.excl.notEditable"); 491 } 492 493 private File[] files; 494 } 495 //-------------------------------------------------------------------------- 496 497 private static class KflCommand extends Command 498 { 499 static String getName() { 500 return "kfl"; 501 } 502 503 KflCommand(ListIterator<String> argIter) throws Fault { 504 super(getName()); 505 506 // in time, we should support -none, -default, -latest etc 507 Vector<File> v = new Vector<>(); 508 509 while (argIter.hasNext()) { 510 String arg = nextArg(argIter); 511 if (arg.startsWith("-")) { 512 putbackArg(argIter); 513 break; 514 } 515 else 516 v.add(new File(arg)); 517 } 518 519 if (v.size() == 0) 520 throw new Fault(i18n, "cnfg.kfl.noFiles"); 521 522 files = new File[v.size()]; 523 v.toArray(files); 524 } 525 526 public void run(CommandContext ctx) throws Fault { 527 InterviewParameters p = getConfig(ctx); 528 p.setKnownFailureFiles(files); 529 // if (p.getExcludeListParameters() instanceof Parameters.MutableExcludeListParameters) { 530 // Parameters.MutableExcludeListParameters eParams = 531 // (Parameters.MutableExcludeListParameters) (p.getExcludeListParameters()); 532 // eParams.setExcludeMode(Parameters.MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST); 533 // eParams.setCustomExcludeFiles(files); 534 // } 535 // else 536 // throw new Fault(i18n, "cnfg.excl.notEditable"); 537 } 538 539 private File[] files; 540 } 541 //-------------------------------------------------------------------------- 542 543 private static class OpenCommand extends Command 544 { 545 static String getName() { 546 return "open"; 547 } 548 549 OpenCommand(File file) throws Fault { 550 super(file.getPath()); 551 cmdForFile = getCommandForFile(file); 552 } 553 554 OpenCommand(ListIterator<String> argIter) throws Fault { 555 super(getName()); 556 557 if (!argIter.hasNext()) 558 throw new Fault(i18n, "cnfg.open.missingArg"); 559 560 String arg = nextArg(argIter); 561 cmdForFile = getCommandForFile(new File(arg)); 562 } 563 564 public void run(CommandContext ctx) throws Fault { 565 cmdForFile.run(ctx); 566 } 567 568 Command getCommandForFile(File file) 569 throws Fault 570 { 571 if (!file.exists()) 572 throw new Fault(i18n, "cnfg.open.cantFindFile", file); 573 574 if (TestSuite.isTestSuite(file)) 575 return new TestSuiteCommand(file); 576 577 if (WorkDirectory.isWorkDirectory(file)) 578 return new WorkDirectoryCommand(file); 579 580 if (FileParameters.isParameterFile(file)) 581 return new ParamFileCommand(file); 582 583 if (InterviewParameters.isInterviewFile(file)) 584 return new ConfigCommand(file); 585 586 if (file.getPath().endsWith(".jte")) 587 throw new Fault(i18n, "cnfg.open.cantOpenJTE", file); 588 589 if (file.getPath().endsWith(".jtt")) 590 throw new Fault(i18n, "cnfg.open.cantOpenJTT", file); 591 592 if (file.getPath().endsWith(".jtx")) 593 throw new Fault(i18n, "cnfg.open.cantOpenJTX", file); 594 595 throw new Fault(i18n, "cnfg.open.unknownFileType", file); 596 } 597 598 private Command cmdForFile; 599 } 600 601 //-------------------------------------------------------------------------- 602 603 private static class KeywordsCommand extends Command 604 { 605 static String getName() { 606 return "keywords"; 607 } 608 609 KeywordsCommand(ListIterator<String> argIter) throws Fault { 610 super(getName()); 611 612 // could support -all -any 613 if (!argIter.hasNext()) 614 throw new Fault(i18n, "cnfg.keywords.missingArg"); 615 616 expr = nextArg(argIter); 617 } 618 619 public void run(CommandContext ctx) throws Fault { 620 InterviewParameters p = getConfig(ctx); 621 if (p.getKeywordsParameters() instanceof Parameters.MutableKeywordsParameters) { 622 Parameters.MutableKeywordsParameters kParams = 623 (Parameters.MutableKeywordsParameters) (p.getKeywordsParameters()); 624 if (expr == null) 625 kParams.setKeywordsMode(Parameters.MutableKeywordsParameters.NO_KEYWORDS); 626 else { 627 kParams.setKeywordsMode(Parameters.MutableKeywordsParameters.MATCH_KEYWORDS); 628 kParams.setMatchKeywords(Parameters.MutableKeywordsParameters.EXPR, expr); 629 } 630 } 631 else 632 throw new Fault(i18n, "cnfg.keywords.notEditable"); 633 } 634 635 private String expr; 636 } 637 638 //-------------------------------------------------------------------------- 639 // Legacy CLI support (-params, jte and jtp files) 640 // Very deprecated. 641 642 private static abstract class ParamsBaseCommand extends Command 643 { 644 ParamsBaseCommand(String name) { 645 super(name); 646 } 647 648 protected void setParameters(CommandContext ctx, FileParameters fp) 649 throws Fault 650 { 651 /*OLD 652 if (ctx.getTestSuite() != null) 653 throw new Command.Fault(i18n, "cnfg.testSuiteAlreadySet"); 654 655 if (ctx.getWorkDirectory() != null) 656 throw new Command.Fault(i18n, "cnfg.workDirAlreadySet"); 657 */ 658 659 try { 660 ctx.setTestSuite(fp.getTestSuite()); 661 662 if (fp.getWorkDirectory() != null) 663 ctx.setWorkDirectory(fp.getWorkDirectory()); 664 665 getConfig(ctx).load(fp); 666 667 // support for old feature 668 File autoRunReportDir = fp.getReportDir(); 669 if (autoRunReportDir == null) { 670 File rd = new File("reports", "report"); 671 autoRunReportDir = ctx.getWorkDirectory().getFile(rd.getPath()); 672 } 673 ctx.setAutoRunReportDir(autoRunReportDir); 674 } 675 catch (TestSuite.Fault e) { 676 throw new Fault(i18n, "cnfg.cantSetParameters", e.getMessage()); 677 } 678 catch (CommandContext.Fault e) { 679 throw new Fault(e); 680 } 681 } 682 } 683 684 //-------------------------------------------------------------------------- 685 686 private static class ParamFileCommand extends ParamsBaseCommand 687 { 688 ParamFileCommand(File path) { 689 super(path.getPath()); 690 this.path = path; 691 } 692 693 public void run(CommandContext ctx) throws Fault { 694 try { 695 FileParameters params = new FileParameters(path); 696 if (!params.isValid()) { 697 throw new Fault(i18n, "cnfg.params.badParameterFile", 698 new Object[] { path, params.getErrorMessage() } ); 699 } 700 setParameters(ctx, params); 701 } 702 catch (FileNotFoundException e) { 703 throw new Fault(i18n, "cnfg.params.cantFindFile", path); 704 } 705 catch (IOException e) { 706 throw new Fault(i18n, "cnfg.params.cantReadFile", 707 new Object[] { path, e } ); 708 } 709 } 710 711 private File path; 712 } 713 714 //-------------------------------------------------------------------------- 715 716 private static class ParamsCommand extends ParamsBaseCommand 717 { 718 static String getName() { 719 return "params"; 720 } 721 722 static HelpTree.Node getHelp() { 723 String[] opts = { 724 "testSuite", "t", 725 "keywords", 726 "status", 727 "exclude", 728 "envfile", 729 "env", 730 "conc", 731 "timeout", 732 "report", "r", 733 "workdir", "w" 734 }; 735 return new HelpTree.Node(i18n, "cnfg.params", opts); 736 } 737 738 ParamsCommand(ListIterator<String> argIter) throws Fault { 739 super(getName()); 740 741 Vector<String> v = new Vector<>(); 742 while (argIter.hasNext()) 743 v.add(nextArg(argIter)); 744 String[] args = new String[v.size()]; 745 v.copyInto(args); 746 747 try { 748 params = new FileParameters(args); 749 } catch (IllegalArgumentException e) { 750 throw new Fault(i18n, "cnfg.params.badValue", e.getMessage()); 751 } 752 753 if (!params.isValid()) 754 throw new Fault(i18n, "cnfg.params.badValue", params.getErrorMessage()); 755 } 756 757 public void run(CommandContext ctx) throws Fault { 758 setParameters(ctx, params); 759 } 760 761 private FileParameters params; 762 } 763 764 //-------------------------------------------------------------------------- 765 766 private static class PriorStatusCommand extends Command 767 { 768 static String getName() { 769 return "priorStatus"; 770 } 771 772 PriorStatusCommand(ListIterator<String> argIter) throws Fault { 773 super(getName()); 774 775 if (!argIter.hasNext()) 776 throw new Fault(i18n, "cnfg.status.missingArg"); 777 778 String arg = nextArg(argIter); 779 String[] words = split(arg.toLowerCase()); 780 boolean any = false; 781 values = new boolean[Status.NUM_STATES]; 782 if (words != null) { 783 for (int i = 0; i < words.length; i++) { 784 String w = words[i]; 785 if (w.startsWith("pass")) { 786 values[Status.PASSED] = any = true; 787 } 788 else if (w.startsWith("fail")) { 789 values[Status.FAILED] = any = true; 790 } 791 else if (w.startsWith("error")) { 792 values[Status.ERROR] = any = true; 793 } 794 else if (w.startsWith("notrun")) { 795 values[Status.NOT_RUN] = any = true; 796 } 797 else 798 throw new Fault(i18n, "cnfg.status.badArg", w); 799 } 800 } 801 802 803 if (!any) 804 throw new Fault(i18n, "cnfg.status.noValues"); 805 } 806 807 public void run(CommandContext ctx) throws Fault { 808 InterviewParameters p = getConfig(ctx); 809 if (p.getPriorStatusParameters() instanceof Parameters.MutablePriorStatusParameters) { 810 Parameters.MutablePriorStatusParameters sParams = 811 (Parameters.MutablePriorStatusParameters) (p.getPriorStatusParameters()); 812 sParams.setPriorStatusMode(Parameters.MutablePriorStatusParameters.MATCH_PRIOR_STATUS); 813 sParams.setMatchPriorStatusValues(values); 814 } 815 else 816 throw new Fault(i18n, "cnfg.status.notEditable"); 817 } 818 819 private static String[] split(String s) { 820 if (s == null) 821 return null; 822 823 Vector<String> v = new Vector<>(); 824 int start = -1; 825 for (int i = 0; i < s.length(); i++) { 826 if (Character.isLetterOrDigit(s.charAt(i))) { 827 if (start == -1) 828 start = i; 829 } 830 else { 831 if (start != -1) 832 v.addElement(s.substring(start, i)); 833 start = -1; 834 } 835 } 836 if (start != -1) 837 v.addElement(s.substring(start)); 838 if (v.size() == 0) 839 return null; 840 String[] a = new String[v.size()]; 841 v.copyInto(a); 842 return a; 843 } 844 845 private boolean[] values; 846 } 847 848 849 //-------------------------------------------------------------------------- 850 851 private static class SetCommand extends Command 852 { 853 static String getName() { 854 return "set"; 855 } 856 857 SetCommand(ListIterator<String> argIter) throws Fault { 858 super(getName()); 859 860 if (!argIter.hasNext()) 861 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 862 863 String arg = nextArg(argIter); 864 if (arg.equals("-f") || arg.equals("-file")) { 865 if (!argIter.hasNext()) 866 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 867 file = new File(nextArg(argIter)); 868 } 869 else { 870 tag = arg; 871 if (!argIter.hasNext()) 872 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 873 value = nextArg(argIter); 874 } 875 } 876 877 public void run(CommandContext ctx) throws Fault { 878 InterviewParameters p = getConfig(ctx); 879 Question[] path = p.getPath(); 880 if (file != null) { 881 Map<String, String> values = loadFile(file); 882 for (int i = 0; i < path.length; i++) { 883 Question q = path[i]; 884 String v = (values.get(q.getTag())); 885 if (v != null) { 886 setValue(q, v); 887 path = p.getPath(); 888 } 889 } 890 } 891 else { 892 for (int i = 0; i < path.length; i++) { 893 Question q = path[i]; 894 if (q.getTag().equals(tag)) { 895 setValue(q, value); 896 return; 897 } 898 } 899 900 // The following is not ideal but works for now. 901 // It is arguably bad form to return such a long detail 902 // string, rather than providing an extra method 903 // to generate the trace if required -- i.e. the Fault 904 // equivalent of e.printStackTrace() 905 throw new Fault(i18n, "cnfg.set.tagNotFound", 906 new Object[] { tag, getPathTrace(path) }); 907 } 908 } 909 910 private void setValue(Question q, String value) throws Fault { 911 try { 912 if (q instanceof CompositeQuestion) { 913 CompositeQuestion cq = (CompositeQuestion)q; 914 int sepIndex = value.indexOf(":"); 915 if (sepIndex > 0) { 916 // decode value and send to question 917 // could be handled differently in the future 918 // text to the left of the colon in the values is the key 919 // all text to the right is the value 920 String key = value.substring(0, sepIndex); 921 String val; 922 if (sepIndex == value.length() + 1) 923 // handles key: 924 val = ""; 925 else 926 // handles key:value 927 val = value.substring(sepIndex + 1); 928 929 cq.setValue(key, val); 930 } 931 else { 932 q.setValue(value); 933 } 934 } 935 else { 936 q.setValue(value); 937 } 938 } 939 catch (InterviewParameters.Fault e) { 940 throw new Fault(i18n, "cnfg.set.cantSetValue", 941 new Object[] { q.getTag(), value, e.getMessage() }); 942 } 943 } 944 945 private static String getPathTrace(Question[] path) { 946 String lineSep = System.getProperty("line.separator"); 947 StringBuffer sb = new StringBuffer(); 948 for (int i = 0; i < path.length; i++) { 949 Question q = path[i]; 950 sb.append(q.getTag()); 951 if (!(q instanceof NullQuestion)) { 952 String s = q.getStringValue(); 953 sb.append(" ("); 954 if (s == null) 955 sb.append("null"); 956 else if (s.length() < 32) 957 sb.append(s); 958 else { 959 sb.append(s.substring(0, 32)); 960 sb.append("..."); 961 } 962 sb.append(")"); 963 } 964 sb.append(lineSep); // arguably better to do it later when printing to terminal 965 } 966 return (sb.toString()); 967 } 968 969 private Map<String, String> loadFile(File file) throws Fault { 970 try (FileInputStream fis = new FileInputStream(file); 971 InputStream in = new BufferedInputStream(fis)) { 972 return com.sun.javatest.util.Properties.load(in); 973 } 974 catch (FileNotFoundException e) { 975 throw new Fault(i18n, "cnfg.set.cantFindFile", file); 976 } 977 catch (IOException e) { 978 throw new Fault(i18n, "cnfg.set.cantReadFile", 979 new Object[] { file, e.getMessage() }); 980 } 981 } 982 983 private File file; 984 private String tag; 985 private String value; 986 } 987 988 //-------------------------------------------------------------------------- 989 990 /** 991 * Sets "external" interview values from the command line. 992 */ 993 private static class SetXCommand extends Command 994 { 995 static String getName() { 996 return "setX"; 997 } 998 999 SetXCommand(ListIterator<String> argIter) throws Fault { 1000 super(getName()); 1001 1002 if (!argIter.hasNext()) 1003 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 1004 1005 String arg = nextArg(argIter); 1006 if (arg.equals("-f") || arg.equals("-file")) { 1007 if (!argIter.hasNext()) 1008 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 1009 file = new File(nextArg(argIter)); 1010 } 1011 else { 1012 name = arg; 1013 if (!argIter.hasNext()) 1014 throw new Fault(i18n, "cnfg.set.insufficientArgs"); 1015 value = nextArg(argIter); 1016 } 1017 } 1018 1019 public void run(CommandContext ctx) throws Fault { 1020 InterviewParameters p = getConfig(ctx); 1021 if (file != null) { 1022 Map<String, String> values = loadFile(file); 1023 Set<String> keys = values.keySet(); 1024 Iterator<String> it = keys.iterator(); 1025 String name = null; 1026 for (int i = 0; it.hasNext(); i++) { 1027 name = it.next(); 1028 /* could do it this way to reject unknown props 1029 String v = p.retrieveProperty(name); 1030 if (v != null) { 1031 p.storeProperty(name, (String)(values.get(name))); 1032 } 1033 */ 1034 p.storeProperty(name, (values.get(name))); 1035 } 1036 } 1037 else { 1038 p.storeProperty(name, value); 1039 } 1040 } 1041 1042 private Map<String, String> loadFile(File file) throws Fault { 1043 try (FileInputStream fis = new FileInputStream(file); 1044 InputStream in = new BufferedInputStream(fis)) { 1045 return com.sun.javatest.util.Properties.load(in); 1046 } 1047 catch (FileNotFoundException e) { 1048 throw new Fault(i18n, "cnfg.set.cantFindFile", file); 1049 } 1050 catch (IOException e) { 1051 throw new Fault(i18n, "cnfg.set.cantReadFile", 1052 new Object[] { file, e.getMessage() }); 1053 } 1054 } 1055 1056 private File file; 1057 private String name; 1058 private String value; 1059 } 1060 1061 //-------------------------------------------------------------------------- 1062 1063 private static class TestsCommand extends Command 1064 { 1065 static String getName() { 1066 return "tests"; 1067 } 1068 1069 TestsCommand(ListIterator<String> argIter) throws Fault { 1070 super(getName()); 1071 1072 Vector<String> v = new Vector<>(); 1073 1074 while (argIter.hasNext()) { 1075 // could possibly support @file or similar syntax here for a list of tests 1076 String arg = nextArg(argIter); 1077 if (arg.startsWith("-")) { 1078 putbackArg(argIter); 1079 break; 1080 } 1081 else 1082 v.add(arg); 1083 } 1084 1085 if (v.size() == 0) 1086 throw new Fault(i18n, "cnfg.tests.noTests"); 1087 1088 tests = new String[v.size()]; 1089 v.toArray(tests); 1090 } 1091 1092 public void run(CommandContext ctx) throws Fault { 1093 InterviewParameters p = getConfig(ctx); 1094 if (p.getTestsParameters() instanceof Parameters.MutableTestsParameters) { 1095 Parameters.MutableTestsParameters iParams = 1096 (Parameters.MutableTestsParameters) (p.getTestsParameters()); 1097 iParams.setTestsMode(Parameters.MutableTestsParameters.SPECIFIED_TESTS); 1098 iParams.setSpecifiedTests(tests); 1099 } 1100 else 1101 throw new Fault(i18n, "cnfg.tests.notEditable"); 1102 } 1103 1104 private String[] tests; 1105 } 1106 1107 //-------------------------------------------------------------------------- 1108 1109 private static class TestSuiteCommand extends Command 1110 { 1111 static String[] getNames() { 1112 return new String[] { "testsuite", "ts" }; 1113 } 1114 1115 TestSuiteCommand(ListIterator<String> argIter) throws Fault { 1116 super(getNames()[0]); 1117 1118 while (argIter.hasNext()) { 1119 String arg = nextArg(argIter); 1120 if (arg.equalsIgnoreCase("-preferred")) 1121 preferFlag = true; 1122 else if (arg.startsWith("-")) 1123 throw new Fault(i18n, "cnfg.ts.badArg", arg); 1124 else { 1125 path = new File(arg); 1126 return; 1127 } 1128 } // while 1129 1130 // if we are here, args are exhausted or invalid 1131 throw new Fault(i18n, "cnfg.ts.missingArg"); 1132 } 1133 1134 TestSuiteCommand(File path) { 1135 super(path.getPath()); 1136 this.path = path; 1137 } 1138 1139 public URL getCustomSplash() { 1140 String basePath = path.getAbsolutePath() + 1141 File.separator + "lib"; 1142 DirectoryClassLoader loader = 1143 new DirectoryClassLoader(basePath); 1144 try { 1145 ResourceBundle b = ResourceBundle.getBundle("splash", 1146 Locale.getDefault(), loader); 1147 String icon = b.getString("splash.icon"); 1148 // could support a classpath value in the bundle 1149 // and use PathClassLoader to generate the icon 1150 File f = new File(icon); 1151 if (!f.isAbsolute()) { 1152 f = new File(basePath, icon); 1153 } 1154 if (f.canRead()) 1155 try { 1156 return f.toURL(); 1157 } 1158 catch (java.net.MalformedURLException e) { 1159 return null; 1160 } 1161 else 1162 return null; 1163 } 1164 // catch all possible exceptions from ResourceBundle 1165 catch (MissingResourceException m) { 1166 return null; 1167 } 1168 catch (NullPointerException e) { 1169 return null; 1170 } 1171 catch (ClassCastException e) { 1172 return null; 1173 } 1174 } 1175 1176 /** 1177 * Get custom help set for harness help. 1178 * A file help.properties must be in the <code>lib</code> directory of 1179 * the test suite. An internationalization-aware search is then done 1180 * to find a properties bundle named "help". That bundle must contain 1181 * a classpath entry, which is then used to generate the return value. 1182 * The classpath value is relative to the root of the test suite, not 1183 * the <code>lib</code> directory. 1184 */ 1185 ClassLoader getCustomHelpLoader() { 1186 try { 1187 String basePath = path.getCanonicalPath() + 1188 File.separator + "lib"; 1189 DirectoryClassLoader loader = 1190 new DirectoryClassLoader(basePath); 1191 1192 ResourceBundle b = ResourceBundle.getBundle("help", 1193 Locale.getDefault(), loader); 1194 String cp = b.getString("classpath"); 1195 1196 // NOTES: PathClassLoader does not currently support resources 1197 // DirectionClassLoader cannot load from jar files 1198 //PathClassLoader cl = new PathClassLoader(path, cp); 1199 //DirectoryClassLoader cl = new DirectoryClassLoader( 1200 // path.getPath() + File.separator + cp); 1201 File f = new File(cp); 1202 if (!f.isAbsolute()) { 1203 f = new File(path.getPath(), cp); 1204 } 1205 URLClassLoader cl = new URLClassLoader(new URL[] {f.toURL()}, 1206 this.getClass().getClassLoader()); 1207 1208 return cl; 1209 } 1210 // catch all possible exceptions from ResourceBundle 1211 catch (MissingResourceException m) { 1212 return null; 1213 } 1214 catch (NullPointerException e) { 1215 return null; 1216 } 1217 catch (ClassCastException e) { 1218 return null; 1219 } 1220 catch (IOException e) { 1221 return null; 1222 } 1223 } 1224 1225 public void run(CommandContext ctx) throws Fault { 1226 /*OLD 1227 if (ctx.getTestSuite() != null) 1228 throw new Fault(i18n, "cnfg.testSuiteAlreadySet"); 1229 1230 try { 1231 ctx.setTestSuite(TestSuite.open(path)); 1232 } 1233 catch (FileNotFoundException e) { 1234 throw new Fault(i18n, "cnfg.ts.cantFindTestSuite", path); 1235 } 1236 catch (TestSuite.Fault e) { 1237 throw new Fault(i18n, "cnfg.ts.cantOpenTestSuite", e.getMessage()); 1238 } 1239 */ 1240 if (!path.exists()) 1241 throw new Fault(i18n, "cnfg.ts.cantFindTestSuite", path); 1242 1243 if (!TestSuite.isTestSuite(path)) 1244 throw new Fault(i18n, "cnfg.ts.notATestSuite", path); 1245 1246 try { 1247 ctx.setTestSuite(path); 1248 1249 if (preferFlag) { 1250 // searching desktop history to find previous compatible workdir 1251 // if none, continue as normal 1252 // this is not the best logical place to do this, but there doesn't 1253 // seem to be another good place in the current architecture. 1254 // although perhaps it would be good to defer this processing to a 1255 // little later in the command processing? 1256 Map<String, String> p = Desktop.getPreviousDesktop(null); 1257 String s = p.get("tool.count"); 1258 if (s != null) { 1259 int count = Integer.parseInt(s); 1260 for (int i = 0; i < count; i++) { 1261 s = p.get("tool." + i + ".class"); 1262 if ("com.sun.javatest.exec.ExecTool".equals(s)) { 1263 s = p.get("tool." + i + ".testSuite"); 1264 1265 // this tool instance does not have a test suite 1266 if (s == null) 1267 continue; 1268 1269 String s1 = path.getPath(); 1270 String s2 = s; 1271 try { 1272 s1 = path.getCanonicalPath(); 1273 } 1274 catch (IOException e) { 1275 // ignore accept default value of s1 1276 } 1277 1278 try { 1279 File file = new File(s2); 1280 s2 = file.getCanonicalPath(); 1281 } 1282 catch (IOException e) { 1283 // ignore accept default value of s2 1284 } 1285 1286 if (s1.equals(s2)) { 1287 s = p.get("tool." + i + ".workDir"); 1288 if (s != null && 1289 WorkDirectory.isUsableWorkDirectory( 1290 new File(s))) { 1291 // found workdir to use as preferred workdir 1292 ctx.setDefaultWorkDir(s); 1293 1294 // we found WD, 1295 // try to restore filter now 1296 1297 s = p.get("tool." + i + ".filter"); 1298 Map<String, String> data = collectSpecificData("tool." + i + ".", p); 1299 1300 if (s != null) { 1301 ctx.setDesktopData(data); 1302 } 1303 1304 break; 1305 } 1306 else { 1307 if (s != null) 1308 System.out.println(i18n.getString("cnfg.badWorkdir", s)); 1309 continue; 1310 } 1311 } 1312 } 1313 } // for 1314 } 1315 } 1316 } 1317 catch (CommandContext.Fault e) { 1318 throw new Fault(e); 1319 } 1320 } 1321 1322 private File path; 1323 private boolean preferFlag; 1324 1325 private Map<String, String> collectSpecificData(String prefix, Map<String, String> p) { 1326 Set<Entry<String, String>> s = p.entrySet(); 1327 Iterator<Entry<String, String>> it = s.iterator(); 1328 Map<String, String> res = new HashMap<>(); 1329 while (it.hasNext()) { 1330 Entry<String, String> en = it.next(); 1331 if (en.getKey().toString().startsWith(prefix)) { 1332 String key = en.getKey(); 1333 key = key.substring(prefix.length()); 1334 if ("-workDir-config-class-mgr-".contains(key)) { 1335 //if ("-class-mgr-".contains(key)) { 1336 continue; 1337 } 1338 res.put(key, en.getValue()); 1339 } 1340 } 1341 return res; 1342 } 1343 } 1344 1345 //-------------------------------------------------------------------------- 1346 1347 private static class TimeoutFactorCommand extends Command 1348 { 1349 static String getName() { 1350 return "timeoutfactor"; 1351 } 1352 1353 TimeoutFactorCommand(ListIterator<String> argIter) throws Fault { 1354 super(getName()); 1355 1356 if (!argIter.hasNext()) 1357 throw new Fault(i18n, "cnfg.tf.missingArg"); 1358 1359 String arg = nextArg(argIter); 1360 1361 NumberFormat fmt = NumberFormat.getNumberInstance(); // will be locale-specific 1362 ParsePosition pos = new ParsePosition(0); 1363 Number num = fmt.parse(arg, pos); 1364 if (num != null && (pos.getIndex() == arg.length())) { 1365 value = num.floatValue(); 1366 if (value < Parameters.TimeoutFactorParameters.MIN_TIMEOUT_FACTOR 1367 || value > Parameters.TimeoutFactorParameters.MAX_TIMEOUT_FACTOR) { 1368 throw new Fault(i18n, "cnfg.tf.badRange", 1369 new Object[] { 1370 arg, 1371 new Float(Parameters.TimeoutFactorParameters.MIN_TIMEOUT_FACTOR), 1372 new Float(Parameters.TimeoutFactorParameters.MAX_TIMEOUT_FACTOR) }); 1373 } 1374 } 1375 else 1376 throw new Fault(i18n, "cnfg.tf.badValue", arg); 1377 } 1378 1379 public void run(CommandContext ctx) throws Fault { 1380 InterviewParameters p = getConfig(ctx); 1381 if (p.getTimeoutFactorParameters() instanceof Parameters.MutableTimeoutFactorParameters) { 1382 Parameters.MutableTimeoutFactorParameters cParams = 1383 (Parameters.MutableTimeoutFactorParameters) (p.getTimeoutFactorParameters()); 1384 cParams.setTimeoutFactor(value); 1385 } 1386 else 1387 throw new Fault(i18n, "cnfg.tf.notEditable"); 1388 } 1389 1390 private float value; 1391 } 1392 1393 //-------------------------------------------------------------------------- 1394 1395 private static class WorkDirectoryCommand extends Command 1396 { 1397 static String[] getNames() { 1398 return new String[] { "workdirectory", "workdir", "wd" }; 1399 } 1400 1401 WorkDirectoryCommand(ListIterator<String> argIter) throws Fault { 1402 super(getNames()[0]); 1403 1404 while (argIter.hasNext()) { 1405 String arg = nextArg(argIter); 1406 if (arg.equalsIgnoreCase("-create")) 1407 createFlag = true; 1408 else if (arg.equalsIgnoreCase("-overwrite")) { 1409 createFlag = true; 1410 overwriteFlag = true; 1411 } 1412 else if (arg.startsWith("-")) 1413 throw new Fault(i18n, "cnfg.wd.badArg", arg); 1414 else { 1415 path = new File(arg); 1416 return; 1417 } 1418 } 1419 1420 // drop through if path not given 1421 throw new Fault(i18n, "cnfg.wd.missingArg"); 1422 } 1423 1424 WorkDirectoryCommand(File path) { 1425 super(path.getPath()); 1426 this.path = path; 1427 } 1428 1429 public void run(CommandContext ctx) throws Fault { 1430 /*OLD 1431 TestSuite ts = ctx.getTestSuite(); 1432 WorkDirectory wd = ctx.getWorkDirectory(); 1433 1434 if (wd != null) 1435 throw new Fault(i18n, "cnfg.workDirAlreadySet"); 1436 1437 if (createFlag) 1438 wd = createWorkDirectory(ts); 1439 else 1440 wd = openWorkDirectory(ts); 1441 1442 try { 1443 ctx.setWorkDirectory(wd); 1444 } 1445 catch (TestSuite.Fault e) { 1446 throw new Fault(i18n, "cnfg.wd.cantOpenTestSuiteForWorkDir", e.getMessage()); 1447 } 1448 */ 1449 if (!createFlag) { 1450 if (!path.exists()) 1451 throw new Fault(i18n, "cnfg.wd.cantFindWorkDir", path); 1452 if (!WorkDirectory.isWorkDirectory(path) 1453 && !WorkDirectory.isEmptyDirectory(path)) 1454 throw new Fault(i18n, "cnfg.wd.notAWorkDirectory", path); 1455 } 1456 1457 if (overwriteFlag) { 1458 remove(path); 1459 if (path.exists()) 1460 throw new Fault(i18n, "cnfg.wd.cantRemoveWorkDir", path); 1461 } 1462 1463 try { 1464 ctx.setWorkDirectory(path, createFlag); 1465 } 1466 catch (CommandContext.Fault e) { 1467 throw new Fault(e); 1468 } 1469 1470 } 1471 1472 /*OLD 1473 private WorkDirectory createWorkDirectory(TestSuite ts) throws Fault { 1474 if (ts == null) 1475 throw new Fault(i18n, "cnfg.wd.cantCreateWorkDir_noTestSuite"); 1476 1477 if (overwriteFlag) { 1478 remove(path); 1479 if (path.exists()) 1480 throw new Fault(i18n, "cnfg.wd.cantRemoveWorkDir", path); 1481 } 1482 1483 try { 1484 return WorkDirectory.create(path, ts); 1485 } 1486 catch (WorkDirectory.Fault e) { 1487 throw new Fault(i18n, "cnfg.wd.cantCreateWorkDir", 1488 new Object[] { path, e.getMessage() } ); 1489 } 1490 } 1491 */ 1492 1493 /*OLD 1494 private WorkDirectory openWorkDirectory(TestSuite ts) throws Fault { 1495 try { 1496 WorkDirectory wd; 1497 if (path.exists()) { 1498 if (WorkDirectory.isWorkDirectory(path)) { 1499 if (ts == null) { 1500 wd = WorkDirectory.open(path); 1501 ts = wd.getTestSuite(); 1502 } 1503 else 1504 wd = WorkDirectory.open(path, ts); 1505 } 1506 else if (WorkDirectory.isEmptyDirectory(path)) { 1507 if (ts == null) 1508 throw new Fault(i18n, "cnfg.wd.cantCreateWorkDir_noTestSuite", path); 1509 else 1510 wd = WorkDirectory.create(path, ts); 1511 } 1512 else 1513 throw new Fault(i18n, "cnfg.wd.notWorkDir", path); 1514 } 1515 else 1516 throw new Fault(i18n, "cnfg.wd.cantFindWorkDir", path); 1517 1518 if (wd.getTestSuite().getID() != ts.getID()) 1519 throw new Fault(i18n, "cnfg.wd.incompatibleWorkDir", path); 1520 1521 return wd; 1522 } 1523 catch (FileNotFoundException e) { 1524 throw new Fault(i18n, "cnfg.wd.cantFindWorkDir", path); 1525 } 1526 catch (WorkDirectory.Fault e) { 1527 throw new Fault(i18n, "cnfg.wd.cantOpenWorkDir", e.getMessage()); 1528 } 1529 } 1530 */ 1531 1532 private void remove(File path) { 1533 if (path.exists()) { 1534 if (path.isDirectory()) { 1535 File[] files = path.listFiles(); 1536 for (int i = 0; i < files.length; i++) 1537 remove(files[i]); 1538 // workaround for leftover .nfs* files 1539 String[] undeletables = path.list(); 1540 if (undeletables != null && undeletables.length > 0) { 1541 for (int i = 0; i < undeletables.length; i++) { 1542 String name = undeletables[i]; 1543 if (name.startsWith(".nfs")) { 1544 File fOld = new File(path, name); 1545 File fNew = new File(path.getParentFile(), name); 1546 boolean ok = fOld.renameTo(fNew); 1547 // discard ok result 1548 } 1549 } 1550 } 1551 } 1552 path.delete(); 1553 } 1554 } 1555 1556 private File path; 1557 private boolean createFlag; 1558 private boolean overwriteFlag; 1559 } 1560 }