Author: pmouawad
Date: Sat Nov 18 13:23:38 2017
New Revision: 1815663
URL: http://svn.apache.org/viewvc?rev=1815663&view=rev
Log:
Bug 61776 - View Results Tree: Expansion of "Add expand/collapse" all menu in
render XML view
Contributed by Maxime Chassagneux and Grahama Russell
This closes #329
This closes #294
Bugzilla Id: 61776
Modified:
jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXML.java
jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
jmeter/trunk/xdocs/changes.xml
jmeter/trunk/xdocs/usermanual/component_reference.xml
Modified:
jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXML.java
URL:
http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXML.java?rev=1815663&r1=1815662&r2=1815663&view=diff
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXML.java
(original)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXML.java
Sat Nov 18 13:23:38 2017
@@ -21,16 +21,27 @@ package org.apache.jmeter.visualizers;
import java.awt.Component;
import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
+import java.util.Enumeration;
+import java.util.function.Consumer;
+import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
+import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.apache.jmeter.samplers.SampleResult;
@@ -49,9 +60,9 @@ public class RenderAsXML extends Sampler
private static final Logger log =
LoggerFactory.getLogger(RenderAsXML.class);
- private static final byte[] XML_PFX = {'<','?','x','m','l',' '};//"<?xml "
+ private static final byte[] XML_PFX = {'<', '?', 'x', 'm', 'l', '
'};//"<?xml "
- public RenderAsXML(){
+ public RenderAsXML() {
activateSearchExtension = false; // TODO work out how to search the
XML pane
}
@@ -66,8 +77,8 @@ public class RenderAsXML extends Sampler
results.setCaretPosition(0);
byte[] source = res.getResponseData();
final ByteArrayInputStream baIS = new ByteArrayInputStream(source);
- for(int i=0; i<source.length-XML_PFX.length; i++){
- if (JOrphanUtils.startsWith(source, XML_PFX, i)){
+ for (int i = 0; i < source.length - XML_PFX.length; i++) {
+ if (JOrphanUtils.startsWith(source, XML_PFX, i)) {
baIS.skip(i);// NOSONAR Skip the leading bytes (if any)
break;
}
@@ -78,12 +89,14 @@ public class RenderAsXML extends Sampler
org.w3c.dom.Document document = tidy.parseDOM(baIS, null);
document.normalize();
if (tidy.getParseErrors() > 0) {
- showErrorMessageDialog(sw.toString(),
+ showErrorMessageDialog(
+ sw.toString(),
"Tidy: " + tidy.getParseErrors() + " errors, " +
tidy.getParseWarnings() + " warnings",
JOptionPane.WARNING_MESSAGE);
}
JPanel domTreePanel = new DOMTreePanel(document);
+ new ExpandPopupMenu().add(domTreePanel);
resultsScrollPane.setViewportView(domTreePanel);
}
@@ -96,18 +109,70 @@ public class RenderAsXML extends Sampler
resultsScrollPane.setViewportView(null); // clear result tab on Ctrl-E
}
+ private static class ExpandPopupMenu extends JPopupMenu implements
ActionListener {
+
+ private static final long serialVersionUID = 1L;
+ private JMenuItem expand;
+ private JMenuItem collapse;
+ private JTree tree;
+
+ ExpandPopupMenu() {
+ expand = new
JMenuItem(JMeterUtils.getResString("menu_expand_all"));
+ expand.addActionListener(this);
+ add(expand);
+ collapse = new
JMenuItem(JMeterUtils.getResString("menu_collapse_all"));
+ collapse.addActionListener(this);
+ add(collapse);
+ }
+
+ void setTree(JTree tree) {
+ this.tree = tree;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == expand) {
+ expandAll(tree.getSelectionPath());
+ }
+ if (e.getSource() == collapse) {
+ collapseAll(tree.getSelectionPath());
+ }
+ }
+
+ private void collapseAll(TreePath parent) {
+ applyToChildren(parent, this::collapseAll);
+ tree.collapsePath(parent);
+ }
+
+ private void expandAll(TreePath parent) {
+ applyToChildren(parent, this::expandAll);
+ tree.expandPath(parent);
+ }
+
+ private void applyToChildren(TreePath parent, Consumer<TreePath>
method) {
+ TreeNode node = ((TreeNode) parent.getLastPathComponent());
+ Enumeration<?> e = node.children();
+ while (e.hasMoreElements()) {
+ TreeNode n = (TreeNode) e.nextElement();
+ TreePath path = parent.pathByAddingChild(n);
+ method.accept(path);
+ }
+ }
+ }
+
/*
*
* A Dom tree panel for to display response as tree view author <a
- * href="mailto:[email protected]">Dave Maung</a>
+ * href="mailto:[email protected]">Dave Maung</a>
* TODO implement to find any nodes in the tree using TreePath.
*
*/
- private static class DOMTreePanel extends JPanel {
+ private static class DOMTreePanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 6871690021183779153L;
private JTree domJTree;
+ private ExpandPopupMenu popupMenu;
public DOMTreePanel(org.w3c.dom.Document document) {
super(new GridLayout(1, 0));
@@ -115,9 +180,11 @@ public class RenderAsXML extends Sampler
Node firstElement = getFirstElement(document);
DefaultMutableTreeNode top = new
XMLDefaultMutableTreeNode(firstElement);
domJTree = new JTree(top);
-
domJTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
domJTree.setShowsRootHandles(true);
+ domJTree.addMouseListener(this);
+ popupMenu = new ExpandPopupMenu();
+ popupMenu.setTree(domJTree);
JScrollPane domJScrollPane = new JScrollPane(domJTree);
domJTree.setAutoscrolls(true);
this.add(domJScrollPane);
@@ -126,7 +193,6 @@ public class RenderAsXML extends Sampler
} catch (SAXException e) {
log.warn("Error trying to parse document", e);
}
-
}
/**
@@ -134,7 +200,6 @@ public class RenderAsXML extends Sampler
* We let user insert them however in DOMTreeView, we don't display
them.
*
* @param parent {@link Node}
- * @return
*/
private Node getFirstElement(Node parent) {
NodeList childNodes = parent.getChildNodes();
@@ -142,7 +207,7 @@ public class RenderAsXML extends Sampler
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
toReturn = childNode;
- if (childNode.getNodeType() == Node.ELEMENT_NODE){
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
break;
}
@@ -154,16 +219,19 @@ public class RenderAsXML extends Sampler
* This class is to view as tooltext. This is very useful, when the
* contents has long string and does not fit in the view. it will also
* automatically wrap line for each 100 characters since tool tip
- * support html.
+ * support html.
*/
private static class DomTreeRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 240210061375790195L;
@Override
- public Component getTreeCellRendererComponent(JTree tree, Object
value, boolean sel, boolean expanded,
+ public Component getTreeCellRendererComponent(
+ JTree tree, Object value, boolean sel, boolean expanded,
boolean leaf, int row, boolean phasFocus) {
- super.getTreeCellRendererComponent(tree, value, sel, expanded,
leaf, row, phasFocus);
+
+ super.getTreeCellRendererComponent(
+ tree, value, sel, expanded, leaf, row, phasFocus);
DefaultMutableTreeNode valueTreeNode =
(DefaultMutableTreeNode) value;
setToolTipText(getHTML(valueTreeNode.toString(), "<br>",
100)); // $NON-NLS-1$
@@ -172,11 +240,6 @@ public class RenderAsXML extends Sampler
/**
* get the html
- *
- * @param str
- * @param separator
- * @param maxChar
- * @return
*/
private String getHTML(String str, String separator, int maxChar) {
StringBuilder strBuf = new StringBuilder("<html><body
bgcolor=\"yellow\"><b>"); // $NON-NLS-1$
@@ -197,26 +260,58 @@ public class RenderAsXML extends Sampler
private String encode(char c) {
String toReturn = String.valueOf(c);
switch (c) {
- case '<': // $NON-NLS-1$
- toReturn = "<"; // $NON-NLS-1$
- break;
- case '>': // $NON-NLS-1$
- toReturn = ">"; // $NON-NLS-1$
- break;
- case '\'': // $NON-NLS-1$
- toReturn = "'"; // $NON-NLS-1$
- break;
- case '\"': // $NON-NLS-1$
- toReturn = """; // $NON-NLS-1$
- break;
- default:
- // ignored
- break;
+ case '<': // $NON-NLS-1$
+ toReturn = "<"; // $NON-NLS-1$
+ break;
+ case '>': // $NON-NLS-1$
+ toReturn = ">"; // $NON-NLS-1$
+ break;
+ case '\'': // $NON-NLS-1$
+ toReturn = "'"; // $NON-NLS-1$
+ break;
+ case '\"': // $NON-NLS-1$
+ toReturn = """; // $NON-NLS-1$
+ break;
+ default:
+ // ignored
+ break;
}
return toReturn;
}
}
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isRightMouseButton(e)) {
+ int x = e.getX();
+ int y = e.getY();
+ JTree tree = (JTree) e.getSource();
+
+ int rowIndex = tree.getClosestRowForLocation(x, y);
+ if (rowIndex > -1) {
+ tree.setSelectionRow(rowIndex);
+ popupMenu.show(tree, x, y);
+ }
+ }
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
}
private static void showErrorMessageDialog(String message, String title,
int messageType) {
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=1815663&r1=1815662&r2=1815663&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
(original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Sat
Nov 18 13:23:38 2017
@@ -677,9 +677,11 @@ md5hex_assertion_title=MD5Hex Assertion
mechanism=Mechanism
menu_assertions=Assertions
menu_collapse_all=Collapse All
+menu_collapse_all_from_selected_node=Collapse All From Selected Node
menu_config_element=Config Element
menu_edit=Edit
menu_expand_all=Expand All
+menu_expand_all_from_selected_node=Expand All From Selected Node
menu_fragments=Test Fragment
menu_generative_controller=Sampler
menu_listener=Listener
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=1815663&r1=1815662&r2=1815663&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
Sat Nov 18 13:23:38 2017
@@ -667,9 +667,11 @@ md5hex_assertion_title=Assertion MD5Hex
mechanism=M\u00E9canisme
menu_assertions=Assertions
menu_collapse_all=R\u00E9duire tout
+menu_collapse_all_from_selected_node=R\u00E9duire tout \u00E0 partir du noeud
s\u00E9lection\u00E9
menu_config_element=Configurations
menu_edit=Editer
menu_expand_all=Etendre tout
+menu_expand_all_from_selected_node=Etendre tout \u00E0 partir du noeud
s\u00E9lection\u00E9
menu_fragments=Fragment d'\u00E9l\u00E9ments
menu_generative_controller=Echantillons
menu_listener=R\u00E9cepteurs
Modified: jmeter/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1815663&r1=1815662&r2=1815663&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Sat Nov 18 13:23:38 2017
@@ -114,6 +114,7 @@ Summary
<ul>
<li><bug>57760</bug>View Results Tree : Cookie Header is wrongly shown as
empty(no cookies) when viewing a recorder Sample Result. Contributed by Ubik
Load Pack (support at ubikloadpack.com)</li>
<li><bug>61769</bug>View Results Tree: Use syntax highlighter in XPath
Tester, JSON Path Tester and CSS/JQuery Tester. Contributed by Ubik Load Pack
(support at ubikloadpack.com)</li>
+ <li><bug>61776</bug>View Results Tree: Expansion of <code>Add
expand/collapse all</code> menu in render XML view. Contributed by Maxime
Chassagneux and Graham Russell</li>
</ul>
<h3>Timers, Assertions, Config, Pre- & Post-Processors</h3>
Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL:
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1815663&r1=1815662&r2=1815663&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Sat Nov 18 13:23:38
2017
@@ -2794,8 +2794,8 @@ are part of the test plan.</p></descript
<component name="View Results Tree" index="§-num;.3.6" width="910"
height="659" screenshot="view_results_tree.png">
<description>
<note>
-View Results Tree MUST NOT BE USED during load test as it consumes a lot of
resources (memory and CPU). Use it only for either functional testing or
-during Test Plan debugging and Validation.
+View Results Tree MUST NOT BE USED during load test as it consumes a lot of
resources (memory and CPU).
+Use it only for either functional testing or during Test Plan debugging and
Validation.
</note>
The View Results Tree shows a tree of all sample responses, allowing you to
view the
response for any sample. In addition to showing the response, you can see the
time it took to get
@@ -2895,8 +2895,9 @@ video/
</source>
<br/></td></tr>
<tr><td><code>XML</code></td>
-<td>The <i>XML view</i> will show response in tree style.
+<td>The <i>XML view</i> will show response in tree style.
Any DTD nodes or Prolog nodes will not show up in tree; however, response may
contain those nodes.
+You can right-click on any node and expand or collapse all nodes below it.
<br/></td></tr>
<tr><td><code>XPath Tester</code></td>
<td>The <i>XPath Tester</i> only works for text responses. It shows the plain
text in the upper panel.