All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xceptance.xlt.api.data.DataProvider Maven / Gradle / Ivy

Go to download

XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.

There is a newer version: 8.1.0
Show newest version
/*
 * Copyright (c) 2005-2022 Xceptance Software Technologies GmbH
 *
 * 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.
 */
package com.xceptance.xlt.api.data;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import com.xceptance.common.util.ParameterCheckUtils;
import com.xceptance.xlt.api.util.XltLogger;
import com.xceptance.xlt.api.util.XltProperties;
import com.xceptance.xlt.api.util.XltRandom;
import com.xceptance.xlt.common.XltConstants;

/**
 * The {@link DataProvider} class provides convenient access to a fixed set of test data strings, which is backed by a
 * data file. Each line in the data file represents exactly one data item.
 * 

* This class does a basic processing of comment lines, for example header lines that describe the data. All lines that * start with the configured line comment marker are filtered out. *

* The specified data file is searched for in the XLT data directory, which is "[testsuite]/config/data" by default. You * may change this directory by setting the XLT property "com.xceptance.xlt.data.directory" to an appropriate value. *

* Note: Be careful when creating instances of this class, as each instance loads the respective data file into memory. * Typically, data providers can/should be shared among test users, so you should have to create just one instance. A * simple way to ensure that there will be only one instance is to use the provided {@link #getInstance(String)} factory * method. But you are free to create (using the constructors) and manage the instances on your own. * * @see GeneralDataProvider * @author René Schwietzke (Xceptance Software Technologies GmbH) */ public class DataProvider { /** * Languages supported. */ public static final String DEFAULT = "default"; /** * The default file encoding ("UTF-8"). */ public static final String DEFAULT_FILE_ENCODING = XltConstants.UTF8_ENCODING; /** * The default line comment character ("#"). */ public static final String DEFAULT_LINE_COMMENT_MARKER = "#"; /** * The global set of data providers, keyed by the data file names. */ private static final Map dataProviders = new ConcurrentHashMap(); /** * Returns the data provider responsible for the given file name. If a data provider has not been requested yet for * this file name, then a new data provider is created, otherwise the previously created provider will be returned. * Note that the data providers will be initialized using {@link #DEFAULT_FILE_ENCODING} and * {@link #DEFAULT_LINE_COMMENT_MARKER}. *

* Use this method to ensure, that only a single data provider instance is created. * * @param fileName * the file name/path of the data file * @return the data provider * @throws FileNotFoundException * if the data file cannot be found * @throws IOException * if the data file cannot be opened or read */ public static DataProvider getInstance(final String fileName) throws FileNotFoundException, IOException { DataProvider dataProvider = dataProviders.get(fileName); if (dataProvider == null) { synchronized (dataProviders) { // check again! dataProvider = dataProviders.get(fileName); if (dataProvider == null) { dataProvider = new DataProvider(fileName); dataProviders.put(fileName, dataProvider); } } } return dataProvider; } /** * The list of data lines. */ private final List dataRows; /** * The string that starts a line comment. */ private final String lineCommentMarker; /** * Creates a new {@link DataProvider} instance and initializes it with the data loaded from the given data file. The * data file is expected to be saved using {@link #DEFAULT_FILE_ENCODING}. Lines in the data file that start with * the {@link #DEFAULT_LINE_COMMENT_MARKER} are considered as comment lines. * * @param fileName * the name/path of the data file * @throws FileNotFoundException * if the data file cannot be found * @throws IOException * if the data file cannot be opened or read */ public DataProvider(final String fileName) throws IOException, FileNotFoundException { this(fileName, DEFAULT_FILE_ENCODING, DEFAULT_LINE_COMMENT_MARKER); } /** * Creates a new {@link DataProvider} instance and initializes it with the data loaded from the given data file. The * data file is expected to be saved using the passed encoding, for example "UTF-8" or "ISO-8859-1". Lines in the * data file that start with the {@link #DEFAULT_LINE_COMMENT_MARKER} are considered as comment lines. * * @param fileName * the name/path of the data file * @param encoding * the data file encoding * @throws FileNotFoundException * if the data file cannot be found * @throws IOException * if the data file cannot be opened or read */ public DataProvider(final String fileName, final String encoding) throws IOException, FileNotFoundException { this(fileName, encoding, DEFAULT_LINE_COMMENT_MARKER); } /** * Creates a new {@link DataProvider} instance and initializes it with the data loaded from the given data file. The * data file is expected to be saved using the passed encoding, for example "UTF-8" or "ISO-8859-1". Lines in the * data file that start with the given line comment marker are considered as comment lines. * * @param fileName * the name/path of the data file * @param encoding * the data file encoding * @param lineCommentMarker * the line comment marker to be used (may be null) * @throws FileNotFoundException * if the data file cannot be found * @throws IOException * if the data file cannot be opened or read */ public DataProvider(final String fileName, final String encoding, final String lineCommentMarker) throws IOException, FileNotFoundException { ParameterCheckUtils.isNotNullOrEmpty(fileName, "fileName"); ParameterCheckUtils.isNotNullOrEmpty(encoding, "encoding"); this.lineCommentMarker = lineCommentMarker; // load the data final String dataDirectory = XltProperties.getInstance().getProperty(XltConstants.XLT_PACKAGE_PATH + ".data.directory", "config" + File.separatorChar + "data"); final File file = new File(dataDirectory, fileName); dataRows = loadData(file, encoding); } /** * Returns all rows as an unmodifiable list to protect the data. * * @return all rows or an empty list, if no data is available */ public synchronized List getAllRows() { return Collections.unmodifiableList(new ArrayList<>(dataRows)); } /** * Returns a randomly-chosen data row. * * @return a row, or null if the data set is empty */ public String getRandomRow() { return getRandomRow(false); } /** * Returns a randomly-chosen data row. * * @param removeWhitespace * whether all whitespace is to be removed from the data * @return a row, or null if the data set is empty */ public synchronized String getRandomRow(final boolean removeWhitespace) { final int r = XltRandom.nextInt(dataRows.size()); return getRow(removeWhitespace, r); } /** * Returns the specified data row. * * @param removeWhitespace * whether all whitespace is to be removed from the data * @param rowNumber * the number of the row to read * @return the row, or null if the specified row number exceeds the size of the data set */ public synchronized String getRow(final boolean removeWhitespace, final int rowNumber) { if (rowNumber < 0 || rowNumber >= dataRows.size()) { return null; } final String s = dataRows.get(rowNumber); return removeWhitespace ? StringUtils.deleteWhitespace(s) : s; } /** * Returns the specified data row. * * @param rowNumber * the number of the row to read * @return the row, or null if the specified row number exceeds the size of the data set */ public String getRow(final int rowNumber) { return getRow(false, rowNumber); } /** * Adds a new data row at the specified row index to the internal store. * * @param rowNumber * the index of the new row * @param row * the new row */ public synchronized void addRow(final int rowNumber, String row) { dataRows.add(rowNumber, row); } /** * Adds a new data row as the last element to the internal store. * * @param row * the new row */ public synchronized void addRow(final String row) { dataRows.add(row); } /** * Removes the data row with the specified row number from the internal store. * * @param rowNumber * the index of the row to remove * @return the row just removed, or null if the specified row number exceeds the size of the data set */ public synchronized String removeRow(final int rowNumber) { if (rowNumber < 0 || rowNumber >= dataRows.size()) { return null; } return dataRows.remove(rowNumber); } /** * Removes the first occurrence of the specified data row from the internal store. * * @param row * the row to remove * @return true if the row was present, false otherwise */ public synchronized boolean removeRow(final String row) { return dataRows.remove(row); } /** * Returns the size of the data set. * * @return the data set size */ public int getSize() { return dataRows.size(); } /** * Loads the data lines from the given file into a list. * * @param file * the data file to load * @param encoding * the data file encoding * @return a list with the data lines * @throws FileNotFoundException * if the data file cannot be found * @throws IOException * if the data file cannot be opened or read */ protected List loadData(final File file, final String encoding) throws IOException, FileNotFoundException { if (XltLogger.runTimeLogger.isDebugEnabled()) { XltLogger.runTimeLogger.debug("Loading data from " + file.getAbsolutePath()); } final List lines = FileUtils.readLines(file, encoding); // post-process the lines return processLines(lines); } /** * Post-processes the data lines just read. This method is responsible for comment line processing. * * @param lines * the data lines * @return the processed data lines */ protected List processLines(final List lines) { final Iterator iterator = lines.iterator(); while (iterator.hasNext()) { final String line = iterator.next(); if (isCommentLine(line)) { iterator.remove(); } } return lines; } /** * Checks whether the given line is a comment line. * * @param line * the line * @return true if this line is a comment line, false otherwise */ private boolean isCommentLine(final String line) { if (lineCommentMarker == null || lineCommentMarker.length() == 0) { return false; } else { return line.trim().startsWith(lineCommentMarker); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy