blob: 57f85dfa122de9bc9184545c11073786988fffcd [file] [log] [blame]
/*
* Copyright 2004-20056 The Apache Software Foundation.
*
* Licensed 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.
*
*/
/*
* Created on Sep 7, 2004
*/
package org.apache.jmeter.samplers;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Properties;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.util.JMeterUtils;
/*
* N.B. to add a new field, remember the following
* - static _xyz
* - instance xyz=_xyz
* - clone s.xyz = xyz
* - setXyz(boolean)
* - saveXyz()
* - update SampleSaveConfigurationConverter to add new field
* - update SampleResultConverter and/or HTTPSampleConverter
* - update CSV routines in OldSaveService
* - update messages.properties to add save_xyz entry
*
*/
/**
* Holds details of which sample attributes to save.
*
* The pop-up dialogue for this is created by the class SavePropertyDialog, which assumes:
* For each field XXX
* - methods have the signature "boolean saveXXX()"
* - a corresponding "void setXXX(boolean)" method
* - messages.properties contains the key save_XXX
*
* @author mstover
*
*/
public class SampleSaveConfiguration implements Cloneable, Serializable {
static final long serialVersionUID = 4;
// ---------------------------------------------------------------------
// PROPERTY FILE CONSTANTS
// ---------------------------------------------------------------------
/** Indicates that the results file should be in XML format. * */
private static final String XML = "xml"; // $NON_NLS-1$
/** Indicates that the results file should be in CSV format. * */
//NOTUSED private static final String CSV = "csv"; // $NON_NLS-1$
/** Indicates that the results should be stored in a database. * */
//NOTUSED private static final String DATABASE = "db"; // $NON_NLS-1$
/** A properties file indicator for true. * */
private static final String TRUE = "true"; // $NON_NLS-1$
/** A properties file indicator for false. * */
private static final String FALSE = "false"; // $NON_NLS-1$
/** A properties file indicator for milliseconds. * */
private static final String MILLISECONDS = "ms"; // $NON_NLS-1$
/** A properties file indicator for none. * */
private static final String NONE = "none"; // $NON_NLS-1$
/** A properties file indicator for the first of a series. * */
private static final String FIRST = "first"; // $NON_NLS-1$
/** A properties file indicator for all of a series. * */
private static final String ALL = "all"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating which assertion results should be
* saved.
**************************************************************************/
private static final String ASSERTION_RESULTS_FAILURE_MESSAGE_PROP =
"jmeter.save.saveservice.assertion_results_failure_message"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating which assertion results should be
* saved.
**************************************************************************/
private static final String ASSERTION_RESULTS_PROP = "jmeter.save.saveservice.assertion_results"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating which delimiter should be used when
* saving in a delimited values format.
**************************************************************************/
private static final String DEFAULT_DELIMITER_PROP = "jmeter.save.saveservice.default_delimiter"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating which format should be used when
* saving the results, e.g., xml or csv.
**************************************************************************/
private static final String OUTPUT_FORMAT_PROP = "jmeter.save.saveservice.output_format"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether field names should be printed
* to a delimited file.
**************************************************************************/
private static final String PRINT_FIELD_NAMES_PROP = "jmeter.save.saveservice.print_field_names"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the data type should be
* saved.
**************************************************************************/
private static final String SAVE_DATA_TYPE_PROP = "jmeter.save.saveservice.data_type"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the label should be saved.
**************************************************************************/
private static final String SAVE_LABEL_PROP = "jmeter.save.saveservice.label"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the response code should be
* saved.
**************************************************************************/
private static final String SAVE_RESPONSE_CODE_PROP = "jmeter.save.saveservice.response_code"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the response data should be
* saved.
**************************************************************************/
private static final String SAVE_RESPONSE_DATA_PROP = "jmeter.save.saveservice.response_data"; // $NON_NLS-1$
private static final String SAVE_RESPONSE_DATA_ON_ERROR_PROP = "jmeter.save.saveservice.response_data.on_error"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the response message should
* be saved.
**************************************************************************/
private static final String SAVE_RESPONSE_MESSAGE_PROP = "jmeter.save.saveservice.response_message"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the success indicator should
* be saved.
**************************************************************************/
private static final String SAVE_SUCCESSFUL_PROP = "jmeter.save.saveservice.successful"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the thread name should be
* saved.
**************************************************************************/
private static final String SAVE_THREAD_NAME_PROP = "jmeter.save.saveservice.thread_name"; // $NON_NLS-1$
// Save bytes read
private static final String SAVE_BYTES_PROP = "jmeter.save.saveservice.bytes"; // $NON_NLS-1$
// Save URL
private static final String SAVE_URL_PROP = "jmeter.save.saveservice.url"; // $NON_NLS-1$
// Save fileName for ResultSaver
private static final String SAVE_FILENAME_PROP = "jmeter.save.saveservice.filename"; // $NON_NLS-1$
/***************************************************************************
* The name of the property indicating whether the time should be saved.
**************************************************************************/
private static final String SAVE_TIME_PROP = "jmeter.save.saveservice.time"; // $NON_NLS-1$
/***************************************************************************
* The name of the property giving the format of the time stamp
**************************************************************************/
private static final String TIME_STAMP_FORMAT_PROP = "jmeter.save.saveservice.timestamp_format"; // $NON_NLS-1$
private static final String SUBRESULTS_PROP = "jmeter.save.saveservice.subresults"; // $NON_NLS-1$
private static final String ASSERTIONS_PROP = "jmeter.save.saveservice.assertions"; // $NON_NLS-1$
private static final String LATENCY_PROP = "jmeter.save.saveservice.latency"; // $NON_NLS-1$
private static final String SAMPLERDATA_PROP = "jmeter.save.saveservice.samplerData"; // $NON_NLS-1$
private static final String RESPONSEHEADERS_PROP = "jmeter.save.saveservice.responseHeaders"; // $NON_NLS-1$
private static final String REQUESTHEADERS_PROP = "jmeter.save.saveservice.requestHeaders"; // $NON_NLS-1$
private static final String ENCODING_PROP = "jmeter.save.saveservice.encoding"; // $NON_NLS-1$
// optional processing instruction for line 2; e.g.
// <?xml-stylesheet type="text/xsl" href="../extras/jmeter-results-detail-report_21.xsl"?>
private static final String XML_PI = "jmeter.save.saveservice.xml_pi"; // $NON_NLS-1$
private static final String SAVE_THREAD_COUNTS = "jmeter.save.saveservice.thread_counts"; // $NON_NLS-1$
// N.B. Remember to update the clone method when adding new variables.
// Initialise values from properties
private boolean time = _time, latency = _latency, timestamp = _timestamp, success = _success, label = _label,
code = _code, message = _message, threadName = _threadName, dataType = _dataType, encoding = _encoding,
assertions = _assertions, subresults = _subresults, responseData = _responseData,
samplerData = _samplerData, xml = _xml, fieldNames = _fieldNames, responseHeaders = _responseHeaders,
requestHeaders = _requestHeaders, responseDataOnError = _responseDataOnError;
private boolean saveAssertionResultsFailureMessage = _saveAssertionResultsFailureMessage;
private boolean url = _url, bytes = _bytes , fileName = _fileName;
private boolean threadCounts = _threadCounts;
// Does not appear to be used (yet)
private int assertionsResultsToSave = _assertionsResultsToSave;
// Don't save this, as not settable via GUI
private transient String delimiter = _delimiter;
// Don't save this, as it is derived from the time format
private transient boolean printMilliseconds = _printMilliseconds;
/** A formatter for the time stamp. */
private transient SimpleDateFormat formatter = _formatter;
/* Make transient as we don't want to save the SimpleDataFormat class
* Also, there's currently no way to change the value via the GUI, so changing it
* later means editting the JMX, or recreating the Listener.
*/
// Defaults from properties:
private static final boolean _time, _timestamp, _success, _label, _code, _message, _threadName, _xml,
_responseData, _dataType, _encoding, _assertions, _latency, _subresults, _samplerData, _fieldNames,
_responseHeaders, _requestHeaders;
private static final boolean _responseDataOnError;
private static final boolean _saveAssertionResultsFailureMessage;
private static final String _timeStampFormat;
private static int _assertionsResultsToSave;
// TODO turn into method?
public static final int SAVE_NO_ASSERTIONS = 0;
public static final int SAVE_FIRST_ASSERTION = SAVE_NO_ASSERTIONS + 1;
public static final int SAVE_ALL_ASSERTIONS = SAVE_FIRST_ASSERTION + 1;
private static final boolean _printMilliseconds;
private static final boolean _bytes;
private static final boolean _url;
private static final boolean _fileName;
private static final boolean _threadCounts;
private static final SimpleDateFormat _formatter;
/**
* The string used to separate fields when stored to disk, for example, the
* comma for CSV files.
*/
private static final String _delimiter;
private static final String DEFAULT_DELIMITER = ","; // $NON_NLS-1$
/**
* Read in the properties having to do with saving from a properties file.
*/
static {
Properties props = JMeterUtils.getJMeterProperties();
_subresults = TRUE.equalsIgnoreCase(props.getProperty(SUBRESULTS_PROP, TRUE));
_assertions = TRUE.equalsIgnoreCase(props.getProperty(ASSERTIONS_PROP, TRUE));
_latency = TRUE.equalsIgnoreCase(props.getProperty(LATENCY_PROP, TRUE));
_samplerData = TRUE.equalsIgnoreCase(props.getProperty(SAMPLERDATA_PROP, FALSE));
_responseHeaders = TRUE.equalsIgnoreCase(props.getProperty(RESPONSEHEADERS_PROP, FALSE));
_requestHeaders = TRUE.equalsIgnoreCase(props.getProperty(REQUESTHEADERS_PROP, FALSE));
_encoding = TRUE.equalsIgnoreCase(props.getProperty(ENCODING_PROP, FALSE));
_delimiter = props.getProperty(DEFAULT_DELIMITER_PROP, DEFAULT_DELIMITER);
_fieldNames = TRUE.equalsIgnoreCase(props.getProperty(PRINT_FIELD_NAMES_PROP, FALSE));
_dataType = TRUE.equalsIgnoreCase(props.getProperty(SAVE_DATA_TYPE_PROP, TRUE));
_label = TRUE.equalsIgnoreCase(props.getProperty(SAVE_LABEL_PROP, TRUE));
_code = TRUE.equalsIgnoreCase(props.getProperty(SAVE_RESPONSE_CODE_PROP, TRUE));
_responseData = TRUE.equalsIgnoreCase(props.getProperty(SAVE_RESPONSE_DATA_PROP, FALSE));
_responseDataOnError = TRUE.equalsIgnoreCase(props.getProperty(SAVE_RESPONSE_DATA_ON_ERROR_PROP, FALSE));
_message = TRUE.equalsIgnoreCase(props.getProperty(SAVE_RESPONSE_MESSAGE_PROP, TRUE));
_success = TRUE.equalsIgnoreCase(props.getProperty(SAVE_SUCCESSFUL_PROP, TRUE));
_threadName = TRUE.equalsIgnoreCase(props.getProperty(SAVE_THREAD_NAME_PROP, TRUE));
_bytes = TRUE.equalsIgnoreCase(props.getProperty(SAVE_BYTES_PROP, FALSE));
_url = TRUE.equalsIgnoreCase(props.getProperty(SAVE_URL_PROP, FALSE));
_fileName = TRUE.equalsIgnoreCase(props.getProperty(SAVE_FILENAME_PROP, FALSE));
_time = TRUE.equalsIgnoreCase(props.getProperty(SAVE_TIME_PROP, TRUE));
_timeStampFormat = props.getProperty(TIME_STAMP_FORMAT_PROP, MILLISECONDS);
_printMilliseconds = MILLISECONDS.equalsIgnoreCase(_timeStampFormat);
// Prepare for a pretty date
if (!_printMilliseconds && !NONE.equalsIgnoreCase(_timeStampFormat) && (_timeStampFormat != null)) {
_formatter = new SimpleDateFormat(_timeStampFormat);
} else {
_formatter = null;
}
_timestamp = !_timeStampFormat.equalsIgnoreCase(NONE);
_saveAssertionResultsFailureMessage = TRUE.equalsIgnoreCase(props.getProperty(
ASSERTION_RESULTS_FAILURE_MESSAGE_PROP, FALSE));
String whichAssertionResults = props.getProperty(ASSERTION_RESULTS_PROP, NONE);
if (NONE.equals(whichAssertionResults)) {
_assertionsResultsToSave = SAVE_NO_ASSERTIONS;
} else if (FIRST.equals(whichAssertionResults)) {
_assertionsResultsToSave = SAVE_FIRST_ASSERTION;
} else if (ALL.equals(whichAssertionResults)) {
_assertionsResultsToSave = SAVE_ALL_ASSERTIONS;
}
String howToSave = props.getProperty(OUTPUT_FORMAT_PROP, XML);
if (XML.equals(howToSave)) {
_xml = true;
} else {
_xml = false;
}
_threadCounts=TRUE.equalsIgnoreCase(props.getProperty(SAVE_THREAD_COUNTS, FALSE));
}
private static final SampleSaveConfiguration _static = new SampleSaveConfiguration();
// Give access to initial configuration
public static SampleSaveConfiguration staticConfig() {
return _static;
}
public SampleSaveConfiguration() {
}
// TODO: may need to implement this to allow for adding new attributes to the config,
// otherwise XStream will not populate the missing attributes
// private Object readResolve() throws ObjectStreamException{
// return this;
// }
public Object clone() {
SampleSaveConfiguration s = new SampleSaveConfiguration();
s.time = time;
s.latency = latency;
s.timestamp = timestamp;
s.success = success;
s.label = label;
s.code = code;
s.message = message;
s.threadName = threadName;
s.dataType = dataType;
s.encoding = encoding;
s.assertions = assertions;
s.subresults = subresults;
s.responseData = responseData;
s.samplerData = samplerData;
s.xml = xml;
s.fieldNames = fieldNames;
s.responseHeaders = responseHeaders;
s.requestHeaders = requestHeaders;
s.formatter = formatter;
s.assertionsResultsToSave = assertionsResultsToSave;
s.saveAssertionResultsFailureMessage = saveAssertionResultsFailureMessage;
s.delimiter = delimiter;
s.printMilliseconds = printMilliseconds;
s.responseDataOnError = responseDataOnError;
s.url = url;
s.bytes = bytes;
s.fileName = fileName;
s.threadCounts = threadCounts;
return s;
}
///////////////////// Start of standard save/set access methods /////////////////////
public boolean saveResponseHeaders() {
return responseHeaders;
}
public void setResponseHeaders(boolean r) {
responseHeaders = r;
}
public boolean saveRequestHeaders() {
return requestHeaders;
}
public void setRequestHeaders(boolean r) {
requestHeaders = r;
}
public boolean saveAssertions() {
return assertions;
}
public void setAssertions(boolean assertions) {
this.assertions = assertions;
}
public boolean saveCode() {
return code;
}
public void setCode(boolean code) {
this.code = code;
}
public boolean saveDataType() {
return dataType;
}
public void setDataType(boolean dataType) {
this.dataType = dataType;
}
public boolean saveEncoding() {
return encoding;
}
public void setEncoding(boolean encoding) {
this.encoding = encoding;
}
public boolean saveLabel() {
return label;
}
public void setLabel(boolean label) {
this.label = label;
}
public boolean saveLatency() {
return latency;
}
public void setLatency(boolean latency) {
this.latency = latency;
}
public boolean saveMessage() {
return message;
}
public void setMessage(boolean message) {
this.message = message;
}
public boolean saveResponseData(SampleResult res) {
return responseData || TestPlan.getFunctionalMode() || (responseDataOnError && !res.isSuccessful());
}
public boolean saveResponseData()
{
return responseData;
}
public void setResponseData(boolean responseData) {
this.responseData = responseData;
}
public boolean saveSamplerData(SampleResult res) {
return samplerData || TestPlan.getFunctionalMode() // as per 2.0 branch
|| (responseDataOnError && !res.isSuccessful());
}
public boolean saveSamplerData()
{
return samplerData;
}
public void setSamplerData(boolean samplerData) {
this.samplerData = samplerData;
}
public boolean saveSubresults() {
return subresults;
}
public void setSubresults(boolean subresults) {
this.subresults = subresults;
}
public boolean saveSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public boolean saveThreadName() {
return threadName;
}
public void setThreadName(boolean threadName) {
this.threadName = threadName;
}
public boolean saveTime() {
return time;
}
public void setTime(boolean time) {
this.time = time;
}
public boolean saveTimestamp() {
return timestamp;
}
public void setTimestamp(boolean timestamp) {
this.timestamp = timestamp;
}
public boolean saveAsXml() {
return xml;
}
public void setAsXml(boolean xml) {
this.xml = xml;
}
public boolean saveFieldNames() {
return fieldNames;
}
public void setFieldNames(boolean printFieldNames) {
this.fieldNames = printFieldNames;
}
public boolean saveUrl() {
return url;
}
public void setUrl(boolean save) {
this.url = save;
}
public boolean saveBytes() {
return bytes;
}
public void setBytes(boolean save) {
this.bytes = save;
}
public boolean saveFileName() {
return fileName;
}
public void setFileName(boolean save) {
this.fileName = save;
}
public boolean saveAssertionResultsFailureMessage() {
return saveAssertionResultsFailureMessage;
}
public void setAssertionResultsFailureMessage(boolean b) {
saveAssertionResultsFailureMessage = b;
}
public boolean saveThreadCounts() {
return threadCounts;
}
public void setThreadCounts(boolean save) {
this.threadCounts = save;
}
///////////////// End of standard field accessors /////////////////////
public boolean printMilliseconds() {
return printMilliseconds;
}
public SimpleDateFormat formatter() {
return formatter;
}
public int assertionsResultsToSave() {
return assertionsResultsToSave;
}
public String getDelimiter() {
return delimiter;
}
public String getXmlPi() {
return JMeterUtils.getJMeterProperties().getProperty(XML_PI, ""); // Defaults to empty;
}
// Used by SampleSaveConfigurationConverter.unmarshall()
public void setDefaultDelimiter() {
delimiter=_delimiter;
}
// Used by SampleSaveConfigurationConverter.unmarshall()
public void setDefaultTimeStampFormat() {
printMilliseconds=_printMilliseconds;
formatter=_formatter;
}
}