You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2011/11/20 23:11:37 UTC

svn commit: r1204280 - in /jmeter/trunk: src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java src/core/org/apache/jmeter/util/XPathUtil.java xdocs/changes.xml xdocs/usermanual/component_reference.xml

Author: pmouawad
Date: Sun Nov 20 22:11:36 2011
New Revision: 1204280

URL: http://svn.apache.org/viewvc?rev=1204280&view=rev
Log:
Bug 43294 - XPath Extractor namespace problems

Added:
    jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java   (with props)
Modified:
    jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml

Added: jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java?rev=1204280&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java Sun Nov 20 22:11:36 2011
@@ -0,0 +1,99 @@
+/*
+ * 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 java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.util.JOrphanUtils;
+import org.apache.log.Logger;
+import org.apache.xml.utils.PrefixResolver;
+import org.apache.xml.utils.PrefixResolverDefault;
+import org.w3c.dom.Node;
+
+/**
+ * {@link PrefixResolver} implementation that loads prefix configuration from jmeter property xpath.namespace.config
+ */
+public class PropertiesBasedPrefixResolver extends PrefixResolverDefault {
+	private static final Logger logger = LoggingManager.getLoggerForClass();
+	private static final String XPATH_NAMESPACE_CONFIG = "xpath.namespace.config";
+	private static final Map<String, String> NAMESPACE_MAP = new HashMap<String, String>();
+	static {
+		String pathToNamespaceConfig = JMeterUtils.getPropDefault(XPATH_NAMESPACE_CONFIG, "");
+		if(!StringUtils.isEmpty(pathToNamespaceConfig)) {
+			Properties properties = new Properties();
+			InputStream inputStream = null;
+			try {
+				File pathToNamespaceConfigFile = JMeterUtils.findFile(pathToNamespaceConfig);
+				if(!pathToNamespaceConfigFile.exists()) {
+					logger.error("Cannot find configured file:'"+
+							pathToNamespaceConfig+"' in property:'"+XPATH_NAMESPACE_CONFIG+"', file does not exist");
+				} else { 
+					if(!pathToNamespaceConfigFile.canRead()) {
+						logger.error("Cannot read configured file:'"+
+								pathToNamespaceConfig+"' in property:'"+XPATH_NAMESPACE_CONFIG+"'");
+					} else {
+						inputStream = new BufferedInputStream(new FileInputStream(pathToNamespaceConfigFile));
+						properties.load(inputStream);
+						properties.entrySet();
+						for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+							NAMESPACE_MAP.put((String) entry.getKey(), (String) entry.getValue());					
+						}
+						logger.info("Read following XPath namespace configuration "+ 
+								NAMESPACE_MAP);
+					}
+				}
+			} catch(IOException e) {
+				logger.error("Error loading namespaces from file:'"+
+						pathToNamespaceConfig+"', message:"+e.getMessage(),e);
+			} finally {
+				JOrphanUtils.closeQuietly(inputStream);
+			}
+		}
+	}
+	/**
+	 * @param xpathExpressionContext Node
+	 */
+	public PropertiesBasedPrefixResolver(Node xpathExpressionContext) {
+		super(xpathExpressionContext);
+	}
+
+	/**
+	 * Searches prefix in NAMESPACE_MAP, if it fails to find it defaults to parent implementation
+	 * @param prefix Prefix
+	 * @param namespaceContext Node
+	 */
+	@Override
+	public String getNamespaceForPrefix(String prefix, Node namespaceContext) {
+		String namespace = NAMESPACE_MAP.get(prefix);
+		if(namespace==null) {
+			return super.getNamespaceForPrefix(prefix, namespaceContext);
+		} else {
+			return namespace;
+		}
+	}
+}
\ No newline at end of file

Propchange: jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolver.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java?rev=1204280&r1=1204279&r2=1204280&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java Sun Nov 20 22:11:36 2011
@@ -39,6 +39,7 @@ import javax.xml.transform.stream.Stream
 import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
+import org.apache.xml.utils.PrefixResolver;
 import org.apache.xpath.XPathAPI;
 import org.apache.xpath.objects.XObject;
 import org.w3c.dom.Document;
@@ -258,6 +259,23 @@ public class XPathUtil {
             }
         }
     }
