jmeter-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Felix Schumacher <felix.schumac...@internetallee.de>
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 Sun, 30 Nov 2014 20:53:01 GMT
Am 30.11.2014 um 21:32 schrieb Philippe Mouawad:
> On Sun, Nov 30, 2014 at 10:19 AM, Felix Schumacher <
> felix.schumacher@internetallee.de> wrote:
>
>>
>> Am 29. November 2014 21:12:00 MEZ, schrieb Philippe Mouawad <
>> philippe.mouawad@gmail.com>:
>>> Hi Felix
>>>
>>> My answer inline.
>>> Regards
>>>
>>> On Sat, Nov 29, 2014 at 11:51 AM, Felix Schumacher <
>>> felix.schumacher@internetallee.de> wrote:
>>>
>>>> Hello Philippe,
>>>>
>>>> Am Sonntag, den 23.11.2014, 12:22 +0100 schrieb Philippe Mouawad:
>>>>> Thanks a lot for your review which pointed to a synchronisation
>>> issue
>>>> that
>>>>> I fixed, good catch!
>>>>>
>>>>> I think I took all your notes into account, let me know if I forgot
>>>>> something.
>>>> in SamplerMetric you have used a sliding window for the statistics.
>>>> * Should we make the length of the window configurable?
>>>>
>>> Yes but it's a new property and we have a lot :-)
>> But the size of the window depends on the number of samples per time slot.
>> Perhaps it could be dynamically sized?
>>
> You mean it needs to be increased if there is a big number of requests in
> time slot for 1 sample ?
> Please clarfify so that I am sure to understand. For now I made it
> configurable through a property.
Right, if you have only a few requests per second but report the stats 
for that window every second, you will get values from other time slots 
too. On the other hand, if you have a few hundred requests per second, 
you might not even report the correct values for the time slot.

Thus I thought it could be made more dynamic, but if it is configurable, 
that might be enough. I don't think many will actually change it. Would you?
>
>>>
>>>> * Should min/max and minThreads/maxThreads be limited to the sliding
>>>> window, also? At least min and max would be simple to do.
>>>>
>>> Dev team opinion is welcome, maybe it would be better
>>> - min would be percentile(0)
>>> - max would be percentile(100)
>> The stats field has methods to get the minimum and the maximum values. I
>> would take those.
>>
> OK , done
>
>>> for minThreads, maxThreads, how would you do it ?
>> Create another statistical field for the number of threads. Then we could
>> provide correct answers for max/min thread numbers plus
>> mean/average/percentile.
>>
>> For this one, I don't see in fact the use case, as number of threads will
> not vary a lot so in what way do you think it is incorrect ?
> Maybe my question is stupid as I don't see currently the problem but I may
> be wrong. Can you clarify ?
> Thx
If every value I get presented is part of a windowed look into the data, 
I would be surprised to find, that one value is actually computed using 
all data available.

The values could vary for example in ramp up time and they will again 
vary at the end of the test run. (They do at least in my tests)

But if we are not using a windowed representation the max threads will 
never go down and the min threads will probably represent the first time 
slot for the whole test.

Does that make sense?

Felix
>
>
>> Regards
>> Felix
>>
>>>
>>>> Regards
>>>>   Felix
>>>>> Regards
>>>>> Philippe
>>>>>
>>>>> On Sunday, November 23, 2014, Felix Schumacher <
>>>>> felix.schumacher@internetallee.de> wrote:
>>>>>
>>>>>> Hi Phillipe,
>>>>>> Am 22.11.2014 um 19:29 schrieb Philippe Mouawad:
>>>>>>
>>>>>>> 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.
>>>>>>>
>>>>>> I did not mean to offend you. I can clearly see, that you put a
>>> lot of
>>>>>> effort
>>>>>> in this listener and I will surely try to integrate jmeter into
>>> our
>>>>>> collectd server.
>>>>>>
>>>>>> Regards
>>>>>>   Felix
>>>>>>
>>>>>>> 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
>>> createBackendListenerClientImp
>>>>>>>>> l(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()));
>>>>>>>>> +
>>>>>>>>> +    }
>>>>>>>>> +
>>>>>>>>>
>>>>
>>>>
>>
>


Mime
View raw message