001: // Copyright © 2002-2007 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.request;
003:
004: import java.io.File;
005: import java.io.IOException;
006: import java.net.URL;
007: import java.util.HashMap;
008: import java.util.Map;
009:
010: import org.apache.commons.lang.StringUtils;
011: import org.xml.sax.SAXException;
012:
013: import com.canoo.webtest.util.FileUtil;
014: import com.canoo.webtest.util.MapUtil;
015: import com.gargoylesoftware.htmlunit.Page;
016: import com.gargoylesoftware.htmlunit.SubmitMethod;
017: import com.gargoylesoftware.htmlunit.WebRequestSettings;
018:
019: /**
020: * Performs an initial request to an url and makes the received response
021: * available for subsequent steps.
022: * <p>
023: * The url may be specified as an absolute url (with protocol) that will be used
024: * directly or as the end part of an url. In this case the protocol, host, port and basepath
025: * properties of the <config> step will be used to build a complete url.
026: * </p>
027: * @author unknown
028: * @author Marc Guillemot
029: * @author Paul King
030: * @webtest.step
031: * category="Core"
032: * name="invoke"
033: * description="This step executes a request to a particular URL."
034: */
035: public class InvokePage extends AbstractTargetAction {
036: private String fUrl;
037: private String fCompleteUrl;
038: private String fMethod = "GET";
039: private File fContentFile;
040: private String fContent;
041:
042: private String fSoapAction;
043:
044: public String getMethod() {
045: return fMethod;
046: }
047:
048: public String getUrl() {
049: return fUrl;
050: }
051:
052: /**
053: * Alternative to set the content of a SOAP message.
054: * @param txt the content
055: * @webtest.nested.parameter
056: * required="no"
057: * description="An alternative way to set the 'url' or the 'content' attribute.
058: * When the 'url' attribute is not specified the nested text is considered as the url value.
059: * Otherwise this is used to set the 'content' attribute for e.g. large content (properties get evaluated in this content)."
060: */
061: public void addText(final String txt) {
062: final String expandedText = getProject().replaceProperties(txt);
063: if (getUrl() == null) {
064: setUrl(expandedText);
065: } else {
066: setContent(expandedText);
067: }
068: }
069:
070: /**
071: * Sets the url.
072: *
073: * @param newUrl the relative or absolute url
074: * @webtest.parameter required="yes"
075: * description="A complete URL or the 'relative' part of an URL which will be appended to the 'static' parts created from the configuration information defined with the <config> step."
076: */
077: public void setUrl(final String newUrl) {
078: fUrl = newUrl;
079: }
080:
081: /**
082: * Sets the HTTP Method.
083: *
084: * @param method
085: * @webtest.parameter
086: * required="no"
087: * default="GET"
088: * description="Sets the HTTP Method, i.e. whether the invoke is a GET or POST."
089: */
090: public void setMethod(final String method) {
091: fMethod = method;
092: }
093:
094: public File getContentFile() {
095: return fContentFile;
096: }
097:
098: /**
099: * Sets the filename of the request contents.
100: *
101: * @param contentFile
102: * @webtest.parameter
103: * required="no"
104: * description="Filename to extract request contents from.
105: * Ignored for GET requests.
106: * Only one of <em>content</em> and <em>contentFile</em> should be set."
107: */
108: public void setContentFile(final File contentFile) {
109: fContentFile = contentFile;
110: }
111:
112: public String getContent() {
113: return fContent;
114: }
115:
116: /**
117: * Sets the request content.
118: *
119: * @param content
120: * @webtest.parameter
121: * required="no"
122: * description="Form data in 'application/x-www-form-urlencoded' format, which will be sent in the body of a POST request. Ignored for GET requests. Only one of <em>content</em> and <em>contentFile</em> should be set."
123: */
124: public void setContent(final String content) {
125: fContent = content;
126: }
127:
128: public String getSoapAction() {
129: return fSoapAction;
130: }
131:
132: /**
133: * Sets the SOAP action.
134: *
135: * @param soapAction
136: * @webtest.parameter
137: * required="no"
138: * description="If the HTTP method is POST and is in fact a SOAP POST request, this allows the SOAP Action header to be set. Ignored for GETs."
139: */
140: public void setSoapAction(final String soapAction) {
141: fSoapAction = soapAction;
142: }
143:
144: protected void verifyParameters() {
145: super .verifyParameters();
146: nullParamCheck(getUrl(), "url");
147: paramCheck(getContent() != null && getContentFile() != null,
148: "Only one of 'content' and 'contentFile' must be set.");
149: paramCheck("POST".equals(getMethod()) && getContent() == null
150: && getContentFile() == null,
151: "One of 'content' or 'contentFile' must be set for POST.");
152: }
153:
154: protected Page findTarget() throws IOException, SAXException {
155: if ("POST".equals(getMethod())) {
156: return findTargetByPost();
157: }
158: fCompleteUrl = getContext().getConfig().getUrlForPage(getUrl());
159: final WebRequestSettings settings = new WebRequestSettings(
160: new URL(fCompleteUrl));
161: settings.setSubmitMethod(SubmitMethod.getInstance(getMethod())); // ready for next HtmlUnit release that will accept HEAD, DELETE, ...
162: return getResponse(settings);
163: }
164:
165: private Page findTargetByPost() throws IOException, SAXException {
166: String url = getContext().getConfig().getUrlForPage(getUrl());
167: WebRequestSettings settings = new WebRequestSettings(new URL(
168: url), SubmitMethod.POST);
169:
170: // get default encoding
171: final String charset = System.getProperty("file.encoding");
172:
173: final Map headers = new HashMap();
174: if (!StringUtils.isEmpty(fSoapAction)) {
175: headers.put("Content-type", "text/xml; charset=" + charset);
176: headers.put("SOAPAction", fSoapAction);
177: } else {
178: // TODO: is this the correct Content-type for non-SOAP posts?
179: headers.put("Content-type",
180: "application/x-www-form-urlencoded");
181: }
182: settings.setAdditionalHeaders(headers);
183: final String content;
184: if (getContent() != null) {
185: content = getContent();
186: } else {
187: content = FileUtil.readFileToString(getContentFile(), this );
188: }
189: settings.setRequestBody(content);
190: settings.setCharset(charset);
191: return getResponse(settings);
192: }
193:
194: protected String getLogMessageForTarget() {
195: return "by URL: " + getUrl();
196: }
197:
198: /**
199: * Adds the computed url if only a part was specified (nice to have in reports)
200: */
201: protected void addComputedParameters(final Map map) {
202: super .addComputedParameters(map);
203: if (!StringUtils.equals(fUrl, fCompleteUrl))
204: MapUtil.putIfNotNull(map, "-> complete url", fCompleteUrl);
205: }
206: }
|