You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2016/12/22 20:38:50 UTC
svn commit: r1775729 - in /jmeter/trunk/src: core/org/apache/jmeter/gui/
core/org/apache/jmeter/gui/action/ core/org/apache/jmeter/resources/
protocol/http/org/apache/jmeter/protocol/http/sampler/
Author: pmouawad
Date: Thu Dec 22 20:38:50 2016
New Revision: 1775729
URL: http://svn.apache.org/viewvc?rev=1775729&view=rev
Log:
Bug 54525 - Search Feature : Enhance it with ability to replace
Implement feature for Sampler subclasses
Bugzilla Id: 54525
Added:
jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java (with props)
Modified:
jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java
jmeter/trunk/src/core/org/apache/jmeter/gui/action/SearchTreeDialog.java
jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java?rev=1775729&r1=1775728&r2=1775729&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java Thu Dec 22 20:38:50 2016
@@ -396,10 +396,18 @@ public final class GuiPackage implements
/**
* Update the GUI for the currently selected node. The GUI component is
* configured to reflect the settings in the current tree node.
- *
*/
public void updateCurrentGui() {
updateCurrentNode();
+ refreshCurrentGui();
+ }
+
+ /**
+ * Refresh GUI from node state.
+ * This method does not update the current node from GUI at the
+ * difference of {@link GuiPackage#updateCurrentGui()}
+ */
+ public void refreshCurrentGui() {
currentNode = treeListener.getCurrentNode();
TestElement element = currentNode.getTestElement();
JMeterGUIComponent comp = getGui(element);
Added: jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java?rev=1775729&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java Thu Dec 22 20:38:50 2016
@@ -0,0 +1,42 @@
+/*
+ * 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.gui;
+
+/**
+ * Interface for nodes that have replaceable content.
+ * <p>
+ * A {@link Replaceable} component will get asked for tokens, that should be used
+ * in a search. These tokens will then be matched against a user given search
+ * string.
+ * @since 3.2
+ */
+public interface Replaceable {
+ /**
+ * Replace in object by replaceBy
+ *
+ * @param regex Regular expression
+ * @param replaceBy Text replacing
+ * @param caseSensitive
+ * @return number of replacements
+ * @throws Exception
+ * when something fails while replacing
+ */
+ int replace(String regex, String replaceBy, boolean caseSensitive)
+ throws Exception;
+}
Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/Replaceable.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/action/SearchTreeDialog.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/action/SearchTreeDialog.java?rev=1775729&r1=1775728&r2=1775729&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/action/SearchTreeDialog.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/action/SearchTreeDialog.java Thu Dec 22 20:38:50 2016
@@ -19,13 +19,16 @@
package org.apache.jmeter.gui.action;
import java.awt.BorderLayout;
+import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.text.MessageFormat;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
import javax.swing.AbstractAction;
import javax.swing.Action;
@@ -38,6 +41,7 @@ import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
+import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTree;
@@ -46,9 +50,11 @@ import javax.swing.tree.TreePath;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.gui.GuiPackage;
+import org.apache.jmeter.gui.Replaceable;
import org.apache.jmeter.gui.Searchable;
import org.apache.jmeter.gui.tree.JMeterTreeModel;
import org.apache.jmeter.gui.tree.JMeterTreeNode;
+import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.ComponentUtil;
import org.apache.jorphan.gui.JLabeledTextField;
@@ -72,6 +78,10 @@ public class SearchTreeDialog extends JD
private JLabeledTextField searchTF;
+ private JLabeledTextField replaceTF;
+
+ private JLabel statusLabel;
+
private JCheckBox isRegexpCB;
private JCheckBox isCaseSensitiveCB;
@@ -85,6 +95,8 @@ public class SearchTreeDialog extends JD
private JButton searchAndExpandButton;
+ private JButton replaceButton;
+
public SearchTreeDialog() {
super((JFrame) null, JMeterUtils.getResString("search_tree_title"), true); //$NON-NLS-1$
init();
@@ -130,8 +142,12 @@ public class SearchTreeDialog extends JD
if(!StringUtils.isEmpty(lastSearch)) {
searchTF.setText(lastSearch);
}
+
+ replaceTF = new JLabeledTextField(JMeterUtils.getResString("search_text_replace"), 20); //$NON-NLS-1$
+ statusLabel = new JLabel();
+ statusLabel.setMinimumSize(new Dimension(100, 30));
isRegexpCB = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_regexp"), false); //$NON-NLS-1$
- isCaseSensitiveCB = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_case"), false); //$NON-NLS-1$
+ isCaseSensitiveCB = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_case"), true); //$NON-NLS-1$
isRegexpCB.setFont(FONT_SMALL);
isCaseSensitiveCB.setFont(FONT_SMALL);
@@ -142,22 +158,31 @@ public class SearchTreeDialog extends JD
JPanel searchPanel = new JPanel();
searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.Y_AXIS));
- searchPanel.setBorder(BorderFactory.createEmptyBorder(7, 3, 3, 3));
- searchPanel.add(searchTF, BorderLayout.NORTH);
- searchPanel.add(searchCriterionPanel, BorderLayout.CENTER);
- JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ searchPanel.setBorder(BorderFactory.createEmptyBorder(7, 3, 3, 3));
+ searchPanel.add(searchTF);
+ searchPanel.add(replaceTF);
+ searchPanel.add(statusLabel);
+ JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
searchButton = new JButton(JMeterUtils.getResString("search")); //$NON-NLS-1$
searchButton.addActionListener(this);
searchAndExpandButton = new JButton(JMeterUtils.getResString("search_expand")); //$NON-NLS-1$
searchAndExpandButton.addActionListener(this);
+ replaceButton = new JButton(JMeterUtils.getResString("search_replace_all")); //$NON-NLS-1$
+ replaceButton.addActionListener(this);
cancelButton = new JButton(JMeterUtils.getResString("cancel")); //$NON-NLS-1$
cancelButton.addActionListener(this);
buttonsPanel.add(searchButton);
buttonsPanel.add(searchAndExpandButton);
+ buttonsPanel.add(replaceButton);
buttonsPanel.add(cancelButton);
- searchPanel.add(buttonsPanel, BorderLayout.SOUTH);
- this.getContentPane().add(searchPanel);
+
+ JPanel searchAndReplacePanel = new JPanel();
+ searchAndReplacePanel.setLayout(new BorderLayout());
+ searchAndReplacePanel.add(searchPanel, BorderLayout.NORTH);
+ searchAndReplacePanel.add(searchCriterionPanel, BorderLayout.CENTER);
+ searchAndReplacePanel.add(buttonsPanel, BorderLayout.SOUTH);
+ this.getContentPane().add(searchAndReplacePanel);
searchTF.requestFocusInWindow();
this.pack();
@@ -170,12 +195,17 @@ public class SearchTreeDialog extends JD
*/
@Override
public void actionPerformed(ActionEvent e) {
+ statusLabel.setText("");
if (e.getSource()==cancelButton) {
searchTF.requestFocusInWindow();
this.setVisible(false);
return;
+ } else if(e.getSource() == searchButton ||
+ e.getSource() == searchAndExpandButton) {
+ doSearch(e);
+ } else {
+ doReplaceAll(e);
}
- doSearch(e);
}
/**
@@ -202,19 +232,19 @@ public class SearchTreeDialog extends JD
GuiPackage guiPackage = GuiPackage.getInstance();
JMeterTreeModel jMeterTreeModel = guiPackage.getTreeModel();
Set<JMeterTreeNode> nodes = new HashSet<>();
+ int numberOfMatches = 0;
for (JMeterTreeNode jMeterTreeNode : jMeterTreeModel.getNodesOfType(Searchable.class)) {
try {
- if (jMeterTreeNode.getUserObject() instanceof Searchable){
- Searchable searchable = (Searchable) jMeterTreeNode.getUserObject();
- List<JMeterTreeNode> matchingNodes = jMeterTreeNode.getPathToThreadGroup();
- List<String> searchableTokens = searchable.getSearchableTokens();
- boolean result = searcher.search(searchableTokens);
- if (result) {
- nodes.addAll(matchingNodes);
- }
+ Searchable searchable = (Searchable) jMeterTreeNode.getUserObject();
+ List<JMeterTreeNode> matchingNodes = jMeterTreeNode.getPathToThreadGroup();
+ List<String> searchableTokens = searchable.getSearchableTokens();
+ boolean result = searcher.search(searchableTokens);
+ if (result) {
+ numberOfMatches++;
+ nodes.addAll(matchingNodes);
}
} catch (Exception ex) {
- logger.error("Error occured searching for word:"+ wordToSearch, ex);
+ logger.error("Error occured searching for word:"+ wordToSearch+ " in node:"+jMeterTreeNode.getName(), ex);
}
}
GuiPackage guiInstance = GuiPackage.getInstance();
@@ -228,6 +258,78 @@ public class SearchTreeDialog extends JD
}
GuiPackage.getInstance().getMainFrame().repaint();
searchTF.requestFocusInWindow();
- this.setVisible(false);
+ if(numberOfMatches > 0) {
+ statusLabel.setText(MessageFormat.format("{0} nodes match the search", new Object[]{numberOfMatches}));
+ }
+ }
+
+ /**
+ * Replace all occurences in nodes that contain {@link Replaceable} Test Elements
+ * @param e {@link ActionEvent}
+ */
+ private void doReplaceAll(ActionEvent e) {
+ String wordToSearch = searchTF.getText();
+ String wordToReplace = replaceTF.getText();
+
+ if (StringUtils.isEmpty(wordToReplace)) {
+ return;
+ }
+ // Save any change to current node
+ GuiPackage.getInstance().updateCurrentNode();
+ // reset previous result
+ ActionRouter.getInstance().doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.SEARCH_RESET));
+ Searcher searcher = null;
+ String regex = null;
+ if (isRegexpCB.isSelected()) {
+ regex = wordToSearch;
+ searcher = new RegexpSearcher(isCaseSensitiveCB.isSelected(), wordToSearch);
+ } else {
+ regex = Pattern.quote(wordToSearch);
+ searcher = new RawTextSearcher(isCaseSensitiveCB.isSelected(), wordToSearch);
+ }
+ GuiPackage guiPackage = GuiPackage.getInstance();
+ JMeterTreeModel jMeterTreeModel = guiPackage.getTreeModel();
+ Set<JMeterTreeNode> nodes = new HashSet<>();
+ boolean caseSensitiveReplacement = isCaseSensitiveCB.isSelected();
+ int totalReplaced = 0;
+ for (JMeterTreeNode jMeterTreeNode : jMeterTreeModel.getNodesOfType(Searchable.class)) {
+ try {
+ Searchable searchable = (Searchable) jMeterTreeNode.getUserObject();
+ List<String> searchableTokens = searchable.getSearchableTokens();
+ boolean result = searcher.search(searchableTokens);
+ if (result) {
+ if(jMeterTreeNode.getUserObject() instanceof Replaceable) {
+ Replaceable replaceable = (Replaceable) jMeterTreeNode.getUserObject();
+ int numberOfReplacements = replaceable.replace(regex, wordToReplace, caseSensitiveReplacement);
+ if(logger.isInfoEnabled()) {
+ logger.info("Replaced "+numberOfReplacements+" in element:"
+ +((TestElement)jMeterTreeNode.getUserObject()).getName());
+ }
+ totalReplaced += numberOfReplacements;
+ if(numberOfReplacements > 0) {
+ List<JMeterTreeNode> matchingNodes = jMeterTreeNode.getPathToThreadGroup();
+ nodes.addAll(matchingNodes);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ logger.error("Error occured replacing data in node:"+jMeterTreeNode.getName(), ex);
+ }
+ }
+ statusLabel.setText(MessageFormat.format("Replaced {0} occurences", new Object[]{totalReplaced}));
+ GuiPackage guiInstance = GuiPackage.getInstance();
+ JTree jTree = guiInstance.getMainFrame().getTree();
+
+ for (JMeterTreeNode jMeterTreeNode : nodes) {
+ jMeterTreeNode.setMarkedBySearch(true);
+ jTree.expandPath(new TreePath(jMeterTreeNode.getPath()));
+ }
+ // Update GUI as current node may be concerned by changes
+ if(totalReplaced>0) {
+ GuiPackage.getInstance().refreshCurrentGui();
+ }
+ GuiPackage.getInstance().getMainFrame().repaint();
+
+ searchTF.requestFocusInWindow();
}
}
Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1775729&r1=1775728&r2=1775729&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Thu Dec 22 20:38:50 2016
@@ -957,6 +957,7 @@ search=Search
search_base=Search base
search_expand=Search & Expand
search_filter=Search Filter
+search_replace_all=Replace All
search_test=Search Test
search_text_button_close=Close
search_text_button_find=Find
@@ -965,6 +966,7 @@ search_text_chkbox_case=Case sensitive
search_text_chkbox_regexp=Regular exp.
search_text_field=Search:
search_text_msg_not_found=Text not found
+search_text_replace=Replace by
search_text_title_not_found=Not found
search_tree_title=Search Tree
searchbase=Search base
Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1775729&r1=1775728&r2=1775729&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Thu Dec 22 20:38:50 2016
@@ -947,6 +947,7 @@ search=Rechercher
search_base=Base de recherche
search_expand=Rechercher & D\u00E9plier
search_filter=Filtre de recherche
+search_replace_all=Tout remplacer
search_test=Recherche
search_text_button_close=Fermer
search_text_button_find=Rechercher
@@ -955,6 +956,7 @@ search_text_chkbox_case=Consid\u00E9rer
search_text_chkbox_regexp=Exp. reguli\u00E8re
search_text_field=Rechercher \:
search_text_msg_not_found=Texte non trouv\u00E9
+search_text_replace=Remplacer par
search_text_title_not_found=Pas trouv\u00E9
search_tree_title=Rechercher dans l'arbre
searchbase=Base de recherche
Modified: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?rev=1775729&r1=1775728&r2=1775729&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java (original)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java Thu Dec 22 20:38:50 2016
@@ -46,6 +46,7 @@ import org.apache.jmeter.config.Argument
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.ConfigTestElement;
import org.apache.jmeter.engine.event.LoopIterationEvent;
+import org.apache.jmeter.gui.Replaceable;
import org.apache.jmeter.protocol.http.control.AuthManager;
import org.apache.jmeter.protocol.http.control.CacheManager;
import org.apache.jmeter.protocol.http.control.Cookie;
@@ -93,7 +94,8 @@ import org.apache.oro.text.regex.Perl5Ma
*
*/
public abstract class HTTPSamplerBase extends AbstractSampler
- implements TestStateListener, TestIterationListener, ThreadListener, HTTPConstantsInterface {
+ implements TestStateListener, TestIterationListener, ThreadListener, HTTPConstantsInterface,
+ Replaceable {
private static final long serialVersionUID = 241L;
@@ -2036,4 +2038,39 @@ public abstract class HTTPSamplerBase ex
String guiClass = configElement.getProperty(TestElement.GUI_CLASS).getStringValue();
return APPLIABLE_CONFIG_CLASSES.contains(guiClass);
}
+
+ /**
+ * Replace by replaceBy in path and body (arguments) properties
+ */
+ @Override
+ public int replace(String regex, String replaceBy, boolean caseSensitive) throws Exception {
+ int totalReplaced = 0;
+ for (JMeterProperty jMeterProperty : getArguments()) {
+ HTTPArgument arg = (HTTPArgument) jMeterProperty.getObjectValue();
+ String value = arg.getValue();
+ if(!StringUtils.isEmpty(value)) {
+ Object[] result = JOrphanUtils.replaceAllWithRegex(value, regex, replaceBy, caseSensitive);
+ // check if there is anything to replace
+ int nbReplaced = ((Integer)result[1]).intValue();
+ if (nbReplaced>0) {
+ String replacedText = (String) result[0];
+ arg.setValue(replacedText);
+ totalReplaced += nbReplaced;
+ }
+ }
+ }
+ String value = getPath();
+ if(!StringUtils.isEmpty(value)) {
+ Object[] result = JOrphanUtils.replaceAllWithRegex(value, regex, replaceBy, caseSensitive);
+ // check if there is anything to replace
+ int nbReplaced = ((Integer)result[1]).intValue();
+ if (nbReplaced>0) {
+ totalReplaced += nbReplaced;
+ String replacedText = (String) result[0];
+ setPath(replacedText);
+ totalReplaced += nbReplaced;
+ }
+ }
+ return totalReplaced;
+ }
}