Home » jakarta-jmeter-2.3.4_src » org.apache.jmeter.visualizers.gui » [javadoc | source]

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *   http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    *
   17    */
   18   
   19   package org.apache.jmeter.visualizers.gui;
   20   
   21   import java.awt.Component;
   22   import java.awt.Container;
   23   import java.awt.event.ActionEvent;
   24   import java.awt.event.ActionListener;
   25   
   26   import javax.swing.JButton;
   27   import javax.swing.JCheckBox;
   28   import javax.swing.JLabel;
   29   import javax.swing.event.ChangeEvent;
   30   import javax.swing.event.ChangeListener;
   31   
   32   import org.apache.jmeter.gui.GuiPackage;
   33   import org.apache.jmeter.gui.SavePropertyDialog;
   34   import org.apache.jmeter.gui.UnsharedComponent;
   35   import org.apache.jmeter.gui.util.FilePanel;
   36   import org.apache.jmeter.reporters.AbstractListenerElement;
   37   import org.apache.jmeter.reporters.ResultCollector;
   38   import org.apache.jmeter.samplers.Clearable;
   39   import org.apache.jmeter.samplers.SampleSaveConfiguration;
   40   import org.apache.jmeter.testelement.TestElement;
   41   import org.apache.jmeter.util.JMeterUtils;
   42   import org.apache.jmeter.visualizers.Visualizer;
   43   import org.apache.jorphan.gui.ComponentUtil;
   44   import org.apache.jorphan.logging.LoggingManager;
   45   import org.apache.log.Logger;
   46   
   47   /**
   48    * This is the base class for JMeter GUI components which can display test
   49    * results in some way. It provides the following conveniences to developers:
   50    * <ul>
   51    * <li>Implements the
   52    * {@link org.apache.jmeter.gui.JMeterGUIComponent JMeterGUIComponent} interface
   53    * that allows your Gui visualizer to "plug-in" to the JMeter GUI environment.
   54    * Provides implementations for the following methods:
   55    * <ul>
   56    * <li>{@link org.apache.jmeter.gui.JMeterGUIComponent#configure(TestElement) configure(TestElement)}.
   57    * Any additional parameters of your Visualizer need to be handled by you.</li>
   58    * <li>{@link org.apache.jmeter.gui.JMeterGUIComponent#createTestElement() createTestElement()}.
   59    * For most purposes, the default
   60    * {@link org.apache.jmeter.reporters.ResultCollector ResultCollector} created
   61    * by this method is sufficient.</li>
   62    * <li>{@link org.apache.jmeter.gui.JMeterGUIComponent#getMenuCategories getMenuCategories()}.
   63    * To control where in the GUI your visualizer can be added.</li>
   64    * <li>{@link org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement) modifyTestElement(TestElement)}.
   65    * Again, additional parameters you require have to be handled by you.</li>
   66    * <li>{@link org.apache.jmeter.gui.JMeterGUIComponent#createPopupMenu() createPopupMenu()}.</li>
   67    * </ul>
   68    * </li>
   69    * <li>Provides convenience methods to help you make a JMeter-compatible GUI:
   70    * <ul>
   71    * <li>{@link #makeTitlePanel()}. Returns a panel that includes the name of
   72    * the component, and a FilePanel that allows users to control what file samples
   73    * are logged to.</li>
   74    * <li>{@link #getModel()} and {@link #setModel(ResultCollector)} methods for
   75    * setting and getting the model class that handles the receiving and logging of
   76    * sample results.</li>
   77    * </ul>
   78    * </li>
   79    * </ul>
   80    * For most developers, making a new visualizer is primarly for the purpose of
   81    * either calculating new statistics on the sample results that other
   82    * visualizers don't calculate, or displaying the results visually in a new and
   83    * interesting way. Making a new visualizer for either of these purposes is easy -
   84    * just extend this class and implement the
   85    * {@link org.apache.jmeter.visualizers.Visualizer#add add(SampleResult)}
   86    * method and display the results as you see fit. This AbstractVisualizer and
   87    * the default
   88    * {@link org.apache.jmeter.reporters.ResultCollector ResultCollector} handle
   89    * logging and registering to receive SampleEvents for you - all you need to do
   90    * is include the JPanel created by makeTitlePanel somewhere in your gui to
   91    * allow users set the log file.
   92    * <p>
   93    * If you are doing more than that, you may need to extend
   94    * {@link org.apache.jmeter.reporters.ResultCollector ResultCollector} as well
   95    * and modify the {@link #configure(TestElement)},
   96    * {@link #modifyTestElement(TestElement)}, and {@link #createTestElement()}
   97    * methods to create and modify your alternate ResultCollector. For an example
   98    * of this, see the
   99    * {@link org.apache.jmeter.visualizers.MailerVisualizer MailerVisualizer}.
  100    * <p>
  101    *
  102    */
  103   public abstract class AbstractVisualizer
  104       extends AbstractListenerGui
  105       implements Visualizer, ChangeListener, UnsharedComponent, Clearable
  106       {
  107       /** Logging. */
  108       private static final Logger log = LoggingManager.getLoggerForClass();
  109   
  110       /** A panel allowing results to be saved. */
  111       private FilePanel filePanel;
  112   
  113       /** A checkbox choosing whether or not only errors should be logged. */
  114       private JCheckBox errorLogging;
  115   
  116       /* A checkbox choosing whether or not only successes should be logged. */
  117       private JCheckBox successOnlyLogging;
  118   
  119       private JButton saveConfigButton;
  120   
  121       protected ResultCollector collector = new ResultCollector();
  122   
  123       protected boolean isStats = false;
  124   
  125       public AbstractVisualizer() {
  126           super();
  127   
  128           // errorLogging and successOnlyLogging are mutually exclusive
  129           errorLogging = new JCheckBox(JMeterUtils.getResString("log_errors_only")); // $NON-NLS-1$
  130           errorLogging.addActionListener(new ActionListener(){
  131               public void actionPerformed(ActionEvent e) {
  132                   if (errorLogging.isSelected()) {
  133                       successOnlyLogging.setSelected(false);
  134                   }
  135               }
  136           });
  137           successOnlyLogging = new JCheckBox(JMeterUtils.getResString("log_success_only")); // $NON-NLS-1$
  138           successOnlyLogging.addActionListener(new ActionListener(){
  139               public void actionPerformed(ActionEvent e) {
  140                   if (successOnlyLogging.isSelected()) {
  141                       errorLogging.setSelected(false);
  142                   }
  143               }
  144           });
  145           saveConfigButton = new JButton(JMeterUtils.getResString("config_save_settings")); // $NON-NLS-1$
  146           saveConfigButton.addActionListener(new ActionListener() {
  147               public void actionPerformed(ActionEvent e) {
  148                   SavePropertyDialog d = new SavePropertyDialog(
  149                           GuiPackage.getInstance().getMainFrame(),
  150                           JMeterUtils.getResString("sample_result_save_configuration"), // $NON-NLS-1$
  151                           true, collector.getSaveConfig());
  152                   d.pack();
  153                   ComponentUtil.centerComponentInComponent(GuiPackage.getInstance().getMainFrame(), d);
  154                   d.setVisible(true);
  155               }
  156           });
  157   
  158           filePanel = new FilePanel(JMeterUtils.getResString("file_visualizer_output_file"), ".jtl"); // $NON-NLS-1$ $NON-NLS-2$
  159           filePanel.addChangeListener(this);
  160           filePanel.add(new JLabel(JMeterUtils.getResString("log_only"))); // $NON-NLS-1$
  161           filePanel.add(errorLogging);
  162           filePanel.add(successOnlyLogging);
  163           filePanel.add(saveConfigButton);
  164   
  165       }
  166   
  167       public boolean isStats() {
  168           return isStats;
  169       }
  170   
  171       /**
  172        * Gets the checkbox which selects whether or not only errors should be
  173        * logged. Subclasses don't normally need to worry about this checkbox,
  174        * because it is automatically added to the GUI in {@link #makeTitlePanel()},
  175        * and the behavior is handled in this base class.
  176        *
  177        * @return the error logging checkbox
  178        */
  179       protected JCheckBox getErrorLoggingCheckbox() {
  180           return errorLogging;
  181       }
  182   
  183       /**
  184        * Provides access to the ResultCollector model class for extending
  185        * implementations. Using this method and setModel(ResultCollector) is only
  186        * necessary if your visualizer requires a differently behaving
  187        * ResultCollector. Using these methods will allow maximum reuse of the
  188        * methods provided by AbstractVisualizer in this event.
  189        */
  190       protected ResultCollector getModel() {
  191           return collector;
  192       }
  193   
  194       /**
  195        * Gets the file panel which allows the user to save results to a file.
  196        * Subclasses don't normally need to worry about this panel, because it is
  197        * automatically added to the GUI in {@link #makeTitlePanel()}, and the
  198        * behavior is handled in this base class.
  199        *
  200        * @return the file panel allowing users to save results
  201        */
  202       protected Component getFilePanel() {
  203           return filePanel;
  204       }
  205   
  206       /**
  207        * Sets the filename which results will be saved to. This will set the
  208        * filename in the FilePanel. Subclasses don't normally need to call this
  209        * method, because configuration of the FilePanel is handled in this base
  210        * class.
  211        *
  212        * @param filename
  213        *            the new filename
  214        *
  215        * @see #getFilePanel()
  216        */
  217       public void setFile(String filename) {
  218           // TODO: Does this method need to be public? It isn't currently
  219           // called outside of this class.
  220           filePanel.setFilename(filename);
  221       }
  222   
  223       /**
  224        * Gets the filename which has been entered in the FilePanel. Subclasses
  225        * don't normally need to call this method, because configuration of the
  226        * FilePanel is handled in this base class.
  227        *
  228        * @return the current filename
  229        *
  230        * @see #getFilePanel()
  231        */
  232       public String getFile() {
  233           // TODO: Does this method need to be public? It isn't currently
  234           // called outside of this class.
  235           return filePanel.getFilename();
  236       }
  237   
  238       /**
  239        * Invoked when the target of the listener has changed its state. This
  240        * implementation assumes that the target is the FilePanel, and will update
  241        * the result collector for the new filename.
  242        *
  243        * @param e
  244        *            the event that has occurred
  245        */
  246       public void stateChanged(ChangeEvent e) {
  247           log.debug("getting new collector");
  248           collector = (ResultCollector) createTestElement();
  249           collector.loadExistingFile();
  250       }
  251   
  252       /* Implements JMeterGUIComponent.createTestElement() */
  253       public TestElement createTestElement() {
  254           if (collector == null) {
  255               collector = new ResultCollector();
  256           }
  257           modifyTestElement(collector);
  258           return (TestElement) collector.clone();
  259       }
  260   
  261       /* Implements JMeterGUIComponent.modifyTestElement(TestElement) */
  262       public void modifyTestElement(TestElement c) {
  263           configureTestElement((AbstractListenerElement) c);
  264           if (c instanceof ResultCollector) {
  265               ResultCollector rc = (ResultCollector) c;
  266               rc.setErrorLogging(errorLogging.isSelected());
  267               rc.setSuccessOnlyLogging(successOnlyLogging.isSelected());
  268               rc.setFilename(getFile());
  269               collector = rc;
  270           }
  271       }
  272   
  273       /* Overrides AbstractJMeterGuiComponent.configure(TestElement) */
  274       public void configure(TestElement el) {
  275           super.configure(el);
  276           setFile(el.getPropertyAsString(ResultCollector.FILENAME));
  277           ResultCollector rc = (ResultCollector) el;
  278           errorLogging.setSelected(rc.isErrorLogging());
  279           successOnlyLogging.setSelected(rc.isSuccessOnlyLogging());
  280           if (collector == null) {
  281               collector = new ResultCollector();
  282           }
  283           collector.setSaveConfig((SampleSaveConfiguration) rc.getSaveConfig().clone());
  284       }
  285   
  286       /**
  287        * This provides a convenience for extenders when they implement the
  288        * {@link org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()}
  289        * method. This method will set the name, gui class, and test class for the
  290        * created Test Element. It should be called by every extending class when
  291        * creating Test Elements, as that will best assure consistent behavior.
  292        *
  293        * @param mc
  294        *            the TestElement being created.
  295        */
  296       protected void configureTestElement(AbstractListenerElement mc) {
  297           // TODO: Should the method signature of this method be changed to
  298           // match the super-implementation (using a TestElement parameter
  299           // instead of AbstractListenerElement)? This would require an
  300           // instanceof check before adding the listener (below), but would
  301           // also make the behavior a bit more obvious for sub-classes -- the
  302           // Java rules dealing with this situation aren't always intuitive,
  303           // and a subclass may think it is calling this version of the method
  304           // when it is really calling the superclass version instead.
  305           super.configureTestElement(mc);
  306           mc.setListener(this);
  307       }
  308   
  309       /**
  310        * Create a standard title section for JMeter components. This includes the
  311        * title for the component and the Name Panel allowing the user to change
  312        * the name for the component. The AbstractVisualizer also adds the
  313        * FilePanel allowing the user to save the results, and the error logging
  314        * checkbox, allowing the user to choose whether or not only errors should
  315        * be logged.
  316        * <p>
  317        * This method is typically added to the top of the component at the
  318        * beginning of the component's init method.
  319        *
  320        * @return a panel containing the component title, name panel, file panel,
  321        *         and error logging checkbox
  322        */
  323       protected Container makeTitlePanel() {
  324           Container panel = super.makeTitlePanel();
  325           // Note: the file panel already includes the error logging checkbox,
  326           // so we don't have to add it explicitly.
  327           panel.add(getFilePanel());
  328           return panel;
  329       }
  330   
  331       /**
  332        * Provides extending classes the opportunity to set the ResultCollector
  333        * model for the Visualizer. This is useful to allow maximum reuse of the
  334        * methods from AbstractVisualizer.
  335        *
  336        * @param collector
  337        */
  338       protected void setModel(ResultCollector collector) {
  339           this.collector = collector;
  340       }
  341   
  342       public void clearGui(){
  343           super.clearGui();
  344           filePanel.clearGui();
  345       }
  346   }

Home » jakarta-jmeter-2.3.4_src » org.apache.jmeter.visualizers.gui » [javadoc | source]