Package com.lazerycode.jmeter

Source Code of com.lazerycode.jmeter.JMeterAbstractMojo

package com.lazerycode.jmeter;

import com.lazerycode.jmeter.configuration.*;
import com.lazerycode.jmeter.properties.PropertyHandler;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.joda.time.format.DateTimeFormat;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static com.lazerycode.jmeter.UtilityFunctions.isSet;
import static org.apache.commons.io.FileUtils.copyFile;
import static org.apache.commons.io.FileUtils.copyInputStreamToFile;

/**
* JMeter Maven plugin.
* This is a base class for the JMeter mojos.
*
* @author Tim McCune
*/
@SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal", "JavaDoc"}) // Mojos get their fields set via reflection
public abstract class JMeterAbstractMojo extends AbstractMojo {

  /**
   * Sets the list of include patterns to use in directory scan for JMX files.
   * Relative to testFilesDirectory.
   */
  @Parameter
  protected List<String> testFilesIncluded;

  /**
   * Sets the list of exclude patterns to use in directory scan for Test files.
   * Relative to testFilesDirectory.
   */
  @Parameter
  protected List<String> testFilesExcluded;

  /**
   * Path under which JMX files are stored.
   */
  @Parameter(defaultValue = "${basedir}/src/test/jmeter")
  protected File testFilesDirectory;

  /**
   * Timestamp the test results.
   */
  @Parameter(defaultValue = "true")
  protected boolean testResultsTimestamp;

  /**
   * Append the results timestamp to the filename
   * (It will be prepended by default if testResultsTimestamp is set to true)
   */
  @Parameter(defaultValue = "false")
  protected boolean appendResultsTimestamp;

  /**
   * Set the format of the timestamp that is appended to the results filename.
   * (This assumes that testResultsTimestamp is set to 'true')
   * For formatting see http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html
   */
  @Parameter()
  protected String resultsFileNameDateFormat;

  /**
   * Set the format of the results generated by JMeter
   * Valid values are: xml, csv (XML set by default).
   */
  @Parameter(defaultValue = "xml")
  protected String resultsFileFormat;

  /**
   * Set the directory that JMeter results are saved to.
   */
  @Parameter
  protected String resultsDirectory;

  /**
   * Absolute path to JMeter custom (test dependent) properties file.
   */
  @Parameter
  protected Map<String, String> propertiesJMeter = new HashMap<String, String>();

  /**
   * JMeter Properties that are merged with precedence into default JMeter file in saveservice.properties
   */
  @Parameter
  protected Map<String, String> propertiesSaveService = new HashMap<String, String>();

  /**
   * JMeter Properties that are merged with precedence into default JMeter file in upgrade.properties
   */
  @Parameter
  protected Map<String, String> propertiesUpgrade = new HashMap<String, String>();

  /**
   * JMeter Properties that are merged with precedence into default JMeter file in user.properties
   * user.properties takes precedence over jmeter.properties
   */
  @Parameter
  protected Map<String, String> propertiesUser = new HashMap<String, String>();

  /**
   * JMeter Global Properties that override those given in jmeterProps. <br>
   * This sets local and remote properties (JMeter's definition of global properties is actually remote properties)
   * and overrides any local/remote properties already set
   */
  @Parameter
  protected Map<String, String> propertiesGlobal = new HashMap<String, String>();

  /**
   * (Java) System properties set for the test run.
   * Properties are merged with precedence into default JMeter file system.properties
   */
  @Parameter
  protected Map<String, String> propertiesSystem = new HashMap<String, String>();

  /**
   * Absolute path to JMeter custom (test dependent) properties file.
   */
  @Parameter
  protected File customPropertiesFile;

  /**
   * Replace the default JMeter properties with any custom properties files supplied.
   * (If set to false any custom properties files will be merged with the default JMeter properties files, custom properties will overwrite default ones)
   */
  @Parameter(defaultValue = "true")
  protected boolean propertiesReplacedByCustomFiles;

  /**
   * Value class that wraps all proxy configurations.
   */
  @Parameter
  protected ProxyConfiguration proxyConfig;

