You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by dm...@apache.org on 2003/05/05 01:53:19 UTC
cvs commit: jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes DescendantContext.java
dmitri 2003/05/04 16:53:19
Modified: jxpath/src/test/org/apache/commons/jxpath
JXPathTestSuite.java
jxpath/src/java/org/apache/commons/jxpath/ri/axes
DescendantContext.java
Added: jxpath/src/test/org/apache/commons/jxpath/ri/axes
RecursiveBean.java RecursiveAxesTest.java
Log:
Added prevention of infinite loop on descent into recursive graphs
Revision Changes Path
1.1 jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/axes/RecursiveBean.java
Index: RecursiveBean.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/axes/RecursiveBean.java,v 1.1 2003/05/04 23:53:19 dmitri Exp $
* $Revision: 1.1 $
* $Date: 2003/05/04 23:53:19 $
*
* ====================================================================
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Plotnix, Inc,
* <http://www.plotnix.com/>.
* For more information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.jxpath.ri.axes;
/**
* This bean is used to test infinite recursion protection in
* descendant search contexts.
*
* @author Dmitri Plotnikov
* @version $Revision: 1.1 $ $Date: 2003/05/04 23:53:19 $
*/
public class RecursiveBean {
private String name;
private RecursiveBean first;
private RecursiveBean second;
public RecursiveBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public RecursiveBean getFirst() {
return first;
}
public void setFirst(RecursiveBean bean) {
this.first = bean;
}
public RecursiveBean getSecond() {
return second;
}
public void setSecond(RecursiveBean bean) {
second = bean;
}
public String toString() {
return name;
}
}
1.1 jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/axes/RecursiveAxesTest.java
Index: RecursiveAxesTest.java
===================================================================
package org.apache.commons.jxpath.ri.axes;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathTestCase;
/**
* Test for the protection mechanism that stops infinite recursion
* in descent down a recursive graph.
*/
public class RecursiveAxesTest extends JXPathTestCase {
private RecursiveBean bean;
private JXPathContext context;
public RecursiveAxesTest(String name) {
super(name);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(RecursiveAxesTest.class);
}
/**
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
bean = new RecursiveBean("zero");
RecursiveBean bean1 = new RecursiveBean("one");
RecursiveBean bean2 = new RecursiveBean("two");
RecursiveBean bean3 = new RecursiveBean("three");
bean.setFirst(bean1);
bean1.setFirst(bean2);
bean2.setFirst(bean1);
bean2.setSecond(bean3);
context = JXPathContext.newContext(null, bean);
}
public void testInfiniteDescent() {
// Existing scalar property
assertXPathPointer(
context,
"//.[name = 'three']",
"/first/first/second");
}
}
1.4 +6 -4 jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/JXPathTestSuite.java
Index: JXPathTestSuite.java
===================================================================
RCS file: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/JXPathTestSuite.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- JXPathTestSuite.java 20 Jan 2003 00:00:26 -0000 1.3
+++ JXPathTestSuite.java 4 May 2003 23:53:19 -0000 1.4
@@ -68,6 +68,7 @@
import junit.textui.TestRunner;
import org.apache.commons.jxpath.ri.JXPathCompiledExpressionTest;
+import org.apache.commons.jxpath.ri.axes.RecursiveAxesTest;
import org.apache.commons.jxpath.ri.axes.SimplePathInterpreterTest;
import org.apache.commons.jxpath.ri.compiler.ContextDependencyTest;
import org.apache.commons.jxpath.ri.compiler.CoreFunctionTest;
@@ -132,6 +133,7 @@
suite.addTestSuite(JDOMModelTest.class);
suite.addTestSuite(MixedModelTest.class);
suite.addTestSuite(BasicTypeConverterTest.class);
+ suite.addTestSuite(RecursiveAxesTest.class);
return suite;
}
}
1.13 +34 -15 jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/DescendantContext.java
Index: DescendantContext.java
===================================================================
RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/DescendantContext.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- DescendantContext.java 11 Mar 2003 00:59:20 -0000 1.12
+++ DescendantContext.java 4 May 2003 23:53:19 -0000 1.13
@@ -63,6 +63,7 @@
import java.util.Stack;
+import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.Compiler;
import org.apache.commons.jxpath.ri.EvalContext;
import org.apache.commons.jxpath.ri.compiler.NodeTest;
@@ -85,7 +86,7 @@
private boolean includeSelf;
private static final NodeTest ELEMENT_NODE_TEST =
new NodeTypeTest(Compiler.NODE_TYPE_NODE);
-
+
public DescendantContext(
EvalContext parentContext,
boolean includeSelf,
@@ -149,22 +150,40 @@
NodeIterator it = (NodeIterator) stack.peek();
if (it.setPosition(it.getPosition() + 1)) {
currentNodePointer = it.getNodePointer();
- if (!currentNodePointer.isLeaf()) {
- stack.push(
- currentNodePointer.childIterator(
- ELEMENT_NODE_TEST,
- false,
- null));
- }
- if (currentNodePointer.testNode(nodeTest)) {
- position++;
- return true;
+ if (!isRecursive()) {
+ if (!currentNodePointer.isLeaf()) {
+ stack.push(
+ currentNodePointer.childIterator(
+ ELEMENT_NODE_TEST,
+ false,
+ null));
+ }
+ if (currentNodePointer.testNode(nodeTest)) {
+ position++;
+ return true;
+ }
}
}
else {
// We get here only if the name test failed
// and the iterator ended
stack.pop();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if we are reentering a bean we have already seen and if so
+ * returns true to prevent infinite recursion.
+ */
+ private boolean isRecursive() {
+ Object node = currentNodePointer.getNode();
+ for (int i = stack.size() - 1; --i >= 0;) {
+ NodeIterator it = (NodeIterator) stack.get(i);
+ Pointer pointer = it.getNodePointer();
+ if (pointer != null && pointer.getNode() == node) {
+ return true;
}
}
return false;
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org