📄 viewresultsfullvisualizer.java
字号:
/*
* 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;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.StringReader;
import java.lang.Character;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.ComponentView;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.Element;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.jmeter.assertions.AssertionResult;
import org.apache.jmeter.samplers.Clearable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* Allows the tester to view the textual response from sampling an Entry. This
* also allows to "single step through" the sampling process via a nice
* "Continue" button.
*
* Created 2001/07/25
*/
public class ViewResultsFullVisualizer extends AbstractVisualizer
implements ActionListener, TreeSelectionListener, Clearable
{
private static final Logger log = LoggingManager.getLoggerForClass();
// N.B. these are not multi-threaded, so don't make it static
private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); // ISO format $NON-NLS-1$
private static final String NL = "\n"; // $NON-NLS-1$
private static final String XML_PFX = "<?xml "; // $NON-NLS-1$
public final static Color SERVER_ERROR_COLOR = Color.red;
public final static Color CLIENT_ERROR_COLOR = Color.blue;
public final static Color REDIRECT_COLOR = Color.green;
private static final String TEXT_HTML = "text/html"; // $NON-NLS-1$
private static final String HTML_COMMAND = "html"; // $NON-NLS-1$
private static final String JSON_COMMAND = "json"; // $NON-NLS-1$
private static final String XML_COMMAND = "xml"; // $NON-NLS-1$
private static final String TEXT_COMMAND = "text"; // $NON-NLS-1$
private static final String STYLE_SERVER_ERROR = "ServerError"; // $NON-NLS-1$
private static final String STYLE_CLIENT_ERROR = "ClientError"; // $NON-NLS-1$
private static final String STYLE_REDIRECT = "Redirect"; // $NON-NLS-1$
private boolean textMode = true;
private static final String ESC_CHAR_REGEX = "\\\\[\"\\\\/bfnrt]|\\\\u[0-9A-Fa-f]{4}"; // $NON-NLS-1$
private static final String NORMAL_CHARACTER_REGEX = "[^\"\\\\]"; // $NON-NLS-1$
private static final String STRING_REGEX = "\"(" + ESC_CHAR_REGEX + "|" + NORMAL_CHARACTER_REGEX + ")*\""; // $NON-NLS-1$
// This 'other value' regex is deliberately weak, even accepting an empty string, to be useful when reporting malformed data.
private static final String OTHER_VALUE_REGEX = "[^\\{\\[\\]\\}\\,]*"; // $NON-NLS-1$
private static final String VALUE_OR_PAIR_REGEX = "((" + STRING_REGEX + "\\s*:)?\\s*(" + STRING_REGEX + "|" + OTHER_VALUE_REGEX + ")\\s*,?\\s*)"; // $NON-NLS-1$
private static final Pattern VALUE_OR_PAIR_PATTERN = Pattern.compile(VALUE_OR_PAIR_REGEX);
// set default command to Text
private String command = TEXT_COMMAND;
// Keep copies of the two editors needed
private static EditorKit customisedEditor = new LocalHTMLEditorKit();
private static EditorKit defaultHtmlEditor = JEditorPane.createEditorKitForContentType(TEXT_HTML);
private DefaultMutableTreeNode root;
private DefaultTreeModel treeModel;
private JTextPane stats;
private JEditorPane results;
private JScrollPane resultsScrollPane;
private JPanel resultsPane;
private JLabel imageLabel;
private JTextArea sampleDataField;
private JPanel requestPane;
private JRadioButton textButton;
private JRadioButton htmlButton;
private JRadioButton jsonButton;
private JRadioButton xmlButton;
private JCheckBox downloadAll;
private JTree jTree;
private JTabbedPane rightSide;
private static final ImageIcon imageSuccess = JMeterUtils.getImage(
JMeterUtils.getPropDefault("viewResultsTree.success", //$NON-NLS-1$
"icon_success_sml.gif")); //$NON-NLS-1$
private static final ImageIcon imageFailure = JMeterUtils.getImage(
JMeterUtils.getPropDefault("viewResultsTree.failure", //$NON-NLS-1$
"icon_warning_sml.gif")); //$NON-NLS-1$
public ViewResultsFullVisualizer() {
super();
log.debug("Start : ViewResultsFullVisualizer1");
init();
log.debug("End : ViewResultsFullVisualizer1");
}
public void add(SampleResult res) {
updateGui(res);
}
public String getLabelResource() {
return "view_results_tree_title"; // $NON-NLS-1$
}
/**
* Update the visualizer with new data.
*/
private synchronized void updateGui(SampleResult res) {
log.debug("Start : updateGui1");
if (log.isDebugEnabled()) {
log.debug("updateGui1 : sample result - " + res);
}
// Add sample
DefaultMutableTreeNode currNode = new DefaultMutableTreeNode(res);
treeModel.insertNodeInto(currNode, root, root.getChildCount());
addSubResults(currNode, res);
// Add any assertion that failed as children of the sample node
AssertionResult assertionResults[] = res.getAssertionResults();
int assertionIndex = currNode.getChildCount();
for (int j = 0; j < assertionResults.length; j++) {
AssertionResult item = assertionResults[j];
if (item.isFailure() || item.isError()) {
DefaultMutableTreeNode assertionNode = new DefaultMutableTreeNode(item);
treeModel.insertNodeInto(assertionNode, currNode, assertionIndex++);
}
}
if (root.getChildCount() == 1) {
jTree.expandPath(new TreePath(root));
}
log.debug("End : updateGui1");
}
private void addSubResults(DefaultMutableTreeNode currNode, SampleResult res) {
SampleResult[] subResults = res.getSubResults();
int leafIndex = 0;
for (int i = 0; i < subResults.length; i++) {
SampleResult child = subResults[i];
if (log.isDebugEnabled()) {
log.debug("updateGui1 : child sample result - " + child);
}
DefaultMutableTreeNode leafNode = new DefaultMutableTreeNode(child);
treeModel.insertNodeInto(leafNode, currNode, leafIndex++);
addSubResults(leafNode, child);
// Add any assertion that failed as children of the sample node
AssertionResult assertionResults[] = child.getAssertionResults();
int assertionIndex = leafNode.getChildCount();
for (int j = 0; j < assertionResults.length; j++) {
AssertionResult item = assertionResults[j];
if (item.isFailure() || item.isError()) {
DefaultMutableTreeNode assertionNode = new DefaultMutableTreeNode(item);
treeModel.insertNodeInto(assertionNode, leafNode, assertionIndex++);
}
}
}
}
/**
* Clears the visualizer.
*/
public void clearData() {
log.debug("Start : clear1");
if (log.isDebugEnabled()) {
log.debug("clear1 : total child - " + root.getChildCount());
}
while (root.getChildCount() > 0) {
// the child to be removed will always be 0 'cos as the nodes are
// removed the nth node will become (n-1)th
treeModel.removeNodeFromParent((DefaultMutableTreeNode) root.getChildAt(0));
}
results.setText("");// Response Data // $NON-NLS-1$
sampleDataField.setText("");// Request Data // $NON-NLS-1$
log.debug("End : clear1");
}
/**
* Returns the description of this visualizer.
*
* @return description of this visualizer
*/
public String toString() {
String desc = "Shows the text results of sampling in tree form";
if (log.isDebugEnabled()) {
log.debug("toString1 : Returning description - " + desc);
}
return desc;
}
/**
* Sets the right pane to correspond to the selected node of the left tree.
*/
public void valueChanged(TreeSelectionEvent e) {
log.debug("Start : valueChanged1");
DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
if (log.isDebugEnabled()) {
log.debug("valueChanged : selected node - " + node);
}
StyledDocument statsDoc = stats.getStyledDocument();
try {
statsDoc.remove(0, statsDoc.getLength());
sampleDataField.setText(""); // $NON-NLS-1$
results.setText(""); // $NON-NLS-1$
if (node != null) {
Object userObject = node.getUserObject();
if(userObject instanceof SampleResult) {
SampleResult res = (SampleResult) userObject;
// We are displaying a SampleResult
setupTabPaneForSampleResult();
if (log.isDebugEnabled()) {
log.debug("valueChanged1 : sample result - " + res);
}
if (res != null) {
// load time label
log.debug("valueChanged1 : load time - " + res.getTime());
String sd = res.getSamplerData();
if (sd != null) {
String rh = res.getRequestHeaders();
if (rh != null) {
StringBuffer sb = new StringBuffer(sd.length() + rh.length()+20);
sb.append(sd);
sb.append("\nRequest Headers:\n");
sb.append(rh);
sd = sb.toString();
}
sampleDataField.setText(sd);
}
StringBuffer statsBuff = new StringBuffer(200);
statsBuff.append("Thread Name: ").append(res.getThreadName()).append(NL);
String startTime = dateFormat.format(new Date(res.getStartTime()));
statsBuff.append("Sample Start: ").append(startTime).append(NL);
statsBuff.append("Load time: ").append(res.getTime()).append(NL);
statsBuff.append("Latency: ").append(res.getLatency()).append(NL);
statsBuff.append("Size in bytes: ").append(res.getBytes()).append(NL);
statsBuff.append("Sample Count: ").append(res.getSampleCount()).append(NL);
statsBuff.append("Error Count: ").append(res.getErrorCount()).append(NL);
statsDoc.insertString(statsDoc.getLength(), statsBuff.toString(), null);
statsBuff = new StringBuffer(); //reset for reuse
String responseCode = res.getResponseCode();
log.debug("valueChanged1 : response code - " + responseCode);
int responseLevel = 0;
if (responseCode != null) {
try {
responseLevel = Integer.parseInt(responseCode) / 100;
} catch (NumberFormatException numberFormatException) {
// no need to change the foreground color
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -