public static void main(String args[]) {
   int port = 8080;
   if (args.length > 0) {
     port = Integer.parseInt(args[0]);
   }
   LoggingManager.setPriority("INFO"); // default level
   LoggingManager.setLoggingLevels(System.getProperties()); // allow override by system properties
   HttpMirrorServer serv = new HttpMirrorServer(port);
   serv.start();
 }
예제 #2
0
public class BSFAssertion extends BSFTestElement implements Cloneable, Assertion, TestBean {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final long serialVersionUID = 234L;

  public AssertionResult getResult(SampleResult response) {
    AssertionResult result = new AssertionResult(getName());
    try {
      BSFManager mgr = getManager();
      if (mgr == null) {
        result.setFailure(true);
        result.setError(true);
        result.setFailureMessage("BSF Manager not found");
        return result;
      }
      mgr.declareBean("SampleResult", response, SampleResult.class);
      mgr.declareBean("AssertionResult", result, AssertionResult.class);
      processFileOrScript(mgr);
      mgr.terminate();
      result.setError(false);
    } catch (BSFException e) {
      log.warn("Problem in BSF script " + e);
      result.setError(true);
      result.setFailureMessage(e.toString());
    }
    return result;
  }
}
  protected void initManager(ScriptEngineManager sem) {
    final String label = getName();
    final String fileName = getFilename();
    final String scriptParameters = getParameters();
    // Use actual class name for log
    final Logger logger = LoggingManager.getLoggerForShortName(getClass().getName());

    sem.put("log", logger);
    sem.put("Label", label);
    sem.put("FileName", fileName);
    sem.put("Parameters", scriptParameters);
    String[] args = JOrphanUtils.split(scriptParameters, " "); // $NON-NLS-1$
    sem.put("args", args);
    // Add variables for access to context and variables
    JMeterContext jmctx = JMeterContextService.getContext();
    sem.put("ctx", jmctx);
    JMeterVariables vars = jmctx.getVariables();
    sem.put("vars", vars);
    Properties props = JMeterUtils.getJMeterProperties();
    sem.put("props", props);
    // For use in debugging:
    sem.put("OUT", System.out);

    // Most subclasses will need these:
    Sampler sampler = jmctx.getCurrentSampler();
    sem.put("sampler", sampler);
    SampleResult prev = jmctx.getPreviousResult();
    sem.put("prev", prev);
  }
  protected void initManager(BSFManager mgr) throws BSFException {
    final String label = getName();
    final String fileName = getFilename();
    final String scriptParameters = getParameters();
    // Use actual class name for log
    final Logger logger = LoggingManager.getLoggerForShortName(getClass().getName());
    mgr.declareBean("log", logger, Logger.class); // $NON-NLS-1$
    mgr.declareBean("Label", label, String.class); // $NON-NLS-1$
    mgr.declareBean("FileName", fileName, String.class); // $NON-NLS-1$
    mgr.declareBean("Parameters", scriptParameters, String.class); // $NON-NLS-1$
    String[] args = JOrphanUtils.split(scriptParameters, " "); // $NON-NLS-1$
    mgr.declareBean("args", args, args.getClass()); // $NON-NLS-1$
    // Add variables for access to context and variables
    JMeterContext jmctx = JMeterContextService.getContext();
    JMeterVariables vars = jmctx.getVariables();
    Properties props = JMeterUtils.getJMeterProperties();

    mgr.declareBean("ctx", jmctx, jmctx.getClass()); // $NON-NLS-1$
    mgr.declareBean("vars", vars, vars.getClass()); // $NON-NLS-1$
    mgr.declareBean("props", props, props.getClass()); // $NON-NLS-1$
    // For use in debugging:
    mgr.declareBean("OUT", System.out, PrintStream.class); // $NON-NLS-1$

    // Most subclasses will need these:
    Sampler sampler = jmctx.getCurrentSampler();
    mgr.declareBean("sampler", sampler, Sampler.class);
    SampleResult prev = jmctx.getPreviousResult();
    mgr.declareBean("prev", prev, SampleResult.class);
  }
예제 #5
0
/**
 * This module controls the Sequence in which user details are returned. This module uses round
 * robin allocation of users.
 *
 * @version $Revision: 701738 $
 */
public class UserSequence implements Serializable {
  private static final long serialVersionUID = 233L;

  private static final Logger log = LoggingManager.getLoggerForClass();

  // -------------------------------------------
  // Constants and Data Members
  // -------------------------------------------
  private List allUsers;

  private transient Iterator indexOfUsers;

  // -------------------------------------------
  // Constructors
  // -------------------------------------------

  public UserSequence() {}

  /**
   * Load all user and parameter data into the sequence module.
   *
   * <p>ie a Set of Mapped "parameter names and parameter values" for each user to be loaded into
   * the sequencer.
   */
  public UserSequence(List allUsers) {
    this.allUsers = allUsers;

    // initalise pointer to first user
    indexOfUsers = allUsers.iterator();
  }

  // -------------------------------------------
  // Methods
  // -------------------------------------------

  /**
   * Returns the parameter data for the next user in the sequence
   *
   * @return a Map object of parameter names and matching parameter values for the next user
   */
  public synchronized Map getNextUserMods() {
    // Use round robin allocation of user details
    if (!indexOfUsers.hasNext()) {
      indexOfUsers = allUsers.iterator();
    }

    Map user;
    if (indexOfUsers.hasNext()) {
      user = (Map) indexOfUsers.next();
      log.debug(
          "UserSequence.getNextuserMods(): current parameters will be " + "changed to: " + user);
    } else {
      // no entries in all users, therefore create an empty Map object
      user = new HashMap();
    }

    return user;
  }
}
/**
 * @author Sergey Marakhov
 * @author Linh Pham
 */
public class AndroidDriverConfig extends WebDriverConfig<AndroidDriver> implements ThreadListener {
  private static final long serialVersionUID = 100L;

  private static final Logger LOGGER = LoggingManager.getLoggerForClass();

  private static final String ANDROID_DRIVER_HOST_PORT = "AndroidDriverConfig.driver_host_port";

  @Override
  public void threadStarted() {
    LOGGER.info("AndroidDriverConfig.threadStarted()");

    if (hasThreadBrowser()) {
      LOGGER.warn(
          "Thread: "
              + currentThreadName()
              + " already has a WebDriver("
              + getThreadBrowser()
              + ") associated with it. ThreadGroup can only contain a single WebDriverConfig.");
      return;
    }
    setThreadBrowser(createBrowser());
  }

  DesiredCapabilities createCapabilities() {
    DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setCapability(CapabilityType.PROXY, createProxy());
    return capabilities;
  }

  @Override
  public void threadFinished() {
    final AndroidDriver androidDriver = removeThreadBrowser();
    if (androidDriver != null) {
      androidDriver.quit();
    }
  }

  @Override
  protected AndroidDriver createBrowser() {
    try {
      return new AndroidDriver(new URL(getAndroidDriverUrl()), createCapabilities());
    } catch (MalformedURLException e) {
      LOGGER.error("MalformedURLException thrown for invalid URL: " + getAndroidDriverUrl());
      return null;
    }
  }

  private String getAndroidDriverUrl() {
    return "http://localhost:" + getAndroidDriverHostPort() + "/wd/hub";
  }

  public void setAndroidDriverHostPort(String port) {
    setProperty(ANDROID_DRIVER_HOST_PORT, port);
  }

  public String getAndroidDriverHostPort() {
    return getPropertyAsString(ANDROID_DRIVER_HOST_PORT);
  }
}
예제 #7
0
public class TimeInMillis extends AbstractFunction {

  private static final List<String> desc = new LinkedList<String>();
  private static final String KEY = "__TimeInMillis";
  private static final int MAX_PARAM_COUNT = 1;
  private static final int MIN_PARAM_COUNT = 0;
  private static final Logger log = LoggingManager.getLoggerForClass();
  private Object[] values;

  static {
    desc.add("(Optional)Pass the milliseconds that should be added/subtracted from current time.");
  }

  /** No-arg constructor. */
  public TimeInMillis() {
    super();
  }

  /** {@inheritDoc} */
  @Override
  public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
      throws InvalidVariableException {
    // JMeterVariables vars = getVariables();
    Calendar cal = Calendar.getInstance();

    if (values.length == 1) { // If user has provided offset value then adjust the time.
      log.info("Got one paramenter");
      try {
        Integer offsetTime = new Integer(((CompoundVariable) values[0]).execute().trim());
        cal.add(Calendar.MILLISECOND, offsetTime);
      } catch (Exception e) { // In case user pass invalid parameter.
        throw new InvalidVariableException(e);
      }
    }

    return String.valueOf(cal.getTimeInMillis());
  }

  /** {@inheritDoc} */
  @Override
  public synchronized void setParameters(Collection<CompoundVariable> parameters)
      throws InvalidVariableException {
    checkParameterCount(parameters, MIN_PARAM_COUNT, MAX_PARAM_COUNT);
    values = parameters.toArray();
  }

  /** {@inheritDoc} */
  @Override
  public String getReferenceKey() {
    return KEY;
  }

  /** {@inheritDoc} */
  @Override
  public List<String> getArgumentDesc() {
    return desc;
  }
}
/**
 * This class implements a listener for SMTP events and a monitor for all threads sending mail. The
 * main purpose is to synchronize the send action with the end of communication with remote smtp
 * server, so that sending time can be measured.
 */
public class SynchronousTransportListener extends TransportAdapter {

  private static final Logger logger = LoggingManager.getLoggerForClass();

  private boolean finished = false;

  private final Object LOCK = new Object();

  /** Creates a new instance of SynchronousTransportListener */
  public SynchronousTransportListener() {}

  /** {@inheritDoc} */
  @Override
  public void messageDelivered(TransportEvent e) {
    logger.debug("Message delivered");
    finish();
  }

  /** {@inheritDoc} */
  @Override
  public void messageNotDelivered(TransportEvent e) {
    logger.debug("Message not delivered");
    finish();
  }

  /** {@inheritDoc} */
  @Override
  public void messagePartiallyDelivered(TransportEvent e) {
    logger.debug("Message partially delivered");
    finish();
  }

  /**
   * Synchronized-method
   *
   * @throws InterruptedException
   */
  public void attend() throws InterruptedException {
    synchronized (LOCK) {
      while (!finished) {
        LOCK.wait();
      }
    }
  }

  /** Synchronized-method */
  public void finish() {
    finished = true;
    synchronized (LOCK) {
      LOCK.notify();
    }
  }
}
예제 #9
0
/** Implements the Add Parent menu command */
public class ChangeParent implements Command {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final Set<String> commands = new HashSet<String>();

  static {
    commands.add(ActionNames.CHANGE_PARENT);
  }

  public ChangeParent() {}

  public void doAction(ActionEvent e) {
    String name = ((Component) e.getSource()).getName();
    GuiPackage guiPackage = GuiPackage.getInstance();
    JMeterTreeNode currentNode = guiPackage.getTreeListener().getCurrentNode();
    if (!(currentNode.getUserObject() instanceof Controller)) {
      Toolkit.getDefaultToolkit().beep();
      return;
    }
    try {
      guiPackage.updateCurrentNode();
      TestElement controller = guiPackage.createTestElement(name);
      changeParent(controller, guiPackage, currentNode);
    } catch (Exception err) {
      Toolkit.getDefaultToolkit().beep();
      log.error("Failed to change parent", err);
    }
  }

  public Set<String> getActionNames() {
    return commands;
  }

  private void changeParent(
      TestElement newParent, GuiPackage guiPackage, JMeterTreeNode currentNode) {
    JMeterTreeModel treeModel = guiPackage.getTreeModel();
    JMeterTreeNode newNode = new JMeterTreeNode(newParent, treeModel);
    JMeterTreeNode parentNode = (JMeterTreeNode) currentNode.getParent();
    int index = parentNode.getIndex(currentNode);
    treeModel.insertNodeInto(newNode, parentNode, index);
    treeModel.removeNodeFromParent(currentNode);
    int childCount = currentNode.getChildCount();
    for (int i = 0; i < childCount; i++) {
      // Using index 0 is voluntary as child is removed in next step and added to new parent
      JMeterTreeNode node = (JMeterTreeNode) currentNode.getChildAt(0);
      treeModel.removeNodeFromParent(node);
      treeModel.insertNodeInto(node, newNode, newNode.getChildCount());
    }
  }
}
예제 #10
0
/** @author undera */
public class JMXMetric extends AbstractPerfMonMetric {

  private static final Logger log = LoggingManager.getLoggerForClass();
  private final AbstractJMXDataProvider dataProvider;
  private int dividingFactor = 1;

