⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 viewresultsfullvisualizer.java

📁 测试工具
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -