Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions extras/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,13 @@

<property name="lib.dir" value="${jmeter.home}/lib"/>

<!-- Use xalan copy from JMeter lib directory to ensure consistent processing with Java 1.4+ -->
<path id="xslt.classpath">
<fileset dir="${lib.dir}" includes="xalan*.jar"/>
<fileset dir="${lib.dir}" includes="serializer*.jar"/>
</path>

<target name="report" depends="xslt-report,copy-images">
<echo>Report generated at ${report.datestamp}</echo>
</target>

<target name="xslt-report" depends="_message_xalan">
<target name="xslt-report">
<tstamp><format property="report.datestamp" pattern="yyyy/MM/dd HH:mm"/></tstamp>
<xslt
classpathref="xslt.classpath"
force="true"
in="${testpath}/${test}.jtl"
out="${testpath}/${test}.html"
Expand All @@ -141,20 +134,4 @@
</condition>
</target>

<!-- Check that the xalan libraries are present -->
<condition property="xalan.present">
<and>
<!-- No need to check all jars; just check a few -->
<available classpathref="xslt.classpath" classname="org.apache.xalan.processor.TransformerFactoryImpl"/>
<available classpathref="xslt.classpath" classname="org.apache.xml.serializer.ExtendedContentHandler"/>
</and>
</condition>

<target name="_message_xalan" unless="xalan.present">
<echo>Cannot find all xalan and/or serialiser jars</echo>
<echo>The XSLT formatting may not work correctly.</echo>
<echo>Check you have xalan and serializer jars in ${lib.dir}</echo>
</target>


</project>
1 change: 0 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ spock-core.version=2.1-groovy-3.0
springframework.version=4.3.17.RELEASE
svgSalamander.version=1.1.2.4
tika.version=1.28.3
xalan.version=2.7.2
xercesImpl.version=2.12.2
xml-apis.version=1.4.01
xmlgraphics-commons.version=2.7
Expand Down
12 changes: 1 addition & 11 deletions lib/aareadme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,6 @@ rsyntaxtextarea-3.0.4
http://fifesoft.com/rsyntaxtextarea/
- syntax coloration

serialiser-2.7.1
----------------
http://www.apache.org/dyn/closer.cgi/xml/xalan-j
- xalan

slf4j-api-1.7.28
----------------
http://www.slf4j.org/
Expand All @@ -258,7 +253,7 @@ commons-dbcp2-2.5.0 (org.apache.commons.dbcp2)
--------------------------
- DataSourceElement (JDBC)

Saxon-HE-9.9.1-5 (net.sf.saxon)
Saxon-HE-11.3 (net.sf.saxon)
--------------------------
- XPath2Extractor (XML)

Expand All @@ -267,11 +262,6 @@ velocity-1.7
http://velocity.apache.org/download.cgi
- Anakia (create documentation) Not used by JMeter runtime

xalan_2.7.1
-----------
http://www.apache.org/dyn/closer.cgi/xml/xalan-j
+org.apache.xalan|xml|xpath

