|
JMeter example source code file (CookieManager.java)
The JMeter CookieManager.java source code
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// For unit tests @see TestCookieManager
package org.apache.jmeter.protocol.http.control;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
import org.apache.commons.httpclient.cookie.MalformedCookieException;
import org.apache.jmeter.config.ConfigTestElement;
import org.apache.jmeter.engine.event.LoopIterationEvent;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
import org.apache.jmeter.testelement.TestListener;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
/**
* This class provides an interface to the netscape cookies file to pass cookies
* along with a request.
*
* Now uses Commons HttpClient parsing and matching code (since 2.1.2)
*
*/
public class CookieManager extends ConfigTestElement implements TestListener, Serializable {
private static final long serialVersionUID = 233L;
private static final Logger log = LoggingManager.getLoggerForClass();
//++ JMX tag values
private static final String CLEAR = "CookieManager.clearEachIteration";// $NON-NLS-1$
private static final String COOKIES = "CookieManager.cookies";// $NON-NLS-1$
private static final String POLICY = "CookieManager.policy"; //$NON-NLS-1$
//-- JMX tag values
private static final String TAB = "\t"; //$NON-NLS-1$
// See bug 33796
private static final boolean DELETE_NULL_COOKIES =
JMeterUtils.getPropDefault("CookieManager.delete_null_cookies", true);// $NON-NLS-1$
// See bug 28715
private static final boolean ALLOW_VARIABLE_COOKIES
= JMeterUtils.getPropDefault("CookieManager.allow_variable_cookies", true);// $NON-NLS-1$
private static final String COOKIE_NAME_PREFIX =
JMeterUtils.getPropDefault("CookieManager.name.prefix", "COOKIE_").trim();// $NON-NLS-1$ $NON-NLS-2$
private static final boolean SAVE_COOKIES =
JMeterUtils.getPropDefault("CookieManager.save.cookies", false);// $NON-NLS-1$
private static final boolean CHECK_COOKIES =
JMeterUtils.getPropDefault("CookieManager.check.cookies", true);// $NON-NLS-1$
private transient CookieSpec cookieSpec;
private transient CollectionProperty initialCookies;
public static final String DEFAULT_POLICY = CookiePolicy.BROWSER_COMPATIBILITY;
public CookieManager() {
clearCookies(); // Ensure that there is always a collection available
}
// ensure that the initial cookies are copied to the per-thread instances
/** {@inheritDoc} */
@Override
public Object clone(){
CookieManager clone = (CookieManager) super.clone();
clone.initialCookies = initialCookies;
clone.cookieSpec = cookieSpec;
return clone;
}
public String getPolicy() {
return getPropertyAsString(POLICY, DEFAULT_POLICY);
}
public void setCookiePolicy(String policy){
setProperty(POLICY, policy, DEFAULT_POLICY);
}
public CollectionProperty getCookies() {
return (CollectionProperty) getProperty(COOKIES);
}
public int getCookieCount() {// Used by GUI
return getCookies().size();
}
public boolean getClearEachIteration() {
return getPropertyAsBoolean(CLEAR);
}
public void setClearEachIteration(boolean clear) {
setProperty(new BooleanProperty(CLEAR, clear));
}
/**
* Save the static cookie data to a file.
* Cookies are only taken from the GUI - runtime cookies are not included.
*/
public void save(String authFile) throws IOException {
File file = new File(authFile);
if (!file.isAbsolute()) {
file = new File(System.getProperty("user.dir") // $NON-NLS-1$
+ File.separator + authFile);
}
PrintWriter writer = new PrintWriter(new FileWriter(file));
writer.println("# JMeter generated Cookie file");// $NON-NLS-1$
PropertyIterator cookies = getCookies().iterator();
long now = System.currentTimeMillis();
while (cookies.hasNext()) {
Cookie cook = (Cookie) cookies.next().getObjectValue();
final long expiresMillis = cook.getExpiresMillis();
if (expiresMillis == 0 || expiresMillis > now) { // only save unexpired cookies
writer.println(cookieToString(cook));
}
}
writer.flush();
writer.close();
}
/**
* Add cookie data from a file.
*/
public void addFile(String cookieFile) throws IOException {
File file = new File(cookieFile);
if (!file.isAbsolute()) {
file = new File(System.getProperty("user.dir") // $NON-NLS-1$
+ File.separator + cookieFile);
}
BufferedReader reader = null;
if (file.canRead()) {
reader = new BufferedReader(new FileReader(file));
} else {
throw new IOException("The file you specified cannot be read.");
}
// N.B. this must agree with the save() and cookieToString() methods
String line;
try {
final CollectionProperty cookies = getCookies();
while ((line = reader.readLine()) != null) {
try {
if (line.startsWith("#") || line.trim().length() == 0) {//$NON-NLS-1$
continue;
}
String[] st = JOrphanUtils.split(line, TAB, false);
final int _domain = 0;
//final int _ignored = 1;
final int _path = 2;
final int _secure = 3;
final int _expires = 4;
final int _name = 5;
final int _value = 6;
final int _fields = 7;
if (st.length!=_fields) {
throw new IOException("Expected "+_fields+" fields, found "+st.length+" in "+line);
}
if (st[_path].length()==0) {
st[_path] = "/"; //$NON-NLS-1$
}
boolean secure = Boolean.valueOf(st[_secure]).booleanValue();
long expires = new Long(st[_expires]).longValue();
if (expires==Long.MAX_VALUE) {
expires=0;
}
//long max was used to represent a non-expiring cookie, but that caused problems
Cookie cookie = new Cookie(st[_name], st[_value], st[_domain], st[_path], secure, expires);
cookies.addItem(cookie);
} catch (NumberFormatException e) {
throw new IOException("Error parsing cookie line\n\t'" + line + "'\n\t" + e);
}
}
} finally {
reader.close();
}
}
private String cookieToString(Cookie c){
StringBuilder sb=new StringBuilder(80);
sb.append(c.getDomain());
//flag - if all machines within a given domain can access the variable.
//(from http://www.cookiecentral.com/faq/ 3.5)
sb.append(TAB).append("TRUE");
sb.append(TAB).append(c.getPath());
sb.append(TAB).append(JOrphanUtils.booleanToSTRING(c.getSecure()));
sb.append(TAB).append(c.getExpires());
sb.append(TAB).append(c.getName());
sb.append(TAB).append(c.getValue());
return sb.toString();
}
/** {@inheritDoc} */
@Override
public void recoverRunningVersion() {
// do nothing, the cookie manager has to accept changes.
}
/** {@inheritDoc} */
@Override
public void setRunningVersion(boolean running) {
// do nothing, the cookie manager has to accept changes.
}
/**
* Add a cookie.
*/
public void add(Cookie c) {
String cv = c.getValue();
String cn = c.getName();
removeMatchingCookies(c); // Can't have two matching cookies
if (DELETE_NULL_COOKIES && (null == cv || cv.length()==0)) {
if (log.isDebugEnabled()) {
log.debug("Dropping cookie with null value " + c.toString());
}
} else {
if (log.isDebugEnabled()) {
log.debug("Add cookie to store " + c.toString());
}
getCookies().addItem(c);
if (SAVE_COOKIES) {
JMeterContext context = getThreadContext();
if (context.isSamplingStarted()) {
context.getVariables().put(COOKIE_NAME_PREFIX+cn, cv);
}
}
}
}
/** {@inheritDoc} */
@Override
public void clear(){
super.clear();
clearCookies(); // ensure data is set up OK initially
}
/*
* Remove all the cookies.
*/
private void clearCookies() {
log.debug("Clear all cookies from store");
setProperty(new CollectionProperty(COOKIES, new ArrayList<Object>()));
}
/**
* Remove a cookie.
*/
public void remove(int index) {// TODO not used by GUI
getCookies().remove(index);
}
/**
* Return the cookie at index i.
*/
public Cookie get(int i) {// Only used by GUI
return (Cookie) getCookies().get(i).getObjectValue();
}
/*
* Create an HttpClient cookie from a JMeter cookie
*/
private org.apache.commons.httpclient.Cookie makeCookie(Cookie jmc){
long exp = jmc.getExpiresMillis();
org.apache.commons.httpclient.Cookie ret=
new org.apache.commons.httpclient.Cookie(
jmc.getDomain(),
jmc.getName(),
jmc.getValue(),
jmc.getPath(),
exp > 0 ? new Date(exp) : null, // use null for no expiry
jmc.getSecure()
);
ret.setPathAttributeSpecified(jmc.isPathSpecified());
ret.setDomainAttributeSpecified(jmc.isDomainSpecified());
ret.setVersion(jmc.getVersion());
return ret;
}
/**
* Get array of valid HttpClient cookies for the URL
*
* @param url the target URL
* @return array of HttpClient cookies
*
*/
public org.apache.commons.httpclient.Cookie[] getCookiesForUrl(URL url){
CollectionProperty jar=getCookies();
org.apache.commons.httpclient.Cookie cookies[]=
new org.apache.commons.httpclient.Cookie[jar.size()];
int i=0;
for (PropertyIterator iter = getCookies().iterator(); iter.hasNext();) {
Cookie jmcookie = (Cookie) iter.next().getObjectValue();
// Set to running version, to allow function evaluation for the cookie values (bug 28715)
if (ALLOW_VARIABLE_COOKIES) {
jmcookie.setRunningVersion(true);
}
cookies[i++] = makeCookie(jmcookie);
if (ALLOW_VARIABLE_COOKIES) {
jmcookie.setRunningVersion(false);
}
}
String host = url.getHost();
String protocol = url.getProtocol();
int port= HTTPSamplerBase.getDefaultPort(protocol,url.getPort());
String path = url.getPath();
boolean secure = HTTPSamplerBase.isSecure(protocol);
return cookieSpec.match(host, port, path, secure, cookies);
}
/**
* Find cookies applicable to the given URL and build the Cookie header from
* them.
*
* @param url
* URL of the request to which the returned header will be added.
* @return the value string for the cookie header (goes after "Cookie: ").
*/
public String getCookieHeaderForURL(URL url) {
org.apache.commons.httpclient.Cookie[] c = getCookiesForUrl(url);
int count = c.length;
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled){
log.debug("Found "+count+" cookies for "+url.toExternalForm());
}
if (count <=0){
return null;
}
String hdr=cookieSpec.formatCookieHeader(c).getValue();
if (debugEnabled){
log.debug("Cookie: "+hdr);
}
return hdr;
}
public void addCookieFromHeader(String cookieHeader, URL url){
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
log.debug("Received Cookie: " + cookieHeader + " From: " + url.toExternalForm());
}
String protocol = url.getProtocol();
String host = url.getHost();
int port= HTTPSamplerBase.getDefaultPort(protocol,url.getPort());
String path = url.getPath();
boolean isSecure=HTTPSamplerBase.isSecure(protocol);
org.apache.commons.httpclient.Cookie[] cookies= null;
try {
cookies = cookieSpec.parse(host, port, path, isSecure, cookieHeader);
} catch (MalformedCookieException e) {
log.warn(cookieHeader+e.getLocalizedMessage());
} catch (IllegalArgumentException e) {
log.warn(cookieHeader+e.getLocalizedMessage());
}
if (cookies == null) {
return;
}
for(int i=0;i<cookies.length;i++){
org.apache.commons.httpclient.Cookie cookie = cookies[i];
try {
if (CHECK_COOKIES) {
cookieSpec.validate(host, port, path, isSecure, cookie);
}
Date expiryDate = cookie.getExpiryDate();
long exp = 0;
if (expiryDate!= null) {
exp=expiryDate.getTime();
}
Cookie newCookie = new Cookie(
cookie.getName(),
cookie.getValue(),
cookie.getDomain(),
cookie.getPath(),
cookie.getSecure(),
exp / 1000,
cookie.isPathAttributeSpecified(),
cookie.isDomainAttributeSpecified()
);
// Store session cookies as well as unexpired ones
if (exp == 0 || exp >= System.currentTimeMillis()) {
newCookie.setVersion(cookie.getVersion());
add(newCookie); // Has its own debug log; removes matching cookies
} else {
removeMatchingCookies(newCookie);
if (debugEnabled){
log.debug("Dropping expired Cookie: "+newCookie.toString());
}
}
} catch (MalformedCookieException e) { // This means the cookie was wrong for the URL
log.debug("Not storing invalid cookie: <"+cookieHeader+"> for URL "+url+" ("+e.getLocalizedMessage()+")");
} catch (IllegalArgumentException e) {
log.warn(cookieHeader+e.getLocalizedMessage());
}
}
}
/**
* Check if cookies match, i.e. name, path and domain are equal.
* <br/>
* TODO - should we compare secure too?
* @param a
* @param b
* @return true if cookies match
*/
private boolean match(Cookie a, Cookie b){
return
a.getName().equals(b.getName())
&&
a.getPath().equals(b.getPath())
&&
a.getDomain().equals(b.getDomain());
}
private void removeMatchingCookies(Cookie newCookie){
// Scan for any matching cookies
PropertyIterator iter = getCookies().iterator();
while (iter.hasNext()) {
Cookie cookie = (Cookie) iter.next().getObjectValue();
if (cookie == null) {// TODO is this possible?
continue;
}
if (match(cookie,newCookie)) {
if (log.isDebugEnabled()) {
log.debug("New Cookie = " + newCookie.toString()
+ " removing matching Cookie " + cookie.toString());
}
iter.remove();
}
}
}
/** {@inheritDoc} */
public void testStarted() {
initialCookies = getCookies();
cookieSpec = CookiePolicy.getCookieSpec(getPolicy());
if (log.isDebugEnabled()){
log.debug("Policy: "+getPolicy()+" Clear: "+getClearEachIteration());
}
}
/** {@inheritDoc} */
public void testEnded() {
}
/** {@inheritDoc} */
public void testStarted(String host) {
testStarted();
}
/** {@inheritDoc} */
public void testEnded(String host) {
}
/** {@inheritDoc} */
public void testIterationStart(LoopIterationEvent event) {
if (getClearEachIteration()) {
log.debug("Initialise cookies from pre-defined list");
// No need to call clear
setProperty((CollectionProperty)initialCookies.clone());
}
}
}
Other JMeter examples (source code examples)Here is a short list of links related to this JMeter CookieManager.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.