+    
+	/**
+	 * Return value for node
+	 * @param node Node
+	 * @return String
+	 */
+	private static String getValueForNode(Node node) {
+        StringWriter sw = new StringWriter();
+        try {
+            Transformer t = TransformerFactory.newInstance().newTransformer();
+            t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            t.transform(new DOMSource(node), new StreamResult(sw));
+        } catch (TransformerException e) {
+            sw.write(e.getMessageAndLocation());
+        }
+        return sw.toString();
+    }
 
     /**
      * Extract NodeList using expression
@@ -267,7 +285,8 @@ public class XPathUtil {
      * @throws TransformerException 
      */
 	public static NodeList selectNodeList(Document document, String xPathExpression) throws TransformerException {
-		return XPathAPI.selectNodeList(document, xPathExpression);
+		XObject xObject = XPathAPI.eval(document, xPathExpression, getPrefixResolver(document));
+		return xObject.nodelist();
 	}
 
 	/**
@@ -282,7 +301,7 @@ public class XPathUtil {
 			String xPathQuery,
 			List<String> matchStrings, boolean fragment) throws TransformerException {
 		String val = null;
-        XObject xObject = XPathAPI.eval(document, xPathQuery);
+        XObject xObject = XPathAPI.eval(document, xPathQuery, getPrefixResolver(document));
         final int objectType = xObject.getType();
         if (objectType == XObject.CLASS_NODESET) {
             NodeList matches = xObject.nodelist();
@@ -315,23 +334,17 @@ public class XPathUtil {
             matchStrings.add(val);
       }
 	}
-	
+
 	/**
-	 * Return value for node
-	 * @param node Node
-	 * @return String
+	 * 
+	 * @param document XML Document
+	 * @return {@link PrefixResolver}
 	 */
-	private static String getValueForNode(Node node) {
-        StringWriter sw = new StringWriter();
-        try {
-            Transformer t = TransformerFactory.newInstance().newTransformer();
-            t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-            t.transform(new DOMSource(node), new StreamResult(sw));
-        } catch (TransformerException e) {
-            sw.write(e.getMessageAndLocation());
-        }
-        return sw.toString();
-    }
+	private static PrefixResolver getPrefixResolver(Document document) {
+		PropertiesBasedPrefixResolver propertiesBasedPrefixResolver =
+				new PropertiesBasedPrefixResolver(document.getDocumentElement());
+		return propertiesBasedPrefixResolver;
+	}
 
 	/**
 	 * Validate xpathString is a valid XPath expression
@@ -340,7 +353,7 @@ public class XPathUtil {
 	 * @throws TransformerException if expression fails to evaluate
 	 */
 	public static void validateXPath(Document document, String xpathString) throws TransformerException {
-		if (XPathAPI.eval(document, xpathString) == null) {
+		if (XPathAPI.eval(document, xpathString, getPrefixResolver(document)) == null) {
             // We really should never get here
             // because eval will throw an exception
             // if xpath is invalid, but whatever, better
@@ -361,7 +374,7 @@ public class XPathUtil {
 			String xPathExpression,
 			boolean isNegated) {
         try {
-            XObject xObject = XPathAPI.eval(doc, xPathExpression);
+            XObject xObject = XPathAPI.eval(doc, xPathExpression, getPrefixResolver(doc));
             switch (xObject.getType()) {
                 case XObject.CLASS_NODESET:
                 	NodeList nodeList = xObject.nodelist();

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1204280&r1=1204279&r2=1204280&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Sun Nov 20 22:11:36 2011
@@ -150,6 +150,7 @@ This behaviour can be changed with prope
 <li>Bug 52215 - Confusing synchronization in StatVisualizer, SummaryReport ,Summariser and issue in StatGraphVisualizer</li>
 <li>Bug 52216 - TableVisualizer : currentData field is badly synchronized</li>
 <li>Bug 52217 - ViewResultsFullVisualizer : Synchronization issues on root and treeModel</li>
+<li>Bug 43294 - XPath Extractor namespace problems</li>
 </ul>
 
 <!-- =================== Improvements =================== -->

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1204280&r1=1204279&r2=1204280&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Sun Nov 20 22:11:36 2011
@@ -3856,6 +3856,20 @@ on XPath.
 <note>
 The non-tolerant parser can be quite slow, as it may need to download the DTD etc.
 </note>
+<note>
+To overcome Xalan XPath parser implementation on which JMeter is based, you can help the parsing by 
+providing a Properties file which will contain:
+<ul>
+<li>prefix1=Full Namespace 1</li>
+<li>prefix2=Full Namespace 2</li>
+<li>...</li>
+</ul>
+
+You reference this file in jmeter.properties file using the property:
+<ul>
+    <li>xpath.namespace.config</li>
+</ul>
+</note>
 </component>
 <component name="XML Schema Assertion" index="&sect-num;.5.9"  width="771" height="171" screenshot="assertion/XMLSchemaAssertion.png">
 <description><p>The XML Schema Assertion allows the user to validate a response against an XML Schema.</p></description>