  public JMXMetric(MetricParams params, JMXConnectorHelper jmxHelper) {
    super(null);
    String url = "localhost:4711";
    String user = "";
    String pwd = "";

    for (int i = 0; i < params.params.length; i++) {
      if (params.params[i].startsWith("url=")) {
        url = MetricParams.getParamValue(params.params[i]);
      } else if (params.params[i].startsWith("user="******"password="******"'url' parameter required for metric type 'jmx'");
    }

    MBeanServerConnection mBeanServerConn = jmxHelper.getServerConnection(url, user, pwd);

    try {
      dataProvider = AbstractJMXDataProvider.getProvider(mBeanServerConn, params.type);
    } catch (Exception ex) {
      log.debug("Failed to get MX Bean data provider", ex);
      throw new RuntimeException("Failed to get MX Bean data provider", ex);
    }

    dividingFactor = getUnitDividingFactor(params.getUnit());
  }

  public void getValue(StringBuffer res) throws Exception {
    if (dataProvider.isBytesValue()) {
      dataProvider.getValue(res, dividingFactor);
    } else {
      dataProvider.getValue(res);
    }
  }
}
public class SocketEmulatorInputStream extends InputStream {
  private static final Logger log = LoggingManager.getLoggerForClass();
  private byte[] bytes;
  private int pos = 0;

  public SocketEmulatorInputStream(byte[] hexStringToByteArray) {
    this();
    setBytesToRead(hexStringToByteArray);
  }

  public SocketEmulatorInputStream() {
    bytes = null;
    pos = 0;
    log.info("Created input stream emulator");
  }

  public final void setBytesToRead(byte[] hexStringToByteArray) {
    log.debug("Set bytes to read: " + Integer.toString(hexStringToByteArray.length));
    bytes = hexStringToByteArray;
  }

  public final void setBytesToRead(String str) {
    setBytesToRead(str.getBytes());
  }

  @Override
  public int read() throws IOException {
    if (bytes == null) {
      log.debug("Expected emulator data was not set");
      return -1;
    }

    if (pos >= bytes.length) {
      log.debug("End of data  reached, resetting buffer");
      bytes = null;
      pos = 0;
      return -1;
    } else {
      final byte byteToret = bytes[pos];
      pos++;
      // log.debug("Byte: #"+Integer.toString(pos)+" "+Byte.toString(byteToret));
      return byteToret;
    }
  }
}
/*
 * Note: This helper class appeared in JavaWorld in June 2001
 * (http://www.javaworld.com) and was written by Michael Daconta.
 *
 */
public class FocusRequester implements Runnable {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private final Component comp;

  public FocusRequester(Component comp) {
    this.comp = comp;
    try {
      SwingUtilities.invokeLater(this);
    } catch (Exception e) {
      log.error("", e); // $NON-NLS-1$
    }
  }

  @Override
  public void run() {
    comp.requestFocus();
  }
}
public class JSR223PostProcessor extends JSR223TestElement
    implements Cloneable, PostProcessor, TestBean {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final long serialVersionUID = 232L;

  public void process() {

    try {
      ScriptEngineManager sem = getManager();
      if (sem == null) {
        return;
      }
      processFileOrScript(sem);
    } catch (ScriptException e) {
      log.warn("Problem in JSR223 script " + e);
    } catch (IOException e) {
      log.warn("Problem in JSR223 script " + e);
    }
  }
}
예제 #14
0
/** Implements an HTML Pane with local hyperlinking enabled. */
public class HtmlPane extends JTextPane {
  private static final Logger log = LoggingManager.getLoggerForClass();

  public HtmlPane() {
    this.addHyperlinkListener(
        new HyperlinkListener() {
          public void hyperlinkUpdate(HyperlinkEvent e) {
            if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
              String ref = e.getURL().getRef();
              if (ref != null && ref.length() > 0) {
                log.debug("reference to scroll to = " + ref);
                scrollToReference(ref);
              }
            }
          }
        });
  }

  public void scrollToReference(String reference) {
    super.scrollToReference(reference);
  }
}
예제 #15
0
/**
 * Thread that copies a stream in the background; closes both input and output streams.
 *
 * @since 2.8
 */
class StreamCopier extends Thread {

  private static final Logger log = LoggingManager.getLoggerForClass();

  private final InputStream is;
  private final OutputStream os;

  /**
   * @param is {@link InputStream}
   * @param is {@link OutputStream}
   * @throws IOException
   */
  StreamCopier(InputStream is, OutputStream os) throws IOException {
    this.is = is;
    this.os = os;
  }

  /** @see java.lang.Thread#run() */
  @Override
  public void run() {
    final boolean isSystemOutput = os.equals(System.out) || os.equals(System.err);
    try {
      IOUtils.copyLarge(is, os);
      if (!isSystemOutput) {
        os.close();
      }
      is.close();
    } catch (IOException e) {
      log.warn("Error writing stream", e);
    } finally {
      IOUtils.closeQuietly(is);
      if (!isSystemOutput) {
        IOUtils.closeQuietly(os);
      }
    }
  }
}
public class PluginManagerMenuCreator implements MenuCreator {
  private static final Logger log = LoggingManager.getLoggerForClass();

  @Override
  public JMenuItem[] getMenuItemsAtLocation(MENU_LOCATION location) {
    if (location == MENU_LOCATION.OPTIONS) {
      try {
        PluginManagerCMDInstaller.main(new String[0]);
      } catch (Throwable e) {
        log.warn("Was unable to install pmgr cmdline tool", e);
      }

      try {
        return new JMenuItem[] {new PluginManagerMenuItem()};
      } catch (Throwable e) {
        log.error("Failed to load Plugins Manager", e);
        return new JMenuItem[0];
      }
    } else {
      return new JMenuItem[0];
    }
  }

  @Override
  public javax.swing.JMenu[] getTopLevelMenus() {
    return new javax.swing.JMenu[0];
  }

  @Override
  public boolean localeChanged(javax.swing.MenuElement menu) {
    return false;
  }

  @Override
  public void localeChanged() {}
}
/** Implements batch reporting for remote testing. */
public class StatisticalSampleSender implements SampleSender, Serializable {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final int DEFAULT_NUM_SAMPLE_THRESHOLD = 100;

  private static final long DEFAULT_TIME_THRESHOLD = 60000L;

  private RemoteSampleListener listener;

  private List sampleStore = new ArrayList();

  private Map sampleTable = new HashMap();

  private int numSamplesThreshold;

  private int sampleCount;

  private long timeThreshold;

  private long batchSendTime = -1;

  public StatisticalSampleSender() {
    log.warn("Constructor only intended for use in testing");
  }

  /**
   * Constructor
   *
   * @param listener that the List of sample events will be sent to.
   */
  StatisticalSampleSender(RemoteSampleListener listener) {
    this.listener = listener;
    init();
    log.info(
        "Using batching for this run."
            + " Thresholds: num="
            + numSamplesThreshold
            + ", time="
            + timeThreshold);
  }

  /**
   * Checks for the Jmeter properties num_sample_threshold and time_threshold, and assigns defaults
   * if not found.
   */
  private void init() {
    this.numSamplesThreshold =
        JMeterUtils.getPropDefault("num_sample_threshold", DEFAULT_NUM_SAMPLE_THRESHOLD);
    this.timeThreshold = JMeterUtils.getPropDefault("time_threshold", DEFAULT_TIME_THRESHOLD);
  }

  /**
   * Checks if any sample events are still present in the sampleStore and sends them to the
   * listener. Informs the listener of the testended.
   */
  public void testEnded() {
    try {
      if (sampleStore.size() != 0) {
        sendBatch();
      }
      listener.testEnded();
    } catch (RemoteException err) {
      log.warn("testEnded()", err);
    }
  }

  /**
   * Checks if any sample events are still present in the sampleStore and sends them to the
   * listener. Informs the listener of the testended.
   *
   * @param host the hostname that the test has ended on.
   */
  public void testEnded(String host) {
    try {
      if (sampleStore.size() != 0) {
        sendBatch();
      }
      listener.testEnded(host);
    } catch (RemoteException err) {
      log.warn("testEnded(hostname)", err);
    }
  }

  /**
   * Stores sample events untill either a time or sample threshold is breached. Both thresholds are
   * reset if one fires. If only one threshold is set it becomes the only value checked against.
   * When a threhold is breached the list of sample events is sent to a listener where the event are
   * fired locally.
   *
   * @param e a Sample Event
   */
  public void sampleOccurred(SampleEvent e) {
    synchronized (sampleStore) {
      // Locate the statistical sample colector
      String key = StatisticalSampleResult.getKey(e);
      StatisticalSampleResult statResult = (StatisticalSampleResult) sampleTable.get(key);
      if (statResult == null) {
        statResult = new StatisticalSampleResult(e.getResult());
        // store the new statistical result collector
        sampleTable.put(key, statResult);
        // add a new wrapper samplevent
        sampleStore.add(new SampleEvent(statResult, e.getThreadGroup()));
      }
      statResult.add(e.getResult());
      sampleCount++;
      if (numSamplesThreshold != -1) {
        if (sampleCount >= numSamplesThreshold) {
          try {
            if (log.isDebugEnabled()) {
              log.debug("Firing sample");
            }
            sendBatch();
          } catch (RemoteException err) {
            log.warn("sampleOccurred", err);
          }
        }
      }

      if (timeThreshold != -1) {
        long now = System.currentTimeMillis();
        // Checking for and creating initial timestamp to cheak against
        if (batchSendTime == -1) {
          this.batchSendTime = now + timeThreshold;
        }

        if (batchSendTime < now) {
          try {
            if (log.isDebugEnabled()) {
              log.debug("Firing time");
            }
            sendBatch();
            this.batchSendTime = now + timeThreshold;
          } catch (RemoteException err) {
            log.warn("sampleOccurred", err);
          }
        }
      }
    }
  }

  private void sendBatch() throws RemoteException {
    if (sampleStore.size() > 0) {
      listener.processBatch(sampleStore);
      sampleStore.clear();
      sampleTable.clear();
      sampleCount = 0;
    }
  }
}
예제 #18
0
/**
 * HtmlParser implementation using regular expressions.
 *
 * <p>This class will find RLs specified in the following ways (where <b>url</b> represents the RL
 * being found:
 *
 * <ul>
 *   <li>&lt;img src=<b>url</b> ... &gt;
 *   <li>&lt;script src=<b>url</b> ... &gt;
 *   <li>&lt;applet code=<b>url</b> ... &gt;
 *   <li>&lt;input type=image src=<b>url</b> ... &gt;
 *   <li>&lt;body background=<b>url</b> ... &gt;
 *   <li>&lt;table background=<b>url</b> ... &gt;
 *   <li>&lt;td background=<b>url</b> ... &gt;
 *   <li>&lt;tr background=<b>url</b> ... &gt;
 *   <li>&lt;applet ... codebase=<b>url</b> ... &gt;
 *   <li>&lt;embed src=<b>url</b> ... &gt;
 *   <li>&lt;embed codebase=<b>url</b> ... &gt;
 *   <li>&lt;object codebase=<b>url</b> ... &gt;
 *   <li>&lt;link rel=stylesheet href=<b>url</b>... gt;
 *   <li>&lt;bgsound src=<b>url</b> ... &gt;
 *   <li>&lt;frame src=<b>url</b> ... &gt;
 * </ul>
 *
 * <p>This class will take into account the following construct:
 *
 * <ul>
 *   <li>&lt;base href=<b>url</b>&gt;
 * </ul>
 *
 * <p>But not the following:
 *
 * <ul>
 *   <li>&lt; ... codebase=<b>url</b> ... &gt;
 * </ul>
 */
class RegexpHTMLParser extends HTMLParser {
  private static final Logger log = LoggingManager.getLoggerForClass();

  /**
   * Regexp fragment matching a tag attribute's value (including the equals sign and any spaces
   * before it). Note it matches unquoted values, which to my understanding, are not conformant to
   * any of the HTML specifications, but are still quite common in the web and all browsers seem to
   * understand them.
   */
  private static final String VALUE =
      "\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\"'\\s>\\\\][^\\s>]*)(?=[\\s>]))";

  // Note there's 3 capturing groups per value

  /** Regexp fragment matching the separation between two tag attributes. */
  private static final String SEP = "\\s(?:[^>]*\\s)?";

