// $Header$
/*
 * Copyright 2005 The Apache Software Foundation.
 *
 * Licensed 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.functions;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

/**
 * The function represented by this class allows data to be read from XML files.
 * Syntax is similar to the CVSRead function. The function allows the test to
 * line-thru the nodes in the XML file - one node per each test. E.g. inserting
 * the following in the test scripts :
 * 
 * ${_XPath(c:/BOF/abcd.xml,/xpath/)} // match the (first) node of
 * 'c:/BOF/abcd.xml' , return the 1st column ( represented by the '0'),
 * ${_XPath(c:/BOF/abcd.xml,/xpath/)} // read (first) match of '/xpath/'
 * expressions ${_XPath(c:/BOF/abcd.xml,/xpath/)} // Go to next match of
 * '/xpath/' expressions
 * 
 * NOTE: A single instance of each different file is opened and used for all
 * threads.
 * 
 * 
 * 
 */
public class XPath extends AbstractFunction implements Serializable {
	transient private static final Logger log = LoggingManager.getLoggerForClass();

	// static {
	// LoggingManager.setPriority("DEBUG","jmeter");
	// LoggingManager.setTarget(new java.io.PrintWriter(System.out));
	// }
	private static final String KEY = "__XPath"; // Function name

	private static final List desc = new LinkedList();

	private Object[] values; // Parameter list

	static {
		desc.add(JMeterUtils.getResString("xpath_file_file_name"));
		desc.add(JMeterUtils.getResString("xpath_expression"));
	}

	public XPath() {
	}

	public Object clone() {
		XPath newReader = new XPath();
		return newReader;
	}

	/**
	 * @see org.apache.jmeter.functions.Function#execute(SampleResult, Sampler)
	 */
	public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
			throws InvalidVariableException {
		String myValue = "";

		String fileName = ((org.apache.jmeter.engine.util.CompoundVariable) values[0]).execute();
		String xpathString = ((org.apache.jmeter.engine.util.CompoundVariable) values[1]).execute();

		log.debug("execute (" + fileName + " " + xpathString + ")   ");

		try {
			myValue = XPathWrapper.getXPathString(fileName, xpathString);
		} catch (NumberFormatException e) {
			log.warn(Thread.currentThread().getName() + " - can't parse column number: " + " " + e.toString());
		} catch (IndexOutOfBoundsException e) {
			log.warn(Thread.currentThread().getName() + " - invalid column number:  at row "
					+ XPathWrapper.getCurrentRow(fileName) + " " + e.toString());
		}

		log.debug("execute value: " + myValue);

		return myValue;
	}

	/**
	 * @see org.apache.jmeter.functions.Function#getArgumentDesc()
	 */
	public List getArgumentDesc() {
		return desc;
	}

	/**
	 * @see org.apache.jmeter.functions.Function#getReferenceKey()
	 */
	public String getReferenceKey() {
		return KEY;
	}

	/**
	 * @see org.apache.jmeter.functions.Function#setParameters(Collection)
	 */
	public void setParameters(Collection parameters) throws InvalidVariableException {
		log.debug("setParameter - Collection.size=" + parameters.size());

		values = parameters.toArray();

		if (log.isDebugEnabled()) {
			for (int i = 0; i < parameters.size(); i++) {
				log.debug("i:" + ((CompoundVariable) values[i]).execute());
			}
		}

		if (values.length != 2) {
			throw new InvalidVariableException("Wrong number of parameters; 2 != " + values.length);
		}

		/*
		 * Need to reset the containers for repeated runs; about the only way
		 * for functions to detect that a run is starting seems to be the
		 * setParameters() call.
		 */
		XPathWrapper.clearAll();// TODO only clear the relevant entry - if
								// possible...

	}
}
@@ -1,16 +1,4 @@
-// $Header$%0A
 /*%0A 
@@ -16,9 +16,9 @@
  200
-5
+6
  The
@@ -1030,16 +1030,86 @@
 ogger;%0A%0A
+// @see org.apache.jmeter.functions.TestXPathFunction for unit tests%0A%0A
 /**%0A * T
@@ -1453,171 +1453,11 @@
 node
- of%0A * 'c:/BOF/abcd.xml' , return the 1st column ( represented by the '0'),%0A * $%7B_XPath(c:/BOF/abcd.xml,/xpath/)%7D // read (first) match of '/xpath/'%0A * expressions
+%0A *
  $%7B_
@@ -1510,19 +1510,16 @@
 match of
-%0A *
  '/xpath
@@ -1531,17 +1531,16 @@
 pression
-s
 %0A * %0A * 
@@ -1585,16 +1585,42 @@
 ent file
+/expression combination%0A *
  is open
@@ -1638,19 +1638,16 @@
  for all
-%0A *
  threads
@@ -1652,24 +1652,16 @@
 ds.%0A * %0A
- * %0A * %0A
  */%0Apubl
@@ -2769,16 +2769,55 @@
 ute();%0A%0A
+        if (log.isDebugEnabled())%7B%0A    
 %09%09log.de
@@ -2878,18 +2878,19 @@
 %22);%0A
-%0A%09%09try %7B%0A%09
+        %7D%0A%0A
 %09%09my
@@ -2953,347 +2953,48 @@
 g);%0A
-%09%09%7D catch (NumberFormatException e) %7B%0A%09%09%09log.warn(Thread.currentThread().getName() + %22 - can't parse column number: %22 + %22 %22 + e.toString());%0A%09%09%7D catch (IndexOutOfBoundsException e) %7B%0A%09%09%09log.warn(Thread.currentThread().getName() + %22 - invalid column number:  at row %22%0A%09%09%09%09%09+ XPathWrapper.getCurrentRow(fileName) + %22 %22 + e.toString());%0A%09%09%7D%0A%0A
+%0A        if (log.isDebugEnabled())%7B%0A    
 %09%09lo
@@ -3030,16 +3030,26 @@
 yValue);
+%0A        %7D
 %0A%0A%09%09retu

Remove redundant code; update Javadoc