[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