  /** Regular expression used against the HTML code to find the URIs of images, etc.: */
  private static final String REGEXP =
      "<(?:"
          + "!--.*?-->"
          + "|BASE"
          + SEP
          + "HREF"
          + VALUE
          + "|(?:IMG|SCRIPT|FRAME|IFRAME|BGSOUND)"
          + SEP
          + "SRC"
          + VALUE
          + "|APPLET"
          + SEP
          + "CODE(?:BASE)?"
          + VALUE
          + "|(?:EMBED|OBJECT)"
          + SEP
          + "(?:SRC|CODEBASE|DATA)"
          + VALUE
          + "|(?:BODY|TABLE|TR|TD)"
          + SEP
          + "BACKGROUND"
          + VALUE
          + "|[^<]+?STYLE\\s*=['\"].*?URL\\(\\s*['\"](.+?)['\"]\\s*\\)"
          + "|INPUT(?:"
          + SEP
          + "(?:SRC"
          + VALUE
          + "|TYPE\\s*=\\s*(?:\"image\"|'image'|image(?=[\\s>])))){2,}"
          + "|LINK(?:"
          + SEP
          + "(?:HREF"
          + VALUE
          + "|REL\\s*=\\s*(?:\"stylesheet\"|'stylesheet'|stylesheet(?=[\\s>])))){2,}"
          + ")";

  // Number of capturing groups possibly containing Base HREFs:
  private static final int NUM_BASE_GROUPS = 3;

  /** Thread-local input: */
  private static final ThreadLocal<PatternMatcherInput> localInput =
      new ThreadLocal<PatternMatcherInput>() {
        @Override
        protected PatternMatcherInput initialValue() {
          return new PatternMatcherInput(new char[0]);
        }
      };

  /** {@inheritDoc} */
  @Override
  protected boolean isReusable() {
    return true;
  }

  /** Make sure to compile the regular expression upon instantiation: */
  protected RegexpHTMLParser() {
    super();
  }

  /** {@inheritDoc} */
  @Override
  public Iterator<URL> getEmbeddedResourceURLs(
      String userAgent, byte[] html, URL baseUrl, URLCollection urls, String encoding)
      throws HTMLParseException {
    Pattern pattern = null;
    Perl5Matcher matcher = null;
    try {
      matcher = JMeterUtils.getMatcher();
      PatternMatcherInput input = localInput.get();
      // TODO: find a way to avoid the cost of creating a String here --
      // probably a new PatternMatcherInput working on a byte[] would do
      // better.
      input.setInput(new String(html, encoding));
      pattern =
          JMeterUtils.getPatternCache()
              .getPattern(
                  REGEXP,
                  Perl5Compiler.CASE_INSENSITIVE_MASK
                      | Perl5Compiler.SINGLELINE_MASK
                      | Perl5Compiler.READ_ONLY_MASK);

      while (matcher.contains(input, pattern)) {
        MatchResult match = matcher.getMatch();
        String s;
        if (log.isDebugEnabled()) {
          log.debug("match groups " + match.groups() + " " + match.toString());
        }
        // Check for a BASE HREF:
        for (int g = 1; g <= NUM_BASE_GROUPS && g <= match.groups(); g++) {
          s = match.group(g);
          if (s != null) {
            if (log.isDebugEnabled()) {
              log.debug("new baseUrl: " + s + " - " + baseUrl.toString());
            }
            try {
              baseUrl = ConversionUtils.makeRelativeURL(baseUrl, s);
            } catch (MalformedURLException e) {
              // Doesn't even look like a URL?
              // Maybe it isn't: Ignore the exception.
              if (log.isDebugEnabled()) {
                log.debug("Can't build base URL from RL " + s + " in page " + baseUrl, e);
              }
            }
          }
        }
        for (int g = NUM_BASE_GROUPS + 1; g <= match.groups(); g++) {
          s = match.group(g);
          if (s != null) {
            if (log.isDebugEnabled()) {
              log.debug("group " + g + " - " + match.group(g));
            }
            urls.addURL(s, baseUrl);
          }
        }
      }
      return urls.iterator();
    } catch (UnsupportedEncodingException e) {
      throw new HTMLParseException(e.getMessage(), e);
    } catch (MalformedCachePatternException e) {
      throw new HTMLParseException(e.getMessage(), e);
    } finally {
      JMeterUtils.clearMatcherMemory(matcher, pattern);
    }
  }
}
/** This is the JMeter server main code. */
public final class RemoteJMeterEngineImpl extends java.rmi.server.UnicastRemoteObject
    implements RemoteJMeterEngine {
  private static final long serialVersionUID = 240L;

  private static final Logger log = LoggingManager.getLoggerForClass();

  static final String JMETER_ENGINE_RMI_NAME = "JMeterEngine"; // $NON-NLS-1$

  private transient JMeterEngine backingEngine;

  private transient Thread ownerThread;

  private static final int DEFAULT_RMI_PORT =
      JMeterUtils.getPropDefault("server.rmi.port", 1099); // $NON-NLS-1$

  private static final int DEFAULT_LOCAL_PORT =
      JMeterUtils.getPropDefault("server.rmi.localport", 0); // $NON-NLS-1$

  static {
    if (DEFAULT_LOCAL_PORT != 0) {
      System.out.println("Using local port: " + DEFAULT_LOCAL_PORT);
    }
  }

  // Should we create our own copy of the RMI registry?
  private static final boolean createServer =
      JMeterUtils.getPropDefault("server.rmi.create", true); // $NON-NLS-1$

  private final Object LOCK = new Object();

  private final int rmiPort;

  private Properties remotelySetProperties;

  private RemoteJMeterEngineImpl(int localPort, int rmiPort) throws RemoteException {
    super(localPort); // Create this object using the specified port (0 means anonymous)
    this.rmiPort = rmiPort;
    System.out.println("Created remote object: " + this.getRef().remoteToString());
  }

  public static void startServer(int rmiPort) throws RemoteException {
    RemoteJMeterEngineImpl engine =
        new RemoteJMeterEngineImpl(DEFAULT_LOCAL_PORT, rmiPort == 0 ? DEFAULT_RMI_PORT : rmiPort);
    engine.init();
  }

  private void init() throws RemoteException {
    log.info("Starting backing engine on " + this.rmiPort);
    InetAddress localHost = null;
    // Bug 47980 - allow override of local hostname
    String host = System.getProperties().getProperty("java.rmi.server.hostname"); // $NON-NLS-1$
    try {
      if (host == null) {
        localHost = InetAddress.getLocalHost();
      } else {
        localHost = InetAddress.getByName(host);
      }
    } catch (UnknownHostException e1) {
      throw new RemoteException("Cannot start. Unable to get local host IP address.", e1);
    }
    log.info("IP address=" + localHost.getHostAddress());
    String hostName = localHost.getHostName();
    // BUG 52469 : Allow loopback address for SSH Tunneling of RMI traffic
    if (localHost.isLoopbackAddress() && host == null) {
      throw new RemoteException("Cannot start. " + hostName + " is a loopback address.");
    }
    if (localHost.isSiteLocalAddress()) {
      // should perhaps be log.warn, but this causes the client-server test to fail
      log.info(
          "IP address is a site-local address; this may cause problems with remote access.\n"
              + "\tCan be overridden by defining the system property 'java.rmi.server.hostname' - see jmeter-server script file");
    }
    log.debug("This = " + this);
    if (createServer) {
      log.info("Creating RMI registry (server.rmi.create=true)");
      try {
        LocateRegistry.createRegistry(this.rmiPort);
      } catch (RemoteException e) {
        String msg = "Problem creating registry: " + e;
        log.warn(msg);
        System.err.println(msg);
        System.err.println("Continuing...");
      }
    }
    try {
      Registry reg = LocateRegistry.getRegistry(this.rmiPort);
      reg.rebind(JMETER_ENGINE_RMI_NAME, this);
      log.info("Bound to registry on port " + this.rmiPort);
    } catch (Exception ex) {
      log.error(
          "rmiregistry needs to be running to start JMeter in server "
              + "mode\n\t"
              + ex.toString());
      // Throw an Exception to ensure caller knows ...
      throw new RemoteException("Cannot start. See server log file.", ex);
    }
  }

  /**
   * Adds a feature to the ThreadGroup attribute of the RemoteJMeterEngineImpl object.
   *
   * @param testTree the feature to be added to the ThreadGroup attribute
   */
  @Override
  public void rconfigure(HashTree testTree, String host, File jmxBase, String scriptName)
      throws RemoteException {
    log.info("Creating JMeter engine on host " + host + " base '" + jmxBase + "'");
    synchronized (LOCK) { // close window where another remote client might jump in
      if (backingEngine != null && backingEngine.isActive()) {
        log.warn("Engine is busy - cannot create JMeter engine");
        throw new IllegalStateException("Engine is busy - please try later");
      }
      ownerThread = Thread.currentThread();
      backingEngine = new StandardJMeterEngine(host);
      backingEngine.configure(testTree); // sets active = true
    }
    FileServer.getFileServer().setScriptName(scriptName);
    FileServer.getFileServer().setBase(jmxBase);
  }

  @Override
  public void rrunTest() throws RemoteException, JMeterEngineException, IllegalStateException {
    log.info("Running test");
    checkOwner("runTest");
    backingEngine.runTest();
  }

  @Override
  public void rreset() throws RemoteException, IllegalStateException {
    // Mail on userlist reported NPE here - looks like only happens if there are network errors, but
    // check anyway
    if (backingEngine != null) {
      log.info("Reset");
      checkOwner("reset");
      backingEngine.reset();
    } else {
      log.warn("Backing engine is null, ignoring reset");
    }
  }

  @Override
  public void rstopTest(boolean now) throws RemoteException {
    if (now) {
      log.info("Stopping test ...");
    } else {
      log.info("Shutting test ...");
    }
    backingEngine.stopTest(now);
    log.info("... stopped");
  }

  /*
   * Called by:
   * - ClientJMeterEngine.exe() which is called on remoteStop
   */
  @Override
  public void rexit() throws RemoteException {
    log.info("Exitting");
    backingEngine.exit();
    // Tidy up any objects we created
    Registry reg = LocateRegistry.getRegistry(this.rmiPort);
    try {
      reg.unbind(JMETER_ENGINE_RMI_NAME);
    } catch (NotBoundException e) {
      log.warn(JMETER_ENGINE_RMI_NAME + " is not bound", e);
    }
    log.info("Unbound from registry");
    // Help with garbage control
    JMeterUtils.helpGC();
  }

  @Override
  public void rsetProperties(Properties p) throws RemoteException, IllegalStateException {
    checkOwner("setProperties");
    if (remotelySetProperties != null) {
      Properties jmeterProperties = JMeterUtils.getJMeterProperties();
      log.info("Cleaning previously set properties " + remotelySetProperties);
      for (Iterator<?> iterator = remotelySetProperties.keySet().iterator(); iterator.hasNext(); ) {
        String key = (String) iterator.next();
        jmeterProperties.remove(key);
      }
    }
    backingEngine.setProperties(p);
    this.remotelySetProperties = p;
  }

  /**
   * Check if the caller owns the engine.
   *
   * @param methodName the name of the method for the log message
   * @throws IllegalStateException if the caller is not the owner.
   */
  private void checkOwner(String methodName) throws IllegalStateException {
    if (ownerThread != null && ownerThread != Thread.currentThread()) {
      String msg = "The engine is not owned by this thread - cannot call " + methodName;
      log.warn(msg);
      throw new IllegalStateException(msg);
    }
  }
}
예제 #20
0
/**
 * Utility class to handle text files as a single lump of text.
 *
 * <p>Note this is just as memory-inefficient as handling a text file can be. Use with restraint.
 *
 * @version $Revision$
 */
public class TextFile extends File {
  private static final long serialVersionUID = 240L;

  private static final Logger log = LoggingManager.getLoggerForClass();

  /** File encoding. null means use the platform's default. */
  private String encoding = null;

  /**
   * Create a TextFile object to handle the named file with the given encoding.
   *
   * @param filename File to be read & written through this object.
   * @param encoding Encoding to be used when reading & writing this file.
   */
  public TextFile(File filename, String encoding) {
    super(filename.toString());
    setEncoding(encoding);
  }

  /**
   * Create a TextFile object to handle the named file with the platform default encoding.
   *
   * @param filename File to be read & written through this object.
   */
  public TextFile(File filename) {
    super(filename.toString());
  }

  /**
   * Create a TextFile object to handle the named file with the platform default encoding.
   *
   * @param filename Name of the file to be read & written through this object.
   */
  public TextFile(String filename) {
    super(filename);
  }

  /**
   * Create a TextFile object to handle the named file with the given encoding.
   *
   * @param filename Name of the file to be read & written through this object.
   * @param encoding Encoding to be used when reading & writing this file.
   */
  public TextFile(String filename, String encoding) {
    super(filename);
    setEncoding(encoding);
  }

  /**
   * Create the file with the given string as content -- or replace it's content with the given
   * string if the file already existed.
   *
   * @param body New content for the file.
   */
  public void setText(String body) {
    Writer writer = null;
    try {
      if (encoding == null) {
        writer = new FileWriter(this);
      } else {
        writer = new OutputStreamWriter(new FileOutputStream(this), encoding);
      }
      writer.write(body);
      writer.flush();
    } catch (IOException ioe) {
      log.error("", ioe);
    } finally {
      JOrphanUtils.closeQuietly(writer);
    }
  }

