From 94e0a434e9906732f088ac6fdaa8b733359be16a Mon Sep 17 00:00:00 2001 From: cramakri <cramakri> Date: Tue, 9 Nov 2010 09:17:54 +0000 Subject: [PATCH] LMS-1767 Added control of whether escaping is shallow or deep. SVN: 18592 --- .../utilities/ReflectingStringEscaper.java | 29 ++++++++++----- .../utilities/ReflectionStringTraverser.java | 31 +++++++++++++--- .../ReflectingStringEscaperTest.java | 37 ++++++++++++++++++- ...ReflectionPrimitiveFieldTraverserTest.java | 2 +- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaper.java b/common/source/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaper.java index d25dc58c2d5..30c2635cf53 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaper.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaper.java @@ -30,13 +30,22 @@ import org.apache.commons.lang.StringEscapeUtils; */ public class ReflectingStringEscaper<T> { - public static <T> T escape(T bean, String... escapedProperties) + public static <T> T escapeShallow(T bean, String... escapedProperties) { ReflectingStringEscaper<T> escaper = - new ReflectingStringEscaper<T>(bean, escapedProperties); + new ReflectingStringEscaper<T>(false, bean, escapedProperties); return escaper.escape(); } + public static <T> T escapeDeep(T bean, String... escapedProperties) + { + ReflectingStringEscaper<T> escaper = + new ReflectingStringEscaper<T>(true, bean, escapedProperties); + return escaper.escape(); + } + + private final boolean isDeep; + private final T bean; private final HashSet<String> escapedProperties; @@ -46,11 +55,6 @@ public class ReflectingStringEscaper<T> public String tryVisit(String value, Object object, Field fieldOrNull) { - // Only change the value on the top-level object - if (object != bean) - { - return null; - } // Only change the value if the name of the field is in the list provided if (null == fieldOrNull) { @@ -62,8 +66,9 @@ public class ReflectingStringEscaper<T> } } - private ReflectingStringEscaper(T bean, String... escapedProperties) + private ReflectingStringEscaper(boolean isDeep, T bean, String... escapedProperties) { + this.isDeep = isDeep; this.bean = bean; this.escapedProperties = new HashSet<String>(); Collections.addAll(this.escapedProperties, escapedProperties); @@ -71,7 +76,13 @@ public class ReflectingStringEscaper<T> private T escape() { - ReflectionStringTraverser.traverse(bean, new Visitor()); + if (isDeep) + { + ReflectionStringTraverser.traverseDeep(bean, new Visitor()); + } else + { + ReflectionStringTraverser.traverseShallow(bean, new Visitor()); + } return bean; } } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ReflectionStringTraverser.java b/common/source/java/ch/systemsx/cisd/common/utilities/ReflectionStringTraverser.java index 2ee03464e4b..5586e624645 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/ReflectionStringTraverser.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ReflectionStringTraverser.java @@ -26,8 +26,9 @@ import java.util.List; import java.util.Set; /** - * Allows to change all non-final and non-static strings referenced within the specified object. - * Traverses the object recursively. Handles lists and sets of strings. + * Allows to change all non-final and non-static strings referenced within the specified object. If + * isDeep is true, traverses the object recursively; otherwise, performs a shallow traversal. + * Handles lists and sets of strings. * * @author Tomasz Pylak */ @@ -45,12 +46,19 @@ public class ReflectionStringTraverser } /** cannot be called for primitive types or collections */ - public static void traverse(Object object, ReflectionFieldVisitor fieldVisitor) + public static void traverseDeep(Object object, ReflectionFieldVisitor fieldVisitor) { Class<?> clazz = object.getClass(); new ReflectionStringTraverser(fieldVisitor).traverseMutable(object, clazz); } + /** cannot be called for primitive types or collections */ + public static void traverseShallow(Object object, ReflectionFieldVisitor fieldVisitor) + { + Class<?> clazz = object.getClass(); + new ReflectionStringTraverser(fieldVisitor, false).traverseMutable(object, clazz); + } + // mutable classes are arrays and classes which are not primitives or collections of primitive // types private void traverseMutable(Object object, Class<?> clazz) @@ -71,9 +79,17 @@ public class ReflectionStringTraverser private final ReflectionFieldVisitor visitor; + private final boolean isDeep; + private ReflectionStringTraverser(ReflectionFieldVisitor fieldVisitor) + { + this(fieldVisitor, true); + } + + private ReflectionStringTraverser(ReflectionFieldVisitor fieldVisitor, boolean isDeep) { this.visitor = fieldVisitor; + this.isDeep = isDeep; } /** @@ -118,10 +134,10 @@ public class ReflectionStringTraverser } Class<?> clazz = fieldValue.getClass(); - if (clazz.isArray()) + if (clazz.isArray() && isDeep) { traverseArray(fieldValue); - } else if (isCollection(fieldValue)) + } else if (isCollection(fieldValue) && isDeep) { traverseCollectionField(object, field, (Collection<?>) fieldValue); } else if (clazz.isPrimitive()) @@ -136,7 +152,10 @@ public class ReflectionStringTraverser } } else { - traverseFields(fieldValue, clazz); + if (isDeep) + { + traverseFields(fieldValue, clazz); + } } } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaperTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaperTest.java index 42ff65c08c5..03a6b0c4273 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaperTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectingStringEscaperTest.java @@ -31,20 +31,53 @@ public class ReflectingStringEscaperTest extends AssertJUnit private String bar; private String baz; + + private TestBean wrappedBean; + } + + @Test + public void testShallowEscaper() + { + TestBean bean = new TestBean(); + bean.foo = "<a>foo</a>"; + bean.bar = "<b>bar</b>"; + bean.baz = "<i>baz</i>"; + bean.wrappedBean = new TestBean(); + bean.wrappedBean.foo = "<a>foo</a>"; + bean.wrappedBean.bar = "<b>bar</b>"; + bean.wrappedBean.baz = "<i>baz</i>"; + + TestBean escaped = ReflectingStringEscaper.escapeShallow(bean, "foo", "baz"); + assertEquals(bean, escaped); + assertEquals("<a>foo</a>", bean.foo); + assertEquals("<b>bar</b>", bean.bar); + assertEquals("<i>baz</i>", bean.baz); + + assertEquals("<a>foo</a>", bean.wrappedBean.foo); + assertEquals("<b>bar</b>", bean.wrappedBean.bar); + assertEquals("<i>baz</i>", bean.wrappedBean.baz); } @Test - public void testEscaper() + public void testDeepEscaper() { TestBean bean = new TestBean(); bean.foo = "<a>foo</a>"; bean.bar = "<b>bar</b>"; bean.baz = "<i>baz</i>"; + bean.wrappedBean = new TestBean(); + bean.wrappedBean.foo = "<a>foo</a>"; + bean.wrappedBean.bar = "<b>bar</b>"; + bean.wrappedBean.baz = "<i>baz</i>"; - TestBean escaped = ReflectingStringEscaper.escape(bean, "foo", "baz"); + TestBean escaped = ReflectingStringEscaper.escapeDeep(bean, "foo", "baz"); assertEquals(bean, escaped); assertEquals("<a>foo</a>", bean.foo); assertEquals("<b>bar</b>", bean.bar); assertEquals("<i>baz</i>", bean.baz); + + assertEquals("<a>foo</a>", bean.wrappedBean.foo); + assertEquals("<b>bar</b>", bean.wrappedBean.bar); + assertEquals("<i>baz</i>", bean.wrappedBean.baz); } } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectionPrimitiveFieldTraverserTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectionPrimitiveFieldTraverserTest.java index e771a09ee2c..1d87d23c6e6 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectionPrimitiveFieldTraverserTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ReflectionPrimitiveFieldTraverserTest.java @@ -82,7 +82,7 @@ public class ReflectionPrimitiveFieldTraverserTest extends AssertJUnit object.stringArray = new String[] { "stringArray1" }; - ReflectionStringTraverser.traverse(object, new ReflectionStringCapitalizerVisitor()); + ReflectionStringTraverser.traverseDeep(object, new ReflectionStringCapitalizerVisitor()); assertEquals("OBJECT", object.text); -- GitLab