xercesImpl-2.12.0
----------------
http://xerces.apache.org/xerces2-j/download.cgi
Expand Down
2 changes: 0 additions & 2 deletions src/bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ dependencies {
apiv("org.slf4j:slf4j-api", "slf4j")
apiv("org.spockframework:spock-core")
apiv("oro:oro")
apiv("xalan:serializer", "xalan")
apiv("xalan:xalan", "xalan")
apiv("xerces:xercesImpl")
apiv("xml-apis:xml-apis")
apiv("xmlpull:xmlpull")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.transform.TransformerException;

import org.apache.jmeter.assertions.AssertionResult;
import org.apache.jmeter.processor.PostProcessor;
Expand Down Expand Up @@ -223,7 +224,7 @@ public void setFragment(boolean selected) {
* @throws FactoryConfigurationError
*/
private void getValuesForXPath(String query, List<String> matchStrings, int matchNumber, String responseData)
throws SaxonApiException, FactoryConfigurationError {
throws SaxonApiException, TransformerException, FactoryConfigurationError {
XPathUtil.putValuesForXPathInListUsingSaxon(responseData, query, matchStrings, getFragment(), matchNumber, getNamespaces());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ public void testAssertionNumber() throws Exception {
testLog.debug("isError() {} isFailure() {}", res.isError(), res.isFailure());
testLog.debug("failure message: {}", res.getFailureMessage());
assertFalse("Should not be an error", res.isError());
assertTrue("Should be a failure",res.isFailure());
//this used to result in isFailure()=true but is now fixed (after switching from Xalan to Saxon for XPath support)
assertFalse("Should not be a failure", res.isFailure());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jmeter.util.XPathUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -195,7 +196,7 @@ public void testVariableExtraction() throws Exception {
// No text, but using fragment mode
extractor.setXPathQuery("//a");
extractor.process();
assertEquals("<a><b/></a>", vars.get(VAL_NAME));
assertEquals(XPathUtil.formatXml("<a><b/></a>"), XPathUtil.formatXml(vars.get(VAL_NAME)));
}

@Test
Expand Down Expand Up @@ -283,7 +284,7 @@ public void testInvalidXpath() throws Exception {
if (Locale.getDefault().getLanguage().startsWith(Locale.ENGLISH.getLanguage())) {
assertThat(
firstResult.getFailureMessage(),
containsString("A location path was expected, but the following token was encountered")
containsString("Unexpected token \"<\" at start of expression")
);
}
assertEquals("Default", vars.get(VAL_NAME));
Expand Down
5 changes: 0 additions & 5 deletions src/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ dependencies {
api("oro:oro") {
because("Perl5Matcher org.apache.jmeter.util.JMeterUtils.getMatcher()")
}
api("xalan:xalan") {
because("PropertiesBasedPrefixResolver extends PrefixResolverDefault")
}
// Note: Saxon should go AFTER xalan so xalan XSLT is used
// org.apache.jmeter.util.XPathUtilTest.testFormatXmlSimple assumes xalan transformer
api("net.sf.saxon:Saxon-HE") {
because("XPathUtil: throws SaxonApiException")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* 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.util;

import javax.xml.XMLConstants;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
* This class implements a generic PrefixResolver that
* can be used to perform prefix-to-namespace lookup
* for the XPath object.
*/
public class PrefixResolverDefault
{

/**
* The context to resolve the prefix from, if the context
* is not given.
*/
Node m_context;

/**
* Construct a PrefixResolverDefault object.
* @param xpathExpressionContext The context from
* which XPath expression prefixes will be resolved.
* Warning: This will not work correctly if xpathExpressionContext
* is an attribute node.
*/
public PrefixResolverDefault(Node xpathExpressionContext)
{
m_context = xpathExpressionContext;
}

/**
* Given a namespace, get the corrisponding prefix. This assumes that
* the PrevixResolver hold's it's own namespace context, or is a namespace
* context itself.
* @param prefix Prefix to resolve.
* @return Namespace that prefix resolves to, or null if prefix
* is not bound.
*/
public String getNamespaceForPrefix(String prefix)
{
return getNamespaceForPrefix(prefix, m_context);
}

/**
* Given a namespace, get the corrisponding prefix.
* Warning: This will not work correctly if namespaceContext
* is an attribute node.
* @param prefix Prefix to resolve.
* @param namespaceContext Node from which to start searching for a
* xmlns attribute that binds a prefix to a namespace.
* @return Namespace that prefix resolves to, or null if prefix
* is not bound.
*/
public String getNamespaceForPrefix(String prefix,
org.w3c.dom.Node namespaceContext)
{

Node parent = namespaceContext;
String namespace = null;

if (prefix.equals("xml"))
{
namespace = XMLConstants.XML_NS_URI;
}
else
{
int type;

while ((null != parent) && (null == namespace)
&& (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
|| (type == Node.ENTITY_REFERENCE_NODE)))
{
if (type == Node.ELEMENT_NODE)
{
if (parent.getNodeName().indexOf(prefix+":") == 0)
{
return parent.getNamespaceURI();
}
NamedNodeMap nnm = parent.getAttributes();

for (int i = 0; i < nnm.getLength(); i++)
{
Node attr = nnm.item(i);
String aname = attr.getNodeName();
boolean isPrefix = aname.startsWith("xmlns:");

if (isPrefix || aname.equals("xmlns"))
{
int index = aname.indexOf(':');
String p = isPrefix ? aname.substring(index + 1) : "";

if (p.equals(prefix))
{
namespace = attr.getNodeValue();

break;
}
}
}
}

parent = parent.getParentNode();
}
}

return namespace;
}

/**
* Return the base identifier.
*
* @return null by default
*/
public String getBaseIdentifier()
{
return null;
}

/**
* @return false by default
*/
public boolean handlesNullPrefixes() {
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,22 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.xml.namespace.NamespaceContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.PrefixResolverDefault;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;

/**
* {@link PrefixResolver} implementation that loads prefix configuration from jmeter property xpath.namespace.config
* PrefixResolver implementation that loads prefix configuration from jmeter property xpath.namespace.config
*/
public class PropertiesBasedPrefixResolver extends PrefixResolverDefault {
public class PropertiesBasedPrefixResolver extends PrefixResolverDefault implements NamespaceContext {
private static final Logger log = LoggerFactory.getLogger(PropertiesBasedPrefixResolver.class);
private static final String XPATH_NAMESPACE_CONFIG = "xpath.namespace.config";
private static final Map<String, String> NAMESPACE_MAP = new HashMap<>();
Expand Down Expand Up @@ -85,11 +86,44 @@ public PropertiesBasedPrefixResolver(Node xpathExpressionContext) {
*/
@Override
public String getNamespaceForPrefix(String prefix, Node namespaceContext) {
String namespace = NAMESPACE_MAP.get(prefix);
String namespace = getNamespaceURI(prefix);
if(namespace==null) {
return super.getNamespaceForPrefix(prefix, namespaceContext);
} else {
return namespace;
}
}

@Override
public String getNamespaceURI(String prefix) {
return NAMESPACE_MAP.get(prefix);
}

@Override
public String getPrefix(String namespaceURI) {
if (namespaceURI != null) {
for (Map.Entry<String, String> entry : NAMESPACE_MAP.entrySet()) {
if (namespaceURI.equals(entry.getValue())) {
return entry.getValue();
}
}
}
return null;
}

@Override
public Iterator<String> getPrefixes(String namespaceURI) {
return NAMESPACE_MAP.keySet().iterator();
}

String getNamespacesAsLineDelimitedProperties() {
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> entry : NAMESPACE_MAP.entrySet()) {
builder.append(entry.getKey())
.append('=')
.append(entry.getValue())
.append('\n');
}
return builder.toString();
}
}
Loading