package com.meterware.httpunit;
/********************************************************************************************************************
*
* Copyright (c) 2000-2007, Russell Gold
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*******************************************************************************************************************/
import com.meterware.httpunit.scripting.NamedDelegate;
import com.meterware.httpunit.scripting.ScriptableDelegate;
import com.meterware.httpunit.scripting.ScriptingHandler;
import com.meterware.httpunit.parsing.HTMLParserFactory;
import com.meterware.httpunit.parsing.DocumentAdapter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.html.HTMLDocument;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;
/**
* This class represents an HTML page returned from a request.
*
* @author Russell Gold
* @author Benoit Xhenseval
**/
public class HTMLPage extends ParsedHTML {
private Scriptable _scriptable;
HTMLPage( WebResponse response, FrameSelector frame, URL baseURL, String baseTarget, String characterSet ) {
super( response, frame, baseURL, baseTarget, null, characterSet );
}
/**
* Returns the title of the page.
**/
public String getTitle() throws SAXException {
NodeList nl = ((Document) getOriginalDOM()).getElementsByTagName( "title" );
if (nl.getLength() == 0) return "";
if (!nl.item(0).hasChildNodes()) return "";
return nl.item(0).getFirstChild().getNodeValue();
}
/**
* Returns the onLoad event script.
*/
public String getOnLoadEvent() throws SAXException {
Element mainElement = getMainElement( ((Document) getOriginalDOM()) );
return mainElement == null ? "" : mainElement.getAttribute( "onload" );
}
private Element getMainElement( Document document ) {
NodeList nl = document.getElementsByTagName( "frameset" );
if (nl.getLength() == 0) nl = document.getElementsByTagName( "body" );
return nl.getLength() == 0 ? null : ((Element) nl.item(0));
}
/**
* Returns the location of the linked stylesheet in the head
*
*
*
**/
public String getExternalStyleSheet() throws SAXException {
NodeList nl = ((Document) getOriginalDOM()).getElementsByTagName( "link" );
int length = nl.getLength();
if (length == 0) return "";
for (int i = 0; i < length; i++) {
if ("stylesheet".equalsIgnoreCase(NodeUtils.getNodeAttribute( nl.item(i), "rel" )))
return NodeUtils.getNodeAttribute( nl.item(i), "href" );
}
return "";
}
/**
* Retrieves the "content" of the meta tags for a key pair attribute-attributeValue.
*
*
*
*
*
* this can be used like this
*
* getMetaTagContent("name","robots") will return { "index","follow" }
* getMetaTagContent("http-equiv","Expires") will return { "now" }
*
**/
public String[] getMetaTagContent(String attribute, String attributeValue) {
Vector matches = new Vector();
NodeList nl = ((Document) getOriginalDOM()).getElementsByTagName("meta");
int length = nl.getLength();
for (int i = 0; i < length; i++) {
if (attributeValue.equalsIgnoreCase(NodeUtils.getNodeAttribute(nl.item(i), attribute))) {
matches.addElement( NodeUtils.getNodeAttribute( nl.item(i), "content" ) );
}
}
String[] result = new String[ matches.size() ];
matches.copyInto( result );
return result;
}
/**
* scriptable for HTML Page
*/
public class Scriptable extends ScriptableDelegate {
/**
* get the Object with the given propertyName
* @param propertyName - the name of the property
*/
public Object get( String propertyName ) {
NamedDelegate delegate = getNamedItem( getForms(), propertyName );
if (delegate != null) return delegate;
delegate = getNamedItem( getLinks(), propertyName );
if (delegate != null) return delegate;
delegate = getNamedItem( getImages(), propertyName );
if (delegate != null) return delegate;
return null;
}
private NamedDelegate getNamedItem( ScriptingHandler[] items, String name ) {
if (name == null) return null;
for (int i = 0; i < items.length; i++) {
if (items[i] instanceof NamedDelegate && name.equals( ((NamedDelegate) items[i]).getName() )) return (NamedDelegate) items[i];
}
return null;
}
/**
* Sets the value of the named property. Will throw a runtime exception if the property does not exist or
* cannot accept the specified value.
**/
public void set( String propertyName, Object value ) {
if (propertyName.equalsIgnoreCase( "location" )) {
getResponse().getScriptableObject().set( "location", value );
} else {
super.set( propertyName, value );
}
}
public WebResponse.Scriptable getParent() {
return getResponse().getScriptableObject();
}
public String getTitle() throws SAXException {
return HTMLPage.this.getTitle();
}
public ScriptingHandler[] getLinks() {
WebLink[] links = HTMLPage.this.getLinks();
ScriptingHandler[] result = new WebLink.Scriptable[ links.length ];
for (int i = 0; i < links.length; i++) {
result[i] = links[i].getScriptingHandler();
}
return result;
}
public ScriptingHandler[] getForms() {
WebForm[] forms = HTMLPage.this.getForms();
ScriptingHandler[] result = new ScriptingHandler[ forms.length ];
for (int i = 0; i < forms.length; i++) {
result[i] = forms[i].getScriptingHandler();
}
return result;
}
public ScriptingHandler[] getImages() {
WebImage[] images = HTMLPage.this.getImages();
ScriptingHandler[] result = new WebImage.Scriptable[ images.length ];
for (int i = 0; i < images.length; i++) {
result[i] = images[i].getScriptingHandler();
}
return result;
}
Scriptable() {}
public boolean replaceText( String text, String contentType ) {
return getResponse().replaceText( text, contentType );
}
public void setCookie( String name, String value ) {
getResponse().setCookie( name, value );
}
public String getCookie() {
return emptyIfNull( getResponse().getCookieHeader() );
}
private String emptyIfNull( String string ) {
return string == null ? "" : string;
}
public ScriptableDelegate getElementWithID( String id ) {
final HTMLElement elementWithID = HTMLPage.this.getElementWithID( id );
return elementWithID == null ? null : (ScriptableDelegate) elementWithID.getScriptingHandler();
}
public ScriptableDelegate[] getElementsByName( String name ) {
return getDelegates( HTMLPage.this.getElementsWithName( name ) );
}
public ScriptableDelegate[] getElementsByTagName( String name ) {
return getDelegates( HTMLPage.this.getElementsByTagName( HTMLPage.this.getRootNode(), name ) );
}
}
Scriptable getScriptableObject() {
if (_scriptable == null) {
_scriptable = new Scriptable();
_scriptable.setScriptEngine( getResponse().getScriptableObject().getScriptEngine( _scriptable ) );
}
return _scriptable;
}
/**
* parse the given test with the given URL
* @param text
* @param pageURL
* @throws SAXException
* @throws IOException
*/
public void parse( String text, URL pageURL ) throws SAXException, IOException {
HTMLParserFactory.getHTMLParser().parse( pageURL, text, new DocumentAdapter() {
public void setDocument(HTMLDocument document ) { HTMLPage.this.setRootNode( document ); }
public String getIncludedScript( String srcAttribute ) throws IOException { return HTMLPage.this.getIncludedScript( srcAttribute ); }
public ScriptingHandler getScriptingHandler() { return getResponse().getScriptingHandler(); }
});
}
}