[java-metadata-aggregator] branch master updated: MDA-52 - Add ElementsStrippingStage
Ian Young
ian at iay.org.uk
Mon Jul 31 13:21:19 EDT 2017
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch master
in repository java-metadata-aggregator.
View the commit online:
http://git.shibboleth.net/view/?p=java-metadata-aggregator.git;a=commit;h=ba2062ab086dae03d4f9157aec0020a9196a9691
The following commit(s) were added to refs/heads/master by this push:
new ba2062a MDA-52 - Add ElementsStrippingStage
ba2062a is described below
commit ba2062ab086dae03d4f9157aec0020a9196a9691
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Mon Jul 31 18:21:10 2017 +0100
MDA-52 - Add ElementsStrippingStage
---
.../metadata/dom/AbstractDOMTraversalStage.java | 11 +-
.../metadata/dom/ElementsStrippingStage.java | 168 +++++++++++++++++++++
.../resources/net/shibboleth/metadata/beans.xml | 3 +
.../metadata/dom/ElementsStrippingStageTest.java | 125 +++++++++++++++
.../dom/ElementsStrippingStage-in-multi.xml | 11 ++
.../metadata/dom/ElementsStrippingStage-in-sb.xml | 16 ++
.../metadata/dom/ElementsStrippingStage-in-sw.xml | 16 ++
.../dom/ElementsStrippingStage-out-multi-b.xml | 11 ++
.../dom/ElementsStrippingStage-out-multi-w.xml | 11 ++
.../metadata/dom/ElementsStrippingStage-out-sb.xml | 12 ++
.../metadata/dom/ElementsStrippingStage-out-sw.xml | 13 ++
11 files changed, 396 insertions(+), 1 deletion(-)
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/AbstractDOMTraversalStage.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/AbstractDOMTraversalStage.java
index 2d8b628..e4cd818 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/AbstractDOMTraversalStage.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/AbstractDOMTraversalStage.java
@@ -47,7 +47,7 @@ public abstract class AbstractDOMTraversalStage extends AbstractIteratingStage<E
private final Item<Element> item;
/** Map of data for this traversal. */
- private final ClassToInstanceMultiMap<Object> stash = new ClassToInstanceMultiMap<>();
+ private final ClassToInstanceMultiMap<Object> stash = new ClassToInstanceMultiMap<>(true);
/**
* Constructor.
@@ -123,6 +123,7 @@ public abstract class AbstractDOMTraversalStage extends AbstractIteratingStage<E
final Element docElement = item.unwrap();
final TraversalContext context = new TraversalContext(item);
traverse(docElement, context);
+ endTraversal(context);
}
/**
@@ -173,4 +174,12 @@ public abstract class AbstractDOMTraversalStage extends AbstractIteratingStage<E
metadata.put(new ErrorStatus(getId(), prefix + error));
}
+ /**
+ * This method is called once the traversal has finished. It may be overridden by subclasses.
+ *
+ * @param context the context for which the traversal has finished
+ */
+ protected void endTraversal(@Nonnull final TraversalContext context) {
+ }
+
}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/ElementsStrippingStage.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/ElementsStrippingStage.java
new file mode 100644
index 0000000..9706f87
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/ElementsStrippingStage.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.metadata.dom;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * A stage which removes all instances of the specified elements from DOM metadata.
+ *
+ * The elements to be removed are specified by the combination of a namespace
+ * (as in {@link ElementStrippingStage}) and a collection of names.
+ *
+ * The stage ignores all elements not in the specified namespace.
+ *
+ * If an element is in the specified namespace, it is by default removed if its
+ * local name is in the specified list of names. In other words, the list of names acts
+ * by default as a blacklist of element names.
+ *
+ * The default behaviour can be changed if the <code>whitelisting</code> property
+ * is set. In this case, the stage still ignores any elements not in the specified
+ * namespace, but elements within that namespace will be removed if their local names
+ * do <i>not</i> appear in the collection of names.
+ */
+ at ThreadSafe
+public class ElementsStrippingStage extends AbstractDOMTraversalStage {
+
+ /** Namespace of the elements to strip. */
+ private String elementNamespace;
+
+ /** Names of the elements to strip. */
+ private Set<String> elementNames = new HashSet<>();
+
+ /** Whether we are operating in a whitelisting mode (<code>false</code> by default). */
+ private boolean whitelisting;
+
+ /**
+ * Get the namespace of the elements to strip.
+ *
+ * @return namespace of the elements to strip
+ */
+ @Nullable public String getElementNamespace() {
+ return elementNamespace;
+ }
+
+ /**
+ * Set the namespace of the elements to strip.
+ *
+ * @param namespace namespace of the elements to strip
+ */
+ public void setElementNamespace(@Nonnull @NotEmpty final String namespace) {
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ elementNamespace = Constraint.isNotNull(StringSupport.trimOrNull(namespace),
+ "target namespace can not be null or empty");
+ }
+
+ /**
+ * Get the names of the elements to strip.
+ *
+ * @return the names of the elements to strip
+ */
+ @Nullable public Collection<String> getElementNames() {
+ return elementNames;
+ }
+
+ /**
+ * Set the names of the elements to strip.
+ *
+ * @param names the names of the elements to strip
+ */
+ public void setElementNames(@Nonnull @NotEmpty final Collection<String> names) {
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ elementNames = new HashSet<String>(names);
+ }
+
+ /**
+ * Set whether the {@link #names} are to be used as a whitelist.
+ *
+ * The default behaviour is for the names to be used as a blacklist.
+ *
+ * @param whitelist <code>true</code> if the names are to be used as a whitelist
+ */
+ public void setWhitelisting(final boolean whitelist) {
+ whitelisting = whitelist;
+ }
+
+ /**
+ * Indicates whether the {@link #names} are being used as a whitelist.
+ *
+ * @return <code>true</code> if the names are being used as a whitelist
+ */
+ public boolean isWhitelisting() {
+ return whitelisting;
+ }
+
+ @Override
+ protected boolean applicable(@Nonnull final Element element) {
+ // ignore all elements not in the given namespace
+ if (!elementNamespace.equals(element.getNamespaceURI())) {
+ return false;
+ }
+
+ // Whitelisting reverses the meaning of presence in the list
+ return whitelisting ^ elementNames.contains(element.getLocalName());
+ }
+
+ @Override
+ protected void visit(@Nonnull final Element element,
+ @Nonnull final TraversalContext context) {
+ context.getStash().put(element);
+ }
+
+ @Override
+ protected void endTraversal(@Nonnull final TraversalContext context) {
+ for (final Element element : context.getStash().get(Element.class)) {
+ element.getParentNode().removeChild(element);
+ }
+ }
+
+ @Override
+ protected void doDestroy() {
+ elementNamespace = null;
+ elementNames = null;
+
+ super.doDestroy();
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+ if (elementNamespace == null) {
+ throw new ComponentInitializationException("target namespace can not be null or empty");
+ }
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/resources/net/shibboleth/metadata/beans.xml b/aggregator-pipeline/src/main/resources/net/shibboleth/metadata/beans.xml
index e3d54e7..fe457f6 100644
--- a/aggregator-pipeline/src/main/resources/net/shibboleth/metadata/beans.xml
+++ b/aggregator-pipeline/src/main/resources/net/shibboleth/metadata/beans.xml
@@ -64,6 +64,9 @@
<bean id="mda.ElementStrippingStage" abstract="true" parent="mda.stage_parent"
class="net.shibboleth.metadata.dom.ElementStrippingStage"/>
+ <bean id="mda.ElementsStrippingStage" abstract="true" parent="mda.stage_parent"
+ class="net.shibboleth.metadata.dom.ElementsStrippingStage"/>
+
<bean id="mda.ElementWhitespaceTrimmingStage" abstract="true" parent="mda.stage_parent"
class="net.shibboleth.metadata.dom.ElementWhitespaceTrimmingStage"/>
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/ElementsStrippingStageTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/ElementsStrippingStageTest.java
new file mode 100644
index 0000000..b7d5c34
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/ElementsStrippingStageTest.java
@@ -0,0 +1,125 @@
+package net.shibboleth.metadata.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.shibboleth.metadata.Item;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Element;
+
+public class ElementsStrippingStageTest extends BaseDOMTest {
+
+ /** Constructor sets class under test. */
+ public ElementsStrippingStageTest() {
+ super(ElementsStrippingStage.class);
+ }
+
+ @Test
+ public void emptyNamesList() throws Exception {
+ final Element doc = readXMLData("in-sb.xml");
+ final Item<Element> item = new DOMElementItem(doc);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ final ElementsStrippingStage stage = new ElementsStrippingStage();
+ stage.setId("stripTest");
+ stage.setElementNamespace("urn:namespace:beta");
+ stage.initialize();
+
+ stage.execute(items);
+
+ // nothing should have changed; compare with original
+ final Element out = readXMLData("in-sb.xml");
+ assertXMLIdentical(out, item.unwrap());
+ }
+
+ // Equivalent to the test for ElementStrippingStage
+ @Test
+ public void singleElementBlacklist() throws Exception {
+ final Element doc = readXMLData("in-sb.xml");
+ final Item<Element> item = new DOMElementItem(doc);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ final ElementsStrippingStage stage = new ElementsStrippingStage();
+ stage.setId("stripTest");
+ stage.setElementNamespace("urn:namespace:beta");
+ final List<String> names = new ArrayList<>();
+ names.add("StripMe");
+ stage.setElementNames(names);
+ stage.initialize();
+
+ stage.execute(items);
+
+ final Element out = readXMLData("out-sb.xml");
+ assertXMLIdentical(out, item.unwrap());
+ }
+
+ @Test
+ public void singleElementWhitelist() throws Exception {
+ final Element doc = readXMLData("in-sw.xml");
+ final Item<Element> item = new DOMElementItem(doc);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ final ElementsStrippingStage stage = new ElementsStrippingStage();
+ stage.setId("stripTest");
+ stage.setElementNamespace("urn:namespace:beta");
+ final List<String> names = new ArrayList<>();
+ names.add("StripMe");
+ stage.setElementNames(names);
+ stage.setWhitelisting(true);
+ stage.initialize();
+
+ stage.execute(items);
+
+ final Element out = readXMLData("out-sw.xml");
+ assertXMLIdentical(out, item.unwrap());
+ }
+
+ @Test
+ public void multiElementWhitelist() throws Exception {
+ final Element doc = readXMLData("in-multi.xml");
+ final Item<Element> item = new DOMElementItem(doc);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ final ElementsStrippingStage stage = new ElementsStrippingStage();
+ stage.setId("stripTest");
+ stage.setElementNamespace("urn:namespace:beta");
+ final List<String> names = new ArrayList<>();
+ names.add("one");
+ names.add("three");
+ stage.setElementNames(names);
+ stage.initialize();
+
+ stage.execute(items);
+
+ final Element out = readXMLData("out-multi-b.xml");
+ assertXMLIdentical(out, item.unwrap());
+ }
+
+ @Test
+ public void multiElementBlacklist() throws Exception {
+ final Element doc = readXMLData("in-multi.xml");
+ final Item<Element> item = new DOMElementItem(doc);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ final ElementsStrippingStage stage = new ElementsStrippingStage();
+ stage.setId("stripTest");
+ stage.setElementNamespace("urn:namespace:beta");
+ final List<String> names = new ArrayList<>();
+ names.add("one");
+ names.add("three");
+ stage.setElementNames(names);
+ stage.setWhitelisting(true);
+ stage.initialize();
+
+ stage.execute(items);
+
+ final Element out = readXMLData("out-multi-w.xml");
+ assertXMLIdentical(out, item.unwrap());
+ }
+}
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-multi.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-multi.xml
new file mode 100644
index 0000000..e5a2c3d
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-multi.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:keep/>
+ <beta:one/>
+ <alpha:keep/>
+ <beta:two/>
+ <alpha:keep/>
+ <beta:three/>
+ <alpha:keep/>
+ <beta:four/>
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sb.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sb.xml
new file mode 100644
index 0000000..96c26a6
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sb.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:nested>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ </alpha:nested>
+ <alpha:keepMe>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ <beta:Keep>
+ <nested/>
+ </beta:Keep>
+ </alpha:keepMe>
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sw.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sw.xml
new file mode 100644
index 0000000..96c26a6
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-in-sw.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:nested>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ </alpha:nested>
+ <alpha:keepMe>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ <beta:Keep>
+ <nested/>
+ </beta:Keep>
+ </alpha:keepMe>
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-b.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-b.xml
new file mode 100644
index 0000000..8b8f1e4
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-b.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:keep/>
+
+ <alpha:keep/>
+ <beta:two/>
+ <alpha:keep/>
+
+ <alpha:keep/>
+ <beta:four/>
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-w.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-w.xml
new file mode 100644
index 0000000..ef80293
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-multi-w.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:keep/>
+ <beta:one/>
+ <alpha:keep/>
+
+ <alpha:keep/>
+ <beta:three/>
+ <alpha:keep/>
+
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sb.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sb.xml
new file mode 100644
index 0000000..cc55e60
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sb.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:nested>
+
+ </alpha:nested>
+ <alpha:keepMe>
+
+ <beta:Keep>
+ <nested/>
+ </beta:Keep>
+ </alpha:keepMe>
+</rootElement>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sw.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sw.xml
new file mode 100644
index 0000000..c897e32
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/ElementsStrippingStage-out-sw.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rootElement xmlns:alpha="urn:namespace:alpha" xmlns:beta="urn:namespace:beta">
+ <alpha:nested>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ </alpha:nested>
+ <alpha:keepMe>
+ <beta:StripMe>
+ <nested/>
+ </beta:StripMe>
+ </alpha:keepMe>
+</rootElement>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list