/* * 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.extractor.json.render; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.ParseException; import java.util.List; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import org.apache.jmeter.extractor.json.jsonpath.JSONManager; import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.visualizers.RenderAsJSON; import org.apache.jmeter.visualizers.ResultRenderer; import org.apache.jmeter.visualizers.ViewResultsFullVisualizer; import org.apache.jorphan.gui.GuiUtils; import org.apache.jorphan.gui.JLabeledTextField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implement ResultsRender for JSON Path tester * @since 3.0 */ public class RenderAsJsonRenderer implements ResultRenderer, ActionListener { private static final Logger log = LoggerFactory.getLogger(RenderAsJsonRenderer.class); private static final String TAB_SEPARATOR = " "; //$NON-NLS-1$ private static final String JSONPATH_TESTER_COMMAND = "jsonpath_tester"; // $NON-NLS-1$ private JPanel jsonWithJSonPathPanel; private JTextArea jsonDataField; private JLabeledTextField jsonPathExpressionField; private JTextArea jsonPathResultField; private JTabbedPane rightSide; private SampleResult sampleResult; private JScrollPane jsonDataPane; /** {@inheritDoc} */ @Override public void clearData() { this.jsonDataField.setText(""); // $NON-NLS-1$ // don't set empty to keep json path this.jsonPathResultField.setText(""); // $NON-NLS-1$ } /** {@inheritDoc} */ @Override public void init() { // Create the panels for the json tab jsonWithJSonPathPanel = createJSonPathExtractorPanel(); } /** * Display the response as text or as rendered HTML. Change the text on the * button appropriate to the current display. * * @param e the ActionEvent being processed */ @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if ((sampleResult != null) && (JSONPATH_TESTER_COMMAND.equals(command))) { String response = jsonDataField.getText(); executeAndShowXPathTester(response); } } /** * Launch json path engine to parse a input text * @param textToParse */ private void executeAndShowXPathTester(String textToParse) { if (textToParse != null && textToParse.length() > 0 && this.jsonPathExpressionField.getText().length() > 0) { this.jsonPathResultField.setText(process(textToParse)); this.jsonPathResultField.setCaretPosition(0); // go to first line } } private String process(String textToParse) { try { List<Object> matchStrings = extractWithJSonPath(textToParse, jsonPathExpressionField.getText()); if (matchStrings.isEmpty()) { return "NO MATCH"; //$NON-NLS-1$ } else { StringBuilder builder = new StringBuilder(); int i = 0; for (Object obj : matchStrings) { String objAsString = obj != null ? obj.toString() : ""; //$NON-NLS-1$ builder.append("Result[").append(i++).append("]=").append(objAsString).append("\n"); //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ } return builder.toString(); } } catch (Exception e) { return "Exception: " + e.getMessage(); //$NON-NLS-1$ } } private List<Object> extractWithJSonPath(String textToParse, String expression) throws ParseException { JSONManager jsonManager = new JSONManager(); return jsonManager.extractWithJsonPath(textToParse, expression); } /*================= internal business =================*/ /** {@inheritDoc} */ @Override public void renderResult(SampleResult sampleResult) { String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); try { jsonDataField.setText(response == null ? "" : RenderAsJSON.prettyJSON(response, TAB_SEPARATOR)); //$NON-NLS-1$ jsonDataField.setCaretPosition(0); } catch (Exception e) { log.error("Exception converting to XML: {}, message: {}", response, e.getMessage(), e); //$NON-NLS-1$ $NON-NLS-2$ jsonDataField.setText("Exception converting to XML: "+response+ ", message: "+e.getMessage()); //$NON-NLS-1$ $NON-NLS-2$ jsonDataField.setCaretPosition(0); } } /** {@inheritDoc} */ @Override public String toString() { return JMeterUtils.getResString("jsonpath_renderer"); // $NON-NLS-1$ } /** {@inheritDoc} */ @Override public void setupTabPane() { // Add json-path tester pane if (rightSide.indexOfTab(JMeterUtils.getResString("jsonpath_tester_title")) < 0) { // $NON-NLS-1$ rightSide.addTab(JMeterUtils.getResString("jsonpath_tester_title"), jsonWithJSonPathPanel); // $NON-NLS-1$ } clearData(); } /** * @return JSON PATH Tester panel */ private JPanel createJSonPathExtractorPanel() { jsonDataField = new JTextArea(); jsonDataField.setEditable(false); jsonDataField.setLineWrap(true); jsonDataField.setWrapStyleWord(true); this.jsonDataPane = GuiUtils.makeScrollPane(jsonDataField); jsonDataPane.setPreferredSize(new Dimension(100, 200)); JPanel panel = new JPanel(new BorderLayout(0, 5)); JSplitPane mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, jsonDataPane, createJSonPathExtractorTasksPanel()); mainSplit.setDividerLocation(0.6d); mainSplit.setOneTouchExpandable(true); panel.add(mainSplit, BorderLayout.CENTER); return panel; } /** * Create the JSON PATH task pane * * @return JSON PATH task pane */ private JPanel createJSonPathExtractorTasksPanel() { JPanel jsonPathActionPanel = new JPanel(); jsonPathActionPanel.setLayout(new BoxLayout(jsonPathActionPanel, BoxLayout.X_AXIS)); Border margin = new EmptyBorder(5, 5, 0, 5); jsonPathActionPanel.setBorder(margin); jsonPathExpressionField = new JLabeledTextField(JMeterUtils.getResString("jsonpath_tester_field")); // $NON-NLS-1$ jsonPathActionPanel.add(jsonPathExpressionField, BorderLayout.WEST); JButton xpathTester = new JButton(JMeterUtils.getResString("jsonpath_tester_button_test")); // $NON-NLS-1$ xpathTester.setActionCommand(JSONPATH_TESTER_COMMAND); xpathTester.addActionListener(this); jsonPathActionPanel.add(xpathTester, BorderLayout.EAST); jsonPathResultField = new JTextArea(); jsonPathResultField.setEditable(false); jsonPathResultField.setLineWrap(true); jsonPathResultField.setWrapStyleWord(true); jsonPathResultField.setMinimumSize(new Dimension(100, 150)); JPanel xpathTasksPanel = new JPanel(new BorderLayout(0, 5)); xpathTasksPanel.add(jsonPathActionPanel, BorderLayout.NORTH); xpathTasksPanel.add(GuiUtils.makeScrollPane(jsonPathResultField), BorderLayout.CENTER); return xpathTasksPanel; } /** {@inheritDoc} */ @Override public synchronized void setRightSide(JTabbedPane side) { rightSide = side; } /** {@inheritDoc} */ @Override public synchronized void setSamplerResult(Object userObject) { if (userObject instanceof SampleResult) { sampleResult = (SampleResult) userObject; } } /** {@inheritDoc} */ @Override public void setLastSelectedTab(int index) { // nothing to do } /** {@inheritDoc} */ @Override public void renderImage(SampleResult sampleResult) { clearData(); jsonDataField.setText(JMeterUtils.getResString("jsonpath_render_no_text")); // $NON-NLS-1$ } /** {@inheritDoc} */ @Override public void setBackgroundColor(Color backGround) { // NOOP } }