  /**
   * Read the whole file content and return it as a string.
   *
   * @return the content of the file
   */
  public String getText() {
    String lineEnd = System.getProperty("line.separator"); // $NON-NLS-1$
    StringBuilder sb = new StringBuilder();
    Reader reader = null;
    BufferedReader br = null;
    try {
      if (encoding == null) {
        reader = new FileReader(this);
      } else {
        reader = new InputStreamReader(new FileInputStream(this), encoding);
      }
      br = new BufferedReader(reader);
      String line = "NOTNULL"; // $NON-NLS-1$
      while (line != null) {
        line = br.readLine();
        if (line != null) {
          sb.append(line + lineEnd);
        }
      }
    } catch (IOException ioe) {
      log.error("", ioe); // $NON-NLS-1$
    } finally {
      JOrphanUtils.closeQuietly(br); // closes reader as well
    }

    return sb.toString();
  }

  /** @return Encoding being used to read & write this file. */
  public String getEncoding() {
    return encoding;
  }

  /** @param string Encoding to be used to read & write this file. */
  public void setEncoding(String string) {
    encoding = string;
  }

  /** {@inheritDoc} */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + ((encoding == null) ? 0 : encoding.hashCode());
    return result;
  }

  /** {@inheritDoc} */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!super.equals(obj)) {
      return false;
    }
    if (!(obj instanceof TextFile)) {
      return false;
    }
    TextFile other = (TextFile) obj;
    if (encoding == null) {
      return other.encoding == null;
    }
    return encoding.equals(other.encoding);
  }
}
/** Implements binary length-prefixed binary data. This is used in ISO8583 for example. */
public class LengthPrefixedBinaryTCPClientImpl extends TCPClientDecorator {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private final int lengthPrefixLen =
      JMeterUtils.getPropDefault("tcp.binarylength.prefix.length", 2); // $NON-NLS-1$

  public LengthPrefixedBinaryTCPClientImpl() {
    super(new BinaryTCPClientImpl());
    tcpClient.setEolByte(Byte.MAX_VALUE + 1);
  }

  /** {@inheritDoc} */
  @Override
  public void write(OutputStream os, String s) throws IOException {
    os.write(intToByteArray(s.length() / 2, lengthPrefixLen));
    if (log.isDebugEnabled()) {
      log.debug("Wrote: " + s.length() / 2 + " bytes");
    }
    this.tcpClient.write(os, s);
  }

  /** {@inheritDoc} */
  @Override
  public void write(OutputStream os, InputStream is) throws IOException {
    this.tcpClient.write(os, is);
  }

  /** {@inheritDoc} */
  @Override
  public String read(InputStream is) throws ReadException {
    byte[] msg = new byte[0];
    int msgLen = 0;
    byte[] lengthBuffer = new byte[lengthPrefixLen];
    try {
      if (is.read(lengthBuffer, 0, lengthPrefixLen) == lengthPrefixLen) {
        msgLen = byteArrayToInt(lengthBuffer);
        msg = new byte[msgLen];
        int bytes = JOrphanUtils.read(is, msg, 0, msgLen);
        if (bytes < msgLen) {
          log.warn("Incomplete message read, expected: " + msgLen + " got: " + bytes);
        }
      }

      String buffer = JOrphanUtils.baToHexString(msg);
      if (log.isDebugEnabled()) {
        log.debug("Read: " + msgLen + "\n" + buffer);
      }
      return buffer;
    } catch (IOException e) {
      throw new ReadException("", e, JOrphanUtils.baToHexString(msg));
    }
  }

  /**
   * Not useful, as the byte is never used.
   *
   * <p>{@inheritDoc}
   */
  @Override
  public byte getEolByte() {
    return tcpClient.getEolByte();
  }

  /** {@inheritDoc} */
  @Override
  public void setEolByte(int eolInt) {
    throw new UnsupportedOperationException("Cannot set eomByte for prefixed messages");
  }
}
public class UserParameters extends AbstractTestElement
    implements Serializable, PreProcessor, LoopIterationListener {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final long serialVersionUID = 233L;

  public static final String NAMES = "UserParameters.names"; // $NON-NLS-1$

  public static final String THREAD_VALUES = "UserParameters.thread_values"; // $NON-NLS-1$

  public static final String PER_ITERATION = "UserParameters.per_iteration"; // $NON-NLS-1$

  /*
   * Although the lock appears to be an instance lock, in fact the lock is
   * shared between all threads in a thread group, but different thread groups
   * have different locks - see the clone() method below
   *
   * The lock ensures that all the variables are processed together, which is
   * important for functions such as __CSVRead and _StringFromFile.
   */
  private transient Object lock = new Object();

  private Object readResolve() { // Lock object must exist
    lock = new Object();
    return this;
  }

  public CollectionProperty getNames() {
    return (CollectionProperty) getProperty(NAMES);
  }

  public CollectionProperty getThreadLists() {
    return (CollectionProperty) getProperty(THREAD_VALUES);
  }

  /**
   * The list of names of the variables to hold values. This list must come in the same order as the
   * sub lists that are given to {@link #setThreadLists(Collection)}.
   */
  public void setNames(Collection<?> list) {
    setProperty(new CollectionProperty(NAMES, list));
  }

  /**
   * The list of names of the variables to hold values. This list must come in the same order as the
   * sub lists that are given to {@link #setThreadLists(CollectionProperty)}.
   */
  public void setNames(CollectionProperty list) {
    setProperty(list);
  }

  /**
   * The thread list is a list of lists. Each list within the parent list is a collection of values
   * for a simulated user. As many different sets of values can be supplied in this fashion to cause
   * JMeter to set different values to variables for different test threads.
   */
  public void setThreadLists(Collection<?> threadLists) {
    setProperty(new CollectionProperty(THREAD_VALUES, threadLists));
  }

  /**
   * The thread list is a list of lists. Each list within the parent list is a collection of values
   * for a simulated user. As many different sets of values can be supplied in this fashion to cause
   * JMeter to set different values to variables for different test threads.
   */
  public void setThreadLists(CollectionProperty threadLists) {
    setProperty(threadLists);
  }

  private CollectionProperty getValues() {
    CollectionProperty threadValues = (CollectionProperty) getProperty(THREAD_VALUES);
    if (threadValues.size() > 0) {
      return (CollectionProperty)
          threadValues.get(getThreadContext().getThreadNum() % threadValues.size());
    }
    return new CollectionProperty("noname", new LinkedList<Object>());
  }

  public boolean isPerIteration() {
    return getPropertyAsBoolean(PER_ITERATION);
  }

  public void setPerIteration(boolean perIter) {
    setProperty(new BooleanProperty(PER_ITERATION, perIter));
  }

  @Override
  public void process() {
    if (log.isDebugEnabled()) {
      log.debug(Thread.currentThread().getName() + " process " + isPerIteration()); // $NON-NLS-1$
    }
    if (!isPerIteration()) {
      setValues();
    }
  }

  private void setValues() {
    synchronized (lock) {
      if (log.isDebugEnabled()) {
        log.debug(
            Thread.currentThread().getName() + " Running up named: " + getName()); // $NON-NLS-1$
      }
      PropertyIterator namesIter = getNames().iterator();
      PropertyIterator valueIter = getValues().iterator();
      JMeterVariables jmvars = getThreadContext().getVariables();
      while (namesIter.hasNext() && valueIter.hasNext()) {
        String name = namesIter.next().getStringValue();
        String value = valueIter.next().getStringValue();
        if (log.isDebugEnabled()) {
          log.debug(
              Thread.currentThread().getName()
                  + " saving variable: "
                  + name
                  + "="
                  + value); //$NON-NLS-1$
        }
        jmvars.put(name, value);
      }
    }
  }

  /** @see LoopIterationListener#iterationStart(LoopIterationEvent) */
  @Override
  public void iterationStart(LoopIterationEvent event) {
    if (log.isDebugEnabled()) {
      log.debug(
          Thread.currentThread().getName() + " iteration start " + isPerIteration()); // $NON-NLS-1$
    }
    if (isPerIteration()) {
      setValues();
    }
  }

  /*
   * (non-Javadoc) A new instance is created for each thread group, and the
   * clone() method is then called to create copies for each thread in a
   * thread group. This means that the lock object is common to a thread
   * group; separate thread groups have separate locks. If this is not
   * intended, the lock object could be made static.
   *
   * @see java.lang.Object#clone()
   */
  @Override
  public Object clone() {
    UserParameters up = (UserParameters) super.clone();
    up.lock = lock; // ensure that clones share the same lock object
    return up;
  }

  /** {@inheritDoc} */
  @Override
  protected void mergeIn(TestElement element) {
    // super.mergeIn(element);
  }
}
public class DependencyResolver {
  private static final Logger log = LoggingManager.getLoggerForClass();
  public static final String JAVA_CLASS_PATH = "java.class.path";
  protected final Set<Plugin> deletions = new HashSet<>();
  protected final Set<Plugin> additions = new HashSet<>();
  protected final Map<String, String> libAdditions = new HashMap<>();
  protected final Set<String> libDeletions = new HashSet<>();
  protected final Map<Plugin, Boolean> allPlugins;

  public DependencyResolver(Map<Plugin, Boolean> allPlugins) {
    this.allPlugins = allPlugins;

    resolveFlags();
    resolveUpgrades();
    resolveDeleteByDependency();
    resolveInstallByDependency();
    resolveDeleteLibs();
    resolveInstallLibs();
  }

  // TODO: return iterators to make values read-only
  public Set<Plugin> getDeletions() {
    return deletions;
  }

  public Set<Plugin> getAdditions() {
    return additions;
  }

  public Map<String, String> getLibAdditions() {
    return libAdditions;
  }

  public Set<String> getLibDeletions() {
    return libDeletions;
  }

  private Plugin getPluginByID(String id) {
    for (Plugin plugin : allPlugins.keySet()) {
      if (plugin.getID().equals(id)) {
        return plugin;
      }
    }
    throw new RuntimeException("Plugin not found by ID: " + id);
  }

  private Set<Plugin> getDependants(Plugin plugin) {
    Set<Plugin> res = new HashSet<>();
    for (Plugin pAll : allPlugins.keySet()) {
      for (String depID : pAll.getDepends()) {
        if (depID.equals(plugin.getID())) {
          res.add(pAll);
        }
      }
    }
    return res;
  }

  private void resolveFlags() {
    for (Map.Entry<Plugin, Boolean> entry : allPlugins.entrySet()) {
      if (entry.getKey().isInstalled()) {
        if (!entry.getValue()) {
          deletions.add(entry.getKey());
        }
      } else if (entry.getValue()) {
        additions.add(entry.getKey());
      }
    }
  }

  private void resolveUpgrades() {
    // detect upgrades
    for (Map.Entry<Plugin, Boolean> entry : allPlugins.entrySet()) {
      Plugin plugin = entry.getKey();
      if (entry.getValue()
          && plugin.isInstalled()
          && !plugin.getInstalledVersion().equals(plugin.getCandidateVersion())) {
        log.debug("Upgrade: " + plugin);
        deletions.add(plugin);
        additions.add(plugin);
      }
    }
  }

  private void resolveDeleteByDependency() {
    // delete by depend
    boolean hasModifications = true;
    while (hasModifications) {
      log.debug("Check uninstall dependencies");
      hasModifications = false;
      for (Plugin plugin : deletions) {
        if (!additions.contains(plugin)) {
          for (Plugin dep : getDependants(plugin)) {
            if (!deletions.contains(dep) && dep.isInstalled()) {
              log.debug("Add to deletions: " + dep);
              deletions.add(dep);
              hasModifications = true;
            }
            if (additions.contains(dep)) {
              log.debug("Remove from additions: " + dep);
              additions.remove(dep);
              hasModifications = true;
            }
          }
        }

        if (hasModifications) {
          break; // prevent ConcurrentModificationException
        }
      }
    }
  }

  private void resolveInstallByDependency() {
    // resolve dependencies
    boolean hasModifications = true;
    while (hasModifications) {
      log.debug("Check install dependencies: " + additions);
      hasModifications = false;
      for (Plugin plugin : additions) {
        for (String pluginID : plugin.getDepends()) {
          Plugin depend = getPluginByID(pluginID);

          if (!depend.isInstalled() || deletions.contains(depend)) {
            if (!additions.contains(depend)) {
              log.debug("Add to install: " + depend);
              additions.add(depend);
              hasModifications = true;
            }
          }
        }

        if (hasModifications) {
          break; // prevent ConcurrentModificationException
        }
      }
    }
  }