  /**
   * Value class that wraps all remote configurations.
   */
  @Parameter
  protected RemoteConfiguration remoteConfig;

  /**
   * Value class that wraps all remote configurations.
   */
  @Parameter
  protected Set<JMeterPlugins> jmeterPlugins;

  /**
   * Value class that wraps all remote configurations.
   */
  @Parameter
  protected Set<JMeterPlugins> junitLibraries;

  /**
   * Value class that wraps all JMeter Process JVM settings.
   */
  @Parameter
  protected JMeterProcessJVMSettings jMeterProcessJVMSettings;

  /**
   * Set a root log level to override all log levels used by JMeter
   * Valid log levels are: FATAL_ERROR, ERROR, WARN, INFO, DEBUG (They are not case sensitive);
   * If you try to set an invalid log level it will be ignored
   */
  @Parameter
  protected String overrideRootLogLevel;

  /**
   * Name of advanced logging configuration file that is in the <testFilesDirectory>
   * Defaults to "logkit.xml"
   */
  @Parameter(defaultValue = "logkit.xml")
  protected String logConfigFilename;

  /**
   * Sets whether FailureScanner should ignore failures in JMeter result file.
   * Failures are for example failed requests
   */
  @Parameter(defaultValue = "false")
  protected boolean ignoreResultFailures;

  /**
   * Suppress JMeter output
   */
  @Parameter(defaultValue = "true")
  protected boolean suppressJMeterOutput;

  /**
   * Get a list of artifacts used by this plugin
   */
  @Parameter(defaultValue = "${plugin.artifacts}", required = true, readonly = true)
  protected List<Artifact> pluginArtifacts;

  /**
   * The information extracted from the Mojo being currently executed
   */
  @Parameter(defaultValue = "${mojoExecution}", required = true, readonly = true)
  protected MojoExecution mojoExecution;

  /**
   * Skip the JMeter tests
   */
  @Parameter(defaultValue = "false")
  protected boolean skipTests;

  //------------------------------------------------------------------------------------------------------------------

  /**
   * Place where the JMeter files will be generated.
   */
  @Parameter(defaultValue = "${project.build.directory}/jmeter")
  protected transient File workDir;

  /**
   * Other directories will be created by this plugin and used by JMeter
   */
  protected File binDir;
  protected File libDir;
  protected File libExtDir;
  protected File libJUnitDir;
  protected File logsDir;
  protected File resultsDir;

  /**
   * All property files are stored in this artifact, comes with JMeter library
   */
  protected final String jmeterConfigArtifact = "ApacheJMeter_config";
  protected JMeterArgumentsArray testArgs;
  protected PropertyHandler pluginProperties;
  protected boolean resultsOutputIsCSVFormat = false;

  //==================================================================================================================

  /**
   * Generate the directory tree utilised by JMeter.
   */
  @SuppressWarnings("ResultOfMethodCallIgnored")
  protected void generateJMeterDirectoryTree() {
    logsDir = new File(workDir, "logs");
    logsDir.mkdirs();
    binDir = new File(workDir, "bin");
    binDir.mkdirs();
    if (null != resultsDirectory) {
      resultsDir = new File(resultsDirectory.replaceAll("\\|/", File.separator));
    } else {
      resultsDir = new File(workDir, "results");
    }
    resultsDir.mkdirs();
    libDir = new File(workDir, "lib");
    libExtDir = new File(libDir, "ext");
    libExtDir.mkdirs();
    libJUnitDir = new File(libDir, "junit");
    libJUnitDir.mkdirs();
  }

  protected void propertyConfiguration() throws MojoExecutionException {
    pluginProperties = new PropertyHandler(testFilesDirectory, binDir, getArtifactNamed(jmeterConfigArtifact), propertiesReplacedByCustomFiles);
    pluginProperties.setJMeterProperties(propertiesJMeter);
    pluginProperties.setJMeterGlobalProperties(propertiesGlobal);
    pluginProperties.setJMeterSaveServiceProperties(propertiesSaveService);
    pluginProperties.setJMeterUpgradeProperties(propertiesUpgrade);
    pluginProperties.setJmeterUserProperties(propertiesUser);
    pluginProperties.setJMeterSystemProperties(propertiesSystem);
    pluginProperties.configureJMeterPropertiesFiles();
    pluginProperties.setDefaultPluginProperties(binDir.getAbsolutePath());
  }

