1 5 package com.meterware.httpunit; 6 7 import java.io.IOException ; 8 import java.net.URL ; 9 import java.util.ArrayList ; 10 import java.util.Arrays ; 11 import java.util.HashMap ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 15 import org.w3c.dom.Document ; 16 import org.w3c.dom.Element ; 17 import org.w3c.dom.Node ; 18 import org.w3c.dom.NodeList ; 19 20 import com.meterware.httpunit.scripting.ScriptableDelegate; 21 22 23 27 class ParsedHTML 28 { 29 30 final static private HTMLElement[] NO_ELEMENTS = new HTMLElement[0]; 31 32 final static private String [] TEXT_ELEMENTS = {"p", "h1", "h2", "h3", "h4", "h5", "h6"}; 33 34 private Node _rootNode; 35 36 protected URL _baseURL; 37 38 protected FrameSelector _frame; 39 40 protected String _baseTarget; 41 42 protected String _characterSet; 43 44 private WebResponse _response; 45 46 private boolean _updateElements = true; 47 48 private boolean _enableNoScriptNodes; 49 50 51 private HashMap _elementsByID = new HashMap (); 52 53 54 private HashMap _elementsByName = new HashMap (); 55 56 57 private HashMap _elements = new HashMap (); 58 59 private ArrayList _formsList = new ArrayList (); 60 61 private WebForm[] _forms; 62 63 private WebForm _activeForm; 64 65 private ArrayList _imagesList = new ArrayList (); 66 67 private WebImage[] _images; 68 69 private ArrayList _linkList = new ArrayList (); 70 71 private WebLink[] _links; 72 73 private ArrayList _blocksList = new ArrayList (); 74 75 private TextBlock[] _blocks; 76 77 private ArrayList _appletList = new ArrayList (); 78 79 private WebApplet[] _applets; 80 81 private ArrayList _tableList = new ArrayList (); 82 83 private WebTable[] _tables; 84 85 private ArrayList _frameList = new ArrayList (); 86 87 private WebFrame[] _frames; 88 89 ParsedHTML( 90 WebResponse response, 91 FrameSelector frame, 92 URL baseURL, 93 String baseTarget, 94 Node rootNode, 95 String characterSet) 96 { 97 _response = response; 98 _frame = frame; 99 _baseURL = baseURL; 100 _baseTarget = baseTarget; 101 _rootNode = rootNode; 102 _characterSet = characterSet; 103 } 104 105 108 public WebForm[] getForms() 109 { 110 if (_forms == null) 111 { 112 loadElements(); 113 _forms = (WebForm[]) _formsList.toArray(new WebForm[_formsList.size()]); 114 } 115 return _forms; 116 } 117 118 121 public WebLink[] getLinks() 122 { 123 if (_links == null) 124 { 125 loadElements(); 126 _links = (WebLink[]) _linkList.toArray(new WebLink[_linkList.size()]); 127 } 128 return _links; 129 } 130 131 134 public WebApplet[] getApplets() 135 { 136 if (_applets == null) 137 { 138 loadElements(); 139 _applets = (WebApplet[]) _appletList.toArray(new WebApplet[_appletList.size()]); 140 } 141 return _applets; 142 } 143 144 147 public WebImage[] getImages() 148 { 149 if (_images == null) 150 { 151 loadElements(); 152 _images = (WebImage[]) _imagesList.toArray(new WebImage[_imagesList.size()]); 153 } 154 return _images; 155 } 156 157 160 public TextBlock[] getTextBlocks() 161 { 162 if (_blocks == null) 163 { 164 loadElements(); 165 _blocks = (TextBlock[]) _blocksList.toArray(new TextBlock[_blocksList.size()]); 166 } 167 return _blocks; 168 } 169 170 173 public TextBlock getFirstMatchingTextBlock(HTMLElementPredicate predicate, Object criteria) 174 { 175 TextBlock[] blocks = getTextBlocks(); 176 for (int i = 0; i < blocks.length; i++) 177 { 178 if (predicate.matchesCriteria(blocks[i], criteria)) 179 return blocks[i]; 180 } 181 return null; 182 } 183 184 public TextBlock getNextTextBlock(TextBlock block) 185 { 186 int index = _blocksList.indexOf(block); 187 if (index < 0 || index == _blocksList.size() - 1) 188 return null; 189 return (TextBlock) _blocksList.get(index + 1); 190 } 191 192 195 public WebTable[] getTables() 196 { 197 if (_tables == null) 198 { 199 loadElements(); 200 _tables = (WebTable[]) _tableList.toArray(new WebTable[_tableList.size()]); 201 } 202 return _tables; 203 } 204 205 208 public HTMLElement getElementWithID(String id) 209 { 210 return (HTMLElement) getElementWithID(id, HTMLElement.class); 211 } 212 213 216 public HTMLElement[] getElementsWithName(String name) 217 { 218 loadElements(); 219 ArrayList elements = (ArrayList ) _elementsByName.get(name); 220 return elements == null ? NO_ELEMENTS : (HTMLElement[]) elements.toArray(new HTMLElement[elements.size()]); 221 } 222 223 226 public HTMLElement[] getElementsWithAttribute(String name, String value) 227 { 228 loadElements(); 229 ArrayList elements = new ArrayList (); 230 for (Iterator i = _elements.values().iterator(); i.hasNext();) 231 { 232 HTMLElement element = (HTMLElement) i.next(); 233 if (value.equals(element.getAttribute(name))) 234 elements.add(element); 235 } 236 return (HTMLElement[]) elements.toArray(new HTMLElement[elements.size()]); 237 } 238 239 242 public String [] getElementNames() 243 { 244 loadElements(); 245 return (String []) _elementsByName.keySet().toArray(new String [_elementsByName.size()]); 246 } 247 248 HTMLElement[] getElementsByTagName(Node dom, String name) 249 { 250 loadElements(); 251 if (dom instanceof Element ) 252 { 253 return getElementsFromList(((Element ) dom).getElementsByTagName(name)); 254 } 255 else 256 { 257 return getElementsFromList(((Document ) dom).getElementsByTagName(name)); 258 } 259 } 260 261 private HTMLElement[] getElementsFromList(NodeList nl) 262 { 263 HTMLElement[] elements = new HTMLElement[nl.getLength()]; 264 for (int i = 0; i < elements.length; i++) 265 { 266 Node node = nl.item(i); 267 elements[i] = (HTMLElement) _elements.get(node); 268 if (elements[i] == null) 269 { 270 elements[i] = toDefaultElement((Element ) node); 271 _elements.put(node, elements[i]); 272 } 273 } 274 return elements; 275 } 276 277 280 public WebForm getFormWithID(String id) 281 { 282 return (WebForm) getElementWithID(id, WebForm.class); 283 } 284 285 288 public WebLink getLinkWithID(String id) 289 { 290 return (WebLink) getElementWithID(id, WebLink.class); 291 292 } 293 294 private Object getElementWithID(String id, final Class klass) 295 { 296 loadElements(); 297 return whenCast(_elementsByID.get(id), klass); 298 } 299 300 private Object whenCast(Object o, Class klass) 301 { 302 return klass.isInstance(o) ? o : null; 303 } 304 305 308 public WebForm getFirstMatchingForm(HTMLElementPredicate predicate, Object criteria) 309 { 310 WebForm[] forms = getForms(); 311 for (int i = 0; i < forms.length; i++) 312 { 313 if (predicate.matchesCriteria(forms[i], criteria)) 314 return forms[i]; 315 } 316 return null; 317 } 318 319 322 public WebForm[] getMatchingForms(HTMLElementPredicate predicate, Object criteria) 323 { 324 ArrayList matches = new ArrayList (); 325 WebForm[] forms = getForms(); 326 for (int i = 0; i < forms.length; i++) 327 { 328 if (predicate.matchesCriteria(forms[i], criteria)) 329 matches.add(forms[i]); 330 } 331 return (WebForm[]) matches.toArray(new WebForm[matches.size()]); 332 } 333 334 337 public WebForm getFormWithName(String name) 338 { 339 return getFirstMatchingForm(WebForm.MATCH_NAME, name); 340 } 341 342 private void interpretScriptElement(Element element) 343 { 344 String script = getScript(element); 345 if (script != null) 346 { 347 try 348 { 349 _updateElements = false; 350 String language = NodeUtils.getNodeAttribute(element, "language", null); 351 if (!getResponse().getScriptableObject().supportsScript(language)) 352 _enableNoScriptNodes = true; 353 getResponse().getScriptableObject().runScript(language, script); 354 } 355 finally 356 { 357 setRootNode(_rootNode); 358 } 359 } 360 } 361 362 private String getScript(Node scriptNode) 363 { 364 String scriptLocation = NodeUtils.getNodeAttribute(scriptNode, "src", null); 365 if (scriptLocation == null) 366 { 367 return NodeUtils.asText(scriptNode.getChildNodes()); 368 } 369 else 370 { 371 try 372 { 373 return getIncludedScript(scriptLocation); 374 } 375 catch (IOException e) 376 { 377 throw new RuntimeException ("Error loading included script: " + e); 378 } 379 } 380 } 381 382 388 String getIncludedScript(String srcAttribute) throws IOException 389 { 390 WebRequest req = new GetMethodWebRequest(getBaseURL(), srcAttribute); 391 WebWindow window = getResponse().getWindow(); 392 if (window == null) 393 throw new IllegalStateException ( 394 "Unable to retrieve script included by this response, since it was loaded by getResource(). Use getResponse() instead."); 395 return window.getResource(req).getText(); 396 } 397 398 401 private HTMLElement toNoscriptElement(Element element) 402 { 403 return _enableNoScriptNodes ? null : new NoScriptElement(element); 404 } 405 406 static class HtmlElementRecorder 407 { 408 409 protected void recordHtmlElement(NodeUtils.PreOrderTraversal pot, Node node, HTMLElement htmlElement) 410 { 411 if (htmlElement != null) 412 { 413 addToMaps(pot, node, htmlElement); 414 addToLists(pot, htmlElement); 415 } 416 } 417 418 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 419 { 420 for (Iterator i = pot.getContexts(); i.hasNext();) 421 { 422 Object o = i.next(); 423 if (o instanceof ParsedHTML) 424 ((ParsedHTML) o).addToList(htmlElement); 425 } 426 } 427 428 protected void addToMaps(NodeUtils.PreOrderTraversal pot, Node node, HTMLElement htmlElement) 429 { 430 for (Iterator i = pot.getContexts(); i.hasNext();) 431 { 432 Object o = i.next(); 433 if (o instanceof ParsedHTML) 434 ((ParsedHTML) o).addToMaps(node, htmlElement); 435 } 436 } 437 438 } 439 440 abstract static class HTMLElementFactory extends HtmlElementRecorder 441 { 442 443 abstract HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element); 444 445 void recordElement(NodeUtils.PreOrderTraversal pot, Element element, ParsedHTML parsedHTML) 446 { 447 HTMLElement htmlElement = toHTMLElement(pot, parsedHTML, element); 448 recordHtmlElement(pot, element, htmlElement); 449 } 450 451 protected boolean isRecognized(ClientProperties properties) 452 { 453 return true; 454 } 455 456 protected boolean addToContext() 457 { 458 return false; 459 } 460 461 final protected ParsedHTML getParsedHTML(NodeUtils.PreOrderTraversal pot) 462 { 463 return (ParsedHTML) getClosestContext(pot, ParsedHTML.class); 464 } 465 466 final protected Object getClosestContext(NodeUtils.PreOrderTraversal pot, Class aClass) 467 { 468 return pot.getClosestContext(aClass); 469 } 470 471 protected ParsedHTML getRootContext(NodeUtils.PreOrderTraversal pot) 472 { 473 return (ParsedHTML) pot.getRootContext(); 474 } 475 } 476 477 static class DefaultElementFactory extends HTMLElementFactory 478 { 479 480 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 481 { 482 if (element.getAttribute("id").equals("")) 483 return null; 484 return parsedHTML.toDefaultElement(element); 485 } 486 487 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 488 { 489 } 490 } 491 492 private HTMLElement toDefaultElement(Element element) 493 { 494 return new HTMLElementBase(element) 495 { 496 497 protected ScriptableDelegate newScriptable() 498 { 499 return new HTMLElementScriptable(this); 500 } 501 502 protected ScriptableDelegate getParentDelegate() 503 { 504 return getResponse().getScriptableObject().getDocument(); 505 } 506 }; 507 } 508 509 static class WebFormFactory extends HTMLElementFactory 510 { 511 512 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 513 { 514 return parsedHTML.toWebForm(element); 515 } 516 517 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 518 { 519 super.addToLists(pot, htmlElement); 520 getRootContext(pot)._activeForm = (WebForm) htmlElement; 521 } 522 } 523 524 static class WebLinkFactory extends HTMLElementFactory 525 { 526 527 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 528 { 529 return parsedHTML.toLinkAnchor(element); 530 } 531 } 532 533 static class TextBlockFactory extends HTMLElementFactory 534 { 535 536 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 537 { 538 return parsedHTML.toTextBlock(element); 539 } 540 541 protected boolean addToContext() 542 { 543 return true; 544 } 545 546 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 547 { 548 for (Iterator i = pot.getContexts(); i.hasNext();) 549 { 550 Object o = i.next(); 551 if (!(o instanceof ParsedHTML)) 552 continue; 553 ((ParsedHTML) o).addToList(htmlElement); 554 break; 555 } 556 } 557 558 } 559 560 static class ScriptFactory extends HTMLElementFactory 561 { 562 563 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 564 { 565 return null; 566 } 567 568 void recordElement(NodeUtils.PreOrderTraversal pot, Element element, ParsedHTML parsedHTML) 569 { 570 parsedHTML.interpretScriptElement(element); 571 } 572 } 573 574 static class NoScriptFactory extends HTMLElementFactory 575 { 576 577 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 578 { 579 return parsedHTML.toNoscriptElement(element); 580 } 581 582 protected boolean addToContext() 583 { 584 return true; 585 } 586 } 587 588 static class WebFrameFactory extends HTMLElementFactory 589 { 590 591 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 592 { 593 return parsedHTML.toWebFrame(element); 594 } 595 } 596 597 static class WebIFrameFactory extends HTMLElementFactory 598 { 599 600 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 601 { 602 return parsedHTML.toWebIFrame(element); 603 } 604 605 protected boolean isRecognized(ClientProperties properties) 606 { 607 return properties.isIframeSupported(); 608 } 609 610 protected boolean addToContext() 611 { 612 return true; 613 } 614 } 615 616 static class WebImageFactory extends HTMLElementFactory 617 { 618 619 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 620 { 621 return parsedHTML.toWebImage(element); 622 } 623 } 624 625 static class WebAppletFactory extends HTMLElementFactory 626 { 627 628 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 629 { 630 return parsedHTML.toWebApplet(element); 631 } 632 633 protected boolean addToContext() 634 { 635 return true; 636 } 637 } 638 639 static class WebTableFactory extends HTMLElementFactory 640 { 641 642 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 643 { 644 return parsedHTML.toWebTable(element); 645 } 646 647 protected boolean addToContext() 648 { 649 return true; 650 } 651 652 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 653 { 654 for (Iterator i = pot.getContexts(); i.hasNext();) 655 { 656 Object o = i.next(); 657 if (o instanceof ParsedHTML) 658 ((ParsedHTML) o).addToList(htmlElement); 659 if (o instanceof TableCell) 660 break; 661 } 662 } 663 } 664 665 static class TableRowFactory extends HTMLElementFactory 666 { 667 668 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 669 { 670 WebTable wt = getWebTable(pot); 671 if (wt == null) 672 return null; 673 return wt.newTableRow(element); 674 } 675 676 private WebTable getWebTable(NodeUtils.PreOrderTraversal pot) 677 { 678 return (WebTable) getClosestContext(pot, WebTable.class); 679 } 680 681 protected boolean addToContext() 682 { 683 return true; 684 } 685 686 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 687 { 688 getWebTable(pot).addRow((TableRow) htmlElement); 689 } 690 } 691 692 static class TableCellFactory extends HTMLElementFactory 693 { 694 695 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 696 { 697 TableRow tr = getTableRow(pot); 698 if (tr == null) 699 return null; 700 return tr.newTableCell(element); 701 } 702 703 private TableRow getTableRow(NodeUtils.PreOrderTraversal pot) 704 { 705 return (TableRow) getClosestContext(pot, TableRow.class); 706 } 707 708 protected boolean addToContext() 709 { 710 return true; 711 } 712 713 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 714 { 715 getTableRow(pot).addTableCell((TableCell) htmlElement); 716 } 717 } 718 719 static class FormControlFactory extends HTMLElementFactory 720 { 721 722 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 723 { 724 final WebForm form = getForm(pot); 725 return form == null ? newControlWithoutForm(parsedHTML, element) : form.newFormControl(element); 726 } 727 728 private HTMLElement newControlWithoutForm(ParsedHTML parsedHTML, Element element) 729 { 730 if ((element.getNodeName().equalsIgnoreCase("button") || element.getNodeName().equalsIgnoreCase("input")) 731 && isValidNonFormButtonType(NodeUtils.getNodeAttribute(element, "type"))) 732 { 733 return parsedHTML.toButtonWithoutForm(element); 734 } 735 else 736 { 737 return null; 738 } 739 } 740 741 private boolean isValidNonFormButtonType(String buttonType) 742 { 743 return buttonType.equals("") || buttonType.equalsIgnoreCase("button"); 744 } 745 746 private WebForm getForm(NodeUtils.PreOrderTraversal pot) 747 { 748 return getRootContext(pot)._activeForm; 749 } 750 751 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 752 { 753 WebForm form = getForm(pot); 754 if (form != null) 755 form.addFormControl((FormControl) htmlElement); 756 } 757 } 758 759 static class WebListFactory extends HTMLElementFactory 760 { 761 762 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 763 { 764 return parsedHTML.toOrderedList(element); 765 } 766 767 protected boolean addToContext() 768 { 769 return true; 770 } 771 772 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 773 { 774 TextBlock textBlock = getTextBlock(pot); 775 if (textBlock != null) 776 textBlock.addList((WebList) htmlElement); 777 } 778 779 private TextBlock getTextBlock(NodeUtils.PreOrderTraversal pot) 780 { 781 return (TextBlock) getClosestContext(pot, TextBlock.class); 782 } 783 } 784 785 static class ListItemFactory extends HTMLElementFactory 786 { 787 788 HTMLElement toHTMLElement(NodeUtils.PreOrderTraversal pot, ParsedHTML parsedHTML, Element element) 789 { 790 WebList webList = getWebList(pot); 791 if (webList == null) 792 return null; 793 return webList.addNewItem(element); 794 } 795 796 private WebList getWebList(NodeUtils.PreOrderTraversal pot) 797 { 798 return (WebList) getClosestContext(pot, WebList.class); 799 } 800 801 protected boolean addToContext() 802 { 803 return true; 804 } 805 806 protected void addToLists(NodeUtils.PreOrderTraversal pot, HTMLElement htmlElement) 807 { 808 } 809 } 810 811 private static HashMap _htmlFactoryClasses = new HashMap (); 812 813 private static HTMLElementFactory _defaultFactory = new DefaultElementFactory(); 814 815 static 816 { 817 _htmlFactoryClasses.put("a", new WebLinkFactory()); 818 _htmlFactoryClasses.put("area", new WebLinkFactory()); 819 _htmlFactoryClasses.put("form", new WebFormFactory()); 820 _htmlFactoryClasses.put("img", new WebImageFactory()); 821 _htmlFactoryClasses.put("applet", new WebAppletFactory()); 822 _htmlFactoryClasses.put("table", new WebTableFactory()); 823 _htmlFactoryClasses.put("tr", new TableRowFactory()); 824 _htmlFactoryClasses.put("td", new TableCellFactory()); 825 _htmlFactoryClasses.put("th", new TableCellFactory()); 826 _htmlFactoryClasses.put("frame", new WebFrameFactory()); 827 _htmlFactoryClasses.put("iframe", new WebIFrameFactory()); 828 _htmlFactoryClasses.put("script", new ScriptFactory()); 829 _htmlFactoryClasses.put("noscript", new NoScriptFactory()); 830 _htmlFactoryClasses.put("ol", new WebListFactory()); 831 _htmlFactoryClasses.put("ul", new WebListFactory()); 832 _htmlFactoryClasses.put("li", new ListItemFactory()); 833 834 for (int i = 0; i < TEXT_ELEMENTS.length; i++) 835 { 836 _htmlFactoryClasses.put(TEXT_ELEMENTS[i], new TextBlockFactory()); 837 } 838 839 for (Iterator i = Arrays.asList(FormControl.getControlElementTags()).iterator(); i.hasNext();) 840 { 841 _htmlFactoryClasses.put(i.next(), new FormControlFactory()); 842 } 843 } 844 845 private static HTMLElementFactory getHTMLElementFactory(String tagName) 846 { 847 final HTMLElementFactory factory = (HTMLElementFactory) _htmlFactoryClasses.get(tagName); 848 return factory != null ? factory : _defaultFactory; 849 } 850 851 private void loadElements() 852 { 853 if (!_updateElements) 854 return; 855 856 NodeUtils.NodeAction action = new NodeUtils.NodeAction() 857 { 858 859 public boolean processElement(NodeUtils.PreOrderTraversal pot, Element element) 860 { 861 HTMLElementFactory factory = getHTMLElementFactory(element.getNodeName().toLowerCase()); 862 if (factory == null || !factory.isRecognized(getClientProperties())) 863 return true; 864 if (pot.getClosestContext(ContentConcealer.class) != null) 865 return true; 866 867 if (!_elements.containsKey(element)) 868 factory.recordElement(pot, element, ParsedHTML.this); 869 if (factory.addToContext()) 870 pot.pushContext(_elements.get(element)); 871 872 return true; 873 } 874 875 public void processTextNode(NodeUtils.PreOrderTraversal pot, Node textNode) 876 { 877 if (textNode.getNodeValue().trim().length() == 0) 878 return; 879 880 Node parent = textNode.getParentNode(); 881 if (!parent.getNodeName().equalsIgnoreCase("body")) 882 return; 883 if (pot.getClosestContext(ContentConcealer.class) != null) 884 return; 885 new HtmlElementRecorder().recordHtmlElement(pot, textNode, newTextBlock(textNode)); 886 } 887 }; 888 NodeUtils.PreOrderTraversal nt = new NodeUtils.PreOrderTraversal(getRootNode()); 889 nt.pushBaseContext(this); 890 nt.perform(action); 891 892 _updateElements = false; 893 } 894 895 private ClientProperties getClientProperties() 896 { 897 WebWindow window = _response.getWindow(); 898 return window == null ? ClientProperties.getDefaultProperties() : window.getClient().getClientProperties(); 899 } 900 901 private Button toButtonWithoutForm(Element element) 902 { 903 return new Button(_response, element); 904 } 905 906 private WebForm toWebForm(Element element) 907 { 908 return new WebForm(_response, _baseURL, element, _frame, _baseTarget, _characterSet); 909 } 910 911 private WebFrame toWebFrame(Element element) 912 { 913 return new WebFrame(_response, _baseURL, element, _frame); 914 } 915 916 private WebFrame toWebIFrame(Element element) 917 { 918 return new WebIFrame(_baseURL, element, _frame); 919 } 920 921 private WebLink toLinkAnchor(Element child) 922 { 923 return (!isWebLink(child)) ? null : new WebLink(_response, _baseURL, child, _frame, _baseTarget, _characterSet); 924 } 925 926 private boolean isWebLink(Node node) 927 { 928 return (node.getAttributes().getNamedItem("href") != null); 929 } 930 931 private WebImage toWebImage(Element child) 932 { 933 return new WebImage(_response, this, _baseURL, child, _frame, _baseTarget, _characterSet); 934 } 935 936 private WebApplet toWebApplet(Element element) 937 { 938 return new WebApplet(_response, element, _baseTarget); 939 } 940 941 private WebTable toWebTable(Element element) 942 { 943 return new WebTable(_response, _frame, element, _baseURL, _baseTarget, _characterSet); 944 } 945 946 private TextBlock toTextBlock(Element element) 947 { 948 return new TextBlock(_response, _frame, _baseURL, _baseTarget, element, _characterSet); 949 } 950 951 private TextBlock newTextBlock(Node textNode) 952 { 953 return new TextBlock(_response, _frame, _baseURL, _baseTarget, textNode, _characterSet); 954 } 955 956 private WebList toOrderedList(Element element) 957 { 958 return new WebList(_response, _frame, _baseURL, _baseTarget, element, _characterSet); 959 } 960 961 private void addToMaps(Node node, HTMLElement htmlElement) 962 { 963 _elements.put(node, htmlElement); 964 if (htmlElement.getID() != null) 965 _elementsByID.put(htmlElement.getID(), htmlElement); 966 if (htmlElement.getName() != null) 967 addNamedElement(htmlElement.getName(), htmlElement); 968 } 969 970 private void addNamedElement(String name, HTMLElement htmlElement) 971 { 972 List list = (List ) _elementsByName.get(name); 973 if (list == null) 974 _elementsByName.put(name, list = new ArrayList ()); 975 list.add(htmlElement); 976 } 977 978 private void addToList(HTMLElement htmlElement) 979 { 980 ArrayList list = getListForElement(htmlElement); 981 if (list != null) 982 list.add(htmlElement); 983 } 984 985 private ArrayList getListForElement(HTMLElement element) 986 { 987 if (element instanceof WebLink) 988 return _linkList; 989 if (element instanceof WebForm) 990 return _formsList; 991 if (element instanceof WebImage) 992 return _imagesList; 993 if (element instanceof WebApplet) 994 return _appletList; 995 if (element instanceof WebTable) 996 return _tableList; 997 if (element instanceof WebFrame) 998 return _frameList; 999 if (element instanceof BlockElement) 1000 return _blocksList; 1001 return null; 1002 } 1003 1004 1007 public WebLink getLinkWith(String text) 1008 { 1009 return getFirstMatchingLink(WebLink.MATCH_CONTAINED_TEXT, text); 1010 } 1011 1012 1015 public WebLink getLinkWithImageText(String text) 1016 { 1017 WebImage image = getImageWithAltText(text); 1018 return image == null ? null : image.getLink(); 1019 } 1020 1021 1024 public WebLink getLinkWithName(String name) 1025 { 1026 return getFirstMatchingLink(WebLink.MATCH_NAME, name); 1027 } 1028 1029 1032 public WebLink getFirstMatchingLink(HTMLElementPredicate predicate, Object criteria) 1033 { 1034 WebLink[] links = getLinks(); 1035 for (int i = 0; i < links.length; i++) 1036 { 1037 if (predicate.matchesCriteria(links[i], criteria)) 1038 return links[i]; 1039 } 1040 return null; 1041 } 1042 1043 1046 public WebLink[] getMatchingLinks(HTMLElementPredicate predicate, Object criteria) 1047 { 1048 ArrayList matches = new ArrayList (); 1049 WebLink[] links = getLinks(); 1050 for (int i = 0; i < links.length; i++) 1051 { 1052 if (predicate.matchesCriteria(links[i], criteria)) 1053 matches.add(links[i]); 1054 } 1055 return (WebLink[]) matches.toArray(new WebLink[matches.size()]); 1056 } 1057 1058 1061 public WebImage getImageWithName(String name) 1062 { 1063 WebImage[] images = getImages(); 1064 for (int i = 0; i < images.length; i++) 1065 { 1066 if (HttpUnitUtils.matches(name, images[i].getName())) 1067 return images[i]; 1068 } 1069 return null; 1070 } 1071 1072 1075 public WebImage getImageWithSource(String source) 1076 { 1077 WebImage[] images = getImages(); 1078 for (int i = 0; i < images.length; i++) 1079 { 1080 if (HttpUnitUtils.matches(source, images[i].getSource())) 1081 return images[i]; 1082 } 1083 return null; 1084 } 1085 1086 1089 public WebImage getImageWithAltText(String altText) 1090 { 1091 WebImage[] images = getImages(); 1092 for (int i = 0; i < images.length; i++) 1093 { 1094 if (HttpUnitUtils.matches(altText, images[i].getAltText())) 1095 return images[i]; 1096 } 1097 return null; 1098 } 1099 1100 1105 public WebTable getFirstMatchingTable(HTMLElementPredicate predicate, Object criteria) 1106 { 1107 return getTableSatisfyingPredicate(getTables(), predicate, criteria); 1108 } 1109 1110 1115 public WebTable[] getMatchingTables(HTMLElementPredicate predicate, Object criteria) 1116 { 1117 return getTablesSatisfyingPredicate(getTables(), predicate, criteria); 1118 } 1119 1120 1125 public WebTable getTableStartingWith(String text) 1126 { 1127 return getFirstMatchingTable(WebTable.MATCH_FIRST_NONBLANK_CELL, text); 1128 } 1129 1130 1135 public WebTable getTableStartingWithPrefix(String text) 1136 { 1137 return getFirstMatchingTable(WebTable.MATCH_FIRST_NONBLANK_CELL_PREFIX, text); 1138 } 1139 1140 1145 public WebTable getTableWithSummary(String summary) 1146 { 1147 return getFirstMatchingTable(WebTable.MATCH_SUMMARY, summary); 1148 } 1149 1150 1155 public WebTable getTableWithID(String ID) 1156 { 1157 return getFirstMatchingTable(WebTable.MATCH_ID, ID); 1158 } 1159 1160 1163 public Node getDOM() 1164 { 1165 return getRootNode().cloneNode( true); 1166 } 1167 1168 1170 public String toString() 1171 { 1172 return _baseURL.toExternalForm() + System.getProperty("line.separator") + _rootNode; 1173 } 1174 1175 1177 1180 void setRootNode(Node rootNode) 1181 { 1182 if (_rootNode != null && rootNode != _rootNode) 1183 throw new IllegalStateException ("The root node has already been defined as " 1184 + _rootNode 1185 + " and cannot be redefined as " 1186 + rootNode); 1187 _rootNode = rootNode; 1188 _links = null; 1189 _forms = null; 1190 _images = null; 1191 _applets = null; 1192 _tables = null; 1193 _frames = null; 1194 _blocks = null; 1195 _updateElements = true; 1196 } 1197 1198 1201 URL getBaseURL() 1202 { 1203 return _baseURL; 1204 } 1205 1206 WebResponse getResponse() 1207 { 1208 return _response; 1209 } 1210 1211 1214 Node getOriginalDOM() 1215 { 1216 return getRootNode(); 1217 } 1218 1219 1222 public WebFrame[] getFrames() 1223 { 1224 if (_frames == null) 1225 { 1226 loadElements(); 1227 _frames = (WebFrame[]) _frameList.toArray(new WebFrame[_frameList.size()]); 1228 } 1229 return _frames; 1230 } 1231 1232 1234 Node getRootNode() 1235 { 1236 if (_rootNode == null) 1237 throw new IllegalStateException ("The root node has not been specified"); 1238 return _rootNode; 1239 } 1240 1241 1244 private WebTable getTableSatisfyingPredicate(WebTable[] tables, HTMLElementPredicate predicate, Object value) 1245 { 1246 for (int i = 0; i < tables.length; i++) 1247 { 1248 if (predicate.matchesCriteria(tables[i], value)) 1249 { 1250 return tables[i]; 1251 } 1252 else 1253 { 1254 for (int j = 0; j < tables[i].getRowCount(); j++) 1255 { 1256 for (int k = 0; k < tables[i].getColumnCount(); k++) 1257 { 1258 TableCell cell = tables[i].getTableCell(j, k); 1259 if (cell != null) 1260 { 1261 WebTable[] innerTables = cell.getTables(); 1262 if (innerTables.length != 0) 1263 { 1264 WebTable result = getTableSatisfyingPredicate(innerTables, predicate, value); 1265 if (result != null) 1266 return result; 1267 } 1268 } 1269 } 1270 } 1271 } 1272 } 1273 return null; 1274 } 1275 1276 1279 private WebTable[] getTablesSatisfyingPredicate(WebTable[] tables, HTMLElementPredicate predicate, Object value) 1280 { 1281 ArrayList matches = new ArrayList (); 1282 for (int i = 0; i < tables.length; i++) 1283 { 1284 if (predicate.matchesCriteria(tables[i], value)) 1285 { 1286 matches.add(tables[i]); 1287 } 1288 for (int j = 0; j < tables[i].getRowCount(); j++) 1289 { 1290 for (int k = 0; k < tables[i].getColumnCount(); k++) 1291 { 1292 TableCell cell = tables[i].getTableCell(j, k); 1293 if (cell != null) 1294 { 1295 WebTable[] innerTables = cell.getTables(); 1296 if (innerTables.length != 0) 1297 { 1298 WebTable[] result = getTablesSatisfyingPredicate(innerTables, predicate, value); 1299 if (result != null && result.length > 0) 1300 { 1301 for (int l = 0; l < result.length; l++) 1302 { 1303 matches.add(result[l]); 1304 } 1305 } 1306 } 1307 } 1308 } 1309 } 1310 } 1311 if (matches.size() > 0) 1312 { 1313 return (WebTable[]) matches.toArray(new WebTable[matches.size()]); 1314 } 1315 else 1316 { 1317 return null; 1318 } 1319 } 1320 1321 class WebIFrame extends WebFrame implements ContentConcealer 1322 { 1323 1324 public WebIFrame(URL baseURL, Node frameNode, FrameSelector parentFrame) 1325 { 1326 super(_response, baseURL, frameNode, parentFrame); 1327 } 1328 } 1329 1330 class NoScriptElement extends HTMLElementBase implements ContentConcealer 1331 { 1332 1333 public NoScriptElement(Node node) 1334 { 1335 super(node); 1336 } 1337 1338 protected ScriptableDelegate newScriptable() 1339 { 1340 return null; 1341 } 1342 1343 protected ScriptableDelegate getParentDelegate() 1344 { 1345 return null; 1346 } 1347 } 1348 1349} 1350 | Popular Tags |