001: package com.meterware.httpunit;
002:
003: /********************************************************************************************************************
004: * $Id: HTMLPage.java,v 1.33 2004/08/08 17:38:18 russgold Exp $
005: *
006: * Copyright (c) 2000-2004, Russell Gold
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
009: * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
011: * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included in all copies or substantial portions
014: * of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
017: * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
019: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020: * DEALINGS IN THE SOFTWARE.
021: *
022: *******************************************************************************************************************/
023: import com.meterware.httpunit.scripting.NamedDelegate;
024: import com.meterware.httpunit.scripting.ScriptableDelegate;
025: import com.meterware.httpunit.parsing.HTMLParserFactory;
026: import com.meterware.httpunit.parsing.DocumentAdapter;
027: import org.w3c.dom.Document;
028: import org.w3c.dom.Element;
029: import org.w3c.dom.Node;
030: import org.w3c.dom.NodeList;
031: import org.xml.sax.SAXException;
032:
033: import java.io.IOException;
034: import java.net.URL;
035: import java.util.Vector;
036:
037: /**
038: * This class represents an HTML page returned from a request.
039: *
040: * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
041: * @author <a href="mailto:bx@bigfoot.com">Benoit Xhenseval</a>
042: **/
043: public class HTMLPage extends ParsedHTML {
044:
045: private Scriptable _scriptable;
046:
047: HTMLPage(WebResponse response, FrameSelector frame, URL baseURL,
048: String baseTarget, String characterSet) throws IOException,
049: SAXException {
050: super (response, frame, baseURL, baseTarget, null, characterSet);
051: }
052:
053: /**
054: * Returns the title of the page.
055: **/
056: public String getTitle() throws SAXException {
057: NodeList nl = ((Document) getOriginalDOM())
058: .getElementsByTagName("title");
059: if (nl.getLength() == 0)
060: return "";
061: if (!nl.item(0).hasChildNodes())
062: return "";
063: return nl.item(0).getFirstChild().getNodeValue();
064: }
065:
066: /**
067: * Returns the onLoad event script.
068: */
069: public String getOnLoadEvent() throws SAXException {
070: Element mainElement = getMainElement(((Document) getOriginalDOM()));
071: return mainElement == null ? "" : mainElement
072: .getAttribute("onload");
073: }
074:
075: private Element getMainElement(Document document) {
076: NodeList nl = document.getElementsByTagName("frameset");
077: if (nl.getLength() == 0)
078: nl = document.getElementsByTagName("body");
079: return nl.getLength() == 0 ? null : ((Element) nl.item(0));
080: }
081:
082: /**
083: * Returns the location of the linked stylesheet in the head
084: * <code>
085: * <link type="text/css" rel="stylesheet" href="/mystyle.css" />
086: * </code>
087: **/
088: public String getExternalStyleSheet() throws SAXException {
089: NodeList nl = ((Document) getOriginalDOM())
090: .getElementsByTagName("link");
091: int length = nl.getLength();
092: if (length == 0)
093: return "";
094:
095: for (int i = 0; i < length; i++) {
096: if ("stylesheet".equalsIgnoreCase(NodeUtils
097: .getNodeAttribute(nl.item(i), "rel")))
098: return NodeUtils.getNodeAttribute(nl.item(i), "href");
099: }
100: return "";
101: }
102:
103: /**
104: * Retrieves the "content" of the meta tags for a key pair attribute-attributeValue.
105: * <code>
106: * <meta name="robots" content="index" />
107: * <meta name="robots" content="follow" />
108: * <meta http-equiv="Expires" content="now" />
109: * </code>
110: * this can be used like this
111: * <code>
112: * getMetaTagContent("name","robots") will return { "index","follow" }
113: * getMetaTagContent("http-equiv","Expires") will return { "now" }
114: * </code>
115: **/
116: public String[] getMetaTagContent(String attribute,
117: String attributeValue) {
118: Vector matches = new Vector();
119: NodeList nl = ((Document) getOriginalDOM())
120: .getElementsByTagName("meta");
121: int length = nl.getLength();
122:
123: for (int i = 0; i < length; i++) {
124: if (attributeValue.equalsIgnoreCase(NodeUtils
125: .getNodeAttribute(nl.item(i), attribute))) {
126: matches.addElement(NodeUtils.getNodeAttribute(nl
127: .item(i), "content"));
128: }
129: }
130: String[] result = new String[matches.size()];
131: matches.copyInto(result);
132: return result;
133: }
134:
135: public class Scriptable extends ScriptableDelegate {
136:
137: public Object get(String propertyName) {
138: NamedDelegate delegate = getNamedItem(getForms(),
139: propertyName);
140: if (delegate != null)
141: return delegate;
142:
143: delegate = getNamedItem(getLinks(), propertyName);
144: if (delegate != null)
145: return delegate;
146:
147: delegate = getNamedItem(getImages(), propertyName);
148: if (delegate != null)
149: return delegate;
150:
151: return super .get(propertyName);
152: }
153:
154: private NamedDelegate getNamedItem(NamedDelegate[] items,
155: String name) {
156: for (int i = 0; i < items.length; i++) {
157: if (items[i].getName().equals(name))
158: return items[i];
159: }
160: return null;
161: }
162:
163: /**
164: * Sets the value of the named property. Will throw a runtime exception if the property does not exist or
165: * cannot accept the specified value.
166: **/
167: public void set(String propertyName, Object value) {
168: if (propertyName.equalsIgnoreCase("location")) {
169: getResponse().getScriptableObject().set("location",
170: value);
171: } else {
172: super .set(propertyName, value);
173: }
174: }
175:
176: public WebResponse.Scriptable getParent() {
177: return getResponse().getScriptableObject();
178: }
179:
180: public String getTitle() throws SAXException {
181: return HTMLPage.this .getTitle();
182: }
183:
184: public WebLink.Scriptable[] getLinks() {
185: WebLink[] links = HTMLPage.this .getLinks();
186: WebLink.Scriptable[] result = new WebLink.Scriptable[links.length];
187: for (int i = 0; i < links.length; i++) {
188: result[i] = links[i].getScriptableObject();
189: }
190: return result;
191: }
192:
193: public WebForm.Scriptable[] getForms() {
194: WebForm[] forms = HTMLPage.this .getForms();
195: WebForm.Scriptable[] result = new WebForm.Scriptable[forms.length];
196: for (int i = 0; i < forms.length; i++) {
197: result[i] = forms[i].getScriptableObject();
198: }
199: return result;
200: }
201:
202: public WebImage.Scriptable[] getImages() {
203: WebImage[] images = HTMLPage.this .getImages();
204: WebImage.Scriptable[] result = new WebImage.Scriptable[images.length];
205: for (int i = 0; i < images.length; i++) {
206: result[i] = images[i].getScriptableObject();
207: }
208: return result;
209: }
210:
211: Scriptable() {
212: }
213:
214: public boolean replaceText(String text, String contentType) {
215: return getResponse().replaceText(text, contentType);
216: }
217:
218: public void setCookie(String name, String value) {
219: getResponse().setCookie(name, value);
220: }
221:
222: public String getCookie() {
223: return emptyIfNull(getResponse().getCookieHeader());
224: }
225:
226: private String emptyIfNull(String string) {
227: return string == null ? "" : string;
228: }
229:
230: public ScriptableDelegate getElementWithID(String id) {
231: final HTMLElement elementWithID = HTMLPage.this
232: .getElementWithID(id);
233: return elementWithID == null ? null : elementWithID
234: .getScriptableDelegate();
235: }
236:
237: public ScriptableDelegate[] getElementsByName(String name) {
238: return getDelegates(HTMLPage.this .getElementsWithName(name));
239: }
240:
241: public ScriptableDelegate[] getElementsByTagName(String name) {
242: return getDelegates(HTMLPage.this .getElementsByTagName(
243: HTMLPage.this .getRootNode(), name));
244: }
245: }
246:
247: Scriptable getScriptableObject() {
248: if (_scriptable == null) {
249: _scriptable = new Scriptable();
250: _scriptable
251: .setScriptEngine(getResponse()
252: .getScriptableObject().getScriptEngine(
253: _scriptable));
254: }
255: return _scriptable;
256: }
257:
258: public void parse(String text, URL pageURL) throws SAXException,
259: IOException {
260: HTMLParserFactory.getHTMLParser().parse(pageURL, text,
261: new DocumentAdapter() {
262: public void setRootNode(Node rootNode) {
263: HTMLPage.this .setRootNode(rootNode);
264: }
265:
266: public String getIncludedScript(String srcAttribute)
267: throws IOException {
268: return HTMLPage.this
269: .getIncludedScript(srcAttribute);
270: }
271:
272: public ScriptableDelegate getScriptableObject() {
273: return HTMLPage.this.getScriptableObject()
274: .getParent();
275: }
276: });
277: }
278:
279: }
|