  private void resolveInstallLibs() {
    for (Plugin plugin : additions) {
      Map<String, String> libs = plugin.getLibs(plugin.getCandidateVersion());
      for (String lib : libs.keySet()) {
        if (Plugin.getLibInstallPath(lib) == null) {
          libAdditions.put(lib, libs.get(lib));
        }
      }
    }
  }

  private void resolveDeleteLibs() {
    for (Plugin plugin : deletions) {
      if (additions.contains(plugin)) { // skip upgrades
        continue;
      }

      Map<String, String> libs = plugin.getLibs(plugin.getInstalledVersion());
      for (String lib : libs.keySet()) {
        if (Plugin.getLibInstallPath(lib) != null) {
          libDeletions.add(lib);
        } else {
          log.warn("Did not find library to uninstall it: " + lib);
        }
      }
    }

    for (Plugin plugin : allPlugins.keySet()) {
      if (additions.contains(plugin) || (plugin.isInstalled() && !deletions.contains(plugin))) {
        String ver =
            additions.contains(plugin)
                ? plugin.getCandidateVersion()
                : plugin.getInstalledVersion();
        // log.debug("Affects " + plugin + " v" + ver);
        Map<String, String> libs = plugin.getLibs(ver);
        for (String lib : libs.keySet()) {
          if (libDeletions.contains(lib)) {
            log.debug("Won't delete lib " + lib + " since it is used by " + plugin);
            libDeletions.remove(lib);
          }
        }
      }
    }
  }
}
예제 #24
0
/**
 * ForeachController that iterates over a list of variables named XXXX_NN stored in {@link
 * JMeterVariables} where NN is a number starting from 1 to number of occurences. This list of
 * variable is usually set by PostProcessor (Regexp PostProcessor or {@link HtmlExtractor})
 * Iteration can take the full list or only a subset (configured through indexes)
 */
public class ForeachController extends GenericController implements Serializable {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final long serialVersionUID = 240L;

  private static final String INPUTVAL = "ForeachController.inputVal"; // $NON-NLS-1$

  private static final String START_INDEX = "ForeachController.startIndex"; // $NON-NLS-1$

  private static final String END_INDEX = "ForeachController.endIndex"; // $NON-NLS-1$

  private static final String RETURNVAL = "ForeachController.returnVal"; // $NON-NLS-1$

  private static final String USE_SEPARATOR = "ForeachController.useSeparator"; // $NON-NLS-1$

  private static final String INDEX_DEFAULT_VALUE =
      ""; // start/end index default value for string getters and setters

  private int loopCount = 0;

  private static final String DEFAULT_SEPARATOR = "_"; // $NON-NLS-1$

  public ForeachController() {}

  /** @param startIndex Start index of loop */
  public void setStartIndex(String startIndex) {
    setProperty(START_INDEX, startIndex, INDEX_DEFAULT_VALUE);
  }

  /** @return start index of loop */
  private int getStartIndex() {
    // Although the default is not the same as for the string value, it is only used internally
    return getPropertyAsInt(START_INDEX, 0);
  }

  /** @return start index of loop as String */
  public String getStartIndexAsString() {
    return getPropertyAsString(START_INDEX, INDEX_DEFAULT_VALUE);
  }

  /** @param endIndex End index of loop */
  public void setEndIndex(String endIndex) {
    setProperty(END_INDEX, endIndex, INDEX_DEFAULT_VALUE);
  }

  /** @return end index of loop */
  private int getEndIndex() {
    // Although the default is not the same as for the string value, it is only used internally
    return getPropertyAsInt(END_INDEX, Integer.MAX_VALUE);
  }

  /** @return end index of loop */
  public String getEndIndexAsString() {
    return getPropertyAsString(END_INDEX, INDEX_DEFAULT_VALUE);
  }

  public void setInputVal(String inputValue) {
    setProperty(new StringProperty(INPUTVAL, inputValue));
  }

  private String getInputVal() {
    getProperty(INPUTVAL).recoverRunningVersion(null);
    return getInputValString();
  }

  public String getInputValString() {
    return getPropertyAsString(INPUTVAL);
  }

  public void setReturnVal(String inputValue) {
    setProperty(new StringProperty(RETURNVAL, inputValue));
  }

  private String getReturnVal() {
    getProperty(RETURNVAL).recoverRunningVersion(null);
    return getReturnValString();
  }

  public String getReturnValString() {
    return getPropertyAsString(RETURNVAL);
  }

  private String getSeparator() {
    return getUseSeparator() ? DEFAULT_SEPARATOR : ""; // $NON-NLS-1$
  }

  public void setUseSeparator(boolean b) {
    setProperty(new BooleanProperty(USE_SEPARATOR, b));
  }

  public boolean getUseSeparator() {
    return getPropertyAsBoolean(USE_SEPARATOR, true);
  }

  /** {@inheritDoc} */
  @Override
  public boolean isDone() {
    if (loopCount >= getEndIndex()) {
      return true;
    }
    JMeterContext context = getThreadContext();
    StringBuilder builder = new StringBuilder(getInputVal().length() + getSeparator().length() + 3);
    String inputVariable =
        builder
            .append(getInputVal())
            .append(getSeparator())
            .append(Integer.toString(loopCount + 1))
            .toString();
    final JMeterVariables variables = context.getVariables();
    final Object currentVariable = variables.getObject(inputVariable);
    if (currentVariable != null) {
      variables.putObject(getReturnVal(), currentVariable);
      if (log.isDebugEnabled()) {
        log.debug("ForEach resultstring isDone=" + variables.get(getReturnVal()));
      }
      return false;
    }
    return super.isDone();
  }

  /** Tests that JMeterVariables contain inputVal_<count>, if not we can stop iterating */
  private boolean endOfArguments() {
    JMeterContext context = getThreadContext();
    String inputVariable = getInputVal() + getSeparator() + (loopCount + 1);
    if (context.getVariables().getObject(inputVariable) != null) {
      log.debug("ForEach resultstring eofArgs= false");
      return false;
    }
    log.debug("ForEach resultstring eofArgs= true");
    return true;
  }

  // Prevent entry if nothing to do
  @Override
  public Sampler next() {
    if (emptyList()) {
      reInitialize();
      resetLoopCount();
      return null;
    }
    return super.next();
  }

  /**
   * Check if there are any matching entries
   *
   * @return whether any entries in the list
   */
  private boolean emptyList() {
    JMeterContext context = getThreadContext();

    StringBuilder builder = new StringBuilder(getInputVal().length() + getSeparator().length() + 3);
    String inputVariable =
        builder
            .append(getInputVal())
            .append(getSeparator())
            .append(Integer.toString(loopCount + 1))
            .toString();
    if (context.getVariables().getObject(inputVariable) != null) {
      return false;
    }
    if (log.isDebugEnabled()) {
      log.debug("No entries found - null first entry: " + inputVariable);
    }
    return true;
  }

  /** {@inheritDoc} */
  @Override
  protected Sampler nextIsNull() throws NextIsNullException {
    reInitialize();
    // Conditions to reset the loop count
    if (endOfArguments() // no more variables to iterate
        || loopCount >= getEndIndex() // we reached end index
    ) {
      // setDone(true);
      resetLoopCount();
      return null;
    }
    return next();
  }

  protected void incrementLoopCount() {
    loopCount++;
  }

  protected void resetLoopCount() {
    loopCount = getStartIndex();
  }

  /** {@inheritDoc} */
  @Override
  protected int getIterCount() {
    return loopCount + 1;
  }

  /** {@inheritDoc} */
  @Override
  protected void reInitialize() {
    setFirst(true);
    resetCurrent();
    incrementLoopCount();
    recoverRunningVersion();
  }

  /** {@inheritDoc} */
  @Override
  public void triggerEndOfLoop() {
    super.triggerEndOfLoop();
    resetLoopCount();
  }

  /**
   * Reset loopCount to Start index
   *
   * @see org.apache.jmeter.control.GenericController#initialize()
   */
  @Override
  public void initialize() {
    super.initialize();
    loopCount = getStartIndex();
  }
}
예제 #25
0
/** Use this Keystore for JMeter specific KeyStores. */
public final class JmeterKeyStore {

  private static final Logger LOG = LoggingManager.getLoggerForClass();

  private final KeyStore store;

  /** first index to consider for a key */
  private final int startIndex;

  /** last index to consider for a key */
  private final int endIndex;

  /** name of the default alias */
  private String clientCertAliasVarName;

  private String[] names = new String[0]; // default empty array to prevent NPEs
  private Map<String, PrivateKey> privateKeyByAlias = new HashMap<String, PrivateKey>();
  private Map<String, X509Certificate[]> certsByAlias = new HashMap<String, X509Certificate[]>();

  // @GuardedBy("this")
  private int last_user;

  /**
   * @param type type of the {@link KeyStore}
   * @param startIndex which keys should be considered starting from <code>0</code>
   * @param endIndex which keys should be considered up to <code>count - 1</code>
   * @param clientCertAliasVarName name for the default key, if empty use the first key available
   * @throws KeyStoreException when the type of the keystore is not supported
   * @throws IllegalArgumentException when <code>startIndex</code> &lt; 0, <code>endIndex</code>
   *     &lt; 0 or <code>endIndex</code> &lt; </code>startIndex</code>
   */
  private JmeterKeyStore(String type, int startIndex, int endIndex, String clientCertAliasVarName)
      throws KeyStoreException {
    if (startIndex < 0 || endIndex < 0 || endIndex < startIndex) {
      throw new IllegalArgumentException(
          "Invalid index(es). Start=" + startIndex + ", end=" + endIndex);
    }
    this.store = KeyStore.getInstance(type);
    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.clientCertAliasVarName = clientCertAliasVarName;
  }

  /**
   * Process the input stream and try to read the keys from the store
   *
   * @param is {@link InputStream} from which the store should be loaded
   * @param pword the password used to check the integrity of the store
   * @throws IOException if there is a problem decoding or reading the store. A bad password might
   *     be the cause for this, or an empty store
   * @throws CertificateException if any of the certificated in the store can not be loaded
   * @throws NoSuchAlgorithmException if the algorithm to check the integrity of the store can not
   *     be found
   * @throws KeyStoreException if the store has not been initialized (should not happen here)
   * @throws UnrecoverableKeyException if the key can not be recovered from the store (should not
   *     happen here, either)
   */
  public void load(InputStream is, String pword)
      throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException,
          UnrecoverableKeyException {
    char pw[] = pword == null ? null : pword.toCharArray();
    store.load(is, pw);

    ArrayList<String> v_names = new ArrayList<String>();
    this.privateKeyByAlias = new HashMap<String, PrivateKey>();
    this.certsByAlias = new HashMap<String, X509Certificate[]>();

    if (null != is) { // No point checking an empty keystore
      PrivateKey _key = null;
      int index = 0;
      Enumeration<String> aliases = store.aliases();
      while (aliases.hasMoreElements()) {
        String alias = aliases.nextElement();
        if (store.isKeyEntry(alias)) {
          if (index >= startIndex && index <= endIndex) {
            _key = (PrivateKey) store.getKey(alias, pw);
            if (null == _key) {
              throw new IOException("No key found for alias: " + alias); // Should not happen
            }
            Certificate[] chain = store.getCertificateChain(alias);
            if (null == chain) {
              throw new IOException("No certificate chain found for alias: " + alias);
            }
            v_names.add(alias);
            X509Certificate[] x509certs = new X509Certificate[chain.length];
            for (int i = 0; i < x509certs.length; i++) {
              x509certs[i] = (X509Certificate) chain[i];
            }

            privateKeyByAlias.put(alias, _key);
            certsByAlias.put(alias, x509certs);
          }
          index++;
        }
      }

      if (null == _key) {
        throw new IOException("No key(s) found");
      }
      if (index <= endIndex - startIndex) {
        LOG.warn(
            "Did not find all requested aliases. Start="
                + startIndex
                + ", end="
                + endIndex
                + ", found="
                + certsByAlias.size());
      }
    }

    /*
     * Note: if is == null, the arrays will be empty
     */
    this.names = v_names.toArray(new String[v_names.size()]);
  }

  /**
   * Get the ordered certificate chain for a specific alias.
   *
   * @param alias the alias for which the certificate chain should be given
   * @return the certificate chain for the alias
   * @throws IllegalArgumentException if no chain could be found for the alias
   */
  public X509Certificate[] getCertificateChain(String alias) {
    X509Certificate[] result = this.certsByAlias.get(alias);
    if (result != null) {
      return result;
    }
    // API expects null not empty array, see
    // http://docs.oracle.com/javase/6/docs/api/javax/net/ssl/X509KeyManager.html
    throw new IllegalArgumentException("No certificate found for alias:'" + alias + "'");
  }

