All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jmeter.visualizers.RenderAsXML Maven / Gradle / Ivy

/*
 * 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.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;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.util.XPathUtil;
import org.apache.jorphan.util.JOrphanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
import org.xml.sax.SAXException;

public class RenderAsXML extends SamplerResultTab
    implements ResultRenderer {

    private static final Logger log = LoggerFactory.getLogger(RenderAsXML.class);

    private static final byte[] XML_PFX = {'<', '?', 'x', 'm', 'l', ' '};//" 0) {
            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);
    }

    /* (non-Javadoc)
     * @see org.apache.jmeter.visualizers.SamplerResultTab#clearData()
     */
    @Override
    public void clearData() {
        super.clearData();
        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 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 Dave Maung
     * TODO implement to find any nodes in the tree using TreePath.
     *
     */
    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));
            try {
                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);
                ToolTipManager.sharedInstance().registerComponent(domJTree);
                domJTree.setCellRenderer(new DomTreeRenderer());
            } catch (SAXException e) {
                log.warn("Error trying to parse document", e);
            }
        }

        /**
         * Skip all DTD nodes, all prolog nodes. They are not supported in tree view
         * We let user insert them however in DOMTreeView, we don't display them.
         *
         * @param parent {@link Node}
         */
        private Node getFirstElement(Node parent) {
            NodeList childNodes = parent.getChildNodes();
            Node toReturn = parent; // Must return a valid node, or may generate an NPE
            for (int i = 0; i < childNodes.getLength(); i++) {
                Node childNode = childNodes.item(i);
                toReturn = childNode;
                if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                    break;
                }

            }
            return toReturn;
        }

        /**
         * 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.
         */
        private static class DomTreeRenderer extends DefaultTreeCellRenderer {

            private static final long serialVersionUID = 240210061375790195L;

            @Override
            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);

                DefaultMutableTreeNode valueTreeNode = (DefaultMutableTreeNode) value;
                setToolTipText(getHTML(valueTreeNode.toString(), "
", 100)); // $NON-NLS-1$ return this; } /** * get the html */ private String getHTML(String str, String separator, int maxChar) { StringBuilder strBuf = new StringBuilder(""); // $NON-NLS-1$ char[] chars = str.toCharArray(); for (int i = 0; i < chars.length; i++) { if (i % maxChar == 0 && i != 0) { strBuf.append(separator); } strBuf.append(encode(chars[i])); } strBuf.append(""); // $NON-NLS-1$ return strBuf.toString(); } 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; } 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) { JOptionPane.showMessageDialog(null, message, title, messageType); } /** {@inheritDoc} */ @Override public String toString() { return JMeterUtils.getResString("view_results_render_xml"); // $NON-NLS-1$ } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy