You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by fs...@apache.org on 2021/03/10 20:03:42 UTC

[jmeter] branch master updated (a5f73f9 -> bfacaf4)

This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git.


    from a5f73f9  Always close filehandle after use
     new 6010d20  OS Process Sampler - Cannot "Add from Clipboard" Command parameters
     new bfacaf4  HTTP Sampler/Files upload tab - add missing buttons

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/jmeter/config/gui/ArgumentsPanel.java   |  42 +++-
 .../apache/jmeter/config/gui/RowDetailDialog.java  | 123 +++++++----
 .../protocol/http/gui/HTTPFileArgsPanel.java       | 231 +++++++++++++++++++--
 .../protocol/system/gui/SystemSamplerGui.java      |  16 +-
 xdocs/changes.xml                                  |   2 +
 5 files changed, 349 insertions(+), 65 deletions(-)


[jmeter] 01/02: OS Process Sampler - Cannot "Add from Clipboard" Command parameters

Posted by fs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git

commit 6010d208454930385547d8b0d8fb4a70ec4f5f98
Author: Felix Schumacher <fe...@internetallee.de>
AuthorDate: Sun Feb 21 18:56:33 2021 +0100

    OS Process Sampler - Cannot "Add from Clipboard" Command parameters
    
    Bugzilla Id: 65152
---
 .../apache/jmeter/config/gui/ArgumentsPanel.java   | 42 ++++++++++--
 .../apache/jmeter/config/gui/RowDetailDialog.java  | 77 +++++++++++-----------
 .../protocol/system/gui/SystemSamplerGui.java      | 16 ++---
 xdocs/changes.xml                                  |  1 +
 4 files changed, 86 insertions(+), 50 deletions(-)

diff --git a/src/core/src/main/java/org/apache/jmeter/config/gui/ArgumentsPanel.java b/src/core/src/main/java/org/apache/jmeter/config/gui/ArgumentsPanel.java
index f71a812..8e95fef 100644
--- a/src/core/src/main/java/org/apache/jmeter/config/gui/ArgumentsPanel.java
+++ b/src/core/src/main/java/org/apache/jmeter/config/gui/ArgumentsPanel.java
@@ -29,6 +29,7 @@ import java.awt.event.ActionListener;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.function.Function;
 
 import javax.swing.BorderFactory;
 import javax.swing.Box;
