jmeter-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Philippe Mouawad <philippe.moua...@gmail.com>
Subject Re: svn commit: r1641081 - in /jmeter/trunk: ./ bin/ res/maven/ src/components/org/apache/jmeter/visualizers/backend/ src/core/org/apache/jmeter/resources/ src/core/org/apache/jmeter/samplers/ src/core/org/apache/jmeter/save/ xdocs/ xdocs/usermanual/
Date Sat, 22 Nov 2014 18:29:19 GMT
Hi Felix,
As I said in thread, I commited code and will improve, feel free to fix
javadocs issues on your side.
I will review your comment.

I have spent many hours if not days on this code and I am aware it is not
yet fully completed (although tests are promising) but my aim when
commiting it was to have feedback and help to finish it.

Regards
Philippe

On Sat, Nov 22, 2014 at 7:21 PM, Felix Schumacher <
felix.schumacher@internetallee.de> wrote:

> Hello Philippe,
>
> I have hidden a few comments inside the cited code.
> They are mostly around javadoc and naming things.
>
> Am 22.11.2014 um 16:36 schrieb pmouawad@apache.org:
>
>> Author: pmouawad
>> Date: Sat Nov 22 15:36:37 2014
>> New Revision: 1641081
>>
>> URL: http://svn.apache.org/r1641081
>> Log:
>> Bug 55932 - Create a Async BackendListener to allow easy plug of new
>> listener (Graphite, JDBC, Console,...)
>> Bugzilla Id: 55932
>>
>> Added:
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> AbstractBackendListenerClient.java   (with props)
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListener.java
>>  (with props)
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerClient.java   (with props)
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListenerContext.java
>>  (with props)
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerGui.java   (with props)
>>      jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/SamplerMetric.java
>>  (with props)
>> Modified:
>>      jmeter/trunk/bin/saveservice.properties
>>      jmeter/trunk/build.properties
>>      jmeter/trunk/build.xml
>>      jmeter/trunk/eclipse.classpath
>>      jmeter/trunk/res/maven/ApacheJMeter_parent.pom
>>      jmeter/trunk/src/core/org/apache/jmeter/resources/
>> messages.properties
>>      jmeter/trunk/src/core/org/apache/jmeter/resources/
>> messages_fr.properties
>>      jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
>>      jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java
>>      jmeter/trunk/xdocs/changes.xml
>>      jmeter/trunk/xdocs/usermanual/component_reference.xml
>>
>> Modified: jmeter/trunk/bin/saveservice.properties
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.
>> properties?rev=1641081&r1=1641080&r2=1641081&view=diff
>> ============================================================
>> ==================
>> --- jmeter/trunk/bin/saveservice.properties (original)
>> +++ jmeter/trunk/bin/saveservice.properties Sat Nov 22 15:36:37 2014
>> @@ -53,7 +53,8 @@ _file_version=$Revision$
>>   # 2.5 = 2.10
>>   # 2.6 = 2.11
>>   # 2.7 = 2.12
>> -_version=2.7
>> +# 2.8 = 2.13
>> +_version=2.8
>>   #
>>   #
>>   # Character set encoding used to read and write JMeter XML files and
>> CSV results
>> @@ -78,6 +79,8 @@ AssertionVisualizer=org.apache.jmeter.vi
>>   AuthManager=org.apache.jmeter.protocol.http.control.AuthManager
>>   Authorization=org.apache.jmeter.protocol.http.control.Authorization
>>   AuthPanel=org.apache.jmeter.protocol.http.gui.AuthPanel
>> +BackendListener=org.apache.jmeter.visualizers.backend.BackendListener
>> +BackendListenerGui=org.apache.jmeter.visualizers.
>> backend.BackendListenerGui
>>   BarChart=org.apache.jmeter.testelement.BarChart
>>   BarChartGui=org.apache.jmeter.report.gui.BarChartGui
>>   BeanShellAssertion=org.apache.jmeter.assertions.BeanShellAssertion
>>
>> Modified: jmeter/trunk/build.properties
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/build.properties?
>> rev=1641081&r1=1641080&r2=1641081&view=diff
>> ============================================================
>> ==================
>> --- jmeter/trunk/build.properties (original)
>> +++ jmeter/trunk/build.properties Sat Nov 22 15:36:37 2014
>> @@ -118,11 +118,21 @@ commons-logging.loc         = ${maven2.r
>>   #commons-logging.md5         = E2C390FE739B2550A218262B28F290CE
>>   commons-logging.md5         = 040b4b4d8eac886f6b4a2a3bd2f31b00
>>   +commons-math3.version         = 3.3
>> +commons-math3.jar             = commons-math3-${commons-math3.
>> version}.jar
>> +commons-math3.loc             = ${maven2.repo}/org/apache/
>> commons/commons-math3/${commons-math3.version}
>> +commons-math3.md5             = 87346cf2772dc2becf106c45e0f63863
>> +
>>   commons-net.version         = 3.3
>>   commons-net.jar             = commons-net-${commons-net.version}.jar
>>   commons-net.loc             = ${maven2.repo}/commons-net/
>> commons-net/${commons-net.version}
>>   commons-net.md5             = c077ca61598e9c21f43f8b6488fbbee9
>>   +commons-pool2.version         = 2.2
>> +commons-pool2.jar             = commons-pool2-${commons-pool2.
>> version}.jar
>> +commons-pool2.loc             = ${maven2.repo}/org/apache/
>> commons/commons-pool2/${commons-pool2.version}
>> +commons-pool2.md5             = 51b56c92883812c56fbeb339866ce2df
>> +
>>   # dnsjava for DNSCacheManager
>>   dnsjava.version             = 2.1.6
>>   dnsjava.jar                 = dnsjava-${dnsjava.version}.jar
>>
>> Modified: jmeter/trunk/build.xml
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/build.xml?rev=
>> 1641081&r1=1641080&r2=1641081&view=diff
>> ============================================================
>> ==================
>> --- jmeter/trunk/build.xml (original)
>> +++ jmeter/trunk/build.xml Sat Nov 22 15:36:37 2014
>> @@ -365,7 +365,9 @@
>>       <include name="${lib.dir}/${commons-jexl2.jar}"/>
>>       <include name="${lib.dir}/${commons-lang3.jar}"/>
>>       <include name="${lib.dir}/${commons-logging.jar}"/>
>> +    <include name="${lib.dir}/${commons-math3}"/>
>>       <include name="${lib.dir}/${commons-net.jar}"/>
>> +    <include name="${lib.dir}/${commons-pool2.jar}"/>
>>       <include name="${lib.dir}/${dnsjava.jar}"/>
>>       <include name="${lib.dir}/${excalibur-datasource.jar}"/>
>>       <include name="${lib.dir}/${excalibur-instrument.jar}"/>
>> @@ -438,8 +440,10 @@
>>       <pathelement location="${lib.dir}/${commons-jexl2.jar}"/>
>>       <pathelement location="${lib.dir}/${commons-lang3.jar}"/>
>>       <pathelement location="${lib.dir}/${commons-logging.jar}"/>
>> +    <pathelement location="${lib.dir}/${commons-math3.jar}"/>
>>       <pathelement location="${lib.dir}/${commons-net.jar}"/>
>> -    <pathelement location="${lib.dir}/${dnsjava.jar}"/>
>> +       <pathelement location="${lib.dir}/${commons-pool2.jar}"/>
>> +       <pathelement location="${lib.dir}/${dnsjava.jar}"/>
>>       <pathelement location="${lib.dir}/${excalibur-datasource.jar}"/>
>>       <pathelement location="${lib.dir}/${excalibur-instrument.jar}"/>
>>       <pathelement location="${lib.dir}/${excalibur-logger.jar}"/>
>> @@ -2909,7 +2913,9 @@ run JMeter unless all the JMeter jars ar
>>           <process_jarfile jarname="commons-jexl2"/>
>>           <process_jarfile jarname="commons-lang3"/>
>>           <process_jarfile jarname="commons-logging"/>
>> +        <process_jarfile jarname="commons-math3"/>
>>           <process_jarfile jarname="commons-net"/>
>> +       <process_jarfile jarname="commons-pool2"/>
>>           <process_jarfile jarname="dnsjava"/>
>>           <process_jarfile jarname="excalibur-datasource"/>
>>           <process_jarfile jarname="excalibur-instrument"/>
>>
>> Modified: jmeter/trunk/eclipse.classpath
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/eclipse.
>> classpath?rev=1641081&r1=1641080&r2=1641081&view=diff
>> ============================================================
>> ==================
>> --- jmeter/trunk/eclipse.classpath (original)
>> +++ jmeter/trunk/eclipse.classpath Sat Nov 22 15:36:37 2014
>> @@ -55,7 +55,9 @@
>>         <classpathentry kind="lib" path="lib/commons-jexl-2.1.1.jar"/>
>>         <classpathentry kind="lib" path="lib/commons-lang3-3.3.2.jar"/>
>>         <classpathentry kind="lib" path="lib/commons-logging-1.2.jar"/>
>> +    <classpathentry kind="lib" path="lib/commons-math3-3.3.jar"/>
>>         <classpathentry kind="lib" path="lib/commons-net-3.3.jar"/>
>> +    <classpathentry kind="lib" path="lib/commons-pool2-2.2.jar"/>
>>         <classpathentry kind="lib" path="lib/dnsjava-2.1.6.jar"/>
>>         <classpathentry kind="lib" path="lib/excalibur-
>> datasource-2.1.jar"/>
>>         <classpathentry kind="lib" path="lib/excalibur-
>> instrument-1.0.jar"/>
>>
>> Modified: jmeter/trunk/res/maven/ApacheJMeter_parent.pom
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/res/maven/
>> ApacheJMeter_parent.pom?rev=1641081&r1=1641080&r2=1641081&view=diff
>> ============================================================
>> ==================
>> --- jmeter/trunk/res/maven/ApacheJMeter_parent.pom (original)
>> +++ jmeter/trunk/res/maven/ApacheJMeter_parent.pom Sat Nov 22 15:36:37
>> 2014
>> @@ -66,7 +66,9 @@ under the License.
>>         <commons-jexl2.version>2.1.1</commons-jexl2.version>
>>         <commons-lang3.version>3.3.2</commons-lang3.version>
>>         <commons-logging.version>1.2</commons-logging.version>
>> +      <commons-math3.version>3.3</commons-math3.version>
>>         <commons-net.version>3.3</commons-net.version>
>> +      <commons-pool2.version>2.2</commons-pool2.version>
>>         <dnsjava.version>2.1.6</dnsjava.version>
>>         <excalibur-datasource.version>2.1</excalibur-datasource.version>
>>         <excalibur-instrument.version>1.0</excalibur-instrument.version>
>> @@ -181,11 +183,21 @@ under the License.
>>           <version>${commons-logging.version}</version>
>>         </dependency>
>>         <dependency>
>> +        <groupId>commons-math3</groupId>
>> +        <artifactId>commons-math3</artifactId>
>> +        <version>${commons-math3.version}</version>
>> +      </dependency>
>> +      <dependency>
>>           <groupId>commons-net</groupId>
>>           <artifactId>commons-net</artifactId>
>>           <version>${commons-net.version}</version>
>>         </dependency>
>>         <dependency>
>> +        <groupId>commons-pool2</groupId>
>> +        <artifactId>commons-pool2</artifactId>
>> +        <version>${commons-pool2.version}</version>
>> +      </dependency>
>> +      <dependency>
>>             <groupId>dnsjava</groupId>
>>             <artifactId>dnsjava</artifactId>
>>             <version>${dnsjava.version}</version>
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> AbstractBackendListenerClient.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/AbstractBackendListenerClient.
>> java?rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> AbstractBackendListenerClient.java (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> AbstractBackendListenerClient.java Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,121 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import java.util.Map;
>> +import java.util.concurrent.ConcurrentHashMap;
>> +
>> +import org.apache.jmeter.config.Arguments;
>> +import org.apache.jmeter.samplers.SampleResult;
>> +import org.apache.jorphan.logging.LoggingManager;
>> +import org.apache.log.Logger;
>> +
>> +/**
>> + * An abstract implementation of the BackendListenerClient interface.
>> This
>> + * implementation provides default implementations of most of the
>> methods in the
>> + * interface, as well as some convenience methods, in order to simplify
>> + * development of BackendListenerClient implementations.
>> + *
>> + * While it may be necessary to make changes to the
>> BackendListenerClient interface
>> + * from time to time (therefore requiring changes to any implementations
>> of this
>> + * interface), we intend to make this abstract class provide reasonable
>> + * implementations of any new methods so that subclasses do not
>> necessarily need
>> + * to be updated for new versions. Therefore, when creating a new
>> + * BackendListenerClient implementation, developers are encouraged to
>> subclass this
>> + * abstract class rather than implementing the BackendListenerClient
>> interface
>> + * directly. Implementing BackendListenerClient directly will continue
>> to be
>> + * supported for cases where extending this class is not possible (for
>> example,
>> + * when the client class is already a subclass of some other class).
>> + * <p>
>> + * The handleSampleResult() method of BackendListenerClient does not
>> have a default
>> + * implementation here, so subclasses must define at least this method.
>> It may
>> + * be useful to override other methods as well.
>> + *
>> + * @see BackendListener#sampleOccurred(org.apache.
>> jmeter.samplers.SampleEvent)
>> + * @since 2.13
>> + */
>> +public abstract class AbstractBackendListenerClient implements
>> BackendListenerClient {
>> +
>> +    private static final Logger log = LoggingManager.
>> getLoggerForClass();
>>
> In classes further down the logger is stored in variables named LOG and
> LOGGER, should we use one name?
> In this class we have a getter for the logger in other classes not. Why?
>
>> +
>> +    private ConcurrentHashMap<String, SamplerMetric> metricsPerSampler =
>> new ConcurrentHashMap<String, SamplerMetric>();
>> +
>> +    /* Implements BackendListenerClient.setupTest(JavaSamplerContext) */
>> +    @Override
>> +    public void setupTest(BackendListenerContext context) throws
>> Exception {
>> +        log.debug(getClass().getName() + ": setupTest");
>> +    }
>> +
>> +    /* Implements BackendListenerClient.teardownTest(JavaSamplerContext)
>> */
>> +    @Override
>> +    public void teardownTest(BackendListenerContext context) throws
>> Exception {
>> +        log.debug(getClass().getName() + ": teardownTest");
>> +        metricsPerSampler.clear();
>> +    }
>> +
>> +    /* Implements BackendListenerClient.getDefaultParameters() */
>> +    @Override
>> +    public Arguments getDefaultParameters() {
>> +        return null;
>> +    }
>> +
>> +    /**
>> +     * Get a Logger instance which can be used by subclasses to log
>> information.
>> +     *
>> +     * @return a Logger instance which can be used for logging
>> +     */
>> +    protected Logger getLogger() {
>> +        return log;
>> +    }
>> +
>> +    /* (non-Javadoc)
>> +     * @see org.apache.jmeter.visualizers.backend.BackendListenerClient#
>> createSampleResult(org.apache.jmeter.samplers.SampleResult)
>> +     */
>> +    @Override
>> +    public SampleResult createSampleResult(BackendListenerContext
>> context, SampleResult result) {
>> +        SampleResult sampleResult = (SampleResult) result.clone();
>> +        return sampleResult;
>> +    }
>> +
>> +    /**
>> +     *
>> +     * @param sampleLabel
>> +     * @return SamplerMetric
>>
> No description of the method and the parameters?
>
>> +     */
>> +    protected SamplerMetric getSamplerMetric(String sampleLabel) {
>> +        SamplerMetric samplerMetric = metricsPerSampler.get(
>> sampleLabel);
>> +        if(samplerMetric == null) {
>> +            samplerMetric = new SamplerMetric();
>> +            SamplerMetric oldValue = metricsPerSampler.putIfAbsent(sampleLabel,
>> samplerMetric);
>> +            if(oldValue != null ){
>> +                samplerMetric = oldValue;
>> +            }
>> +        }
>> +        return samplerMetric;
>> +    }
>> +
>> +    /**
>> +     *
>> +     * @return Map<String, SamplerMetric>
>>
> No description of the method and usage of forbidden characters :) there
> are still more than 800 warnings in the javadoc to prune, so don't
> introduce new ones, please.
>
>> +     */
>> +    protected Map<String, SamplerMetric> getMetricsPerSampler() {
>> +        return metricsPerSampler;
>> +    }
>> +
>> +}
>>
>> Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/AbstractBackendListenerClient.java
>> ------------------------------------------------------------
>> ------------------
>>      svn:mime-type = text/plain
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListener.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/BackendListener.java?
>> rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListener.java
>> (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListener.java
>> Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,448 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import java.io.Serializable;
>> +import java.lang.reflect.Method;
>> +import java.util.ArrayList;
>> +import java.util.HashSet;
>> +import java.util.List;
>> +import java.util.Set;
>> +import java.util.concurrent.ArrayBlockingQueue;
>> +import java.util.concurrent.BlockingQueue;
>> +import java.util.concurrent.locks.LockSupport;
>> +
>> +import org.apache.jmeter.config.Arguments;
>> +import org.apache.jmeter.engine.util.NoThreadClone;
>> +import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
>> +import org.apache.jmeter.samplers.Remoteable;
>> +import org.apache.jmeter.samplers.SampleEvent;
>> +import org.apache.jmeter.samplers.SampleListener;
>> +import org.apache.jmeter.samplers.SampleResult;
>> +import org.apache.jmeter.testelement.AbstractTestElement;
>> +import org.apache.jmeter.testelement.TestElement;
>> +import org.apache.jmeter.testelement.TestStateListener;
>> +import org.apache.jmeter.testelement.property.TestElementProperty;
>> +import org.apache.jorphan.logging.LoggingManager;
>> +import org.apache.log.Logger;
>> +
>> +/**
>> + * Async Listener that delegates SampleResult handling to
>> implementations of {@link BackendListenerClient}
>> + * @since 2.13
>> + */
>> +public class BackendListener extends AbstractTestElement
>> +    implements Serializable, SampleListener, TestStateListener,
>> NoThreadClone, Remoteable  {
>> +
>> +    /**
>> +     *
>> +     */
>> +    private static final long serialVersionUID = 8184103677832024335L;
>> +
>> +    private static final Logger log = LoggingManager.
>> getLoggerForClass();
>>
> See naming comment of log from above
>
>> +
>> +    /**
>> +     * Set used to register instances which implement teardownTest.
>> +     * This is used so that the BackendListenerClient can be notified
>> when the test ends.
>> +     */
>> +    private static final Set<BackendListener> TEAR_DOWN_SET = new
>> HashSet<BackendListener>();
>> +
>> +    /**
>> +     * Property key representing the classname of the
>> BackendListenerClient to user.
>> +     */
>> +    public static final String CLASSNAME = "classname";
>> +
>> +    /**
>> +     * Queue size
>> +     */
>> +    public static final String QUEUE_SIZE = "QUEUE_SIZE";
>> +
>> +    /**
>> +     * Property key representing the arguments for the
>> BackendListenerClient.
>> +     */
>> +    public static final String ARGUMENTS = "arguments";
>> +
>> +    /**
>> +     * The BackendListenerClient class used by this sampler.
>> +     * Created by testStarted; copied to cloned instances.
>> +     */
>> +    private Class<?> javaClass;
>>
> Could probably named clientClass instead of javaClass, since we already
> know it is a java class.
>
>> +
>> +    /**
>> +     * If true, the BackendListenerClient class implements teardownTest.
>> +     * Created by testStarted; copied to cloned instances.
>> +     */
>> +    private boolean isToBeRegistered;
>> +
>> +    /**
>> +     * The BackendListenerClient instance
>> +     */
>> +    private transient BackendListenerClient backendListenerClient = null;
>> +
>> +    /**
>> +     * The JavaSamplerContext instance used by this sampler to hold
>> information
>>
> BackendListenerContext?
>
>> +     * related to the test run, such as the parameters specified for the
>> sampler
>> +     * client.
>> +     */
>> +    private transient BackendListenerContext context = null;
>> +
>> +    private static final int DEFAULT_QUEUE_SIZE = 5000;
>> +
>> +    private transient BlockingQueue<SampleResult> queue; // created by
>> server in readResolve method
>> +
>> +    private transient long queueWaits; // how many times we had to wait
>> to queue a sample
>> +
>> +    private transient long queueWaitTime; // how long we had to wait
>> (nanoSeconds)
>> +
>> +    // Create unique object as marker for end of queue
>> +    private transient static final SampleResult FINAL_EVENT = new
>> SampleResult();
>> +
>> +    /**
>> +     * Create a BackendListener.
>> +     */
>> +    public BackendListener() {
>> +        setArguments(new Arguments());
>> +    }
>> +
>> +    /*
>> +     * Ensure that the required class variables are cloned,
>> +     * as this is not currently done by the super-implementation.
>> +     */
>> +    @Override
>> +    public Object clone() {
>> +        BackendListener clone = (BackendListener) super.clone();
>> +        clone.javaClass = this.javaClass;
>> +        clone.isToBeRegistered = this.isToBeRegistered;
>> +        return clone;
>> +    }
>> +
>> +    private void initClass() {
>> +        String name = getClassname().trim();
>> +        try {
>> +            javaClass = Class.forName(name, false,
>> Thread.currentThread().getContextClassLoader());
>> +            Method method = javaClass.getMethod("teardownTest", new
>> Class[]{BackendListenerContext.class});
>> +            isToBeRegistered = !method.getDeclaringClass().equals(
>> AbstractBackendListenerClient.class);
>> +            log.info("Created class: " + name + ". Uses teardownTest: "
>> + isToBeRegistered);
>> +        } catch (Exception e) {
>> +            log.error(whoAmI() + "\tException initialising: " + name, e);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Retrieves reference to BackendListenerClient.
>> +     *
>> +     * Convience method used to check for null reference without actually
>> +     * creating a BackendListenerClient
>> +     *
>> +     * @return reference to BackendListenerClient NOTUSED private
>> BackendListenerClient
>> +     *         retrieveJavaClient() { return javaClient; }
>> +     */
>>
> Javadoc for non-existant method?
>
>> +
>> +    /**
>> +     * Generate a String identifier of this instance for debugging
>> purposes.
>> +     *
>> +     * @return a String identifier for this sampler instance
>> +     */
>> +    private String whoAmI() {
>> +        StringBuilder sb = new StringBuilder();
>> +        sb.append(Thread.currentThread().getName());
>> +        sb.append("@");
>> +        sb.append(Integer.toHexString(hashCode()));
>> +        sb.append("-");
>> +        sb.append(getName());
>> +        return sb.toString();
>> +    }
>> +
>> +    // TestStateListener implementation
>> +    /* Implements TestStateListener.testStarted() */
>> +    @Override
>> +    public void testStarted() {
>> +        testStarted("");
>> +    }
>> +
>> +    /* Implements TestStateListener.testStarted(String) */
>> +    @Override
>> +    public void testStarted(String host) {
>> +        log.debug(whoAmI() + "\ttestStarted(" + host + ")");
>>
> Maybe use isDebugEnabled to guard whoAmI() call?
>
>> +        queue = new ArrayBlockingQueue<SampleResult>(getQueueSize());
>> +        initClass();
>> +        queueWaits=0L;
>> +        queueWaitTime=0L;
>> +        log.info(getName()+":Starting worker with class:"+javaClass +"
>> and queue capacity:"+getQueueSize());
>> +
>> +        backendListenerClient = createBackendListenerClientImp
>> l(javaClass);
>> +        context = new BackendListenerContext((Arguments)getArguments().
>> clone());
>> +        if(isToBeRegistered) {
>>
> space after if and before (?
>
>> +            TEAR_DOWN_SET.add(this);
>> +        }
>> +        try {
>> +            backendListenerClient.setupTest(context);
>> +        } catch (Exception e) {
>> +            throw new java.lang.IllegalStateException("Failed calling
>> setupTest", e);
>> +        }
>> +
>> +        Worker worker = new Worker(javaClass, backendListenerClient,
>> (Arguments) getArguments().clone(), queue);
>> +        worker.setDaemon(true);
>> +        worker.start();
>>
> Don't we want to stop worker after we're done with one test?
>
>> +        log.info(getName()+":Started  worker with class:"+javaClass);
>>
> Spaces after :?
>
>> +
>> +    }
>> +
>> +    /* (non-Javadoc)
>> +     * @see org.apache.jmeter.samplers.SampleListener#sampleOccurred(
>> org.apache.jmeter.samplers.SampleEvent)
>> +     */
>> +    @Override
>> +    public void sampleOccurred(SampleEvent e) {
>>
> Longer name then 'e'? I expect e to be an exception, not an event.
>
>> +        Arguments args = getArguments();
>> +        context = new BackendListenerContext(args);
>> +
>> +        SampleResult sr = backendListenerClient.createSampleResult(context,
>> e.getResult());
>> +        try {
>> +            if (!queue.offer(sr)){ // we failed to add the element first
>> time
>> +                queueWaits++;
>> +                long t1 = System.nanoTime();
>> +                queue.put(sr);
>> +                long t2 = System.nanoTime();
>> +                queueWaitTime += t2-t1;
>>
> Will sampleOccurred be called concurrently? If so, than queueWaitTime +=
> will not be correct.
>
>> +            }
>> +        } catch (Exception err) {
>> +            log.error("sampleOccurred, failed to queue the sample", err);
>> +        }
>> +    }
>> +
>> +    private static final class Worker extends Thread {
>> +
>> +        private final BlockingQueue<SampleResult> queue;
>> +        private final BackendListenerContext context;
>> +        private final BackendListenerClient backendListenerClient;
>> +        private Worker(Class<?> javaClass, BackendListenerClient
>> backendListenerClient, Arguments arguments, BlockingQueue<SampleResult> q){
>>
> Same naming argument as above. clientclass instead of javaClass?
>
>> +            queue = q;
>> +            // Allow BackendListenerClient implementations to get access
>> to test element name
>> +            arguments.addArgument(TestElement.NAME, getName());
>> +            context = new BackendListenerContext(arguments);
>> +            this.backendListenerClient = backendListenerClient;
>> +        }
>> +
>> +
>> +        @Override
>> +        public void run() {
>> +            boolean isDebugEnabled = log.isDebugEnabled();
>> +            List<SampleResult> l = new ArrayList<SampleResult>(queue.
>> size());
>>
> samples instead of l?
>
>> +            try {
>> +                boolean eof = false;
>>
> endOfLoop?
>
>> +                while (!eof) {
>> +                    if(isDebugEnabled) {
>> +                        log.debug("Thread:"+Thread.currentThread().getName()+"
>> taking SampleResult from queue:"+queue.size());
>> +                    }
>> +                    SampleResult e = queue.take();
>>
> Could be named result, or sample instead of e
>
>> +                    if(isDebugEnabled) {
>> +                        log.debug("Thread:"+Thread.currentThread().getName()+"
>> took SampleResult:"+e+", isFinal:" + (e==FINAL_EVENT));
>> +                    }
>> +                    while (!(eof = (e == FINAL_EVENT)) && e != null ) {
>> // try to process as many as possible
>> +                        l.add(e);
>> +                        if(isDebugEnabled) {
>> +                            log.debug("Thread:"+Thread.currentThread().getName()+"
>> polling from queue:"+queue.size());
>> +                        }
>> +                        e = queue.poll(); // returns null if nothing on
>> queue currently
>> +                        if(isDebugEnabled) {
>> +                            log.debug("Thread:"+Thread.currentThread().getName()+"
>> took from queue:"+e+", isFinal:" + (e==FINAL_EVENT));
>> +                        }
>> +                    }
>> +                    if(isDebugEnabled) {
>> +                        log.debug("Thread:"+Thread.
>> currentThread().getName()+
>> +                                " exiting with FINAL EVENT:"+(e ==
>> FINAL_EVENT)
>> +                                +", null:" + (e==null));
>> +                    }
>> +                    int size = l.size();
>>
> No need for a temporary variable.
>
>> +                    if (size > 0) {
>> +                        backendListenerClient.handleSampleResults(l,
>> context);
>> +                        l.clear();
>> +                    }
>> +                    if(!eof) {
>> +                        LockSupport.parkNanos(100);
>> +                    }
>> +                }
>> +            } catch (InterruptedException e) {
>> +                // NOOP
>> +            }
>> +            // We may have been interrupted
>> +            int size = l.size();
>> +            if (size > 0) {
>> +                backendListenerClient.handleSampleResults(l, context);
>> +                l.clear();
>> +            }
>>
> Same code as a few lines above, could be factored out into a method
> handleSamples(l, context)
>
>> +            log.info("Worker ended");
>> +        }
>> +    }
>> +
>> +
>> +    /**
>> +     * Returns reference to <code>BackendListenerClient</code>.
>>
> Could use a {@link...}
>
>> +     *
>> +     *
>> +     * @return BackendListenerClient reference.
>> +     */
>> +    static BackendListenerClient createBackendListenerClientImpl(Class<?>
>> javaClass) {
>> +        if (javaClass == null) { // failed to initialise the class
>> +            return new ErrorBackendListenerClient();
>> +        }
>> +        BackendListenerClient client;
>> +        try {
>> +            client = (BackendListenerClient) javaClass.newInstance();
>> +        } catch (Exception e) {
>> +            log.error("Exception creating: " + javaClass, e);
>> +            client = new ErrorBackendListenerClient();
>> +        }
>> +        return client;
>>
> I would return newInstance() in try Block and return new Error.. in catch
> Block. javaClass -> clientClass
>
>> +    }
>> +
>> +    /**
>> +     * Method called at the end of the test. This is called only on one
>> instance
>> +     * of BackendListener. This method will loop through all of the other
>> +     * BackendListenerClients which have been registered (automatically
>> in the
>> +     * constructor) and notify them that the test has ended, allowing the
>> +     * BackendListenerClients to cleanup.
>> +     */
>> +    @Override
>> +    public void testEnded() {
>> +        try {
>> +            queue.put(FINAL_EVENT);
>> +        } catch (Exception ex) {
>> +            log.warn("testEnded() with exception:"+ex.getMessage(), ex);
>> +        }
>> +        if (queueWaits > 0) {
>> +            log.warn("QueueWaits: "+queueWaits+"; QueueWaitTime:
>> "+queueWaitTime+" (nanoseconds), you may need to increase queue capacity,
>> see property 'backend_queue_capacity'");
>> +        }
>> +        synchronized (TEAR_DOWN_SET) {
>> +            for (BackendListener backendListener : TEAR_DOWN_SET) {
>> +                BackendListenerClient client = backendListener.
>> backendListenerClient;
>> +                if (client != null) {
>> +                    try {
>> +                        client.teardownTest(backendListener.context);
>> +                    } catch (Exception e) {
>> +                        throw new java.lang.IllegalStateException("Failed
>> calling teardownTest", e);
>>
> If we throw an exception here, we will not try every client.
>
>> +                    }
>> +                }
>> +            }
>> +            TEAR_DOWN_SET.clear();
>> +        }
>> +    }
>> +
>> +    /* Implements TestStateListener.testEnded(String) */
>> +    @Override
>> +    public void testEnded(String host) {
>> +        testEnded();
>> +    }
>> +
>> +    /**
>> +     * A {@link BackendListenerClient} implementation used for error
>> handling. If an
>> +     * error occurs while creating the real BackendListenerClient
>> object, it is
>> +     * replaced with an instance of this class. Each time a sample
>> occurs with
>> +     * this class, the result is marked as a failure so the user can see
>> that
>> +     * the test failed.
>> +     */
>> +    static class ErrorBackendListenerClient extends
>> AbstractBackendListenerClient {
>> +        /**
>> +         * Return SampleResult with data on error.
>> +         *
>> +         * @see BackendListenerClient#runTest(JavaSamplerContext)
>> +         */
>> +        @Override
>> +        public void handleSampleResults(List<SampleResult>
>> sampleResults, BackendListenerContext context) {
>> +            log.warn("ErrorBackendListenerClient#handleSampleResult
>> called, noop");
>> +            Thread.yield();
>> +        }
>> +    }
>> +
>> +    /* (non-Javadoc)
>> +     * @see org.apache.jmeter.samplers.SampleListener#sampleStarted(
>> org.apache.jmeter.samplers.SampleEvent)
>> +     */
>> +    @Override
>> +    public void sampleStarted(SampleEvent e) {
>> +        // NOOP
>> +
>> +    }
>> +
>> +    /* (non-Javadoc)
>> +     * @see org.apache.jmeter.samplers.SampleListener#sampleStopped(
>> org.apache.jmeter.samplers.SampleEvent)
>> +     */
>> +    @Override
>> +    public void sampleStopped(SampleEvent e) {
>> +        // NOOP
>> +
>> +    }
>> +
>> +    /**
>> +     * Set the arguments (parameters) for the BackendListenerClient to
>> be executed
>> +     * with.
>> +     *
>> +     * @param args
>> +     *            the new arguments. These replace any existing
>> arguments.
>> +     */
>> +    public void setArguments(Arguments args) {
>> +        setProperty(new TestElementProperty(ARGUMENTS, args));
>> +    }
>> +
>> +    /**
>> +     * Get the arguments (parameters) for the BackendListenerClient to
>> be executed
>> +     * with.
>> +     *
>> +     * @return the arguments
>> +     */
>> +    public Arguments getArguments() {
>> +        return (Arguments) getProperty(ARGUMENTS).getObjectValue();
>> +    }
>> +
>> +    /**
>> +     * Sets the Classname of the BackendListenerClient object
>> +     *
>> +     * @param classname
>> +     *            the new Classname value
>> +     */
>> +    public void setClassname(String classname) {
>> +        setProperty(CLASSNAME, classname);
>> +    }
>> +
>> +    /**
>> +     * Gets the Classname of the BackendListenerClient object
>> +     *
>> +     * @return the Classname value
>> +     */
>> +    public String getClassname() {
>> +        return getPropertyAsString(CLASSNAME);
>> +    }
>> +
>> +    /**
>> +     * Sets the queue size
>> +     *
>> +     * @param queueSize
>> +     *
>> +     */
>> +    public void setQueueSize(int queueSize) {
>> +        setProperty(QUEUE_SIZE, queueSize, DEFAULT_QUEUE_SIZE);
>> +    }
>> +
>> +    /**
>> +     * Gets the queue size
>> +     *
>> +     * @return int queueSize
>> +     */
>> +    public int getQueueSize() {
>> +        return getPropertyAsInt(QUEUE_SIZE, DEFAULT_QUEUE_SIZE);
>> +    }
>> +}
>>
>> Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListener.java
>> ------------------------------------------------------------
>> ------------------
>>      svn:mime-type = text/plain
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerClient.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/BackendListenerClient.
>> java?rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerClient.java (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerClient.java Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,128 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import java.util.List;
>> +
>> +import org.apache.jmeter.config.Arguments;
>> +import org.apache.jmeter.samplers.SampleResult;
>> +
>> +/**
>> + * This interface defines the interactions between the BackendListener
>> and external
>> + * Java programs which can be executed by JMeter. Any Java class which
>> wants to
>> + * be executed as a JMeter test must implement this interface (either
>> directly
>> + * or indirectly through AbstractBackendListenerClient).
>> + * <p>
>> + * JMeter will create one instance of a BackendListenerClient
>> implementation for
>> + * each user/thread in the test. Additional instances may be created for
>> + * internal use by JMeter (for example, to find out what parameters are
>> + * supported by the client).
>> + * <p>
>> + * When the test is started, setupTest() will be called on each thread's
>> + * BackendListenerClient instance to initialize the client. Then
>> handleSampleResult() will be
>> + * called for each SampleResult notification. Finally, teardownTest()
>> will be called
>> + * to allow the client to do any necessary clean-up.
>> + * <p>
>> + * The JMeter BackendListener GUI allows a list of parameters to be
>> defined for the
>> + * test. These are passed to the various test methods through the
>> + * {@link BackendListenerContext}. A list of default parameters can be
>> defined
>> + * through the getDefaultParameters() method. These parameters and any
>> default
>> + * values associated with them will be shown in the GUI. Users can add
>> other
>> + * parameters as well.
>> + * <p>
>> + * When possible, Listeners should extend {@link
>> AbstractBackendListenerClient
>> + * AbstractBackendListenerClient} rather than implementing
>> BackendListenerClient
>> + * directly. This should protect your tests from future changes to the
>> + * interface. While it may be necessary to make changes to the
>> BackendListenerClient
>> + * interface from time to time (therefore requiring changes to any
>> + * implementations of this interface), we intend to make this abstract
>> class
>> + * provide reasonable default implementations of any new methods so that
>> + * subclasses do not necessarily need to be updated for new versions.
>> + * Implementing BackendListenerClient directly will continue to be
>> supported for
>> + * cases where extending this class is not possible (for example, when
>> the
>> + * client class is already a subclass of some other class).
>> + *
>> + * @since 2.13
>> + */
>> +public interface BackendListenerClient {
>> +    /**
>> +     * Do any initialization required by this client. It is generally
>> +     * recommended to do any initialization such as getting parameter
>> values in
>> +     * the setupTest method rather than the runTest method in order to
>> add as
>> +     * little overhead as possible to the test.
>> +     *
>> +     * @param context
>> +     *            the context to run with. This provides access to
>> +     *            initialization parameters.
>> +     */
>> +    void setupTest(BackendListenerContext context) throws Exception;
>> +
>> +    /**
>> +     * Perform a single sample for each iteration. This method returns a
>> +     * <code>SampleResult</code> object. <code>SampleResult</code> has
>> many
>> +     * fields which can be used. At a minimum, the test should use
>> +     * <code>SampleResult.sampleStart</code> and
>> +     * <code>SampleResult.sampleEnd</code>to set the time that the test
>>
> use {@link..} instead of <code>..?
>
>> +     * required to execute. It is also a good idea to set the
>> sampleLabel and
>> +     * the successful flag.
>> +     *
>> +     * @see org.apache.jmeter.samplers.SampleResult#sampleStart()
>> +     * @see org.apache.jmeter.samplers.SampleResult#sampleEnd()
>> +     * @see org.apache.jmeter.samplers.SampleResult#setSuccessful(
>> boolean)
>> +     * @see org.apache.jmeter.samplers.SampleResult#setSampleLabel(
>> String)
>> +     *
>> +     * @param context
>> +     *            the context to run with. This provides access to
>> +     *            initialization parameters.
>> +     *
>> +     */
>> +    void handleSampleResults(List<SampleResult> sampleResults,
>> BackendListenerContext context);
>> +
>> +    /**
>> +     * Do any clean-up required by this test at the end of a test run.
>> +     *
>> +     * @param context
>> +     *            the context to run with. This provides access to
>> +     *            initialization parameters.
>> +     */
>> +    void teardownTest(BackendListenerContext context) throws Exception;
>> +
>> +    /**
>> +     * Provide a list of parameters which this test supports. Any
>> parameter
>> +     * names and associated values returned by this method will appear
>> in the
>> +     * GUI by default so the user doesn't have to remember the exact
>> names. The
>> +     * user can add other parameters which are not listed here. If this
>> method
>> +     * returns null then no parameters will be listed. If the value for
>> some
>> +     * parameter is null then that parameter will be listed in the GUI
>> with an
>> +     * empty value.
>> +     *
>> +     * @return a specification of the parameters used by this test which
>> should
>> +     *         be listed in the GUI, or null if no parameters should be
>> listed.
>> +     */
>> +    Arguments getDefaultParameters();
>> +
>> +    /**
>> +     *
>> +     * @param context
>> +     * @param result
>> +     * @return
>> +     */
>> +    SampleResult createSampleResult(
>> +            BackendListenerContext context, SampleResult result);
>> +}
>>
>> Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerClient.java
>> ------------------------------------------------------------
>> ------------------
>>      svn:mime-type = text/plain
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> BackendListenerContext.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/BackendListenerContext.java?
>> rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListenerContext.java
>> (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/BackendListenerContext.java
>> Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,237 @@
>> +/*
>> +
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import java.util.Iterator;
>> +import java.util.Map;
>> +
>> +import org.apache.jmeter.config.Arguments;
>> +import org.apache.jorphan.logging.LoggingManager;
>> +import org.apache.log.Logger;
>> +
>> +/**
>> + * BackendListenerContext is used to provide context information to a
>> + * BackendListenerClient implementation. This currently consists of the
>> + * initialization parameters which were specified in the GUI.
>> + * @since 2.13
>> + */
>> +public class BackendListenerContext {
>> +    /*
>> +     * Implementation notes:
>> +     *
>> +     * All of the methods in this class are currently read-only. If
>> update
>> +     * methods are included in the future, they should be defined so
>> that a
>> +     * single instance of BackendListenerContext can be associated with
>> each thread.
>> +     * Therefore, no synchronization should be needed. The same instance
>> should
>> +     * be used for the call to setupTest, all calls to runTest, and the
>> call to
>> +     * teardownTest.
>> +     */
>> +
>> +    /** Logging */
>> +    private static final Logger log = LoggingManager.
>> getLoggerForClass();
>>
> See naming comments for logger above
>
>> +
>> +    /**
>> +     * Map containing the initialization parameters for the
>> BackendListenerClient.
>> +     */
>> +    private final Map<String, String> params;
>> +
>> +    /**
>> +     *
>> +     * @param args
>> +     *            the initialization parameters.
>> +     */
>> +    public BackendListenerContext(Arguments args) {
>> +        this.params = args.getArgumentsAsMap();
>> +    }
>> +
>> +    /**
>> +     * Determine whether or not a value has been specified for the
>> parameter
>> +     * with this name.
>> +     *
>> +     * @param name
>> +     *            the name of the parameter to test
>> +     * @return true if the parameter value has been specified, false
>> otherwise.
>> +     */
>> +    public boolean containsParameter(String name) {
>>
> hasParameter instead of containsParameter?
>
>> +        return params.containsKey(name);
>> +    }
>> +
>> +    /**
>> +     * Get an iterator of the parameter names. Each entry in the
>> Iterator is a
>> +     * String.
>> +     *
>> +     * @return an Iterator of Strings listing the names of the
>> parameters which
>> +     *         have been specified for this test.
>> +     */
>> +    public Iterator<String> getParameterNamesIterator() {
>> +        return params.keySet().iterator();
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specific parameter as a String, or null if the
>> value
>> +     * was not specified.
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @return the value of the parameter, or null if the value was not
>> +     *         specified
>> +     */
>> +    public String getParameter(String name) {
>> +        return getParameter(name, null);
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specified parameter as a String, or return the
>> +     * specified default value if the value was not specified.
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @param defaultValue
>> +     *            the default value to return if the value of this
>> parameter was
>> +     *            not specified
>> +     * @return the value of the parameter, or the default value if the
>> parameter
>> +     *         was not specified
>> +     */
>> +    public String getParameter(String name, String defaultValue) {
>> +        if (params == null || !params.containsKey(name)) {
>> +            return defaultValue;
>> +        }
>> +        return params.get(name);
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specified parameter as an integer. An
>> exception will
>> +     * be thrown if the parameter is not specified or if it is not an
>> integer.
>> +     * The value may be specified in decimal, hexadecimal, or octal, as
>> defined
>> +     * by Integer.decode().
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @return the value of the parameter
>> +     *
>> +     * @throws NumberFormatException
>> +     *             if the parameter is not specified or is not an integer
>> +     *
>> +     * @see java.lang.Integer#decode(java.lang.String)
>> +     */
>> +    public int getIntParameter(String name) throws NumberFormatException
>> {
>> +        if (params == null || !params.containsKey(name)) {
>> +            throw new NumberFormatException("No value for parameter
>> named '" + name + "'.");
>>
> I would expect an IllegalArgumentException, if no parameter of that name
> is found
>
>> +        }
>> +
>> +        return Integer.decode(params.get(name)).intValue();
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specified parameter as an integer, or return
>> the
>> +     * specified default value if the value was not specified or is not
>> an
>> +     * integer. A warning will be logged if the value is not an integer.
>> The
>> +     * value may be specified in decimal, hexadecimal, or octal, as
>> defined by
>> +     * Integer.decode().
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @param defaultValue
>> +     *            the default value to return if the value of this
>> parameter was
>> +     *            not specified
>> +     * @return the value of the parameter, or the default value if the
>> parameter
>> +     *         was not specified
>> +     *
>> +     * @see java.lang.Integer#decode(java.lang.String)
>> +     */
>> +    public int getIntParameter(String name, int defaultValue) {
>> +        if (params == null || !params.containsKey(name)) {
>> +            return defaultValue;
>> +        }
>> +
>> +        try {
>> +            return Integer.decode(params.get(name)).intValue();
>> +        } catch (NumberFormatException e) {
>> +            log.warn("Value for parameter '" + name + "' not an integer:
>> '" + params.get(name) + "'.  Using default: '"
>> +                    + defaultValue + "'.", e);
>> +            return defaultValue;
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specified parameter as a long. An exception
>> will be
>> +     * thrown if the parameter is not specified or if it is not a long.
>> The
>> +     * value may be specified in decimal, hexadecimal, or octal, as
>> defined by
>> +     * Long.decode().
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @return the value of the parameter
>> +     *
>> +     * @throws NumberFormatException
>> +     *             if the parameter is not specified or is not a long
>> +     *
>> +     * @see Long#decode(String)
>> +     */
>> +    public long getLongParameter(String name) throws
>> NumberFormatException {
>> +        if (params == null || !params.containsKey(name)) {
>> +            throw new NumberFormatException("No value for parameter
>> named '" + name + "'.");
>> +        }
>> +
>> +        return Long.decode(params.get(name)).longValue();
>> +    }
>> +
>> +    /**
>> +     * Get the value of a specified parameter as along, or return the
>> specified
>> +     * default value if the value was not specified or is not a long. A
>> warning
>> +     * will be logged if the value is not a long. The value may be
>> specified in
>> +     * decimal, hexadecimal, or octal, as defined by Long.decode().
>> +     *
>> +     * @param name
>> +     *            the name of the parameter whose value should be
>> retrieved
>> +     * @param defaultValue
>> +     *            the default value to return if the value of this
>> parameter was
>> +     *            not specified
>> +     * @return the value of the parameter, or the default value if the
>> parameter
>> +     *         was not specified
>> +     *
>> +     * @see Long#decode(String)
>> +     */
>> +    public long getLongParameter(String name, long defaultValue) {
>> +        if (params == null || !params.containsKey(name)) {
>> +            return defaultValue;
>> +        }
>> +        try {
>> +            return Long.decode(params.get(name)).longValue();
>> +        } catch (NumberFormatException e) {
>> +            log.warn("Value for parameter '" + name + "' not a long: '"
>> + params.get(name) + "'.  Using default: '"
>> +                    + defaultValue + "'.", e);
>> +            return defaultValue;
>> +        }
>> +    }
>> +
>> +    /**
>> +     *
>> +     * @param name
>> +     * @param defaultValue
>> +     * @return
>>
> No javadoc? Again three warnings more :)
>
>> +     */
>> +    public boolean getBooleanParameter(String name, boolean
>> defaultValue) {
>> +        if (params == null || !params.containsKey(name)) {
>> +            return defaultValue;
>> +        }
>> +        return Boolean.valueOf(params.get(name));
>> +    }
>> +}
>>
>> Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerContext.java
>> ------------------------------------------------------------
>> ------------------
>>      svn:mime-type = text/plain
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerGui.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/BackendListenerGui.
>> java?rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerGui.java (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerGui.java Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,282 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import java.awt.BorderLayout;
>> +import java.awt.event.ActionEvent;
>> +import java.awt.event.ActionListener;
>> +import java.util.ArrayList;
>> +import java.util.HashSet;
>> +import java.util.List;
>> +import java.util.Map;
>> +import java.util.Set;
>> +
>> +import javax.swing.ComboBoxModel;
>> +import javax.swing.JComboBox;
>> +import javax.swing.JLabel;
>> +import javax.swing.JPanel;
>> +import javax.swing.JTextField;
>> +
>> +import org.apache.jmeter.config.Argument;
>> +import org.apache.jmeter.config.Arguments;
>> +import org.apache.jmeter.config.gui.ArgumentsPanel;
>> +import org.apache.jmeter.gui.util.HorizontalPanel;
>> +import org.apache.jmeter.testelement.TestElement;
>> +import org.apache.jmeter.testelement.property.PropertyIterator;
>> +import org.apache.jmeter.util.JMeterUtils;
>> +import org.apache.jmeter.visualizers.gui.AbstractListenerGui;
>> +import org.apache.jorphan.logging.LoggingManager;
>> +import org.apache.jorphan.reflect.ClassFinder;
>> +import org.apache.log.Logger;
>> +
>> +/**
>> + * The <code>BackendListenerGui</code> class provides the user
>> interface for the
>> + * {@link BackendListener} object.
>> + * @since 2.13
>> + */
>> +public class BackendListenerGui extends AbstractListenerGui implements
>> ActionListener {
>> +
>> +    /**
>> +     *
>> +     */
>> +    private static final long serialVersionUID = 4331668988576438604L;
>> +
>> +    /** Logging */
>> +    private static final Logger log = LoggingManager.
>> getLoggerForClass();
>> +
>> +    /** A combo box allowing the user to choose a backend class. */
>> +    private JComboBox classnameCombo;
>> +
>> +    /**
>> +     * A field allowing the user to specify the size of Queue
>> +     */
>> +    private JTextField queueSize;
>> +
>> +    /** A panel allowing the user to set arguments for this test. */
>> +    private ArgumentsPanel argsPanel;
>> +
>> +    /**
>> +     * Create a new BackendListenerGui as a standalone component.
>> +     */
>> +    public BackendListenerGui() {
>> +        super();
>> +        init();
>> +    }
>> +
>> +
>> +    /** {@inheritDoc} */
>> +    @Override
>> +    public String getLabelResource() {
>> +        return "backend_listener"; // $NON-NLS-1$
>> +    }
>> +
>> +    /**
>> +     * Initialize the GUI components and layout.
>> +     */
>> +    private void init() {// called from ctor, so must not be overridable
>> +        setLayout(new BorderLayout(0, 5));
>> +
>> +        setBorder(makeBorder());
>> +        add(makeTitlePanel(), BorderLayout.NORTH);
>> +
>> +        JPanel classnameRequestPanel = new JPanel(new BorderLayout(0,
>> 5));
>> +        classnameRequestPanel.add(createClassnamePanel(),
>> BorderLayout.NORTH);
>> +        classnameRequestPanel.add(createParameterPanel(),
>> BorderLayout.CENTER);
>> +
>> +        add(classnameRequestPanel, BorderLayout.CENTER);
>> +    }
>> +
>> +    /**
>> +     * Create a panel with GUI components allowing the user to select a
>> test
>> +     * class.
>> +     *
>> +     * @return a panel containing the relevant components
>> +     */
>> +    private JPanel createClassnamePanel() {
>> +        List<String> possibleClasses = new ArrayList<String>();
>> +
>> +        try {
>> +            // Find all the classes which implement the
>> BackendListenerClient
>> +            // interface.
>> +            possibleClasses = ClassFinder.findClassesThatExtend(
>> JMeterUtils.getSearchPaths(),
>> +                    new Class[] { BackendListenerClient.class });
>> +
>> +            // Remove the BackendListener class from the list since it
>> only
>>
> ErrorBackendListener
>
>> +            // implements the interface for error conditions.
>> +
>> +            possibleClasses.remove(BackendListener.class.getName() +
>> "$ErrorBackendListenerClient");
>> +        } catch (Exception e) {
>> +            log.debug("Exception getting interfaces.", e);
>> +        }
>> +
>> +        JLabel label = new JLabel(JMeterUtils.getResString("backend_listener_classname"));
>> // $NON-NLS-1$
>> +
>> +        classnameCombo = new JComboBox(possibleClasses.toArray());
>> +        classnameCombo.addActionListener(this);
>> +        classnameCombo.setEditable(false);
>> +        label.setLabelFor(classnameCombo);
>> +
>> +        HorizontalPanel classNamePanel = new HorizontalPanel();
>> +        classNamePanel.add(label);
>> +        classNamePanel.add(classnameCombo);
>> +
>> +        queueSize = new JTextField("", 5);
>> +        queueSize.setName("Queue Size"); //$NON-NLS-1$
>> +        JLabel queueSizeLabel = new JLabel(JMeterUtils.
>> getResString("backend_listener_queue_size")); // $NON-NLS-1$
>> +        queueSizeLabel.setLabelFor(queueSize);
>> +        HorizontalPanel queueSizePanel = new HorizontalPanel();
>> +        queueSizePanel.add(queueSizeLabel, BorderLayout.WEST);
>> +        queueSizePanel.add(queueSize);
>> +
>> +        JPanel panel = new JPanel(new BorderLayout(0, 5));
>> +        panel.add(classNamePanel, BorderLayout.NORTH);
>> +        panel.add(queueSizePanel, BorderLayout.CENTER);
>> +        return panel;
>> +    }
>> +
>> +    /**
>> +     * Handle action events for this component. This method currently
>> handles
>> +     * events for the classname combo box.
>> +     *
>> +     * @param evt
>>
> I would spend the few extra characters to make it event instead of evt
>
>> +     *            the ActionEvent to be handled
>> +     */
>> +    @Override
>> +    public void actionPerformed(ActionEvent evt) {
>> +        if (evt.getSource() == classnameCombo) {
>> +            String className = ((String) classnameCombo.
>> getSelectedItem()).trim();
>> +            try {
>> +                BackendListenerClient client = (BackendListenerClient)
>> Class.forName(className, true,
>> +                        Thread.currentThread().getContextClassLoader()).
>> newInstance();
>> +
>> +                Arguments currArgs = new Arguments();
>> +                argsPanel.modifyTestElement(currArgs);
>> +                Map<String, String> currArgsMap =
>> currArgs.getArgumentsAsMap();
>> +
>> +                Arguments newArgs = new Arguments();
>> +                Arguments testParams = null;
>> +                try {
>> +                    testParams = client.getDefaultParameters();
>> +                } catch (AbstractMethodError e) {
>> +                    log.warn("BackendListenerClient doesn't implement "
>> +                            + "getDefaultParameters.  Default parameters
>> won't "
>> +                            + "be shown.  Please update your client
>> class: " + className);
>> +                }
>> +
>> +                if (testParams != null) {
>> +                    PropertyIterator i = testParams.getArguments().
>> iterator();
>>
> I would try a for loop instead of explicitly using an iterator
>
>> +                    while (i.hasNext()) {
>> +                        Argument arg = (Argument)
>> i.next().getObjectValue();
>> +                        String name = arg.getName();
>> +                        String value = arg.getValue();
>> +
>> +                        // If a user has set parameters in one test, and
>> then
>> +                        // selects a different test which supports the
>> same
>> +                        // parameters, those parameters should have the
>> same
>> +                        // values that they did in the original test.
>> +                        if (currArgsMap.containsKey(name)) {
>> +                            String newVal = currArgsMap.get(name);
>> +                            if (newVal != null && newVal.length() > 0) {
>> +                                value = newVal;
>> +                            }
>> +                        }
>> +                        newArgs.addArgument(name, value);
>> +                    }
>> +                }
>> +
>> +                argsPanel.configure(newArgs);
>> +            } catch (Exception e) {
>> +                log.error("Error getting argument list for " +
>> className, e);
>> +            }
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Create a panel containing components allowing the user to provide
>> +     * arguments to be passed to the test class instance.
>> +     *
>> +     * @return a panel containing the relevant components
>> +     */
>> +    private JPanel createParameterPanel() {
>> +        argsPanel = new ArgumentsPanel(JMeterUtils.
>> getResString("backend_listener_paramtable")); // $NON-NLS-1$
>> +        return argsPanel;
>> +    }
>> +
>> +    /** {@inheritDoc} */
>> +    @Override
>> +    public void configure(TestElement config) {
>> +        super.configure(config);
>> +
>> +        argsPanel.configure((Arguments) config.getProperty(
>> BackendListener.ARGUMENTS).getObjectValue());
>> +
>> +        String className = config.getPropertyAsString(
>> BackendListener.CLASSNAME);
>> +        if(checkContainsClassName(classnameCombo.getModel(),
>> className)) {
>> +            classnameCombo.setSelectedItem(className);
>> +        } else {
>> +            log.error("Error setting class:'"+className+"' in
>> BackendListener: "+getName()+
>> +                    ", check for a missing jar in your jmeter
>> 'search_paths' and 'plugin_dependency_paths' properties");
>> +        }
>> +        queueSize.setText(Integer.toString(((BackendListener)
>> config).getQueueSize()));
>> +    }
>> +
>> +    /**
>> +     * Check combo contains className
>> +     * @param model ComboBoxModel
>> +     * @param className String class name
>> +     * @return boolean
>>
> explain "boolean" or the other params a bit more?
>
>> +     */
>> +    private static final boolean checkContainsClassName(ComboBoxModel
>> model, String className) {
>> +        int size = model.getSize();
>> +        Set<String> set = new HashSet<String>(size);
>> +        for (int i = 0; i < size; i++) {
>> +            set.add((String)model.getElementAt(i));
>> +        }
>> +        return set.contains(className);
>> +    }
>> +
>> +    /** {@inheritDoc} */
>> +    @Override
>> +    public TestElement createTestElement() {
>> +        BackendListener config = new BackendListener();
>> +        modifyTestElement(config);
>> +        return config;
>> +    }
>> +
>> +    /** {@inheritDoc} */
>> +    @Override
>> +    public void modifyTestElement(TestElement config) {
>> +        configureTestElement(config);
>> +        BackendListener backendListener = (BackendListener) config;
>> +        backendListener.setArguments((Arguments)
>> argsPanel.createTestElement());
>> +        backendListener.setClassname(String.valueOf(classnameCombo.
>> getSelectedItem()));
>> +        backendListener.setQueueSize(Integer.parseInt(queueSize.
>> getText()));
>> +
>> +    }
>> +
>> +    /* (non-Javadoc)
>> +     * @see org.apache.jmeter.gui.AbstractJMeterGuiComponent#clearGui()
>> +     */
>> +    @Override
>> +    public void clearGui() {
>> +        super.clearGui();
>> +        argsPanel.clearGui();
>> +        classnameCombo.setSelectedIndex(0);
>> +        queueSize.setText("");
>> +    }
>> +}
>>
>> Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/BackendListenerGui.java
>> ------------------------------------------------------------
>> ------------------
>>      svn:mime-type = text/plain
>>
>> Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> backend/SamplerMetric.java
>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> org/apache/jmeter/visualizers/backend/SamplerMetric.java?
>> rev=1641081&view=auto
>> ============================================================
>> ==================
>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/SamplerMetric.java
>> (added)
>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/SamplerMetric.java
>> Sat Nov 22 15:36:37 2014
>> @@ -0,0 +1,138 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version
>> 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + *
>> + */
>> +
>> +package org.apache.jmeter.visualizers.backend;
>> +
>> +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
>> +import org.apache.jmeter.samplers.SampleResult;
>> +
>> +/**
>> + * Sampler metric
>> + * @since 2.13
>> + */
>> +public class SamplerMetric {
>> +    // Limit to sliding window of 100 values
>> +    private DescriptiveStatistics stats = new DescriptiveStatistics(100);
>> +    private int success;
>
>


-- 
Cordialement.
Philippe Mouawad.

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message