001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry.junit.mock; 016 017 import ognl.Ognl; 018 import ognl.OgnlException; 019 import ognl.OgnlRuntime; 020 import org.apache.hivemind.ApplicationRuntimeException; 021 import org.apache.hivemind.HiveMind; 022 import org.apache.hivemind.Resource; 023 import org.apache.hivemind.util.PropertyUtils; 024 import org.apache.oro.text.regex.*; 025 import org.apache.tapestry.ApplicationServlet; 026 import org.apache.tapestry.test.mock.*; 027 import org.apache.tapestry.util.xml.DocumentParseException; 028 import org.jdom.Document; 029 import org.jdom.Element; 030 import org.jdom.input.SAXBuilder; 031 import org.testng.annotations.AfterClass; 032 import org.testng.annotations.AfterMethod; 033 import org.testng.annotations.DataProvider; 034 import org.testng.annotations.Test; 035 036 import javax.servlet.ServletException; 037 import javax.servlet.http.Cookie; 038 import java.beans.Introspector; 039 import java.io.*; 040 import java.util.*; 041 042 /** 043 * A complex class that reads an XML description of a test involving the Mock objects and executes 044 * it, pretending to be a running servlet container. 045 * <p> 046 * The XML format is pretty simple, it contains declarations similar to a web.xml deployment 047 * descriptor, a description of the active HttpSession (if any), a description of the HttpRequest, 048 * and then a set of expectations for the output stream from the request. 049 * 050 * @author Howard Lewis Ship 051 * @since 2.2 052 */ 053 054 public class TestMockApplications 055 { 056 public static final String LOGS_DIR = "target/logs"; 057 058 public static final String DEFAULT_BASE_DIR = "./"; 059 060 public static final String SCRIPTS_DIR = "src/scripts"; 061 062 private static String _baseDir; 063 064 private String _testRootDirectory; 065 066 private String _path; 067 068 private String _fileName; 069 070 private Document _document; 071 072 private MockContext _context; 073 074 private String _servletName; 075 076 private ApplicationServlet _servlet; 077 078 private MockRequest _request; 079 080 private MockResponse _response; 081 082 private int _requestNumber = 0; 083 084 private Map _ognlContext = Ognl.createDefaultContext(this); 085 086 private Throwable _exception; 087 088 /** 089 * Shared cache of compiled patterns. 090 */ 091 092 private static Map _patternCache = new HashMap(); 093 094 private PatternMatcher _matcher = new Perl5Matcher(); 095 096 private PatternCompiler _compiler = new Perl5Compiler(); 097 098 private PrintStream _savedOut; 099 100 private PrintStream _savedErr; 101 102 private SAXBuilder _builder = new SAXBuilder(); 103 104 /** 105 * Closes System.out and System.err, then restores them to their original values. 106 */ 107 @AfterMethod 108 public void tearDown() throws Exception 109 { 110 System.err.close(); 111 System.setErr(_savedErr); 112 113 System.out.close(); 114 System.setOut(_savedOut); 115 116 _requestNumber = 0; 117 _request = null; 118 _response = null; 119 } 120 121 @DataProvider(name = "mockTestScripts") 122 public Object[][] createTestParameters() 123 { 124 List data = new ArrayList(); 125 126 File scriptsDir = new File(getBaseDirectory() + SCRIPTS_DIR); 127 128 String[] names = scriptsDir.list(); 129 130 for (int i = 0; i < names.length; i++) 131 { 132 String name = names[i]; 133 134 if (name.endsWith(".xml")) 135 { 136 data.add(new Object[] { 137 getBaseDirectory() + "/src/test-data/", 138 getBaseDirectory() + SCRIPTS_DIR + "/" + name, 139 name 140 }); 141 } 142 } 143 144 return (Object[][])data.toArray(new Object[data.size()][3]); 145 } 146 147 public String toString() 148 { 149 StringBuffer buffer = new StringBuffer("MockTester["); 150 151 if (_document != null) 152 buffer.append(_document); 153 154 buffer.append(']'); 155 156 return buffer.toString(); 157 } 158 159 /** 160 * Invoked to execute the request cycle. 161 */ 162 @Test(dataProvider = "mockTestScripts", enabled = false) 163 public void execute(String testRootDirectory, String path, String fileName) 164 throws Exception 165 { 166 _testRootDirectory = testRootDirectory; 167 _path = path; 168 _fileName = fileName; 169 170 // setup and get environment ready 171 createLogs(); 172 parse(); 173 setup(); 174 175 Element root = _document.getRootElement(); 176 177 List l = root.getChildren("request"); 178 int count = l.size(); 179 180 for (int i = 0; i < count; i++) 181 { 182 Element request = (Element) l.get(i); 183 184 _requestNumber = i + 1; 185 186 executeRequest(request); 187 } 188 189 _servlet.destroy(); 190 191 PropertyUtils.clearCache(); 192 OgnlRuntime.clearCache(); 193 Introspector.flushCaches(); 194 } 195 196 private void executeRequest(Element request) throws IOException, DocumentParseException 197 { 198 Cookie[] oldRequestCookies = (_request == null ? null : _request.getCookies()); 199 200 _request = new MockRequest(_context, "/" + _servlet.getServletName()); 201 202 String contentType = request.getAttributeValue("content-type"); 203 if (contentType != null) 204 _request.setContentType(contentType); 205 206 String contentPath = request.getAttributeValue("content-path"); 207 if (contentPath != null) 208 _request.setContentPath(_testRootDirectory + contentPath); 209 210 _request.addCookies(oldRequestCookies); 211 212 if (_response != null) 213 _request.addCookies(_response.getCookies()); 214 215 setupRequest(request); 216 217 _exception = null; 218 219 _response = new MockResponse(_request); 220 221 try 222 { 223 _servlet.service(_request, _response); 224 } 225 catch (ServletException ex) 226 { 227 _exception = ex; 228 } 229 catch (IOException ex) 230 { 231 _exception = ex; 232 } 233 234 _response.end(); 235 236 System.out.println("=== Response #" + _requestNumber + " ===\n\n"); 237 System.out.println(_response.getOutputString()); 238 System.out.println("\n\n"); 239 240 executeAssertions(request); 241 } 242 243 private void parse() 244 throws Exception 245 { 246 _document = _builder.build(_path); 247 } 248 249 private void setup() throws ServletException 250 { 251 Element root = _document.getRootElement(); 252 253 if (!root.getName().equals("mock-test")) 254 throw new RuntimeException("Root element of " + _path + " must be 'mock-test'."); 255 256 System.setProperty("org.apache.tapestry.disable-caching", "false"); 257 258 setupContext(root); 259 setupServlet(root); 260 } 261 262 private void setupContext(Element parent) 263 { 264 _context = new MockContext(_testRootDirectory); 265 266 Element context = parent.getChild("context"); 267 268 if (context == null) 269 return; 270 271 String name = context.getAttributeValue("name"); 272 273 if (name != null) 274 _context.setServletContextName(name); 275 276 String root = context.getAttributeValue("root"); 277 278 if (root != null) 279 _context.setRootDirectory(_testRootDirectory + root); 280 281 setInitParameters(context, _context); 282 } 283 284 private void setupServlet(Element parent) throws ServletException 285 { 286 Element servlet = parent.getChild("servlet"); 287 288 String className = servlet.getAttributeValue("class"); 289 _servletName = servlet.getAttributeValue("name"); 290 291 _servlet = createServlet(className); 292 293 MockServletConfig config = new MockServletConfig(_servletName, _context); 294 295 setInitParameters(servlet, config); 296 297 _servlet.init(config); 298 } 299 300 private void setupRequest(Element request) 301 { 302 String method = request.getAttributeValue("method"); 303 if (method != null) 304 _request.setMethod(method); 305 306 // It's really just the language from the locale. 307 308 String locale = request.getAttributeValue("locale"); 309 if (locale != null) 310 _request.setLocale(new Locale(locale, "", "")); 311 312 List parameters = request.getChildren("parameter"); 313 int count = parameters.size(); 314 315 for (int i = 0; i < count; i++) 316 { 317 Element parameter = (Element) parameters.get(i); 318 319 setRequestParameter(parameter); 320 } 321 322 String failover = request.getAttributeValue("failover"); 323 324 if (failover != null && failover.equals("true")) 325 _request.simulateFailover(); 326 327 // TBD: Headers, etc., etc. 328 } 329 330 private void setRequestParameter(Element parameter) 331 { 332 List values = new ArrayList(); 333 334 String name = parameter.getAttributeValue("name"); 335 336 String value = parameter.getAttributeValue("value"); 337 if (value != null) 338 values.add(value); 339 340 List children = parameter.getChildren("value"); 341 int count = children.size(); 342 for (int i = 0; i < count; i++) 343 { 344 Element e = (Element) children.get(i); 345 value = e.getTextTrim(); 346 347 values.add(value); 348 } 349 350 String[] array = (String[]) values.toArray(new String[values.size()]); 351 352 _request.setParameter(name, array); 353 } 354 355 private void setInitParameters(Element parent, InitParameterHolder holder) 356 { 357 List children = parent.getChildren("init-parameter"); 358 359 int count = children.size(); 360 for (int i = 0; i < count; i++) 361 { 362 Element e = (Element) children.get(i); 363 364 String name = e.getAttributeValue("name"); 365 String value = e.getAttributeValue("value"); 366 367 holder.setInitParameter(name, value); 368 } 369 } 370 371 private ApplicationServlet createServlet(String className) 372 { 373 Throwable t = null; 374 try 375 { 376 Class servletClass = Class.forName(className); 377 378 return (ApplicationServlet) servletClass.newInstance(); 379 } 380 catch (ClassNotFoundException ex) 381 { 382 t = ex; 383 } 384 catch (InstantiationException ex) 385 { 386 t = ex; 387 } 388 catch (IllegalAccessException ex) 389 { 390 t = ex; 391 } 392 393 // Just a convient wrapper to percolate to the top and 394 // mark this test as an error. 395 396 throw new ApplicationRuntimeException("Unable to instantiate servlet class " + className 397 + ".", t); 398 } 399 400 public MockContext getContext() 401 { 402 return _context; 403 } 404 405 public MockRequest getRequest() 406 { 407 return _request; 408 } 409 410 public MockResponse getResponse() 411 { 412 return _response; 413 } 414 415 public ApplicationServlet getServlet() 416 { 417 return _servlet; 418 } 419 420 private void executeAssertions(Element request) throws DocumentParseException 421 { 422 executeOutputAssertions(request); 423 executeNoOutputAssertions(request); 424 executeRegexpAssertions(request); 425 executeExpressionAssertions(request); 426 executeOutputMatchesAssertions(request); 427 executeCookieAssertions(request); 428 executeOutputStreamAssertions(request); 429 executeExceptionAssertions(request); 430 } 431 432 /** 433 * Handles <assert> elements inside <request>. Each assertion is in the form of a 434 * boolean expression which must be true. 435 */ 436 437 private void executeExpressionAssertions(Element request) throws DocumentParseException 438 { 439 List l = request.getChildren("assert"); 440 int count = l.size(); 441 442 for (int i = 0; i < count; i++) 443 { 444 Element a = (Element) l.get(i); 445 446 String name = a.getAttributeValue("name"); 447 String expression = a.getTextTrim(); 448 449 checkExpression(name, expression); 450 } 451 } 452 453 private void checkExpression(String name, String expression) throws DocumentParseException 454 { 455 456 boolean result = evaluate(expression); 457 458 if (result) 459 return; 460 461 throw new AssertionError(buildTestName(name) + ": Expression '" + expression 462 + "' was not true."); 463 464 } 465 466 private boolean evaluate(String expression) throws DocumentParseException 467 { 468 Object value = null; 469 470 try 471 { 472 value = Ognl.getValue(expression, _ognlContext, this); 473 } 474 catch (OgnlException ex) 475 { 476 throw new DocumentParseException("Expression '" + expression + "' is not valid.", ex); 477 } 478 479 if (value == null) 480 return false; 481 482 if (value instanceof Boolean) 483 return ((Boolean) value).booleanValue(); 484 485 if (value instanceof Number) 486 return ((Number) value).longValue() != 0; 487 488 if (value instanceof String) 489 return ((String) value).length() > 0; 490 491 throw new DocumentParseException("Expression '" + expression + "' evaluates to (" 492 + value.getClass().getName() + ") " + value 493 + ", which cannot be interpreted as a boolean."); 494 } 495 496 /** 497 * Handles <assert-regexp> elements inside <request>. Checks that a regular 498 * expression appears in the output. Content of element is the regular expression. 499 * <p> 500 * Attribute name is used in error messages. 501 */ 502 503 private void executeRegexpAssertions(Element request) 504 throws DocumentParseException 505 { 506 String outputString = null; 507 508 List assertions = request.getChildren("assert-regexp"); 509 int count = assertions.size(); 510 511 for (int i = 0; i < count; i++) 512 { 513 Element a = (Element) assertions.get(i); 514 515 String name = a.getAttributeValue("name"); 516 String pattern = a.getTextTrim(); 517 518 if (HiveMind.isBlank(pattern)) 519 throw new DocumentParseException("Pattern is null in " + a); 520 521 if (outputString == null) 522 outputString = _response.getOutputString(); 523 524 matchRegexp(name, outputString, pattern); 525 } 526 527 } 528 529 /** 530 * Handles <assert-output> elements inside <request>. Checks that a substring 531 * appears in the output. Content of element is the substring to search for. 532 * <p> 533 * Attribute name is used in error messages. 534 */ 535 536 private void executeOutputAssertions(Element request) 537 throws DocumentParseException 538 { 539 String outputString = null; 540 541 List assertions = request.getChildren("assert-output"); 542 int count = assertions.size(); 543 544 for (int i = 0; i < count; i++) 545 { 546 Element a = (Element) assertions.get(i); 547 548 String name = a.getAttributeValue("name"); 549 String substring = a.getTextTrim(); 550 551 if (HiveMind.isBlank(substring)) 552 throw new DocumentParseException("Substring is null in " + a); 553 554 if (outputString == null) 555 outputString = _response.getOutputString(); 556 557 matchSubstring(name, outputString, substring); 558 } 559 560 } 561 562 /** 563 * Handles <assert-no-output> elements inside <request>. Checks that a substring 564 * does not appear in the output. Content of element is the substring to search for. 565 * <p> 566 * Attribute name is used in error messages. 567 */ 568 569 private void executeNoOutputAssertions(Element request) 570 throws DocumentParseException 571 { 572 String outputString = null; 573 574 List assertions = request.getChildren("assert-no-output"); 575 int count = assertions.size(); 576 577 for (int i = 0; i < count; i++) 578 { 579 Element a = (Element) assertions.get(i); 580 581 String name = a.getAttributeValue("name"); 582 String substring = a.getTextTrim(); 583 584 if (HiveMind.isBlank(substring)) 585 throw new DocumentParseException("Substring is null in " + a, (Resource) null); 586 587 if (outputString == null) 588 outputString = _response.getOutputString(); 589 590 matchNoSubstring(name, outputString, substring); 591 } 592 593 } 594 595 private PatternMatcher getMatcher() 596 { 597 return _matcher; 598 } 599 600 private Pattern compile(String pattern) 601 throws DocumentParseException 602 { 603 Pattern result = (Pattern) _patternCache.get(pattern); 604 605 if (result != null) 606 return result; 607 608 try 609 { 610 result = _compiler.compile(pattern, Perl5Compiler.MULTILINE_MASK); 611 612 } 613 catch (MalformedPatternException ex) 614 { 615 throw new ApplicationRuntimeException("Malformed regular expression: " + pattern 616 + " in " + _path + ".", ex); 617 } 618 619 _patternCache.put(pattern, result); 620 621 return result; 622 } 623 624 private void matchRegexp(String name, String text, String pattern) 625 throws DocumentParseException 626 { 627 Pattern compiled = compile(pattern); 628 629 if (getMatcher().contains(text, compiled)) 630 return; 631 632 System.err.println(text); 633 634 throw new AssertionError(buildTestName(name) 635 + ": Response does not contain regular expression '" + pattern + "'."); 636 } 637 638 private void matchSubstring(String name, String text, String substring) 639 { 640 if (text == null) 641 throw new AssertionError(buildTestName(name) + " : Response is null."); 642 643 if (text.indexOf(substring) >= 0) 644 return; 645 646 System.err.println(text); 647 648 throw new AssertionError(buildTestName(name) + ":" + text + "\n Response does not contain string '" 649 + substring + "'."); 650 } 651 652 private void matchNoSubstring(String name, String text, String substring) 653 { 654 if (text == null) 655 throw new AssertionError(buildTestName(name) + " : Response is null."); 656 657 if (text.indexOf(substring) < 0) 658 return; 659 660 System.err.println(text); 661 662 throw new AssertionError(buildTestName(name) + ": Response contains string '" 663 + substring + "'."); 664 } 665 666 private void executeOutputMatchesAssertions(Element request) throws DocumentParseException 667 { 668 List l = request.getChildren("assert-output-matches"); 669 int count = l.size(); 670 String outputString = null; 671 672 for (int i = 0; i < count; i++) 673 { 674 Element e = (Element) l.get(i); 675 676 if (outputString == null) 677 outputString = _response.getOutputString(); 678 679 executeOutputMatchAssertion(e, outputString); 680 } 681 682 } 683 684 private void executeOutputMatchAssertion(Element element, String outputString) 685 throws DocumentParseException 686 { 687 String name = element.getAttributeValue("name"); 688 String value = element.getAttributeValue("subgroup"); 689 int subgroup = (value == null) ? 0 : Integer.parseInt(value); 690 691 String pattern = element.getTextTrim(); 692 693 if (HiveMind.isBlank(pattern)) 694 throw new DocumentParseException("Pattern is null in " + element); 695 696 PatternMatcherInput input = new PatternMatcherInput(outputString); 697 698 PatternMatcher matcher = getMatcher(); 699 Pattern compiled = compile(pattern); 700 701 List<Element> l = element.getChildren("match"); 702 int count = l.size(); 703 int i = 0; 704 705 while (matcher.contains(input, compiled)) 706 { 707 MatchResult match = matcher.getMatch(); 708 String actual = match.group(subgroup); 709 710 boolean matched = contentContains(l, actual); 711 712 if (i >= count) 713 { 714 System.err.println(outputString); 715 throw new AssertionError(buildTestName(name) + ": Too many matches for '" 716 + pattern + "'."); 717 } 718 719 if (!matched) { 720 System.err.println(outputString); 721 throw new AssertionError(buildTestName(name) + ": No expected match found for " 722 + "output of '" + actual + "'. "); 723 } 724 725 i++; 726 } 727 728 if (i < count) 729 { 730 System.err.println(outputString); 731 throw new AssertionError(buildTestName(name) + ": Too few matches for '" 732 + pattern + "' (expected " + count + " but got " + i + ")."); 733 } 734 } 735 736 private boolean contentContains(List<Element> elements, String text) 737 { 738 for (Element e : elements) { 739 if (e.getTextTrim().equals(text)) 740 return true; 741 } 742 743 return false; 744 } 745 746 private void executeExceptionAssertions(Element request) 747 { 748 List l = request.getChildren("assert-exception"); 749 int count = l.size(); 750 751 for (int i = 0; i < count; i++) 752 { 753 Element assertion = (Element) l.get(i); 754 755 executeExceptionAssertion(assertion); 756 } 757 758 } 759 760 private void executeExceptionAssertion(Element assertion) 761 { 762 String name = assertion.getAttributeValue("name"); 763 String value = assertion.getTextTrim(); 764 765 if (_exception == null) 766 throw new AssertionError(buildTestName(name) + " no exception thrown."); 767 String message = _exception.getMessage(); 768 769 if (message.indexOf(value) >= 0) 770 return; 771 772 throw new AssertionError(buildTestName(name) + " exception message (" + message 773 + ") does not contain '" + value + "'."); 774 } 775 776 private void executeCookieAssertions(Element request) 777 { 778 List l = request.getChildren("assert-cookie"); 779 int count = l.size(); 780 781 for (int i = 0; i < count; i++) 782 { 783 Element assertion = (Element) l.get(i); 784 785 executeCookieAssertion(assertion); 786 } 787 } 788 789 private void executeCookieAssertion(Element assertion) 790 { 791 String name = assertion.getAttributeValue("name"); 792 String value = assertion.getAttributeValue("value"); 793 794 Cookie[] cookies = _response.getCookies(); 795 796 for (int i = 0; i < cookies.length; i++) 797 { 798 if (!cookies[i].getName().equals(name)) 799 continue; 800 801 if (cookies[i].getValue().equals(value)) 802 return; 803 804 throw new AssertionError(buildTestName(name) + ": Response cookie '" + name 805 + "': expected '" + value + "', but was '" + cookies[i].getValue() + "'."); 806 } 807 808 throw new AssertionError(buildTestName(name) + ": Could not find cookie named '" 809 + name + "' in response."); 810 } 811 812 private String buildTestName(String name) 813 { 814 return "Request #" + _requestNumber + "/" + name; 815 } 816 817 private void executeOutputStreamAssertions(Element request) throws DocumentParseException 818 { 819 List l = request.getChildren("assert-output-stream"); 820 int count = l.size(); 821 822 for (int i = 0; i < count; i++) 823 { 824 Element assertion = (Element) l.get(i); 825 826 executeOutputStreamAssertion(assertion); 827 } 828 829 } 830 831 private void executeOutputStreamAssertion(Element element) throws DocumentParseException 832 { 833 String name = element.getAttributeValue("name"); 834 String contentType = element.getAttributeValue("content-type"); 835 String path = element.getAttributeValue("path"); 836 837 String actualContentType = _response.getContentType(); 838 839 if (!contentType.equals(actualContentType)) 840 throw new AssertionError(buildTestName(name) + " content-type was '" 841 + actualContentType + "', expected '" + contentType + "'."); 842 843 byte[] actualContent = _response.getResponseBytes(); 844 byte[] expectedContent = getFileContent(getBaseDirectory() + "/" + path); 845 846 if (actualContent.length != expectedContent.length) 847 throw new AssertionError(buildTestName(name) + " actual length of " 848 + actualContent.length + " bytes does not match expected length of " 849 + expectedContent.length + " bytes."); 850 851 for (int i = 0; i < actualContent.length; i++) 852 { 853 if (actualContent[i] != expectedContent[i]) 854 throw new AssertionError(buildTestName(name) 855 + " content mismatch at index + " + i + "."); 856 857 } 858 } 859 860 private byte[] getFileContent(String path) 861 { 862 try 863 { 864 InputStream in = new FileInputStream(path); 865 ByteArrayOutputStream out = new ByteArrayOutputStream(); 866 867 byte[] buffer = new byte[1000]; 868 869 while (true) 870 { 871 int length = in.read(buffer); 872 if (length < 0) 873 break; 874 875 out.write(buffer, 0, length); 876 } 877 878 in.close(); 879 out.close(); 880 881 return out.toByteArray(); 882 } 883 catch (FileNotFoundException ex) 884 { 885 throw new ApplicationRuntimeException("File '" + path + "' not found.", ex); 886 } 887 catch (IOException ex) 888 { 889 throw new ApplicationRuntimeException("Unable to read file '" + path + "'.", ex); 890 } 891 } 892 893 private void createLogs() 894 throws Exception 895 { 896 File outDir = new File(getBaseDirectory() + LOGS_DIR); 897 898 if (!outDir.isDirectory()) 899 outDir.mkdirs(); 900 901 _savedOut = System.out; 902 _savedErr = System.err; 903 904 System.setOut(createPrintStream(outDir.getPath() + "/" + _fileName, "out")); 905 System.setErr(createPrintStream(outDir.getPath() + "/" + _fileName, "err")); 906 } 907 908 private PrintStream createPrintStream(String path, String extension) throws Exception 909 { 910 File file = new File(path + "." + extension); 911 912 // Open and truncate file. 913 914 FileOutputStream fos = new FileOutputStream(file); 915 916 BufferedOutputStream bos = new BufferedOutputStream(fos); 917 918 return new PrintStream(bos, true); 919 } 920 921 @AfterClass 922 public static void deleteDir() 923 { 924 File file = new File(getBaseDirectory() + "/target/.private"); 925 926 if (!file.exists()) 927 return; 928 929 deleteRecursive(file); 930 } 931 932 private static void deleteRecursive(File file) 933 { 934 if (file.isFile()) 935 { 936 file.delete(); 937 return; 938 } 939 940 String[] names = file.list(); 941 942 for (int i = 0; i < names.length; i++) 943 { 944 File f = new File(file, names[i]); 945 deleteRecursive(f); 946 } 947 948 file.delete(); 949 } 950 951 public static String getBaseDirectory() 952 { 953 if (_baseDir == null) { 954 _baseDir = System.getProperty("BASEDIR", DEFAULT_BASE_DIR); 955 File test = new File(_baseDir + SCRIPTS_DIR); 956 if (!test.exists()) { 957 test = new File(_baseDir + "tapestry-framework/" + SCRIPTS_DIR); 958 if (test.exists()) 959 _baseDir = _baseDir + "tapestry-framework/"; 960 } 961 } 962 963 return _baseDir; 964 } 965 }