  /**
   * Get the next or only alias.
   *
   * @return the next or only alias.
   * @throws IllegalArgumentException if {@link JmeterKeyStore#clientCertAliasVarName
   *     clientCertAliasVarName} is not empty and no key for this alias could be found
   */
  public String getAlias() {
    if (!StringUtils.isEmpty(clientCertAliasVarName)) {
      // We return even if result is null
      String aliasName =
          JMeterContextService.getContext().getVariables().get(clientCertAliasVarName);
      if (StringUtils.isEmpty(aliasName)) {
        LOG.error("No var called '" + clientCertAliasVarName + "' found");
        throw new IllegalArgumentException("No var called '" + clientCertAliasVarName + "' found");
      }
      return aliasName;
    }
    int length = this.names.length;
    if (length == 0) { // i.e. is == null
      return null;
    }
    return this.names[getIndexAndIncrement(length)];
  }

  public int getAliasCount() {
    return this.names.length;
  }

  public String getAlias(int index) {
    int length = this.names.length;
    if (length == 0 && index == 0) { // i.e. is == null
      return null;
    }
    if (index >= length || index < 0) {
      throw new ArrayIndexOutOfBoundsException(index);
    }
    return this.names[index];
  }

  /**
   * Return the private Key for a specific alias
   *
   * @param alias the name of the alias for the private key
   * @return the private key for the given <code>alias</code>
   * @throws IllegalArgumentException when no private key could be found
   */
  public PrivateKey getPrivateKey(String alias) {
    PrivateKey pk = this.privateKeyByAlias.get(alias);
    if (pk != null) {
      return pk;
    }
    throw new IllegalArgumentException("No PrivateKey found for alias:'" + alias + "'");
  }

  /**
   * Create a keystore which returns a range of aliases (if available)
   *
   * @param type store type (e.g. JKS)
   * @param startIndex first index (from 0)
   * @param endIndex last index (to count -1)
   * @param clientCertAliasVarName name of the default key to, if empty the first key will be used
   *     as default key
   * @return the keystore
   * @throws KeyStoreException when the type of the store is not supported
   * @throws IllegalArgumentException when <code>startIndex</code> &lt; 0, <code>endIndex</code>
   *     &lt; 0, or <code>endIndex</code> &lt; <code>startIndex</code>
   */
  public static JmeterKeyStore getInstance(
      String type, int startIndex, int endIndex, String clientCertAliasVarName)
      throws KeyStoreException {
    return new JmeterKeyStore(type, startIndex, endIndex, clientCertAliasVarName);
  }

  /**
   * Create a keystore which returns the first alias only.
   *
   * @param type of the store e.g. JKS
   * @return the keystore
   * @throws KeyStoreException when the type of the store is not supported
   */
  public static JmeterKeyStore getInstance(String type) throws KeyStoreException {
    return getInstance(type, 0, 0, null);
  }

  /**
   * Gets current index and increment by rolling if index is equal to length
   *
   * @param length Number of keys to roll
   */
  private int getIndexAndIncrement(int length) {
    synchronized (this) {
      int result = last_user++;
      if (last_user >= length) {
        last_user = 0;
      }
      return result;
    }
  }

  /**
   * Compiles the list of all client aliases with a private key. TODO Currently, keyType and issuers
   * are both ignored.
   *
   * @param keyType the key algorithm type name (RSA, DSA, etc.)
   * @param issuers the CA certificates we are narrowing our selection on.
   * @return the array of aliases; may be empty
   */
  public String[] getClientAliases(String keyType, Principal[] issuers) {
    int count = getAliasCount();
    String[] aliases = new String[count];
    for (int i = 0; i < aliases.length; i++) {
      //            if (keys[i].getAlgorithm().equals(keyType)){
      //
      //            }
      aliases[i] = this.names[i];
    }
    if (aliases.length > 0) {
      return aliases;
    } else {
      // API expects null not empty array, see
      // http://docs.oracle.com/javase/6/docs/api/javax/net/ssl/X509KeyManager.html
      return null;
    }
  }
}
예제 #26
0
public class MD5HexAssertion extends AbstractTestElement implements Serializable, Assertion {

  private static final Logger log = LoggingManager.getLoggerForClass();

  /** Key for storing assertion-informations in the jmx-file. */
  private static final String MD5HEX_KEY = "MD5HexAssertion.size";

  /*
   * @param response @return
   */
  public AssertionResult getResult(SampleResult response) {

    AssertionResult result = new AssertionResult(getName());
    result.setFailure(false);
    byte[] resultData = response.getResponseData();

    if (resultData.length == 0) {
      result.setError(false);
      result.setFailure(true);
      result.setFailureMessage("Response was null");
      return result;
    }

    // no point in checking if we don't have anything to compare against
    if (getAllowedMD5Hex().equals("")) {
      result.setError(false);
      result.setFailure(true);
      result.setFailureMessage("MD5Hex to test against is empty");
      return result;
    }

    String md5Result = baMD5Hex(resultData);

    // String md5Result = DigestUtils.md5Hex(resultData);

    if (!md5Result.equalsIgnoreCase(getAllowedMD5Hex())) {
      result.setFailure(true);

      Object[] arguments = {md5Result, getAllowedMD5Hex()};
      String message =
          MessageFormat.format(
              JMeterUtils.getResString("md5hex_assertion_failure"), arguments); // $NON-NLS-1$
      result.setFailureMessage(message);
    }

    return result;
  }

  public void setAllowedMD5Hex(String hex) {
    setProperty(new StringProperty(MD5HexAssertion.MD5HEX_KEY, hex));
  }

  public String getAllowedMD5Hex() {
    return getPropertyAsString(MD5HexAssertion.MD5HEX_KEY);
  }

  // package protected so can be accessed by test class
  static String baMD5Hex(byte ba[]) {
    byte[] md5Result = {};

    try {
      MessageDigest md;
      md = MessageDigest.getInstance("MD5");
      md5Result = md.digest(ba);
    } catch (NoSuchAlgorithmException e) {
      log.error("", e);
    }
    return JOrphanUtils.baToHexString(md5Result);
  }
}
/** @author Maciej Zaleski */
public class WebSocketSampler extends AbstractSampler implements TestStateListener {
  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final String ARG_VAL_SEP = "="; // $NON-NLS-1$
  private static final String QRY_SEP = "&"; // $NON-NLS-1$
  private static final String WS_PREFIX = "ws://"; // $NON-NLS-1$
  private static final String WSS_PREFIX = "wss://"; // $NON-NLS-1$
  private static final String DEFAULT_PROTOCOL = "ws";

  private static Map<String, ServiceSocket> connectionList;

  public WebSocketSampler() {
    super();
    setName("WebSocket sampler");
  }

  private ServiceSocket getConnectionSocket() throws URISyntaxException, Exception {
    URI uri = getUri();

    String connectionId = getThreadName() + getConnectionId();
    ServiceSocket socket;
    WebSocketClient webSocketClient;
    if (isStreamingConnection()) {
      if (connectionList.containsKey(connectionId)) {
        socket = connectionList.get(connectionId);
        socket.initialize();
        return socket;
      } else {
        socket = new ServiceSocket(this);
        connectionList.put(connectionId, socket);
      }
    } else {
      socket = new ServiceSocket(this);
    }

    SslContextFactory sslContexFactory = new SslContextFactory();
    sslContexFactory.setTrustAll(isIgnoreSslErrors());
    webSocketClient = new WebSocketClient(sslContexFactory);

    webSocketClient.start();
    ClientUpgradeRequest request = new ClientUpgradeRequest();
    webSocketClient.connect(socket, uri, request);

    int connectionTimeout = Integer.parseInt(getConnectionTimeout());
    socket.awaitOpen(connectionTimeout, TimeUnit.MILLISECONDS);

    return socket;
  }

  @Override
  public SampleResult sample(Entry entry) {
    ServiceSocket socket = null;
    SampleResult sampleResult = new SampleResult();
    sampleResult.setSampleLabel(getName());
    sampleResult.setDataEncoding(getContentEncoding());

    StringBuilder errorList = new StringBuilder();
    errorList.append("\n\n[Problems]\n");

    boolean isOK = false;

    String payloadMessage = getRequestPayload();
    sampleResult.setSamplerData(payloadMessage);
    sampleResult.sampleStart();

    try {
      socket = getConnectionSocket();
      if (socket == null) {
        sampleResult.setResponseCode("500");
        sampleResult.setSuccessful(false);
        sampleResult.sampleEnd();
        sampleResult.setResponseMessage(errorList.toString());
        errorList.append(" - Connection couldn't be opened").append("\n");
        return sampleResult;
      }

      if (!payloadMessage.isEmpty()) {
        socket.sendMessage(payloadMessage);
      }

      int responseTimeout = Integer.parseInt(getResponseTimeout());
      socket.awaitClose(responseTimeout, TimeUnit.MILLISECONDS);

      if (socket.getResponseMessage() == null || socket.getResponseMessage().isEmpty()) {
        sampleResult.setResponseCode("204");
      }

      if (socket.getError() != 0) {
        isOK = false;
        sampleResult.setResponseCode(socket.getError().toString());
      } else {
        sampleResult.setResponseCodeOK();
        isOK = true;
      }

      sampleResult.setResponseData(socket.getResponseMessage(), getContentEncoding());

    } catch (URISyntaxException e) {
      errorList
          .append(" - Invalid URI syntax: ")
          .append(e.getMessage())
          .append("\n")
          .append(StringUtils.join(e.getStackTrace(), "\n"))
          .append("\n");
    } catch (IOException e) {
      errorList
          .append(" - IO Exception: ")
          .append(e.getMessage())
          .append("\n")
          .append(StringUtils.join(e.getStackTrace(), "\n"))
          .append("\n");
    } catch (NumberFormatException e) {
      errorList
          .append(" - Cannot parse number: ")
          .append(e.getMessage())
          .append("\n")
          .append(StringUtils.join(e.getStackTrace(), "\n"))
          .append("\n");
    } catch (InterruptedException e) {
      errorList
          .append(" - Execution interrupted: ")
          .append(e.getMessage())
          .append("\n")
          .append(StringUtils.join(e.getStackTrace(), "\n"))
          .append("\n");
    } catch (Exception e) {
      errorList
          .append(" - Unexpected error: ")
          .append(e.getMessage())
          .append("\n")
          .append(StringUtils.join(e.getStackTrace(), "\n"))
          .append("\n");
    }

    sampleResult.sampleEnd();
    sampleResult.setSuccessful(isOK);

    String logMessage = (socket != null) ? socket.getLogMessage() : "";
    sampleResult.setResponseMessage(logMessage + errorList);
    return sampleResult;
  }

  @Override
  public void setName(String name) {
    if (name != null) {
      setProperty(TestElement.NAME, name);
    }
  }

  @Override
  public String getName() {
    return getPropertyAsString(TestElement.NAME);
  }

  @Override
  public void setComment(String comment) {
    setProperty(new StringProperty(TestElement.COMMENTS, comment));
  }

  @Override
  public String getComment() {
    return getProperty(TestElement.COMMENTS).getStringValue();
  }

  public URI getUri() throws URISyntaxException {
    String path = this.getContextPath();
    // Hack to allow entire URL to be provided in host field
    if (path.startsWith(WS_PREFIX) || path.startsWith(WSS_PREFIX)) {
      return new URI(path);
    }
    String domain = getServerAddress();
    String protocol = getProtocol();
    // HTTP URLs must be absolute, allow file to be relative
    if (!path.startsWith("/")) { // $NON-NLS-1$
      path = "/" + path; // $NON-NLS-1$
    }

    String queryString = getQueryString(getContentEncoding());
    if (isProtocolDefaultPort()) {
      return new URI(protocol, null, domain, -1, path, queryString, null);
    }
    return new URI(
        protocol, null, domain, Integer.parseInt(getServerPort()), path, queryString, null);
  }

  /**
   * Tell whether the default port for the specified protocol is used
   *
   * @return true if the default port number for the protocol is used, false otherwise
   */
  public boolean isProtocolDefaultPort() {
    final int port = Integer.parseInt(getServerPort());
    final String protocol = getProtocol();
    return ("ws".equalsIgnoreCase(protocol) && port == HTTPConstants.DEFAULT_HTTP_PORT)
        || ("wss".equalsIgnoreCase(protocol) && port == HTTPConstants.DEFAULT_HTTPS_PORT);
  }

  public String getServerPort() {
    final String port_s = getPropertyAsString("serverPort", "0");
    Integer port;
    String protocol = getProtocol();

    try {
      port = Integer.parseInt(port_s);
    } catch (Exception ex) {
      port = 0;
    }

    if (port == 0) {
      if ("wss".equalsIgnoreCase(protocol)) {
        return String.valueOf(HTTPConstants.DEFAULT_HTTPS_PORT);
      } else if ("ws".equalsIgnoreCase(protocol)) {
        return String.valueOf(HTTPConstants.DEFAULT_HTTP_PORT);
      }
    }
    return port.toString();
  }

