Michael Morris wrote:
> Hi everyone,
>
> I wonder if anyone has any ideas how to do this.
>
> I am testing a piece of software with which the client creates an entity
> (i.e a new record in a database) and then edits it. The entity has an id
> which is sent back to the client as a hidden parameter. This id then needs
> to be included as one of the parameters sent to the server in order to
> access the editing page. My question is, how/if I can use JMeter to pick up
> the id and feed it back into the next controller to access the edit page.
>
> I hope this makes some sense.
>
> Michael
>
> --
> To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
I once had the same problem. I remember updating a lot of jmeter files an
finally i got it working. (hidden fields are passed on from response to
request)
I remember having some trouble using a 'normal' modification manager, and i
created my own config element instead.
That' why i also had to update the HTTPSampler.
Anyway, i attached some files i updated in order to get it working.
/*
* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache JMeter" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache JMeter", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.jmeter.protocol.http.parser;
import java.net.*;
import java.util.*;
import org.apache.jmeter.config.*;
import org.apache.jmeter.protocol.http.config.UrlConfig;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.config.Argument;
import junit.framework.TestCase;
import org.apache.oro.text.regex.*;
import org.apache.log4j.*;
import org.w3c.tidy.Tidy;
import java.io.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/************************************************************
* Title: Description: Copyright: Copyright (c) 2001 Company:
*
*@author Michael Stover
*@created June 14, 2001
*@version 1.0
***********************************************************/
public class HtmlParser implements Serializable
{
private int compilerOptions = Perl5Compiler.CASE_INSENSITIVE_MASK |
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK;
protected static Category catClass =
Category.getInstance(HtmlParser.class.getName());
protected static String utfEncodingName;
private transient static Perl5Compiler compiler = new Perl5Compiler();
private transient static Perl5Matcher matcher = new Perl5Matcher();
/************************************************************
* Constructor for the HtmlParser object
***********************************************************/
public HtmlParser()
{
}
/************************************************************
* !ToDoo (Method description)
*
*@param newLink !ToDo (Parameter description)
*@param config !ToDo (Parameter description)
*@return !ToDo (Return description)
*@exception MalformedPatternException !ToDo (Exception description)
***********************************************************/
public static synchronized boolean isAnchorMatched(UrlConfig newLink,
UrlConfig config) throws MalformedPatternException
{
boolean ok = true;
Iterator iter = config.getArguments().iterator();
String query = newLink.getQueryString();
if (query == null && config.getArguments().getArgumentCount() > 0)
{
return false;
}
while (iter.hasNext())
{
Argument item = (Argument)iter.next();
if (!(ok = ok && matcher.contains(query,
compiler.compile(item.getName() + "=" + item.getValue()))))
{
return false;
}
}
if (!(ok = ok && matcher.matches(newLink.getDomain(),
compiler.compile(config.getDomain()))))
{
return false;
}
if (!(ok = ok && matcher.matches(newLink.getPath(),
compiler.compile("[/]*"+config.getPath()))))
{
return false;
}
if (!(ok = ok && matcher.matches(newLink.getProtocol(),
compiler.compile(config.getProtocol()))))
{
return false;
}
return ok;
}
public static synchronized boolean isArgumentMatched(Argument arg,Argument
patternArg) throws MalformedPatternException
{
return
matcher.matches(arg.getName(),compiler.compile(patternArg.getName())) &&
matcher.matches((String)arg.getValue(),compiler.compile((String)patternArg.getValue()));
}
/************************************************************
* Returns <code>tidy</code> as HTML parser
*
*@return a <code>tidy</code> HTML parser
***********************************************************/
public static Tidy getParser()
{
catClass.debug("Start : getParser1");
Tidy tidy = new Tidy();
tidy.setCharEncoding(org.w3c.tidy.Configuration.UTF8);
tidy.setQuiet(true);
tidy.setShowWarnings(false);
if (catClass.isDebugEnabled())
{
catClass.debug("getParser1 : tidy parser created - " + tidy);
}
catClass.debug("End : getParser1");
return tidy;
}
/************************************************************
* Returns a node representing a whole xml given an xml document
*
*@param text an xml document
*@return a node representing a whole xml
*@exception SAXException !ToDo (Exception description)
***********************************************************/
public static Node getDOM(String text) throws SAXException
{
catClass.debug("Start : getDOM1");
try
{
Node node = getParser().parseDOM(new
ByteArrayInputStream(text.getBytes(getUTFEncodingName())), null);
if (catClass.isDebugEnabled())
{
catClass.debug("node : " + node);
}
catClass.debug("End : getDOM1");
return node;
}
catch (UnsupportedEncodingException e)
{
catClass.error("getDOM1 : Unsupported encoding exception - " +
e);
catClass.debug("End : getDOM1");
throw new RuntimeException("UTF-8 encoding failed");
}
}
/************************************************************
* Returns the encoding type which is different for different jdks even though
* the mean the same thing i.e. UTF8 or UTF-8
*
*@return either UTF8 or UTF-8 depending on the jdk version
***********************************************************/
public static String getUTFEncodingName()
{
catClass.debug("Start : getUTFEncodingName1");
if (utfEncodingName == null)
{
String versionNum = System.getProperty("java.version");
if (catClass.isDebugEnabled())
{
catClass.debug("getUTFEncodingName1 : versionNum - " +
versionNum);
}
if (versionNum.startsWith("1.1"))
{
utfEncodingName = "UTF8";
}
else
{
utfEncodingName = "UTF-8";
}
}
if (catClass.isDebugEnabled())
{
catClass.debug("getUTFEncodingName1 : Returning
utfEncodingName - " +
utfEncodingName);
}
catClass.debug("End : getUTFEncodingName1");
return utfEncodingName;
}
/************************************************************
* !ToDo (Method description)
*
*@return !ToDo (Return description)
***********************************************************/
public static Document createEmptyDoc()
{
return new Tidy().createEmptyDocument();
}
/************************************************************
* Create a new URL based on an HREF string plus a contextual URL object.
* Given that an HREF string might be of three possible forms, some processing
* is required.
*
*@param parsedUrlString !ToDo (Parameter description)
*@param context !ToDo (Parameter description)
*@return !ToDo (Return description)
*@exception MalformedURLException !ToDo (Exception description)
***********************************************************/
public static UrlConfig createUrlFromAnchor(String parsedUrlString, URL
context) throws MalformedURLException
{
UrlConfig url = new UrlConfig();
url.setDomain(context.getHost());
url.setProtocol(context.getProtocol());
url.setPort(context.getPort());
int queryStarts = parsedUrlString.indexOf("?");
if (queryStarts == -1)
{
queryStarts = parsedUrlString.length();
}
if (parsedUrlString.startsWith("/"))
{
url.setPath(parsedUrlString.substring(0, queryStarts));
}
else if (parsedUrlString.startsWith(".."))
{
url.setPath(context.getPath().substring(0,
context.getPath().substring(0,
context.getPath().lastIndexOf("/")).lastIndexOf("/")) +
parsedUrlString.substring(2, queryStarts));
}
else if (!parsedUrlString.toLowerCase().startsWith("http"))
{
url.setPath(context.getPath().substring(0,
context.getPath().lastIndexOf("/")) +
"/" + parsedUrlString.substring(0,
queryStarts));
}
else
{
URL u = new URL(parsedUrlString);
url.setPath(u.getPath());
url.setDomain(u.getHost());
url.setProtocol(u.getProtocol());
url.setPort(u.getPort());
}
if (queryStarts < parsedUrlString.length())
{
url.parseArguments(parsedUrlString.substring(queryStarts + 1));
}
return url;
}
/************************************************************
* !ToDo (Method description)
*
*@param formNode !ToDo (Parameter description)
*@param context !ToDo (Parameter description)
*@return !ToDo (Return description)
*@exception MalformedURLException !ToDo (Exception description)
***********************************************************/
public static UrlConfig createURLFromForm(Node formNode, URL context) throws
MalformedURLException
{
String selectName = null;
NodeList childNodes = formNode.getChildNodes();
NamedNodeMap atts = formNode.getAttributes();
String action = "";
if (atts.getNamedItem("action") != null){
action = atts.getNamedItem("action").getNodeValue();
} else{
action = context.getFile();
}
UrlConfig url = createUrlFromAnchor(action, context);
recurseForm(childNodes, url, selectName);
return url;
}
/************************************************************
* !ToDo (Class description)
*
*@author $Author: mstover1 $
*@created $Date: 2001/09/24 12:02:27 $
*@version $Revision: 1.13 $
***********************************************************/
public static class Test extends TestCase
{
private static Category catClass =
Category.getInstance(Test.class.getName());
/************************************************************
* !ToDo (Constructor description)
*
*@param name !ToDo (Parameter description)
***********************************************************/
public Test(String name)
{
super(name);
}
/************************************************************
* !ToDo
***********************************************************/
public void testGetUTFEncodingName()
{
catClass.debug("Start : testGetUTFEncodingName1");
String javaVersion = System.getProperty("java.version");
utfEncodingName = null;
System.setProperty("java.version", "1.1");
assertEquals("UTF8", HtmlParser.getUTFEncodingName());
// need to clear utfEncodingName variable first 'cos
// getUTFEncodingName checks to see if it's null
utfEncodingName = null;
System.setProperty("java.version", "1.2");
assertEquals("UTF-8", HtmlParser.getUTFEncodingName());
System.setProperty("java.version", javaVersion);
catClass.debug("End : testGetUTFEncodingName1");
}
/************************************************************
* !ToDo
***********************************************************/
protected void setUp()
{
}
}
private static void recurseForm(NodeList childNodes, UrlConfig url, String
selectName)
{
for (int x = 0; x < childNodes.getLength(); x++)
{
Node tempNode = childNodes.item(x);
NamedNodeMap nodeAtts = tempNode.getAttributes();
String tag = tempNode.getNodeName();
try
{
if (tag.equalsIgnoreCase("input"))
{
url.addArgument(getAttributeValue(nodeAtts,"name"),
getAttributeValue(nodeAtts,"value"));
}
else if (tag.equalsIgnoreCase("textarea"))
{
url.addArgument(getAttributeValue(nodeAtts,"name"),
tempNode.getFirstChild().getNodeValue());
}
else if (tag.equalsIgnoreCase("select"))
{
selectName =
getAttributeValue(nodeAtts,"name");
}
else if (tag.equalsIgnoreCase("option"))
{
String value =
getAttributeValue(nodeAtts,"value");
if (value == null || value.equals(""))
{
value =
tempNode.getFirstChild().getNodeValue();
}
url.addArgument(selectName, value);
}
}
catch (Exception ex) {
System.out.println("Some bad HTML
"+printNode(tempNode));
}
recurseForm(tempNode.getChildNodes(),url,selectName);
}
}
public static Arguments findHiddenFormAttributes(Document html){
NodeList nodeList = html.getElementsByTagName("form");
Arguments args = new Arguments();
for(int x = 0;x < nodeList.getLength();x++){
Node tempNode = nodeList.item(x);
Node form = tempNode.cloneNode(true);
findHiddenFormAttributes(form.getChildNodes(), args);
}
return args;
}
/**
* Usefull for silverstream
*/
private static void findHiddenFormAttributes(NodeList childNodes, Arguments res){
for (int x = 0; x < childNodes.getLength(); x++){
Node tempNode = childNodes.item(x);
String tag = tempNode.getNodeName();
try{
if (tag.equalsIgnoreCase("input")){
NamedNodeMap nodeAtts = tempNode.getAttributes();
String type = getAttributeValue(nodeAtts,"type");
if ((type != null) && type.equalsIgnoreCase("hidden")){
res.addArgument(getAttributeValue(nodeAtts,"name"),getAttributeValue(nodeAtts,"value"));
}
}
}catch (Exception ex) {
System.out.println("Some bad HTML "+printNode(tempNode));
}
findHiddenFormAttributes(tempNode.getChildNodes(),res);
}
}
private static String getAttributeValue(NamedNodeMap att,String attName)
{
try {
return att.getNamedItem(attName).getNodeValue();
}
catch (Exception ex)
{
return "";
}
}
private static String printNode(Node node)
{
StringBuffer buf = new StringBuffer();
buf.append("<");
buf.append(node.getNodeName());
NamedNodeMap atts = node.getAttributes();
for(int x = 0;x < atts.getLength();x++)
{
buf.append(" ");
buf.append(atts.item(x).getNodeName());
buf.append("=\"");
buf.append(atts.item(x).getNodeValue());
buf.append("\"");
}
buf.append(">");
return buf.toString();
}
}
package org.apache.jmeter.protocol.http.control;
import java.io.*;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import org.apache.jmeter.config.*;
import org.apache.jmeter.gui.JMeterComponentModel;
import org.apache.jmeter.protocol.http.save.*;
import org.apache.jmeter.protocol.http.config.*;
import org.apache.jmeter.protocol.http.parser.*;
import org.apache.jmeter.protocol.http.sampler.*;
import org.apache.jmeter.save.Saveable;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.net.*;
import org.apache.jmeter.samplers.*;
/**
* Kind of reponse based modifier, but better.
* A response based modifier does not save correctly.
*
* @author Koen Janssens
* @version $Revision: 1.12 $ $Date: 2001/08/30 17:19:02 $
*/
import com.sssw.shr.aghttp.AgoHttpURLConnection;
public class HiddenFieldManager extends AbstractConfigElement implements
JMeterComponentModel,Saveable,Serializable
{
private SampleResult currentResult;
private static List addableList = new LinkedList();
public static class AgHttpURLConnectionWrapper implements
HTTPSampler.URLConnectionWrapper{
public void setFollowRedirects(URLConnection con, boolean r){
if (con instanceof AgoHttpURLConnection){
((AgoHttpURLConnection)con).setFollowRedirects(r);
}
}
public void setRequestMethod(URLConnection con, String method) throws
ProtocolException{
if (con instanceof AgoHttpURLConnection){
((AgoHttpURLConnection)con).setRequestMethod(method);
}
}
public int getResponseCode(URLConnection con) throws IOException{
if (con instanceof AgoHttpURLConnection){
return ((AgoHttpURLConnection)con).getResponseCode();
}
return -1;
}
public String getResponseMessage(URLConnection con) throws IOException{
if (con instanceof AgoHttpURLConnection){
return ((AgoHttpURLConnection)con).getResponseMessage();
}
return null;
}
}
public HiddenFieldManager () {
// com.sssw.rt.util.AgRuntime.init(null);
// HTTPSampler.WRAPPER=new AgHttpURLConnectionWrapper();
}
public Object clone()
{
HiddenFieldManager ck = new HiddenFieldManager();
ck.currentResult = currentResult;
if (getName() != null){
ck.setName(getName());
}
return ck;
}
public boolean expectsModification()
{
return true;
}
public Collection getAddList()
{
return addableList;
}
public boolean isEditable()
{
return true;
}
/************************************************************
* This allows config elements to combine and give a "layered" effect. for
* example, say there are two HTTPConfigElements, which have properties for
* domain, path, method, and parameters. If element A has everything filled
* in, but null for domain, and element B is added, which has only domain
* filled in, then after adding B to A, A will have the domain from B. If A
* already had a domain, then the correct behavior is for A to ignore the
* addition of element B.
*
*@param config !ToDo
***********************************************************/
public void addConfigElement(ConfigElement config)
{
/*if (config instanceof CookieManager)
{
this.cookies.addAll(((CookieManager)config).getCookies());
}*/
}
public void setCurrentResult(SampleResult res){
currentResult = res;
}
public boolean modifyEntry(Entry entry){
SampleResult result = currentResult;
try{
if (result == null) return false;
UrlConfig entryConfig =
(UrlConfig)entry.getConfigElement(UrlConfig.class);
if (entryConfig == null) return false;
if (entryConfig.getMethod().equals(UrlConfig.GET)) return false;
String url = entryConfig.getUrl().toString();
int i = 0;
if ((i = url.indexOf("?")) > 0) url = url.substring(0, i);
String s = (String)result.getValue(SampleResult.SAMPLE_LABEL);
if ((i = s.indexOf(",")) > 0) s = s.substring(0, i);
if ((i = s.indexOf("?")) > 0) s = s.substring(0, i);
if (!url.equals(s)) return false;
List potentialLinks = new ArrayList();
Document html;
String responseText =
(String)result.getValue(SampleResult.TEXT_RESPONSE);
try{
html = (Document)HtmlParser.getDOM(responseText);
}
catch (SAXException e){
e.printStackTrace();
return false;
}
Arguments args = HtmlParser.findHiddenFormAttributes(html);
System.out.println("Following hidden field will be posted " + args);
boolean modified = false;
for (i = 0; i < args.getArgumentCount();i++){
Argument arg=args.getArgument(i);
entryConfig.addArgument(arg.getName(), arg.getValue().toString());
modified = true;
}
return modified;
}catch (Exception ex){
ex.printStackTrace();
}
return false;
}
public String getClassLabel()
{
return "Hidden Field Manager";
}
}
/*
* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache JMeter" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache JMeter", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.jmeter.protocol.http.sampler;
import java.io.*;
import java.net.*;
import java.security.Security;
import java.util.*;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.protocol.http.control.*;
import org.apache.jmeter.protocol.http.config.UrlConfig;
import org.apache.jmeter.config.*;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.HttpSampleResult;
import org.apache.jmeter.samplers.Entry;
import org.apache.log4j.*;
/**
* A sampler which understands all the parts necessary to read statistics about
* HTTP requests, including cookies and authentication.
*
*@author Michael Stover
*@created $Date: 2001/09/13 14:41:16 $
*@version $Revision: 1.27 $
*/
public class HTTPSampler implements Sampler
{
public static interface URLConnectionWrapper{
public void setFollowRedirects(URLConnection con, boolean r);
public void setRequestMethod(URLConnection con, String method) throws
ProtocolException;
public int getResponseCode(URLConnection con) throws IOException;
public String getResponseMessage(URLConnection con) throws IOException;
}
public static class HttpURLConnectionWrapper implements URLConnectionWrapper{
public void setFollowRedirects(URLConnection con, boolean r){
if (con instanceof HttpURLConnection){
((HttpURLConnection)con).setFollowRedirects(r);
}
}
public void setRequestMethod(URLConnection con, String method) throws
ProtocolException{
if (con instanceof HttpURLConnection){
((HttpURLConnection)con).setRequestMethod(method);
}
}
public int getResponseCode(URLConnection con) throws IOException{
if (con instanceof HttpURLConnection){
return ((HttpURLConnection)con).getResponseCode();
}
return -1;
}
public String getResponseMessage(URLConnection con) throws IOException{
if (con instanceof HttpURLConnection){
return ((HttpURLConnection)con).getResponseMessage();
}
return null;
}
}
public static URLConnectionWrapper WRAPPER = new HttpURLConnectionWrapper();
/**
* Description of the Field
*/
public final static String ARGUMENTS = "httpsampler.Arguments";
/**
* Description of the Field
*/
public final static String URL = "httpsampler.URL";
/**
* Description of the Field
*/
public final static String POST = "httpsampler.POST";
/**
* Description of the Field
*/
public final static String GET = "httpsampler.GET";
/**
* Description of the Field
*/
public final static String FILE_NAME = "httpsampler.FILE_NAME";
/**
* Description of the Field
*/
public final static String FILE_FIELD = "httpsampler.FILE_FIELD";
/**
* Description of the Field
*/
public final static String FILE_DATA = "httpsampler.FILE_DATA";
/**
* Description of the Field
*/
public final static String FILE_MIMETYPE = "httpsampler.FILE_MIMETYPE";
/**
* Description of the Field
*/
public final static String CONTENT_TYPE = "httpsampler.CONTENT_TYPE";
/**
* Description of the Field
*/
public final static String NORMAL_FORM = "normal_form";
/**
* Description of the Field
*/
public final static String MULTIPART_FORM = "multipart_form";
protected static String encoding = "iso-8859-1";
protected static final String NON_HTTP_RESPONSE_CODE =
"Non HTTP response code";
protected static final String NON_HTTP_RESPONSE_MESSAGE =
"Non HTTP response message";
private static Category catClass = Category.getInstance(
HTTPSampler.class.getName());
/**
* Constructor for the HTTPSampler object
*/
public HTTPSampler()
{
System.getProperties().list(System.out);
}
/**
* A convenience method to call <code>sample</code> with no redirection
*
* @param e <code>Entry</code> to be sampled
* @return results of the sampling
* @see
org.apache.jmeter.protocol.http.sampler.HTTPSampler.sample(org.apache.jmeter.samplers.Entry,
boolean)
*/
public SampleResult sample(Entry e)
{
return sample(e, false);
}
/**
* Send POST data from <code>Entry</code> to the open connection.
*
* @param connection <code>URLConnection</code> of where POST data should be
* sent
* @param url contains the query string for POST
* @exception IOException if an I/O exception occurs
*/
public void sendPostData(URLConnection connection, UrlConfig url)
throws IOException
{
//((HttpURLConnection) connection).setRequestMethod("POST");
WRAPPER.setRequestMethod(connection, "POST");
String postData = url.getQueryString();
connection.setRequestProperty("Content-length", "" +
postData.length());
connection.setRequestProperty("Content-type",
"application/x-www-form-urlencoded");
connection.setDoOutput(true);
PrintWriter out = new PrintWriter(connection.getOutputStream());
out.print(postData);
out.close();
}
/**
* Returns a <code>HttpURLConnection</code> with request method(GET or POST),
* headers, cookies, authorization properly set for the URL request
*
* @param u <code>URL</code> of the URL request
* @param url <code>UrlConfig</code> of the URL request
* @param e <code>Entry</code> from which all other info can
* be derived from e.g. cookies, header, authorization
* @return <code>HttpURLConnection</code> of the URL request
* @exception IOException if an I/O Exception occurs
*/
protected URLConnection setupConnection(URL u, UrlConfig url, Entry e) throws
IOException
{
URLConnection conn;
conn = u.openConnection();
// conn.setFollowRedirects(false);
// conn.setRequestMethod((String) url.getProperty(UrlConfig.METHOD));
WRAPPER.setFollowRedirects(conn, false);
WRAPPER.setRequestMethod(conn, (String)
url.getProperty(UrlConfig.METHOD));
setConnectionHeaders(conn, u, (HeaderManager)
e.getConfigElement(HeaderManager.class));
setConnectionCookie(conn, u, (CookieManager)
e.getConfigElement(CookieManager.class));
setConnectionAuthorization(conn, u, (AuthManager)
e.getConfigElement(AuthManager.class));
return conn;
}
/**
* Gets the UrlConfig attribute of the HTTPSampler object
*
* @param e Description of Parameter
* @return The UrlConfig value
*/
public UrlConfig getUrlConfig(Entry e)
{
UrlConfig urlConfig = (UrlConfig)e.getConfigElement(UrlConfig.class);
catClass.debug("getUrlConfig1 : Returning urlConfig - " + urlConfig);
return urlConfig;
}
/**
* This method will setup <code>HttpURLConnection</code> to handle post using
* <code>sendPostData</code> method if the URL request is actually a html form
* that needs to be posted
*
* @param redirected does <code>HttpURLConnection</code> allow
redirection
* @param url contains query string for POST
* @param conn <HttpURLConnection> of the URL request
* @exception IOException if
*/
protected void writeToStream(boolean redirected, UrlConfig url, URLConnection
conn) throws IOException
{
if (!redirected &&
url.getProperty(UrlConfig.METHOD).equals(UrlConfig.POST))
{
sendPostData(conn, url);
}
}
/*
* Uploading a file - put in separate sampler
* else if (contentType.equals(MULTIPART_FORM))
* {
*
* }
* }
*/
/**
* Extracts all the required cookies for that particular URL request and set
them
* in the <code>HttpURLConnection</code> passed in
*
* @param conn <code>HttpUrlConnection</code> which represents the
* URL request
* @param u <code>URL</code> of the URL request
* @param cookieManager the <code>CookieManager</code> containing all the
* cookies for this <code>UrlConfig</code>
*/
private void setConnectionCookie(URLConnection conn, URL u, CookieManager
cookieManager)
{
if (cookieManager != null)
{
String cookieHeader = cookieManager.getCookieHeaderForURL(u);
if (cookieHeader != null)
{
conn.setRequestProperty("Cookie", cookieHeader);
}
}
}
/**
* Extracts all the required headers for that particular URL request and set
them
* in the <code>HttpURLConnection</code> passed in
*
* @param conn <code>HttpUrlConnection</code> which represents the
* URL request
* @param u <code>URL</code> of the URL request
* @param headerManager the <code>HeaderManager</code> containing all the
* cookies for this <code>UrlConfig</code>
*/
private void setConnectionHeaders(URLConnection conn, URL u, HeaderManager
headerManager)
{
if (headerManager != null)
{
Collection headers = headerManager.getHeaders();
if (headers != null)
{
Iterator i = headers.iterator();
while (i.hasNext())
{
Header header = (Header) i.next();
conn.setRequestProperty(header.getName(),
header.getValue());
}
}
}
}
/**
* Extracts all the required authorization for that particular URL request and
set
* them in the <code>HttpURLConnection</code> passed in
*
* @param conn <code>HttpUrlConnection</code> which represents the
* URL request
* @param u <code>URL</code> of the URL request
* @param authManager the <code>AuthManager</code> containing all the
* cookies for this <code>UrlConfig</code>
*/
private void setConnectionAuthorization(URLConnection conn, URL u, AuthManager
authManager)
{
if (authManager != null)
{
String authHeader = authManager.getAuthHeaderForURL(u);
if (authHeader != null)
{
conn.setRequestProperty("Authorization", authHeader);
}
}
}
/**
* Get the response code of the URL connection and divide it by 100 thus
* returning 2(for 2xx response codes), 3(for 3xx reponse codes), etc
*
* @param conn <code>HttpURLConnection</code> of URL request
* @param res where all results of sampling will be stored
* @param time time when the URL request was first started
* @return HTTP response code divided by 100
*/
private int getErrorLevel(URLConnection conn, SampleResult res, long time)
throws IOException
{
int errorLevel = 2;
int responseCode = 0;
String message = null;
try
{
// responseCode = ((HttpURLConnection) conn).getResponseCode();
responseCode = WRAPPER.getResponseCode(conn);
errorLevel = responseCode / 100;
//message = ((HttpURLConnection) conn).getResponseMessage();
message = WRAPPER.getResponseMessage(conn);
res.putValue(this.RESPONSE_CODE,
String.valueOf(responseCode));
res.putValue(this.RESPONSE_MESSAGE,
message);
}
catch (Exception e2)
{
e2.printStackTrace();
res.putValue(SampleResult.TEXT_RESPONSE, e2.toString());
res.putValue(this.RESPONSE_CODE, e2.toString());
// NON_HTTP_RESPONSE_CODE);
res.putValue(this.RESPONSE_MESSAGE,
NON_HTTP_RESPONSE_MESSAGE);
res.setTime(System.currentTimeMillis() - time);
res.putValue(SampleResult.SUCCESS, new Boolean(false));
}
return errorLevel;
}
/**
* Follow redirection manually. Normally if the web server does a redirection
the
* intermediate page is not returned. Only the resultant page and the
response code
* for the page will be returned. With redirection turned off, the response
code of
* 3xx will be returned together with a "Location" header-value pair to
indicate
* that the "Location" value needs to be followed to get the resultant page.
*
* @param conn connection
* @param u
* @exception MalformedURLException if URL is not understood
*/
private void redirectUrl(URLConnection conn, URL u, UrlConfig urlConfig)
throws MalformedURLException
{
String loc = conn.getHeaderField("Location");
if (loc != null)
{
if (loc.indexOf("http") == -1)
{
String tempURL = u.toString();
if (loc.startsWith("/"))
{
int ind = tempURL.indexOf("//") + 2;
loc = tempURL.substring(0,
tempURL.indexOf("/", ind) + 1) + loc.substring(1);
}
else
{
loc = u.toString().substring(0,
u.toString().lastIndexOf('/')
+ 1) + loc;
}
}
}
URL newUrl = new URL(loc);
urlConfig.putProperty(UrlConfig.DOMAIN, newUrl.getHost());
urlConfig.putProperty(UrlConfig.PATH, newUrl.getFile());
}
/**
* Samples <code>Entry</code> passed in and stores the result in
* <code>SampleResult</code>
*
* @param e <code>Entry</code> to be sampled
* @param redirected whether redirection is turned on
* @return results of the sampling
*/
private SampleResult sample(Entry e, boolean redirected)
{
catClass.debug("Start : sample2");
HiddenFieldManager man = ((HiddenFieldManager)
e.getConfigElement(HiddenFieldManager.class));
if (man != null){
man.modifyEntry(e);
}
long time;
SampleResult res = new HttpSampleResult();
if (man != null){
man.setCurrentResult(res);
}
UrlConfig url = getUrlConfig(e);
URL u = null;
try
{
u = url.getUrl();
res.putValue(SampleResult.SAMPLE_LABEL, u.toString());
res.putValue(HTTPSampler.URL,u);
// specify the data to the result.
res.putValue(HttpSampleResult.DATA, url);
System.out.println("["+Thread.currentThread().getName()+"]
Sampling url: "+ u);
if(catClass.isDebugEnabled())
{
catClass.debug("sample2 : sampling url - " + u);
}
URLConnection conn = null;
try{
conn = setupConnection(u, url, e);
// System.out.println(conn.getClass().getName());
writeToStream(redirected, url, conn);
time = System.currentTimeMillis();
res.putValue(SampleResult.START_TIME,
String.valueOf(time));
conn.connect();
saveConnectionCookies(conn, u, (CookieManager)
e.getConfigElement(CookieManager.class));
int errorLevel = getErrorLevel(conn, res, time);
if (errorLevel == 2)
{
String ret = readResponse(conn);
time = System.currentTimeMillis() - time;
res.putValue(SampleResult.TEXT_RESPONSE, ret);
res.putValue(SampleResult.SUCCESS, new
Boolean(true));
getResponseHeaders(conn, res);
}
else if (errorLevel == 3)
{
redirectUrl(conn, u, url);
time = System.currentTimeMillis() - time;
res = sample(e, true);
time += res.getTime();
}
else
{
// Could not sample the URL
//time can be interesting even in case of error (eg
timeout)
time = System.currentTimeMillis() - time;
res.setTime(time);
System.out.println("URL = " + u);
// int responseCode = ((HttpURLConnection)
conn).getResponseCode();
// String responseMessage = ((HttpURLConnection)
conn).getResponseMessage();
int responseCode = WRAPPER.getResponseCode(conn);
String responseMessage =
WRAPPER.getResponseMessage(conn);
System.out.println(responseCode+"
"+responseMessage);
//throw new RuntimeException("Thread Stopped after
error");
//throw new IOException(responseMessage+"
"+responseCode);
}
res.setTime(time);
return res;
}finally{
//05/01/2001 Added to decrease amount of open TCP
connections.
if (conn != null){
// conn.disconnect();
}
}
}
catch (IOException ex)
{
ex.printStackTrace();
// res.putValue(this.RESPONSE_CODE,
// NON_HTTP_RESPONSE_CODE);
// res.putValue(this.RESPONSE_MESSAGE,
// NON_HTTP_RESPONSE_MESSAGE);
res.putValue(SampleResult.TEXT_RESPONSE, ex.toString());
res.putValue(SampleResult.SUCCESS, new Boolean(false));
}
catClass.debug("End : sample2");
return res;
}
/**
* From the <code>HttpURLConnection</code>, store all the "set-cookie" key-pair
* values in the cookieManager of the <code>UrlConfig</code>
*
* @param conn <code>HttpUrlConnection</code> which represents the
* URL request
* @param u <code>URL</code> of the URL request
* @param cookieManager the <code>CookieManager</code> containing all the
* cookies for this <code>UrlConfig</code>
*/
private void saveConnectionCookies(URLConnection conn, URL u, CookieManager
cookieManager)
{
if (cookieManager != null)
{
for (int i = 1; conn.getHeaderFieldKey(i) != null; i++)
{
if
(conn.getHeaderFieldKey(i).equalsIgnoreCase("set-cookie"))
{
cookieManager.addCookieFromHeader(conn.getHeaderField(i), u);
}
}
}
}
/**
* Reads the response from the URL connection
*
* @param conn URL from which to read response
* @return response in <code>String</code>
* @exception IOException if an I/O exception occurs
*/
protected String readResponse(URLConnection conn) throws IOException
{
byte[] buffer = new byte[4096];
BufferedInputStream in = new
BufferedInputStream(conn.getInputStream());
java.io.ByteArrayOutputStream w = new ByteArrayOutputStream();
int x = 0;
while ((x = in.read(buffer)) != -1)
{
w.write(buffer, 0, x);
}
in.close();
return w.toString();
}
static
{
if (!JMeterUtils.getPropDefault("ssl.provider", "none").equals("none")
&&
!JMeterUtils.getPropDefault("ssl.pkgs","none").equals("none"))
{
try
{
Class c =
Class.forName("org.apache.jmeter.protocol.http.util.SSLStaticProvider");
c.newInstance();
}
catch (Exception ex)
{
System.err.println("Could not find SSL Provider");
ex.printStackTrace();
}
}
}
/**
* Gets the ResponseHeaders from the URLConnection, save them to the
SampleResults
* object.
*
*@param conn connection from which the headers are read
*@param res where the headers read are stored
*/
protected void getResponseHeaders(URLConnection conn, SampleResult res)
{
HashMap hValues = new HashMap(20);
for (int i = 1; conn.getHeaderFieldKey(i) != null; i++)
{
hValues.put(conn.getHeaderFieldKey(i), conn.getHeaderField(i));
}
res.putValue(Sampler.HEADER, hValues);
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>