Author: pmouawad
Date: Mon Nov 11 21:56:26 2013
New Revision: 1540858
URL: http://svn.apache.org/r1540858
Log:
Bug 55610 - View Results Tree : Add an XPath Tester
Bugzilla Id: 55610
Added:
jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java (with props)
Modified:
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
Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java?rev=1540858&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java Mon Nov 11
21:56:26 2013
@@ -0,0 +1,301 @@
+/*
+ * 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.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+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 javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.jmeter.assertions.gui.XMLConfPanel;
+import org.apache.jmeter.extractor.XPathExtractor;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jmeter.util.TidyException;
+import org.apache.jmeter.util.XPathUtil;
+import org.apache.jorphan.gui.GuiUtils;
+import org.apache.jorphan.gui.JLabeledTextField;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.util.JOrphanUtils;
+import org.apache.log.Logger;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Implement ResultsRender for XPath tester
+ */
+public class RenderAsXPath implements ResultRenderer, ActionListener {
+
+ private static final Logger logger = LoggingManager.getLoggerForClass();
+
+ private static final String XPATH_TESTER_COMMAND = "xpath_tester"; // $NON-NLS-1$
+
+ private JPanel xmlWithXPathPane;
+
+ private JTextArea xmlDataField;
+
+ private JLabeledTextField xpathExpressionField;
+
+ private JTextArea xpathResultField;
+
+ private JTabbedPane rightSide;
+
+ private SampleResult sampleResult = null;
+
+ private JScrollPane xmlDataPane;
+
+ // Should we return fragment as text, rather than text of fragment?
+ private final JCheckBox getFragment =
+ new JCheckBox(JMeterUtils.getResString("xpath_tester_fragment"));//$NON-NLS-1$
+
+ private final XMLConfPanel xmlConfPanel = new XMLConfPanel();
+
+ /** {@inheritDoc} */
+ @Override
+ public void clearData() {
+ this.xmlDataField.setText(""); // $NON-NLS-1$
+ // don't set empty to keep xpath
+ // xpathExpressionField.setText(""); // $NON-NLS-1$
+ this.xpathResultField.setText(""); // $NON-NLS-1$
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void init() {
+ // Create the panels for the xpath tab
+ xmlWithXPathPane = createXpathExtractorPanel();
+ }
+
+ /**
+ * 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) && (XPATH_TESTER_COMMAND.equals(command))) {
+ String response = xmlDataField.getText();
+ XPathExtractor extractor = new XPathExtractor();
+ xmlConfPanel.modifyTestElement(extractor);
+ extractor.setFragment(getFragment.isSelected());
+ executeAndShowXPathTester(response, extractor);
+ }
+ }
+
+ /**
+ * Launch xpath engine to parse a input text
+ * @param textToParse
+ */
+ private void executeAndShowXPathTester(String textToParse, XPathExtractor extractor)
{
+ if (textToParse != null && textToParse.length() > 0
+ && this.xpathExpressionField.getText().length() > 0) {
+ this.xpathResultField.setText(process(textToParse, extractor));
+ this.xpathResultField.setCaretPosition(0); // go to first line
+ }
+ }
+
+ private String process(String textToParse, XPathExtractor extractor) {
+ try {
+ Document doc = parseResponse(textToParse, extractor);
+ List<String> matchStrings = new ArrayList<String>();
+ XPathUtil.putValuesForXPathInList(doc, xpathExpressionField.getText(),
+ matchStrings, extractor.getFragment());
+ StringBuilder builder = new StringBuilder();
+ int nbFound = matchStrings.size();
+ builder.append("Match count: ").append(nbFound).append("\n");
+ for (int i = 0; i < nbFound; i++) {
+ builder.append("Match[").append(i+1).append("]=").append(matchStrings.get(i)).append("\n");
+ }
+ return builder.toString();
+ } catch (Exception e) {
+ return "Exception:"+ ExceptionUtils.getStackTrace(e);
+ }
+ }
+
+ /*================= internal business =================*/
+ /**
+ * Converts (X)HTML response to DOM object Tree.
+ * This version cares of charset of response.
+ * @param unicodeData
+ * @return
+ *
+ */
+ private Document parseResponse(String unicodeData, XPathExtractor extractor)
+ throws UnsupportedEncodingException, IOException, ParserConfigurationException,SAXException,TidyException
+ {
+ //TODO: validate contentType for reasonable types?
+
+ // NOTE: responseData encoding is server specific
+ // Therefore we do byte -> unicode -> byte conversion
+ // to ensure UTF-8 encoding as required by XPathUtil
+ // convert unicode String -> UTF-8 bytes
+ byte[] utf8data = unicodeData.getBytes("UTF-8"); // $NON-NLS-1$
+ ByteArrayInputStream in = new ByteArrayInputStream(utf8data);
+ boolean isXML = JOrphanUtils.isXML(utf8data);
+ // this method assumes UTF-8 input data
+ return XPathUtil.makeDocument(in,false,false,extractor.useNameSpace(),
+ extractor.isTolerant(),extractor.isQuiet(),extractor.showWarnings(),
+ extractor.reportErrors(),isXML, extractor.isDownloadDTDs());
+ }
+
+
+ /** {@inheritDoc} */
+ @Override
+ public void renderResult(SampleResult sampleResult) {
+ String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult);
+ try {
+ xmlDataField.setText(response == null ? "" : XPathUtil.formatXml(response));
+ xmlDataField.setCaretPosition(0);
+ } catch (Exception e) {
+ logger.error("Exception converting to XML:"+response+ ", message:"+e.getMessage(),e);
+ xmlDataField.setText("Exception converting to XML:"+response+ ", message:"+e.getMessage());
+ xmlDataField.setCaretPosition(0);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return JMeterUtils.getResString("xpath_tester"); // $NON-NLS-1$
+ }
+
+
+ /** {@inheritDoc} */
+ @Override
+ public void setupTabPane() {
+ // Add xpath tester pane
+ if (rightSide.indexOfTab(JMeterUtils.getResString("xpath_tester_title")) < 0)
{ // $NON-NLS-1$
+ rightSide.addTab(JMeterUtils.getResString("xpath_tester_title"), xmlWithXPathPane);
// $NON-NLS-1$
+ }
+ clearData();
+ }
+
+ /**
+ * @return XPath Tester panel
+ */
+ private JPanel createXpathExtractorPanel() {
+
+ xmlDataField = new JTextArea();
+ xmlDataField.setEditable(false);
+ xmlDataField.setLineWrap(true);
+ xmlDataField.setWrapStyleWord(true);
+
+ this.xmlDataPane = GuiUtils.makeScrollPane(xmlDataField);
+ xmlDataPane.setMinimumSize(new Dimension(0, 400));
+
+ JPanel pane = new JPanel(new BorderLayout(0, 5));
+
+ JSplitPane mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ xmlDataPane, createXpathExtractorTasksPanel());
+ mainSplit.setDividerLocation(400);
+ pane.add(mainSplit, BorderLayout.CENTER);
+ return pane;
+ }
+
+ /**
+ * Create the XPath task pane
+ *
+ * @return XPath task pane
+ */
+ private JPanel createXpathExtractorTasksPanel() {
+ Box xpathActionPanel = Box.createVerticalBox();
+
+ Box selectorAndButton = Box.createHorizontalBox();
+
+ Border margin = new EmptyBorder(5, 5, 0, 5);
+ xpathActionPanel.setBorder(margin);
+ xpathExpressionField = new JLabeledTextField(JMeterUtils.getResString("xpath_tester_field"));
// $NON-NLS-1$
+
+ JButton xpathTester = new JButton(JMeterUtils.getResString("xpath_tester_button_test"));
// $NON-NLS-1$
+ xpathTester.setActionCommand(XPATH_TESTER_COMMAND);
+ xpathTester.addActionListener(this);
+
+ selectorAndButton.add(xpathExpressionField);
+ selectorAndButton.add(xpathTester);
+
+ xpathActionPanel.add(selectorAndButton);
+ xpathActionPanel.add(xmlConfPanel);
+ xpathActionPanel.add(getFragment);
+
+ xpathResultField = new JTextArea();
+ xpathResultField.setEditable(false);
+ xpathResultField.setLineWrap(true);
+ xpathResultField.setWrapStyleWord(true);
+
+ JPanel xpathTasksPanel = new JPanel(new BorderLayout(0, 5));
+ xpathTasksPanel.add(xpathActionPanel, BorderLayout.NORTH);
+ xpathTasksPanel.add(GuiUtils.makeScrollPane(xpathResultField), 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();
+ xmlDataField.setText(JMeterUtils.getResString("xpath_tester_no_text")); // $NON-NLS-1$
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setBackgroundColor(Color backGround) {
+ }
+}
Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
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=1540858&r1=1540857&r2=1540858&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Mon Nov 11 21:56:26
2013
@@ -1284,6 +1284,12 @@ xpath_extractor_fragment=Return entire X
xpath_extractor_query=XPath query:
xpath_extractor_title=XPath Extractor
xpath_file_file_name=XML file to get values from
+xpath_tester=XPath Tester
+xpath_tester_button_test=Test
+xpath_tester_field=XPath expression
+xpath_tester_fragment=Return entire XPath fragment instead of text content?
+xpath_tester_no_text=Data response result isn't text.
+xpath_tester_title=XPath Tester
xpath_tidy_quiet=Quiet
xpath_tidy_report_errors=Report errors
xpath_tidy_show_warnings=Show warnings
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=1540858&r1=1540857&r2=1540858&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 Mon Nov 11 21:56:26
2013
@@ -1277,6 +1277,12 @@ xpath_extractor_fragment=Retourner le fr
xpath_extractor_query=Requ\u00EAte XPath \:
xpath_extractor_title=Extracteur XPath
xpath_file_file_name=Fichier XML contenant les valeurs
+xpath_tester=Testeur XPath
+xpath_tester_button_test=Tester
+xpath_tester_field=Expression XPath
+xpath_tester_fragment=etourner le fragment XPath entier au lieu du contenu?
+xpath_tester_no_text=Les donn\u00E9es de r\u00E9ponse ne sont pas du texte.
+xpath_tester_title=Testeur XPath
xpath_tidy_quiet=Silencieux
xpath_tidy_report_errors=Rapporter les erreurs
xpath_tidy_show_warnings=Afficher les alertes
Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1540858&r1=1540857&r2=1540858&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Mon Nov 11 21:56:26 2013
@@ -181,6 +181,7 @@ A workaround is to use a Java 7 update 4
<h3>Listeners</h3>
<ul>
+<li><bugzilla>55610</bugzilla> - View Results Tree : Add an XPath Tester</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=1540858&r1=1540857&r2=1540858&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Mon Nov 11 21:56:26 2013
@@ -2793,6 +2793,11 @@ video/
<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.
<br/></td></tr>
+<tr><td><b>XPath Tester</b></td>
+<td>The <i>XPath Tester</i> only works for text responses. It shows the
plain text in the upper panel.
+The "Test" button allows the user to apply the XPath query to the upper panel and the results
+will be displayed in the lower panel.<br/>
+</td></tr>
</table>
<p><i>Scroll automatically?</i> option permit to have last node display
in tree selection</p>
<p>
|