  public void setServerPort(String port) {
    setProperty("serverPort", port);
  }

  public String getResponseTimeout() {
    return getPropertyAsString("responseTimeout", "20000");
  }

  public void setResponseTimeout(String responseTimeout) {
    setProperty("responseTimeout", responseTimeout);
  }

  public String getConnectionTimeout() {
    return getPropertyAsString("connectionTimeout", "5000");
  }

  public void setConnectionTimeout(String connectionTimeout) {
    setProperty("connectionTimeout", connectionTimeout);
  }

  public void setProtocol(String protocol) {
    setProperty("protocol", protocol);
  }

  public String getProtocol() {
    String protocol = getPropertyAsString("protocol");
    if (protocol == null || protocol.isEmpty()) {
      return DEFAULT_PROTOCOL;
    }
    return protocol;
  }

  public void setServerAddress(String serverAddress) {
    setProperty("serverAddress", serverAddress);
  }

  public String getServerAddress() {
    return getPropertyAsString("serverAddress");
  }

  public void setImplementation(String implementation) {
    setProperty("implementation", implementation);
  }

  public String getImplementation() {
    return getPropertyAsString("implementation");
  }

  public void setContextPath(String contextPath) {
    setProperty("contextPath", contextPath);
  }

  public String getContextPath() {
    return getPropertyAsString("contextPath");
  }

  public void setContentEncoding(String contentEncoding) {
    setProperty("contentEncoding", contentEncoding);
  }

  public String getContentEncoding() {
    return getPropertyAsString("contentEncoding", "UTF-8");
  }

  public void setRequestPayload(String requestPayload) {
    setProperty("requestPayload", requestPayload);
  }

  public String getRequestPayload() {
    return getPropertyAsString("requestPayload");
  }

  public void setIgnoreSslErrors(Boolean ignoreSslErrors) {
    setProperty("ignoreSslErrors", ignoreSslErrors);
  }

  public Boolean isIgnoreSslErrors() {
    return getPropertyAsBoolean("ignoreSslErrors");
  }

  public void setStreamingConnection(Boolean streamingConnection) {
    setProperty("streamingConnection", streamingConnection);
  }

  public Boolean isStreamingConnection() {
    return getPropertyAsBoolean("streamingConnection");
  }

  public void setConnectionId(String connectionId) {
    setProperty("connectionId", connectionId);
  }

  public String getConnectionId() {
    return getPropertyAsString("connectionId");
  }

  public void setResponsePattern(String responsePattern) {
    setProperty("responsePattern", responsePattern);
  }

  public String getResponsePattern() {
    return getPropertyAsString("responsePattern");
  }

  public void setCloseConncectionPattern(String closeConncectionPattern) {
    setProperty("closeConncectionPattern", closeConncectionPattern);
  }

  public String getCloseConncectionPattern() {
    return getPropertyAsString("closeConncectionPattern");
  }

  public void setProxyAddress(String proxyAddress) {
    setProperty("proxyAddress", proxyAddress);
  }

  public String getProxyAddress() {
    return getPropertyAsString("proxyAddress");
  }

  public void setProxyPassword(String proxyPassword) {
    setProperty("proxyPassword", proxyPassword);
  }

  public String getProxyPassword() {
    return getPropertyAsString("proxyPassword");
  }

  public void setProxyPort(String proxyPort) {
    setProperty("proxyPort", proxyPort);
  }

  public String getProxyPort() {
    return getPropertyAsString("proxyPort");
  }

  public void setProxyUsername(String proxyUsername) {
    setProperty("proxyUsername", proxyUsername);
  }

  public String getProxyUsername() {
    return getPropertyAsString("proxyUsername");
  }

  public void setMessageBacklog(String messageBacklog) {
    setProperty("messageBacklog", messageBacklog);
  }

  public String getMessageBacklog() {
    return getPropertyAsString("messageBacklog", "3");
  }

  public String getQueryString(String contentEncoding) {
    // Check if the sampler has a specified content encoding
    if (JOrphanUtils.isBlank(contentEncoding)) {
      // We use the encoding which should be used according to the HTTP spec, which is UTF-8
      contentEncoding = EncoderCache.URL_ARGUMENT_ENCODING;
    }
    StringBuilder buf = new StringBuilder();
    PropertyIterator iter = getQueryStringParameters().iterator();
    boolean first = true;
    while (iter.hasNext()) {
      HTTPArgument item = null;
      Object objectValue = iter.next().getObjectValue();
      try {
        item = (HTTPArgument) objectValue;
      } catch (ClassCastException e) {
        item = new HTTPArgument((Argument) objectValue);
      }
      final String encodedName = item.getEncodedName();
      if (encodedName.length() == 0) {
        continue; // Skip parameters with a blank name (allows use of optional variables in
                  // parameter lists)
      }
      if (!first) {
        buf.append(QRY_SEP);
      } else {
        first = false;
      }
      buf.append(encodedName);
      if (item.getMetaData() == null) {
        buf.append(ARG_VAL_SEP);
      } else {
        buf.append(item.getMetaData());
      }

      // Encode the parameter value in the specified content encoding
      try {
        buf.append(item.getEncodedValue(contentEncoding));
      } catch (UnsupportedEncodingException e) {
        log.warn(
            "Unable to encode parameter in encoding "
                + contentEncoding
                + ", parameter value not included in query string");
      }
    }
    return buf.toString();
  }

  public void setQueryStringParameters(Arguments queryStringParameters) {
    setProperty(new TestElementProperty("queryStringParameters", queryStringParameters));
  }

  public Arguments getQueryStringParameters() {
    Arguments args = (Arguments) getProperty("queryStringParameters").getObjectValue();
    return args;
  }

  @Override
  public void testStarted() {
    testStarted("unknown");
  }

  @Override
  public void testStarted(String host) {
    connectionList = new ConcurrentHashMap<String, ServiceSocket>();
  }

  @Override
  public void testEnded() {
    testEnded("unknown");
  }

  @Override
  public void testEnded(String host) {
    for (ServiceSocket socket : connectionList.values()) {
      socket.close();
    }
  }
}
public class BaseTestListenerImpl implements BaseTestListener {

  // static variables
  /** Logger */
  private static final Logger LOGGER = LoggingManager.getLoggerForClass();

  private final Translator<SampleEvent, BaseSampleEntity[]> mTranslator;

  /** Aggregates data for the trend line */
  private final Aggregator<Long, AggregationKey, Integer> mTrendLineAggregator;

  /**
   * Efficiently writes objects to the DB. Defaulted to {@link NOPSampleWriter}, but initialized to
   * real object during {@link #testStarted()}
   */
  private final AsynchSampleWriter<AgentDataPoint> mSWriter;

  /**
   * Handles retries, in case the agent is locked. Defaulted to {@link NOPSampleWriter}, but set to
   * real updater during {@link #testStarted()}
   */
  private final SampleWriter<TestJobAgentWorker> mAgentUpdater;

  private final Provider<TestJobAgentWorker> mAgentProvider;

  private final Long mTimeBound;

  private final Long mAgentThreadCount;

  private final String mTargetWebServer;

  private final Timer mTrendLineTimer;

  private final TimerTask mTrendLineTask;

  private final long mTrendLinePeriod;

  /** used to represent all threads, all actions/transactiosn */
  private final AggregationKey mNullKey;

  /**
   * Bypasses both {@link #mLimitErrorSamples} and {@link #mErrorSampleLimitCountDown}, will keep
   * all raw data for all trends (action, transaction, errors)
   */
  private final boolean mCollectRawData;

  //	609828[Error store limit] Limit the maximum error number to be stored.
  /**
   * When this counter reaches 0, no more error samples will be collected. However, error counts and
   * percentages will still be processed.
   */
  private final AtomicInteger mErrorSampleLimitCountDown;

  /**
   * Unchangeable value that indicates if individual error samples should be limit if < 0, then
   * bypasses the limit set by {@link #mErrorSampleLimitCountDown}
   */
  private final boolean mLimitErrorSamples;

  private Timestamp mStartTimeStamp;

  private Thread mAgentUpdateThread;

  /**
   * @param writer
   * @param agentUpdater
   * @param translator
   * @param trendLineAggregator
   * @param agentProvider
   * @param timeBound
   * @param agentThreadCount
   * @param targetWebServer
   * @param trendLineTimer
   * @param trendLineTask
   * @param trendLinePeriod
   * @param nullAggregatorKey
   * @param collectRawData
   * @param errorSampleLimit
   */
  @Inject
  public BaseTestListenerImpl(
      AsynchSampleWriter<AgentDataPoint> writer,
      SampleWriter<TestJobAgentWorker> agentUpdater,
      Translator<SampleEvent, BaseSampleEntity[]> translator,
      Aggregator<Long, AggregationKey, Integer> trendLineAggregator,
      @Retrieve Provider<TestJobAgentWorker> agentProvider,
      @Named("timebound") Long timeBound,
      @Named("threadCount") Long agentThreadCount,
      @Named("webServer") String targetWebServer,
      @Named("trend.line") Timer trendLineTimer,
      @Named("trend.line") TimerTask trendLineTask,
      @Named("trend.line.period") long trendLinePeriod,
      @Named("null") AggregationKey nullAggregatorKey,
      @Named("collect.raw.data") boolean collectRawData,
      @Named("error.sample.limit") int errorSampleLimit) {

    // TODO [write error to file] pass in a new writer for error (wrap the MS Writer for database)

    mTranslator = translator;
    mTrendLineAggregator = trendLineAggregator;
    mSWriter = writer;
    mAgentUpdater = agentUpdater;
    mAgentProvider = agentProvider;
    mTimeBound = timeBound;
    mAgentThreadCount = agentThreadCount;
    mTargetWebServer = targetWebServer;

    //		609828[Error store limit] Limit the maximum error number to be stored.
    mErrorSampleLimitCountDown = new AtomicInteger(errorSampleLimit);
    mLimitErrorSamples = errorSampleLimit >= 0;
    //		615093: [Error limit -1] Error limit -1 doesn't work well.
    LOGGER.info(
        String.format(
            "Will limit error sample collection [%b] to [%d]",
            mLimitErrorSamples, mErrorSampleLimitCountDown.get()));

    mTrendLineTimer = trendLineTimer;
    mTrendLineTask = trendLineTask;
    mTrendLinePeriod = trendLinePeriod;
    mNullKey = nullAggregatorKey;
    mCollectRawData = collectRawData;

    mTrendLineTimer.schedule(mTrendLineTask, mTrendLinePeriod, mTrendLinePeriod);

    mStartTimeStamp = new Timestamp(System.currentTimeMillis());

    updateAgent();

    mAgentUpdateThread =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                LOGGER.info("Running agent update Thread");
                try {
                  while (!Thread.interrupted()) {
                    LOGGER.info("Waiting for agent update");

                    Thread.sleep((long) (2 * Math.random() * 1000));

                    LOGGER.info("Updating agent");
                    updateAgent();
                  }
                } catch (InterruptedException e) {
                  LOGGER.info("agent update thread interrupted");
                }
                LOGGER.info("agent update stop");
              }
            });
    mAgentUpdateThread.setDaemon(true);
    mAgentUpdateThread.setName("agent update thread");

    mAgentUpdateThread.start();
  }

  private void updateAgent() {

    // We need to write the agent to the db,
    // We'll potentially need to retry due to possible database locking
    // so we use the JPAAgentUpdater that already knows
    // how to do this
    try {
      // initial agent parameters
      final TestJobAgentWorker lAgent = mAgentProvider.get();

      LOGGER.info("Successfully retrieved agent " + lAgent);

      if (lAgent.getProcessID() != null) {
        LOGGER.info(
            "Process succsesfully retrieved "
                + lAgent.getProcessID()
                + ". Stopping agent update thread");

        mAgentUpdateThread.interrupt();
        return;
      }

      LOGGER.info("PID not yet set, retrieving and updating");
      configureAgentInitialParameters(lAgent);
      LOGGER.info("Updating agent");

      mAgentUpdater.write(lAgent);
    } catch (Exception e) {
      LOGGER.error("Couldn't write the agent", e);
    }
  }

  private void configureAgentInitialParameters(final TestJobAgentWorker lAgent)
      throws UnknownHostException {

    lAgent.setTimeBound(mTimeBound);
    lAgent.setThreadNumber(mAgentThreadCount);
    lAgent.setTargetWebServer(mTargetWebServer);
    HibernateUtils.setMachineData(lAgent);
    lAgent.setStartTimestamp(mStartTimeStamp);
    lAgent.setComputationalInterval(mTrendLinePeriod);
  }

  /* (non-Javadoc)
   * @see com.microstrategy.mfloadtest.jdbcwriter.BaseTestListener#sampleOccurred(org.apache.jmeter.samplers.SampleEvent)
   */
  @Override
  public void sampleOccurred(SampleEvent event) {

    // multi threads will be accessing this
    // with different callstacks

    // do not check for the mSession==null,
    // all the objects here are safe without a db connection

    // will obtain the entities in order:
    // action, transaction, errors
    final BaseSampleEntity[] lEntities = mTranslator.translate(event);

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Sending entries to aggregator");
    }

    final ArrayList<BaseSampleEntity> lErrors = new ArrayList<BaseSampleEntity>();

    // make sure to populate all the aggregators
    // in the same interval
    // within the same interval
    synchronized (mTrendLineAggregator) {
      for (BaseSampleEntity lEntity : lEntities) {
        if (lEntity instanceof ActionSampleEntity) {
          sendActionToAggregator((ActionSampleEntity) lEntity);
        } else if (lEntity instanceof SampleEntity) {
          sendTransactionToAggregator((SampleEntity) lEntity);
        } else if (lEntity instanceof ErrorSampleEntity) {
          if (!mLimitErrorSamples || mErrorSampleLimitCountDown.decrementAndGet() >= 0) {
            lErrors.add(lEntity);
          } else if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Error not logged, because limit was reached");
          }
          sendErrorToAggregator((ErrorSampleEntity) lEntity);
        }
      }
    }

    if (LOGGER.isDebugEnabled()) { // be careful about performance
      LOGGER.debug(String.format("entries commited %s", mTrendLineAggregator));
      LOGGER.debug("sending entities to writer");
    }

    if (mCollectRawData) {
      // this has to happen at the end, because the transactions are lost
      mSWriter.write(lEntities);
    } else {
      mSWriter.write(lErrors.toArray(new BaseSampleEntity[0]));
    }
  }

  private void sendErrorToAggregator(ErrorSampleEntity lEntity) {
    LOGGER.debug("sending error to aggregator");
    final AggregationKey lKey =
        new AggregationKey(
            AggregationKey.Type.ERROR, lEntity.getThreadGroup(), lEntity.getTransaction());

    // just add 1, what we need is the count
    mTrendLineAggregator.getMetric(MetricID.COUNT, lKey).addSample(1L);
  }

  private void sendTransactionToAggregator(SampleEntity lEntity) {

    LOGGER.debug("sending transaction to aggregator");
    final AggregationKey lKey =
        new AggregationKey(
            AggregationKey.Type.TRANSACTION, lEntity.getThreadGroup(), lEntity.getTransaction());

    mTrendLineAggregator
        .getMetric(MetricID.RESPONSE_TIME, lKey)
        .addSample(lEntity.getResponseTime());
  }

  private void sendActionToAggregator(ActionSampleEntity lAction) {

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("sending action to aggregator");
    }

    final AggregationKey lKey =
        new AggregationKey(
            AggregationKey.Type.ACTION, lAction.getThreadGroup(), lAction.getTransaction());

    mTrendLineAggregator
        .getMetric(MetricID.RESPONSE_TIME, lKey)
        .addSample(lAction.getResponseTime());
    mTrendLineAggregator
        .getMetric(MetricID.THREAD_COUNT, mNullKey)
        .addSample(lAction.getActiveThreads());
    mTrendLineAggregator.getMetric(MetricID.BYTE_COUNT, lKey).addSample(lAction.getByteCount());

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug(String.format("Response Time [%s]%d", lKey, lAction.getResponseTime()));
      LOGGER.debug(String.format("Active Threads [%s]%d", lKey, lAction.getActiveThreads()));
      LOGGER.debug(String.format("Byte Count [%s]%d", lKey, lAction.getByteCount()));
    }
  }

  /* (non-Javadoc)
   * @see com.microstrategy.mfloadtest.jdbcwriter.BaseTestListener#testEnded()
   */
  @Override
  public void testEnded() {

    // this can only come from 1 thread
    final Timestamp lTimeStamp = new Timestamp(new Date().getTime());

    // do unconditionally
    mTrendLineTimer.cancel();

    try {

      final TestJobAgentWorker lAgent = mAgentProvider.get();

      lAgent.setEndTimestamp(lTimeStamp);
      lAgent.setLastNumberOfActiveThreads(0l);

      mAgentUpdater.write(lAgent);
      mSWriter.flush();
      mSWriter.close();
      mAgentUpdateThread.interrupt();

    } catch (Exception e) {
      LOGGER.error("testEnded", e);
      throw new RuntimeException("testEnded", e);
    }
  }
}
예제 #29
0
/**
 * A function which understands BeanShell
 *
 * @since 1.X
 */