@@ -62,7 +63,7 @@ import org.apache.jorphan.reflect.Functor;
 @TestElementMetadata(labelResource = "user_defined_variables")
 public class ArgumentsPanel extends AbstractConfigGui implements ActionListener {
 
-    private static final long serialVersionUID = 240L;
+    private static final long serialVersionUID = 241L;
 
     /** The title label for this component. */
     private JLabel tableLabel;
@@ -107,6 +108,8 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
     /** Disable buttons :Detail, Add, Add from Clipboard, Delete, Up and Down*/
     private final boolean disableButtons;
 
+    private final Function<String[], Argument> argCreator;
+
     /** Command for adding a row to the table. */
     private static final String ADD = "add"; // $NON-NLS-1$
 
@@ -175,7 +178,7 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
      * @param label the title for the component.
      */
     public ArgumentsPanel(boolean disableButtons, String label) {
-        this(label, null, false, false, null, disableButtons);
+        this(label, null, false, false, null, disableButtons, null);
     }
 
     /**
@@ -195,7 +198,7 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
      * @param standalone is standalone
      */
     public ArgumentsPanel(String label, Color bkg, boolean enableUpDown, boolean standalone) {
-        this(label, bkg, enableUpDown, standalone, null, false);
+        this(label, bkg, enableUpDown, standalone, null, false, null);
     }
 
     /**
@@ -207,7 +210,20 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
      * @param model the table model to use
      */
     public ArgumentsPanel(String label, Color bkg, boolean enableUpDown, boolean standalone, ObjectTableModel model) {
-        this(label, bkg, enableUpDown, standalone, model, false);
+        this(label, bkg, enableUpDown, standalone, model, null);
+    }
+
+    /**
+     * Create a new ArgumentsPanel with a border and color background
+     * @param label text for label
+     * @param bkg background colour
+     * @param enableUpDown Add up/down buttons
+     * @param standalone is standalone
+     * @param model the table model to use
+     * @param argCreator function to create {@link Argument}s from Strings taken from clipboard
+     */
+    public ArgumentsPanel(String label, Color bkg, boolean enableUpDown, boolean standalone, ObjectTableModel model, Function<String[], Argument> argCreator) {
+        this(label, bkg, enableUpDown, standalone, model, false, argCreator);
     }
 
     /**
@@ -220,12 +236,27 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
      * @param disableButtons Remove all buttons
      */
     public ArgumentsPanel(String label, Color bkg, boolean enableUpDown, boolean standalone, ObjectTableModel model, boolean disableButtons) {
+        this(label, bkg, enableUpDown, standalone, model, disableButtons, null);
+    }
+
+    /**
+     * Create a new ArgumentsPanel with a border and color background
+     * @param label text for label
+     * @param bkg background colour
+     * @param enableUpDown Add up/down buttons
+     * @param standalone is standalone
+     * @param model the table model to use
+     * @param disableButtons Remove all buttons
+     * @param argCreator function to create {@link Argument}s from Strings taken from clipboard
+     */
+    public ArgumentsPanel(String label, Color bkg, boolean enableUpDown, boolean standalone, ObjectTableModel model, boolean disableButtons, Function<String[], Argument> argCreator) {
         tableLabel = new JLabel(label);
         this.enableUpDown = enableUpDown;
         this.disableButtons = disableButtons;
         this.background = bkg;
         this.standalone = standalone;
         this.tableModel = model;
+        this.argCreator = argCreator;
         init();
     }
 
@@ -584,6 +615,9 @@ public class ArgumentsPanel extends AbstractConfigGui implements ActionListener
     }
 
     protected Argument createArgumentFromClipboard(String[] clipboardCols) {
+        if (argCreator != null) {
+            return argCreator.apply(clipboardCols);
+        }
         Argument argument = makeNewArgument();
         argument.setName(clipboardCols[0]);
         if (clipboardCols.length > 1) {
diff --git a/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java b/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
index ec90c81..f07997e 100644
--- a/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
+++ b/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
@@ -21,12 +21,12 @@ import java.awt.BorderLayout;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ActionMap;
-import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
 import javax.swing.InputMap;
 import javax.swing.JButton;
 import javax.swing.JComponent;
@@ -38,6 +38,7 @@ import javax.swing.JRootPane;
 import javax.swing.JTextField;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
 
 import org.apache.jmeter.gui.action.KeyStrokes;
 import org.apache.jmeter.gui.util.JSyntaxTextArea;
@@ -46,6 +47,8 @@ import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jorphan.gui.ComponentUtil;
 import org.apache.jorphan.gui.ObjectTableModel;
 
+import net.miginfocom.swing.MigLayout;
+
 /**
  * Show detail of a Row
  */
@@ -64,13 +67,7 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
 
     private static final String UPDATE = "update"; // $NON-NLS-1$
 
-    private JLabel nameLabel;
-
-    private JTextField nameTF;
-
-    private JLabel valueLabel;
-
-    private JSyntaxTextArea valueTA;
+    private List<JTextComponent> dataAreas;
 
     private JButton nextButton;
 
@@ -132,30 +129,31 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
     private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
         this.getContentPane().setLayout(new BorderLayout(10,10));
 
-        nameLabel = new JLabel(JMeterUtils.getResString("name")); //$NON-NLS-1$
-        nameTF = new JTextField(JMeterUtils.getResString("name"), 20); //$NON-NLS-1$
-        nameTF.getDocument().addDocumentListener(this);
-        JPanel namePane = new JPanel(new BorderLayout());
-        namePane.add(nameLabel, BorderLayout.WEST);
-        namePane.add(nameTF, BorderLayout.CENTER);
+        JPanel dataPanel = new JPanel(new MigLayout("fillx, wrap 2", "[][fill, grow]"));
+        dataAreas = new ArrayList<>();
+
+        for (int i=0; i < tableModel.getColumnCount(); i++) {
+            JLabel dataLabel = new JLabel(JMeterUtils.getResString(tableModel.getColumnName(i)));
+            dataPanel.add(dataLabel);
+            if (i > 0 || tableModel.getColumnCount() == 1) {
+                JSyntaxTextArea dataArea = JSyntaxTextArea.getInstance(30, 80);
+                dataArea.getDocument().addDocumentListener(this);
+                dataAreas.add(dataArea);
+                dataPanel.add(JTextScrollPane.getInstance(dataArea));
+                dataLabel.setLabelFor(dataArea);
+            } else {
+                final JTextField nameTF = new JTextField("", 20);
+                dataAreas.add(nameTF);
+                nameTF.getDocument().addDocumentListener(this);
+                dataPanel.add(nameTF);
+                dataLabel.setLabelFor(nameTF);
+            }
+        }
 
-        valueLabel = new JLabel(JMeterUtils.getResString("value")); //$NON-NLS-1$
-        valueTA = JSyntaxTextArea.getInstance(30, 80);
-        valueTA.getDocument().addDocumentListener(this);
         setValues(selectedRow);
-        JPanel valuePane = new JPanel(new BorderLayout());
-        valuePane.add(valueLabel, BorderLayout.NORTH);
-        JTextScrollPane jTextScrollPane = JTextScrollPane.getInstance(valueTA);
-        valuePane.add(jTextScrollPane, BorderLayout.CENTER);
-
-        JPanel detailPanel = new JPanel(new BorderLayout());
-        detailPanel.add(namePane, BorderLayout.NORTH);
-        detailPanel.add(valuePane, BorderLayout.CENTER);
 
-        JPanel mainPanel = new JPanel();
-        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
-        mainPanel.setBorder(BorderFactory.createEmptyBorder(7, 3, 3, 3));
-        mainPanel.add(detailPanel, BorderLayout.CENTER);
+        JPanel mainPanel = new JPanel(new MigLayout());
+        mainPanel.add(dataPanel, "wrap");
 
         JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
 
@@ -178,9 +176,9 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
         buttonsPanel.add(previousButton);
         buttonsPanel.add(nextButton);
         buttonsPanel.add(closeButton);
-        mainPanel.add(buttonsPanel, BorderLayout.SOUTH);
+        mainPanel.add(buttonsPanel, "center");
         this.getContentPane().add(mainPanel);
-        nameTF.requestFocusInWindow();
+        dataAreas.get(0).requestFocusInWindow();
 
         this.pack();
         ComponentUtil.centerComponentInWindow(this);
@@ -218,9 +216,13 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
      * @param selectedRow Selected row
      */
     private void setValues(int selectedRow) {
-        nameTF.setText((String)tableModel.getValueAt(selectedRow, 0));
-        valueTA.setInitialText((String)tableModel.getValueAt(selectedRow, 1));
-        valueTA.setCaretPosition(0);
+        for (int i=0; i < tableModel.getColumnCount(); i++) {
+            final JTextComponent dataArea = dataAreas.get(i);
+            dataArea.setText((String)tableModel.getValueAt(selectedRow, i));
+            if (dataArea instanceof JSyntaxTextArea) {
+                dataArea.setCaretPosition(0);
+            }
+        }
         textChanged = false;
     }
 
@@ -229,8 +231,9 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
      * @param actionEvent the event that led to this call
      */
     protected void doUpdate(ActionEvent actionEvent) {
-        tableModel.setValueAt(nameTF.getText(), selectedRow, 0);
-        tableModel.setValueAt(valueTA.getText(), selectedRow, 1);
+        for (int i=0; i < tableModel.getColumnCount(); i++) {
+            tableModel.setValueAt(dataAreas.get(i).getText(), selectedRow, i);
+        }
         // Change Cancel label to Close
         closeButton.setText(JMeterUtils.getResString("close")); //$NON-NLS-1$
         textChanged = false;
diff --git a/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/gui/SystemSamplerGui.java b/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/gui/SystemSamplerGui.java
index 6c884a5..7b43e03 100644
--- a/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/gui/SystemSamplerGui.java
+++ b/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/gui/SystemSamplerGui.java
@@ -213,19 +213,17 @@ public class SystemSamplerGui extends AbstractSamplerGui implements ItemListener
         return panel;
     }
 
-
     /**
      * @return JPanel Arguments Panel
      */
     private JPanel makeArgumentsPanel() {
-        argsPanel = new ArgumentsPanel(JMeterUtils.getResString("arguments_panel_title"), null, true, false ,  // $NON-NLS-1$
-                new ObjectTableModel(new String[] { ArgumentsPanel.COLUMN_RESOURCE_NAMES_1 },
-                        Argument.class,
-                        new Functor[] {
-                        new Functor("getValue") },  // $NON-NLS-1$
-                        new Functor[] {
-                        new Functor("setValue") }, // $NON-NLS-1$
-                        new Class[] {String.class }));
+        final ObjectTableModel objectTableModel = new ObjectTableModel(
+                new String[] { ArgumentsPanel.COLUMN_RESOURCE_NAMES_1 }, Argument.class,
+                new Functor[] { new Functor("getValue") }, // $NON-NLS-1$
+                new Functor[] { new Functor("setValue") }, // $NON-NLS-1$
+                new Class[] { String.class });
+        argsPanel = new ArgumentsPanel(JMeterUtils.getResString("arguments_panel_title"), null, true, false, // $NON-NLS-1$
+                objectTableModel, cols -> new Argument("", cols[0]));
         return argsPanel;
     }
 
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 4be11ef..1761010 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -132,6 +132,7 @@ Summary
 
 <h3>Other Samplers</h3>
 <ul>
+  <li><bug>65152</bug>OS Process Sampler - Cannot <code>Add from Clipboard</code> Command parameters</li>
 </ul>
 
 <h3>Controllers</h3>


[jmeter] 02/02: HTTP Sampler/Files upload tab - add missing buttons

Posted by fs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git

commit bfacaf43f4debe663d5937cb42e6efa9adca8317
Author: Felix Schumacher <fe...@internetallee.de>
AuthorDate: Fri Jan 1 15:45:24 2021 +0100

    HTTP Sampler/Files upload tab - add missing buttons
    
    Bugzilla Id: 65020
---
 .../apache/jmeter/config/gui/RowDetailDialog.java  |  96 ++++++---
 .../protocol/http/gui/HTTPFileArgsPanel.java       | 231 +++++++++++++++++++--
 xdocs/changes.xml                                  |   1 +
 3 files changed, 288 insertions(+), 40 deletions(-)

diff --git a/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java b/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
index f07997e..13799dc 100644
--- a/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
+++ b/src/core/src/main/java/org/apache/jmeter/config/gui/RowDetailDialog.java
@@ -21,6 +21,8 @@ import java.awt.BorderLayout;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -29,6 +31,7 @@ import javax.swing.Action;
 import javax.swing.ActionMap;
 import javax.swing.InputMap;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JComponent;
 import javax.swing.JDialog;
 import javax.swing.JFrame;
@@ -52,7 +55,7 @@ import net.miginfocom.swing.MigLayout;
 /**
  * Show detail of a Row
  */
-public class RowDetailDialog extends JDialog implements ActionListener, DocumentListener {
+public class RowDetailDialog extends JDialog implements ActionListener, DocumentListener, ItemListener {
 
     private static final long serialVersionUID = 6578889215615435475L;
 
@@ -67,7 +70,7 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
 
     private static final String UPDATE = "update"; // $NON-NLS-1$
 
-    private List<JTextComponent> dataAreas;
+    private List<JComponent> dataComponents;
 
     private JButton nextButton;
 
@@ -130,24 +133,17 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
         this.getContentPane().setLayout(new BorderLayout(10,10));
 
         JPanel dataPanel = new JPanel(new MigLayout("fillx, wrap 2", "[][fill, grow]"));
-        dataAreas = new ArrayList<>();
+        dataComponents = new ArrayList<>();
 
-        for (int i=0; i < tableModel.getColumnCount(); i++) {
-            JLabel dataLabel = new JLabel(JMeterUtils.getResString(tableModel.getColumnName(i)));
+        final int columnCount = tableModel.getColumnCount();
+        final int linesPerTextArea = Math.max(5, Math.round(30 / Math.max(columnCount - 1, 1)));
+        for (int column = 0; column < columnCount; column++) {
+            JLabel dataLabel = new JLabel(JMeterUtils.getResString(tableModel.getColumnName(column)));
             dataPanel.add(dataLabel);
-            if (i > 0 || tableModel.getColumnCount() == 1) {
-                JSyntaxTextArea dataArea = JSyntaxTextArea.getInstance(30, 80);
-                dataArea.getDocument().addDocumentListener(this);
-                dataAreas.add(dataArea);
-                dataPanel.add(JTextScrollPane.getInstance(dataArea));
-                dataLabel.setLabelFor(dataArea);
-            } else {
-                final JTextField nameTF = new JTextField("", 20);
-                dataAreas.add(nameTF);
-                nameTF.getDocument().addDocumentListener(this);
-                dataPanel.add(nameTF);
-                dataLabel.setLabelFor(nameTF);
-            }
+            JComponent component = createComponentForRow(columnCount, linesPerTextArea, column,
+                    tableModel.getValueAt(selectedRow, column));
+            dataPanel.add(component);
+            dataLabel.setLabelFor(component);
         }
 
         setValues(selectedRow);
@@ -178,12 +174,43 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
         buttonsPanel.add(closeButton);
         mainPanel.add(buttonsPanel, "center");
         this.getContentPane().add(mainPanel);
-        dataAreas.get(0).requestFocusInWindow();
+        dataComponents.get(0).requestFocusInWindow();
 
         this.pack();
         ComponentUtil.centerComponentInWindow(this);
     }
 
+    private JComponent createComponentForRow(final int columnCount, final int linesPerTextArea, int column, Object value) {
+        if (column > 0 || columnCount == 1) {
+            if (tableModel.getColumnClass(column).equals(Boolean.class)) {
+                JCheckBox checkBox = new JCheckBox();
+                if (value instanceof Boolean) {
+                    checkBox.setSelected((Boolean) value);
+                }
+                checkBox.addItemListener(this);
+                dataComponents.add(checkBox);
+                return checkBox;
+            } else {
+                JSyntaxTextArea dataArea = JSyntaxTextArea
+                        .getInstance(linesPerTextArea, 80);
+                if (value instanceof String) {
+                    dataArea.setInitialText((String) value);
+                }
+                dataArea.getDocument().addDocumentListener(this);
+                dataComponents.add(dataArea);
+                return JTextScrollPane.getInstance(dataArea);
+            }
+        } else {
+            final JTextField nameTF = new JTextField("");
+            if (value instanceof String) {
+                nameTF.setText((String) value);
+            }
+            nameTF.getDocument().addDocumentListener(this);
+            dataComponents.add(nameTF);
+            return nameTF;
+        }
+    }
+
     /**
      * Do search
      * @param e {@link ActionEvent}
@@ -212,15 +239,20 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
     }
 
     /**
-     * Set TextField and TA values from model
+     * Set dataComponents fields based on the value of the tableModel
      * @param selectedRow Selected row
      */
     private void setValues(int selectedRow) {
-        for (int i=0; i < tableModel.getColumnCount(); i++) {
-            final JTextComponent dataArea = dataAreas.get(i);
-            dataArea.setText((String)tableModel.getValueAt(selectedRow, i));
-            if (dataArea instanceof JSyntaxTextArea) {
-                dataArea.setCaretPosition(0);
+        for (int i = 0; i < tableModel.getColumnCount(); i++) {
+            final JComponent component = dataComponents.get(i);
+            if (component instanceof JTextComponent) {
+                JTextComponent dataArea = (JTextComponent) component;
+                dataArea.setText((String) tableModel.getValueAt(selectedRow, i));
+                if (dataArea instanceof JSyntaxTextArea) {
+                    dataArea.setCaretPosition(0);
+                }
+            } else if (component instanceof JCheckBox) {
+                ((JCheckBox) component).setSelected((Boolean) tableModel.getValueAt(selectedRow, i));
             }
         }
         textChanged = false;
@@ -231,8 +263,13 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
      * @param actionEvent the event that led to this call
      */
     protected void doUpdate(ActionEvent actionEvent) {
-        for (int i=0; i < tableModel.getColumnCount(); i++) {
-            tableModel.setValueAt(dataAreas.get(i).getText(), selectedRow, i);
+        for (int i = 0; i < tableModel.getColumnCount(); i++) {
+            final JComponent component = dataComponents.get(i);
+            if (component instanceof JTextComponent) {
+                tableModel.setValueAt(((JTextComponent) component).getText(), selectedRow, i);
+            } else if (component instanceof JCheckBox) {
+                tableModel.setValueAt(((JCheckBox) component).isSelected(), selectedRow, i);
+            }
         }
         // Change Cancel label to Close
         closeButton.setText(JMeterUtils.getResString("close")); //$NON-NLS-1$
@@ -264,4 +301,9 @@ public class RowDetailDialog extends JDialog implements ActionListener, Document
         changeLabelButton();
     }
 
+    @Override
+    public void itemStateChanged(ItemEvent e) {
+        changeLabelButton();
+    }
+
 }
diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPFileArgsPanel.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPFileArgsPanel.java
index 9bbe30c..f101ff5 100644
--- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPFileArgsPanel.java
+++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPFileArgsPanel.java
@@ -19,21 +19,29 @@ package org.apache.jmeter.protocol.http.gui;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.File;
+import java.io.IOException;
 import java.util.Iterator;
 
+import javax.swing.AbstractButton;
 import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.JButton;
 import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
+import javax.swing.JViewport;
 import javax.swing.ListSelectionModel;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.jmeter.config.gui.RowDetailDialog;
 import org.apache.jmeter.gui.util.FileDialoger;
 import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer;
 import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
@@ -72,15 +80,26 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
     /** A button for removing files from the table. */
     private JButton delete;
 
+    private AbstractButton showDetail;
+
     /** Command for adding a row to the table. */
     private static final String ADD = "add"; // $NON-NLS-1$
 
     /** Command for browsing filesystem to set path of selected row in table. */
     private static final String BROWSE = "browse"; // $NON-NLS-1$
 
+    /** Command for adding rows from the clipboard */
+    private static final String ADD_FROM_CLIPBOARD = "addFromClipboard"; // $NON-NLS-1$
+
     /** Command for removing a row from the table. */
     private static final String DELETE = "delete"; // $NON-NLS-1$
 
+    /** Command for moving a row up in the table. */
+    private static final String UP = "up"; // $NON-NLS-1$
+
+    /** Command for moving a row down in the table. */
+    private static final String DOWN = "down"; // $NON-NLS-1$
+
     private static final String FILEPATH = "send_file_filename_label"; // $NON-NLS-1$
 
     /** The parameter name column title of file table. */
@@ -89,6 +108,14 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
     /** The mime type column title of file table. */
     private static final String MIMETYPE = "send_file_mime_label"; //$NON-NLS-1$
 
+    /** When pasting from the clipboard, split lines on linebreak */
+    private static final String CLIPBOARD_LINE_DELIMITERS = "\n"; //$NON-NLS-1$
+
+    /** When pasting from the clipboard, split parameters on tab */
+    private static final String CLIPBOARD_ARG_DELIMITERS = "\t"; //$NON-NLS-1$
+
+    /** Command for showing detail. */
+    private static final String DETAIL = "detail"; // $NON-NLS-1$
 
     /**
      * Create a new HTTPFileArgsPanel as an embedded component
@@ -162,7 +189,7 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
             for(HTTPFileArg file : base.getHTTPFiles()){
                 tableModel.addRow(file);
             }
-            checkDeleteAndBrowseStatus();
+            checkButtonsStatus();
         }
     }
 
@@ -171,16 +198,13 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
      * Enable or disable the delete button depending on whether or not there is
      * a row to be deleted.
      */
-    private void checkDeleteAndBrowseStatus() {
-        // Disable DELETE and BROWSE buttons if there are no rows in
+    private void checkButtonsStatus() {
+        // Disable DETAILS, DELETE and BROWSE buttons if there are no rows in
         // the table to delete.
-        if (tableModel.getRowCount() == 0) {
-            browse.setEnabled(false);
-            delete.setEnabled(false);
-        } else {
-            browse.setEnabled(true);
-            delete.setEnabled(true);
-        }
+        final boolean hasRows = tableModel.getRowCount() > 0;
+        browse.setEnabled(hasRows);
+        delete.setEnabled(hasRows);
+        showDetail.setEnabled(hasRows);
     }
 
     /**
@@ -203,6 +227,14 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
         String action = e.getActionCommand();
         if (action.equals(ADD)) {
             addFile(""); //$NON-NLS-1$
+        } else if (action.equals(ADD_FROM_CLIPBOARD)) {
+            addFromClipboard();
+        } else if (action.equals(UP)) {
+            moveUp();
+        } else if (action.equals(DOWN)) {
+            moveDown();
+        } else if (action.equals(DETAIL)) {
+            showDetail();
         }
         runCommandOnSelectedFile(action);
     }
@@ -224,7 +256,7 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
             runCommandOnRow(command, rowSelected);
             tableModel.fireTableDataChanged();
             // Disable DELETE and BROWSE if there are no rows in the table to delete.
-            checkDeleteAndBrowseStatus();
+            checkButtonsStatus();
             // Table still contains one or more rows, so highlight (select)
             // the appropriate one.
             if (tableModel.getRowCount() != 0) {
@@ -267,7 +299,7 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
 
         tableModel.addRow(new HTTPFileArg(path));
 
-        checkDeleteAndBrowseStatus();
+        checkButtonsStatus();
 
         // Highlight (select) the appropriate row.
         int rowToSelect = tableModel.getRowCount() - 1;
@@ -330,16 +362,38 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
         delete = new JButton(JMeterUtils.getResString("delete")); // $NON-NLS-1$
         delete.setActionCommand(DELETE);
 
-        checkDeleteAndBrowseStatus();
+        showDetail = new JButton(JMeterUtils.getResString("detail")); // $NON-NLS-1$
+        showDetail.setActionCommand(DETAIL);
+        showDetail.setEnabled(true);
+        showDetail.addActionListener(this);
+
+        // A button for adding new arguments to the table from the clipboard
+        JButton addFromClipboard = new JButton(JMeterUtils.getResString("add_from_clipboard")); // $NON-NLS-1$
+        addFromClipboard.setActionCommand(ADD_FROM_CLIPBOARD);
+
+        JButton up = new JButton(JMeterUtils.getResString("up")); // $NON-NLS-1$
+        up.setActionCommand(UP);
+
+        JButton down = new JButton(JMeterUtils.getResString("down")); // $NON-NLS-1$
+        down.setActionCommand(DOWN);
+
+        checkButtonsStatus();
 
         JPanel buttonPanel = new JPanel();
         buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
         add.addActionListener(this);
         browse.addActionListener(this);
+        addFromClipboard.addActionListener(this);
         delete.addActionListener(this);
+        up.addActionListener(this);
+        down.addActionListener(this);
+        buttonPanel.add(showDetail);
         buttonPanel.add(add);
         buttonPanel.add(browse);
+        buttonPanel.add(addFromClipboard);
         buttonPanel.add(delete);
+        buttonPanel.add(up);
+        buttonPanel.add(down);
         return buttonPanel;
     }
 
@@ -364,4 +418,155 @@ public class HTTPFileArgsPanel extends JPanel implements ActionListener {
         pane.setPreferredSize(pane.getMinimumSize());
         return GuiUtils.emptyBorder(pane);
     }
+
+
+    /**
+     * Move a row down
+     */
+    private void moveDown() {
+        //get the selected rows before stopping editing
+        // or the selected rows will be unselected
+        int[] rowsSelected = table.getSelectedRows();
+        GuiUtils.stopTableEditing(table);
+
+        if (rowsSelected.length > 0 && rowsSelected[rowsSelected.length - 1] < table.getRowCount() - 1) {
+            table.clearSelection();
+            for (int i = rowsSelected.length - 1; i >= 0; i--) {
+                int rowSelected = rowsSelected[i];
+                tableModel.moveRow(rowSelected, rowSelected + 1, rowSelected + 1);
+            }
+            for (int rowSelected : rowsSelected) {
+                table.addRowSelectionInterval(rowSelected + 1, rowSelected + 1);
+            }
+
+            scrollToRowIfNotVisible(rowsSelected[0]+1);
+        }
+    }
+
+    /**
+     * ensure that a row is visible in the viewport
+     * @param rowIndex row index
+     */
+    private void scrollToRowIfNotVisible(int rowIndex) {
+        if(table.getParent() instanceof JViewport) {
+            Rectangle visibleRect = table.getVisibleRect();
+            final int cellIndex = 0;
+            Rectangle cellRect = table.getCellRect(rowIndex, cellIndex, false);
+            if (visibleRect.y > cellRect.y) {
+                table.scrollRectToVisible(cellRect);
+            } else {
+                Rectangle rect2 = table.getCellRect(rowIndex + getNumberOfVisibleRows(table), cellIndex, true);
+                int width = rect2.y - cellRect.y;
+                table.scrollRectToVisible(new Rectangle(cellRect.x, cellRect.y, cellRect.width, cellRect.height + width));
+            }
+        }
+    }
+
+    /**
+     * @param table {@link JTable}
+     * @return number of visible rows
+     */
+    private static int getNumberOfVisibleRows(JTable table) {
+        Rectangle vr = table.getVisibleRect();
+        int first = table.rowAtPoint(vr.getLocation());
+        vr.translate(0, vr.height);
+        return table.rowAtPoint(vr.getLocation()) - first;
+    }
+
+    /**
+     *  Move a row down
+     */
+    private void moveUp() {
+        //get the selected rows before stopping editing
+        // or the selected rows will be unselected
+        int[] rowsSelected = table.getSelectedRows();
+        GuiUtils.stopTableEditing(table);
+
+        if (rowsSelected.length > 0 && rowsSelected[0] > 0) {
+            table.clearSelection();
+            for (int rowSelected : rowsSelected) {
+                tableModel.moveRow(rowSelected, rowSelected + 1, rowSelected - 1);
+            }
+
+            for (int rowSelected : rowsSelected) {
+                table.addRowSelectionInterval(rowSelected - 1, rowSelected - 1);
+            }
+
+            scrollToRowIfNotVisible(rowsSelected[0]-1);
+        }
+    }
+
+    private void addFromClipboard() {
+        addFromClipboard(CLIPBOARD_LINE_DELIMITERS, CLIPBOARD_ARG_DELIMITERS);
+    }
+
+    /**
+     * Add values from the clipboard
+     * @param lineDelimiter Delimiter string to split clipboard into lines
+     * @param argDelimiter Delimiter string to split line into key-value pair
+     */
+    private void addFromClipboard(String lineDelimiter, String argDelimiter) {
+        GuiUtils.stopTableEditing(table);
+        int rowCount = table.getRowCount();
+        try {
+            String clipboardContent = GuiUtils.getPastedText();
+            if(clipboardContent == null) {
+                return;
+            }
+            String[] clipboardLines = clipboardContent.split(lineDelimiter);
+            for (String clipboardLine : clipboardLines) {
+                String[] clipboardCols = clipboardLine.split(argDelimiter);
+                if (clipboardCols.length > 0) {
+                    HTTPFileArg argument = createHTTPFileArgFromClipboard(clipboardCols);
+                    if (argument != null) {
+                        tableModel.addRow(argument);
+                    }
+                }
+            }
+            if (table.getRowCount() > rowCount) {
+                checkButtonsStatus();
+
+                // Highlight (select) and scroll to the appropriate rows.
+                int rowToSelect = tableModel.getRowCount() - 1;
+                table.setRowSelectionInterval(rowCount, rowToSelect);
+                table.scrollRectToVisible(table.getCellRect(rowCount, 0, true));
+            }
+        } catch (IOException ioe) {
+            JOptionPane.showMessageDialog(this,
+                    "Could not add read file arguments from clipboard:\n" + ioe.getLocalizedMessage(), "Error",
+                    JOptionPane.ERROR_MESSAGE);
+        } catch (UnsupportedFlavorException ufe) {
+            JOptionPane.showMessageDialog(this,
+                    "Could not add retrieve " + DataFlavor.stringFlavor.getHumanPresentableName()
+                            + " from clipboard" + ufe.getLocalizedMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    private HTTPFileArg createHTTPFileArgFromClipboard(String[] clipboardCols) {
+        if (clipboardCols.length == 1) {
+            return new HTTPFileArg(clipboardCols[0]);
+        } else if (clipboardCols.length == 2) {
+            return new HTTPFileArg(clipboardCols[0], clipboardCols[1], "");
+        } else if (clipboardCols.length == 3) {
+            return new HTTPFileArg(clipboardCols[0], clipboardCols[1], clipboardCols[2]);
+        }
+        return null;
+    }
+
+    /**
+     * Show Row Detail
+     */
+    private void showDetail() {
+        //get the selected rows before stopping editing
+        // or the selected will be unselected
+        int[] rowsSelected = table.getSelectedRows();
+        GuiUtils.stopTableEditing(table);
+
+        if (rowsSelected.length == 1) {
+            table.clearSelection();
+            RowDetailDialog detailDialog = new RowDetailDialog(tableModel, rowsSelected[0]);
+            detailDialog.setVisible(true);
+        }
+    }
+
 }
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 1761010..5bc40df 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -79,6 +79,7 @@ Summary
 <h3>HTTP Samplers and Test Script Recorder</h3>
 <ul>
   <li><bug>65027</bug>Detect mime-type for files automatically when adding files to HTTP Sampler</li>
+  <li><bug>65020</bug>HTTP Sampler/Files upload tab - add missing buttons</li>
 </ul>
 
 <h3>Other samplers</h3>