  /**
   * Create the JMeter directory tree and copy all compile time JMeter dependencies into it.
   * Generic compile time artifacts are copied into the libDir
   * ApacheJMeter_* artifacts are copied into the libExtDir
   * Runtime dependencies set by the user are also copied into the libExtDir
   *
   * @throws MojoExecutionException
   */
  protected void populateJMeterDirectoryTree() throws MojoExecutionException {
    for (Artifact artifact : pluginArtifacts) {
      try {
        if (Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact.getScope())) {
          if (artifact.getArtifactId().equals(jmeterConfigArtifact)) {
            extractConfigSettings(artifact);
          } else if (artifact.getArtifactId().equals("ApacheJMeter")) {
            copyFile(artifact.getFile(), new File(binDir + File.separator + artifact.getArtifactId() + ".jar"));
          } else if (artifact.getArtifactId().startsWith("ApacheJMeter_")) {
            copyFile(artifact.getFile(), new File(libExtDir + File.separator + artifact.getFile().getName()));
          } else if (isArtifactAJMeterDependency(artifact)) {
            copyFile(artifact.getFile(), new File(libDir + File.separator + artifact.getFile().getName()));
          } else if (isArtifactAnExplicitDependency(artifact)) {
            if (isArtifactMarkedAsAJMeterPlugin(artifact)) {
              copyFile(artifact.getFile(), new File(libExtDir + File.separator + artifact.getFile().getName()));
            } else if (isArtifactMarkedAsAJUnitLib(artifact)) {
              copyFile(artifact.getFile(), new File(libJUnitDir + File.separator + artifact.getFile().getName()));
            } else {
              copyFile(artifact.getFile(), new File(libDir + File.separator + artifact.getFile().getName()));
            }
          }
        }
      } catch (IOException e) {
        throw new MojoExecutionException("Unable to populate the JMeter directory tree: " + e);
      }
    }
  }

  /**
   * Extract the configuration settings (not properties files) form the configuration artifact and load them into the /bin directory
   *
   * @param artifact Configuration artifact
   * @throws IOException
   */
  private void extractConfigSettings(Artifact artifact) throws IOException {
    JarFile configSettings = new JarFile(artifact.getFile());
    Enumeration<JarEntry> entries = configSettings.entries();
    while (entries.hasMoreElements()) {
      JarEntry jarFileEntry = entries.nextElement();
      // Only interested in files in the /bin directory that are not properties files
      if (!jarFileEntry.isDirectory() && jarFileEntry.getName().startsWith("bin") && !jarFileEntry.getName().endsWith(".properties")) {
        File fileToCreate = new File(workDir.getCanonicalPath() + File.separator + jarFileEntry.getName());
        if (jarFileEntry.getName().endsWith(logConfigFilename) && fileToCreate.exists()) {
          break;
        }
        copyInputStreamToFile(configSettings.getInputStream(jarFileEntry), fileToCreate);
      }
    }
    configSettings.close();
  }

  protected boolean isArtifactMarkedAsAJMeterPlugin(Artifact artifact) {
    return isMarkedAs(jmeterPlugins, artifact);
  }

  protected boolean isArtifactMarkedAsAJUnitLib(Artifact artifact) {
    return isMarkedAs(junitLibraries, artifact);
  }

  private boolean isMarkedAs(Set<JMeterPlugins> plugins, Artifact artifact) {
    if (null != plugins) {
      for (JMeterPlugins identifiedPlugin : plugins) {
        if (identifiedPlugin.toString().equals(artifact.getGroupId() + ":" + artifact.getArtifactId())) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Check if the given artifact is needed by an explicit dependency (a dependency, that is explicitly defined in
   * the pom of the project using the jmeter-maven-plugin).
   *
   * @param artifact Artifact to examine
   * @return true if the given artifact is needed by a explicit dependency.
   */
  protected boolean isArtifactAnExplicitDependency(Artifact artifact) {
    try {
      //Maven 3
      List<Dependency> pluginDependencies = mojoExecution.getPlugin().getDependencies();
      for (Dependency dependency : pluginDependencies) {
        for (String parent : artifact.getDependencyTrail()) {
          if (parent.contains(dependency.getGroupId() + ":" + dependency.getArtifactId()) && parent.contains(dependency.getVersion())) {
            return true;
          }
        }
      }
    } catch (NoSuchMethodError ignored) {
      //Maven 2
      Set<Artifact> pluginDependentArtifacts = mojoExecution.getMojoDescriptor().getPluginDescriptor().getIntroducedDependencyArtifacts();
      for (Artifact dependency : pluginDependentArtifacts) {
        for (String parent : artifact.getDependencyTrail()) {
          if (parent.contains(dependency.getGroupId() + ":" + dependency.getArtifactId()) && parent.contains(dependency.getBaseVersion())) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Work out if an artifact is a JMeter dependency
   *
   * @param artifact Artifact to examine
   * @return true if a Jmeter dependency, false if a plugin dependency.
   */
  protected boolean isArtifactAJMeterDependency(Artifact artifact) {
    for (String dependency : artifact.getDependencyTrail()) {
      if (dependency.contains("org.apache.jmeter")) {
        return true;
      }
    }
    return false;
  }

  /**
   * Search the list of plugin artifacts for an artifact with a specific name
   *
   * @param artifactName
   * @return
   * @throws MojoExecutionException
   */
  protected Artifact getArtifactNamed(String artifactName) throws MojoExecutionException {
    for (Artifact artifact : pluginArtifacts) {
      if (artifact.getArtifactId().equals(artifactName)) {
        return artifact;
      }
    }
    throw new MojoExecutionException("Unable to find artifact '" + artifactName + "'!");
  }

  /**
   * Generate the initial JMeter Arguments array that is used to create the command line that we pass to JMeter.
   *
   * @throws MojoExecutionException
   */
  protected void initialiseJMeterArgumentsArray(boolean disableGUI) throws MojoExecutionException {
    testArgs = new JMeterArgumentsArray(disableGUI, workDir.getAbsolutePath());
    testArgs.setResultsDirectory(resultsDir.getAbsolutePath());
    testArgs.setResultFileOutputFormatIsCSV(resultsOutputIsCSVFormat);
    if (testResultsTimestamp) {
      testArgs.setResultsTimestamp(testResultsTimestamp);
      testArgs.appendTimestamp(appendResultsTimestamp);
      if (isSet(resultsFileNameDateFormat)) {
        try {
          testArgs.setResultsFileNameDateFormat(DateTimeFormat.forPattern(resultsFileNameDateFormat));
        } catch (Exception ex) {
          getLog().error("'" + resultsFileNameDateFormat + "' is an invalid DateTimeFormat.  Defaulting to Standard ISO_8601.");
        }
      }
    }
    testArgs.setProxyConfig(proxyConfig);
    testArgs.setACustomPropertiesFile(customPropertiesFile);
    testArgs.setLogRootOverride(overrideRootLogLevel);
    testArgs.setLogsDirectory(logsDir.getAbsolutePath());
  }

  protected void setJMeterResultFileFormat() {
    if (resultsFileFormat.toLowerCase().equals("csv")) {
      propertiesJMeter.put("jmeter.save.saveservice.output_format", "csv");
      resultsOutputIsCSVFormat = true;
    } else {
      propertiesJMeter.put("jmeter.save.saveservice.output_format", "xml");
      resultsOutputIsCSVFormat = false;
    }
  }

  protected void configureAdvancedLogging() throws MojoFailureException {
    File advancedLoggingSetting = new File(testFilesDirectory + File.separator + logConfigFilename);
    if (advancedLoggingSetting.exists()) {
      try {
        copyFile(advancedLoggingSetting, new File(binDir + File.separator + logConfigFilename));
      } catch (IOException ex) {
        throw new MojoFailureException(ex.getMessage());
      }
      propertiesJMeter.put("log_config", logConfigFilename);
    }
  }
}
TOP

Related Classes of com.lazerycode.jmeter.JMeterAbstractMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.