public class BeanShell extends AbstractFunction {

  private static final Logger log = LoggingManager.getLoggerForClass();

  private static final List<String> desc = new LinkedList<String>();

  private static final String KEY = "__BeanShell"; // $NON-NLS-1$

  public static final String INIT_FILE = "beanshell.function.init"; // $NON-NLS-1$

  static {
    desc.add(JMeterUtils.getResString("bsh_function_expression")); // $NON-NLS1$
    desc.add(JMeterUtils.getResString("function_name_paropt")); // $NON-NLS1$
  }

  private Object[] values;

  private BeanShellInterpreter bshInterpreter = null;

  public BeanShell() {}

  /** {@inheritDoc} */
  @Override
  public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
      throws InvalidVariableException {

    if (bshInterpreter == null) // did we find BeanShell?
    {
      throw new InvalidVariableException("BeanShell not found");
    }

    JMeterContext jmctx = JMeterContextService.getContext();
    JMeterVariables vars = jmctx.getVariables();

    String script = ((CompoundVariable) values[0]).execute();
    String varName = ""; // $NON-NLS-1$
    if (values.length > 1) {
      varName = ((CompoundVariable) values[1]).execute().trim();
    }

    String resultStr = ""; // $NON-NLS-1$

    log.debug("Script=" + script);

    try {

      // Pass in some variables
      if (currentSampler != null) {
        bshInterpreter.set("Sampler", currentSampler); // $NON-NLS-1$
      }

      if (previousResult != null) {
        bshInterpreter.set("SampleResult", previousResult); // $NON-NLS-1$
      }

      // Allow access to context and variables directly
      bshInterpreter.set("ctx", jmctx); // $NON-NLS-1$
      bshInterpreter.set("vars", vars); // $NON-NLS-1$
      bshInterpreter.set("props", JMeterUtils.getJMeterProperties()); // $NON-NLS-1$
      bshInterpreter.set("threadName", Thread.currentThread().getName()); // $NON-NLS-1$

      // Execute the script
      Object bshOut = bshInterpreter.eval(script);
      if (bshOut != null) {
        resultStr = bshOut.toString();
      }
      if (vars != null && varName.length() > 0) { // vars will be null on TestPlan
        vars.put(varName, resultStr);
      }
    } catch (Exception ex) // Mainly for bsh.EvalError
    {
      log.warn("Error running BSH script", ex);
    }

    log.debug("Output=" + resultStr);
    return resultStr;
  }

  /*
   * Helper method for use by scripts
   *
   */
  public void log_info(String s) {
    log.info(s);
  }

  /** {@inheritDoc} */
  @Override
  public synchronized void setParameters(Collection<CompoundVariable> parameters)
      throws InvalidVariableException {

    checkParameterCount(parameters, 1, 2);

    values = parameters.toArray();

    try {
      bshInterpreter = new BeanShellInterpreter(JMeterUtils.getProperty(INIT_FILE), log);
    } catch (ClassNotFoundException e) {
      throw new InvalidVariableException("BeanShell not found", e);
    }
  }

  /** {@inheritDoc} */
  @Override
  public String getReferenceKey() {
    return KEY;
  }

  /** {@inheritDoc} */
  @Override
  public List<String> getArgumentDesc() {
    return desc;
  }
}
/** @author undera */
public class RawRequestSourcePreProcessor extends AbstractTestElement
    implements PreProcessor, NoThreadClone {

  public static final String regexp = "\\s";
  private static final Logger log = LoggingManager.getLoggerForClass();
  public static final String VARIABLE_NAME = "variable_name";
  public static final String FILENAME = "filename";
  public static final String REWIND = "rewind";
  public static final String ENCODE_HEX = "isHex";
  private FileChannel file;
  private final ByteBuffer metaBuf = ByteBuffer.allocateDirect(1024);
  private final ByteBuffer oneByte = ByteBuffer.allocateDirect(1);
  public static final Charset binaryCharset = Charset.forName("UTF8");

  public RawRequestSourcePreProcessor() {
    super();
  }

  @Override
  public synchronized void process() {
    if (file == null) {
      log.info("Creating file object: " + getFileName());
      try {
        file = new FileInputStream(getFileName()).getChannel();
      } catch (FileNotFoundException ex) {
        log.error(getFileName(), ex);
        return;
      }
    }
    String rawData;

    try {
      rawData = readNextChunk(getNextChunkSize());
    } catch (EndOfFileException ex) {
      if (getRewindOnEOF()) {
        if (log.isDebugEnabled()) {
          log.debug("Rewind file");
        }
        try {
          file.position(0);
        } catch (IOException ex1) {
          log.error("Cannot rewind", ex1);
        }
        process();
        return;
      } else {
        log.info("End of file reached: " + getFileName());
        if (JMeterContextService.getContext().getThread() != null) {
          JMeterContextService.getContext().getThread().stop();
        }
        throw new RuntimeEOFException("End of file reached", ex);
      }
    } catch (IOException ex) {
      log.error("Error reading next chunk", ex);
      throw new RuntimeException("Error reading next chunk", ex);
    }

    final JMeterVariables vars = JMeterContextService.getContext().getVariables();
    if (vars != null) {
      vars.put(getVarName(), rawData);
    }
  }

  private synchronized String readNextChunk(int capacity) throws IOException {
    if (capacity == 0) {
      throw new EndOfFileException("Zero chunk size, possibly end of file reached.");
    }

    ByteBuffer buf = ByteBuffer.allocateDirect(capacity);
    byte[] dst = new byte[capacity];

    int cnt = file.read(buf);
    // log.debug("Read " + cnt);
    if (cnt != capacity) {
      throw new IOException(
          "Expected chunk size (" + capacity + ") differs from read bytes count (" + cnt + ")");
    }

    buf.flip();
    buf.get(dst);
    if (log.isDebugEnabled()) {
      log.debug("Chunk : " + new String(dst));
    }

    if (isHexEncode()) {
      return JOrphanUtils.baToHexString(dst);
    } else {
      return new String(dst, binaryCharset);
    }
  }

  private int getNextChunkSize() throws IOException {
    metaBuf.clear();
    while (true) {
      byte b = getOneByte();
      if (b == 10 || b == 13) {
        // if we have \r\n then skip \n
        byte b2 = getOneByte();
        if (b2 != 10) {
          file.position(file.position() - 1);
        }

        // ignore newlines before length marker
        if (metaBuf.position() > 0) {
          break;
        }
      } else {
        // if (log.isDebugEnabled()) log.debug("Read byte: "+b);
        metaBuf.put(b);
      }
    }
    // if (log.isDebugEnabled()) log.debug("Meta line:
    // "+JMeterPluginsUtils.byteBufferToString(metaBuf));

    byte[] bLine = new byte[metaBuf.position()];
    metaBuf.rewind();
    metaBuf.get(bLine);
    String sLine = new String(bLine).trim();
    String[] ar = sLine.split(regexp);
    if (log.isDebugEnabled()) {
      log.debug("Chunk size: " + ar[0]);
    }

    int res = 0;
    try {
      res = Integer.parseInt(ar[0]);
    } catch (NumberFormatException ex) {
      log.error("Error reading chunk size near: " + sLine, ex);
      throw new IOExceptionWithCause(ex);
    }
    return res;
  }

  private byte getOneByte() throws IOException {
    oneByte.rewind();
    if (file.read(oneByte) < 1) {
      throw new EndOfFileException(getFileName());
    }
    return oneByte.get(0);
  }

  public String getVarName() {
    return getPropertyAsString(VARIABLE_NAME);
  }

  public void setVarName(String name) {
    setProperty(VARIABLE_NAME, name);
  }

  public String getFileName() {
    return getPropertyAsString(FILENAME);
  }

  public void setFileName(String filename) {
    setProperty(FILENAME, filename);
    file = null;
  }

  public void setRewindOnEOF(boolean isRew) {
    setProperty(new BooleanProperty(REWIND, isRew));
  }

  public boolean getRewindOnEOF() {
    return getPropertyAsBoolean(REWIND);
  }

  public boolean isHexEncode() {
    return getPropertyAsBoolean(ENCODE_HEX);
  }

  public void setEncodeHex(boolean b) {
    setProperty(ENCODE_HEX, b);
  }
}