[java-metadata-aggregator] 02/02: MDA-231 - Add stage to validate selected DOM attributes as strings
Ian Young
ian at iay.org.uk
Fri Oct 21 16:54:45 UTC 2022
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch main
in repository java-metadata-aggregator.
View the commit online:
http://git.shibboleth.net/view/?p=java-metadata-aggregator.git;a=commit;h=bd1cdc6d2ff034fc11b259368a9cdeb7b6d24595
commit bd1cdc6d2ff034fc11b259368a9cdeb7b6d24595
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Fri Oct 21 17:54:40 2022 +0100
MDA-231 - Add stage to validate selected DOM attributes as strings
https://shibboleth.atlassian.net/browse/MDA-231
---
.../dom/AbstractAttributeValidationStage.java | 175 +++++++++++++++++++++
.../dom/AbstractElementValidationStage.java | 7 +-
...ge.java => StringAttributeValidationStage.java} | 14 +-
.../metadata/dom/StringElementValidationStage.java | 6 +-
.../resources/net/shibboleth/metadata/beans.xml | 3 +
.../net/shibboleth/metadata/dom/BaseDOMTest.java | 18 ++-
.../dom/StringAttributeValidationStageTest.java | 148 +++++++++++++++++
.../validate/testing/CollectingValidator.java | 77 +++++++++
.../metadata/validate/testing/package-info.java} | 22 +--
.../StringAttributeValidationStage-multiple.xml | 132 ++++++++++++++++
10 files changed, 569 insertions(+), 33 deletions(-)
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractAttributeValidationStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractAttributeValidationStage.java
new file mode 100644
index 0000000..9a64c27
--- /dev/null
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractAttributeValidationStage.java
@@ -0,0 +1,175 @@
+/*
+ * 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.concurrent.GuardedBy;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+import net.shibboleth.metadata.pipeline.StageProcessingException;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Abstract base class allowing a selected subset of XML attributes in a DOM document
+ * to be validated as a given type.
+ *
+ * @param <T> type to convert each attribute to for validation
+ *
+ * @since 0.10.0
+ */
+public abstract class AbstractAttributeValidationStage<T> extends AbstractElementValidationStage<T> {
+
+ /**
+ * Collection of attribute names for those attributes we will be visiting.
+ *
+ * <p>Internally, this is always held as a {@link Set} of {@link QName}s,
+ * and that's how it will be returned by the getter. There are four setters,
+ * however, for both collections and singletons, and both simple attribute
+ * names and qualified names (@link QName}s).</p>
+ *
+ * <p>Because of type erasure, those setters can't all be overloads of the
+ * same method name, so the {@link String}-based unqualified name forms
+ * (which will by far dominate use cases) are given the preferred
+ * identifiers.</p>
+ */
+ @SuppressWarnings("null")
+ @NonnullElements @Unmodifiable @GuardedBy("this")
+ private @Nonnull Set<@Nonnull QName> attributeNames = Set.of();
+
+ /**
+ * Gets the collection of attribute names to visit.
+ *
+ * @return collection of attribute names to visit
+ */
+ public final synchronized @Nonnull Collection<@Nonnull QName> getAttributeNames() {
+ return attributeNames;
+ }
+
+ /**
+ * Sets the collection of attribute names to visit, as a collection of unqualified
+ * {@link String} values.
+ *
+ * @param names collection of attribute names to visit
+ */
+ public final synchronized void setAttributeNames(@Nonnull final Collection<@Nonnull String> names) {
+ checkSetterPreconditions();
+ Constraint.isNotNull(names, "attributeNames may not be null");
+ final var qnames = new HashSet<QName>();
+ for (final var name : names) {
+ qnames.add(new QName(name));
+ }
+ attributeNames = Set.copyOf(qnames);
+ }
+
+ /**
+ * Sets a single attribute name to be visited.
+ *
+ * <p>Shorthand for use when a single unqualified attribute name, expressed as a
+ * {@link String}, is used.</p>
+ *
+ * @param name name for the attribute to be visited
+ */
+ public final synchronized void setAttributeName(@Nonnull final String name) {
+ checkSetterPreconditions();
+ Constraint.isNotNull(name, "unqualifiedAttributeName may not be null");
+ attributeNames = Set.of(new QName(name));
+ }
+
+ /**
+ * Sets the collection of attribute names to visit.
+ *
+ * @param names collection of qualified attribute names to visit
+ */
+ public final synchronized void setQualifiedAttributeNames(@Nonnull final Collection<@Nonnull QName> names) {
+ checkSetterPreconditions();
+ Constraint.isNotNull(names, "attributeNames may not be null");
+ attributeNames = Set.copyOf(names);
+ }
+
+ /**
+ * Sets a single attribute name to be visited.
+ *
+ * @param name {@link QName} for the attribute to be visited
+ */
+ public final synchronized void setQualifiedAttributeName(@Nonnull final QName name) {
+ checkSetterPreconditions();
+ Constraint.isNotNull(name, "attributeName may not be null");
+ attributeNames = Set.of(name);
+ }
+
+ @Override
+ protected @Nonnull T convert(final @Nonnull Element element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void visit(@Nonnull final Element element, @Nonnull final DOMTraversalContext context)
+ throws StageProcessingException {
+
+ // Look at the attributes. If there are none, we're done.
+ final var attributes = element.getAttributes();
+ if (attributes == null) return;
+
+ // Iterate through the attributes on this element.
+ for (int i = 0; i < attributes.getLength(); i++) {
+ final var attr = (Attr)attributes.item(i);
+ if (attr != null && applicable(attr, context)) {
+ applyValidators(convert(attr), context);
+ }
+ }
+ }
+
+ /**
+ * Convert the visited {@link Attr} to the type to be validated.
+ *
+ * @param element {@link Attr} being validated
+ * @return converted value
+ */
+ protected abstract @Nonnull T convert(final @Nonnull Attr attr);
+
+ /**
+ * Returns whether the given attribute is applicable to our traversal.
+ *
+ * @param attr {@link Attr} candidate for visiting
+ * @param context
+ * @return
+ */
+ protected boolean applicable(@Nonnull final Attr attr, @Nonnull final DOMTraversalContext context) {
+ final var attrName = new QName(attr.getNamespaceURI(), attr.getLocalName());
+ return attributeNames.contains(attrName);
+ }
+
+ @Override
+ protected synchronized void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (attributeNames.isEmpty()) {
+ throw new ComponentInitializationException("attributeNames may not be empty");
+ }
+ }
+}
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractElementValidationStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractElementValidationStage.java
index fa77de6..1a731c4 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractElementValidationStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/dom/AbstractElementValidationStage.java
@@ -39,6 +39,8 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
* to be validated as a given type.
*
* @param <T> type to convert each {@link Element} to for validation
+ *
+ * @since 0.10.0
*/
@ThreadSafe
public abstract class AbstractElementValidationStage<T> extends AbstractDOMValidationStage<T, DOMTraversalContext> {
@@ -70,7 +72,7 @@ public abstract class AbstractElementValidationStage<T> extends AbstractDOMValid
/**
* Sets a single element name to be visited.
*
- * Shorthand for {@link #setElementNames} with a singleton set.
+ * <p>Shorthand for {@link #setElementNames} with a singleton set.</p>
*
* @param name {@link QName} for the element to be visited.
*/
@@ -92,8 +94,7 @@ public abstract class AbstractElementValidationStage<T> extends AbstractDOMValid
* @param element {@link Element} being validated
* @return converted value
*/
- @Nonnull
- protected abstract T convert(@Nonnull final Element element);
+ protected abstract @Nonnull T convert(@Nonnull final Element element);
@Override
protected void visit(@Nonnull final Element element, @Nonnull final DOMTraversalContext context)
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringAttributeValidationStage.java
similarity index 74%
copy from mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
copy to mda-framework/src/main/java/net/shibboleth/metadata/dom/StringAttributeValidationStage.java
index a4593be..42e9f00 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringAttributeValidationStage.java
@@ -20,20 +20,22 @@ package net.shibboleth.metadata.dom;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
-import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
import net.shibboleth.metadata.pipeline.Stage;
/**
- * A {@link Stage} allowing validation of DOM {@link Element}s treated as {@link String}s.
+ * A {@link Stage} allowing validation of DOM {@link Attr}s treated as {@link String}s.
+ *
+ * @since 0.10.0
*/
@ThreadSafe
-public class StringElementValidationStage extends AbstractElementValidationStage<String> {
+public class StringAttributeValidationStage extends AbstractAttributeValidationStage<String> {
+ @SuppressWarnings("null")
@Override
- @Nonnull
- protected String convert(@Nonnull final Element element) {
- return element.getTextContent();
+ protected @Nonnull String convert(@Nonnull final Attr attr) {
+ return attr.getTextContent();
}
}
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
index a4593be..3af2ed9 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
@@ -26,13 +26,15 @@ import net.shibboleth.metadata.pipeline.Stage;
/**
* A {@link Stage} allowing validation of DOM {@link Element}s treated as {@link String}s.
+ *
+ * @since 0.10.0
*/
@ThreadSafe
public class StringElementValidationStage extends AbstractElementValidationStage<String> {
+ @SuppressWarnings("null")
@Override
- @Nonnull
- protected String convert(@Nonnull final Element element) {
+ protected @Nonnull String convert(@Nonnull final Element element) {
return element.getTextContent();
}
diff --git a/mda-framework/src/main/resources/net/shibboleth/metadata/beans.xml b/mda-framework/src/main/resources/net/shibboleth/metadata/beans.xml
index 67c5ad1..d0bfb14 100644
--- a/mda-framework/src/main/resources/net/shibboleth/metadata/beans.xml
+++ b/mda-framework/src/main/resources/net/shibboleth/metadata/beans.xml
@@ -79,6 +79,9 @@
<bean id="mda.NamespaceStrippingStage" abstract="true" parent="mda.stage_parent"
class="net.shibboleth.metadata.dom.NamespaceStrippingStage"/>
+ <bean id="mda.StringAttributeValidationStage" abstract="true" parent="mda.stage_parent"
+ class="net.shibboleth.metadata.dom.StringAttributeValidationStage"/>
+
<bean id="mda.StringElementValidationStage" abstract="true" parent="mda.stage_parent"
class="net.shibboleth.metadata.dom.StringElementValidationStage"/>
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/dom/BaseDOMTest.java b/mda-framework/src/test/java/net/shibboleth/metadata/dom/BaseDOMTest.java
index edfa449..ec90f72 100644
--- a/mda-framework/src/test/java/net/shibboleth/metadata/dom/BaseDOMTest.java
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/dom/BaseDOMTest.java
@@ -18,6 +18,7 @@
package net.shibboleth.metadata.dom;
import java.io.InputStream;
+import java.io.StringReader;
import java.util.List;
import javax.annotation.Nonnull;
@@ -129,15 +130,28 @@ public abstract class BaseDOMTest extends BaseTest {
*
* @param path classpath path to the data file, never null
*
- * @return an {@link Item} wrapping the document representing the data file, never null
+ * @return an {@link Item} wrapping the document representing the data file, never <code>null</code>
*
* @throws XMLParserException if the file does not exist or there is a problem parsing it
*/
- public Item<Element> readDOMItem(final String path) throws XMLParserException {
+ public @Nonnull Item<Element> readDOMItem(final String path) throws XMLParserException {
final Element e = readXMLData(path);
return new DOMElementItem(e);
}
+ /**
+ * Create a DOM {@link Item} from a {@link String}.
+ *
+ * @param text text to turn into a DOM item
+ * @return DOM item corresponding to the provided text
+ * @throws XMLParserException
+ */
+ protected @Nonnull Item<Element> parseDOMItem(final @Nonnull String text) throws XMLParserException {
+ try (var reader = new StringReader(text)) {
+ return new DOMElementItem(getParserPool().parse(reader));
+ }
+ }
+
/**
* Checks whether two nodes are identical.
*
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/dom/StringAttributeValidationStageTest.java b/mda-framework/src/test/java/net/shibboleth/metadata/dom/StringAttributeValidationStageTest.java
new file mode 100644
index 0000000..5676e12
--- /dev/null
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/dom/StringAttributeValidationStageTest.java
@@ -0,0 +1,148 @@
+
+package net.shibboleth.metadata.dom;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import javax.xml.namespace.QName;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.w3c.dom.Element;
+
+import net.shibboleth.metadata.ErrorStatus;
+import net.shibboleth.metadata.Item;
+import net.shibboleth.metadata.dom.saml.SAMLMetadataSupport;
+import net.shibboleth.metadata.validate.RejectAllValidator;
+import net.shibboleth.metadata.validate.Validator;
+import net.shibboleth.metadata.validate.testing.CollectingValidator;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.XMLConstants;
+
+public class StringAttributeValidationStageTest extends BaseDOMTest {
+
+ protected StringAttributeValidationStageTest() {
+ super(StringAttributeValidationStage.class);
+ }
+
+ @Test
+ public void testLifecycle() throws Exception {
+ var stage = new StringAttributeValidationStage();
+ stage.setId("test");
+ stage.setElementName(new QName("test"));
+ stage.setAttributeName("test");
+ stage.initialize();
+ stage.destroy();
+ }
+
+ @Test(expectedExceptions = ComponentInitializationException.class)
+ public void noAttributeNames() throws Exception {
+ var stage = new StringAttributeValidationStage();
+ stage.setId("test");
+ stage.setElementName(new QName("test"));
+ stage.initialize();
+ stage.destroy();
+ }
+
+ /**
+ * Simple test to see if we can reach a singleton attribute
+ * on an unqualified element.
+ *
+ * @throws Exception if something goes wrong
+ */
+ @Test
+ public void testSimpleXY() throws Exception {
+ var item = parseDOMItem("<a><x y='a'/></a>");
+ var items = new ArrayList<Item<Element>>();
+ items.add(item);
+
+ var reject = new RejectAllValidator<String>();
+ reject.setId("reject");
+ reject.initialize();
+ var collect = CollectingValidator.<String>getInstance("collect");
+ var validators = new ArrayList<Validator<String>>();
+ validators.add(collect);
+ validators.add(reject);
+
+ var stage = new StringAttributeValidationStage();
+ stage.setId("test");
+ stage.setElementName(new QName("x"));
+ stage.setAttributeName("y");
+ stage.setValidators(validators);
+ stage.initialize();
+ stage.execute(items);
+
+ stage.destroy();
+ reject.destroy();
+
+ var values = collect.getValues();
+ collect.destroy();
+ Assert.assertEquals(values.size(), 1);
+ Assert.assertEquals(values.get(0), "a");
+
+ var errors = item.getItemMetadata().get(ErrorStatus.class);
+ Assert.assertEquals(errors.size(), 1);
+ var error = errors.get(0);
+ Assert.assertEquals(error.getStatusMessage(), "value rejected: 'a'");
+ }
+
+ /**
+ * Comprehensive test with multiple applicable elements and attributes,
+ * both with namespaces and without.
+ *
+ * @throws Exception if something goes wrong
+ */
+ @Test
+ public void testMultiple() throws Exception {
+ var item = readDOMItem("multiple.xml");
+ var items = new ArrayList<Item<Element>>();
+ items.add(item);
+
+ /*
+ * We are going to pick off a few attributes:
+ *
+ * - The entityID from each of three EntityDescriptor elements (3)
+ * - The index from each of 12 AssertionConsumerService elements (0..5, twice)
+ * - The xml:lang from each of three OrganizationName elements (3)
+ *
+ * Total of: 18.
+ *
+ * This will happen by intersecting the element names with the
+ * attribute names.
+ */
+ var elements = new HashSet<QName>();
+ elements.add(SAMLMetadataSupport.ENTITY_DESCRIPTOR_NAME);
+ elements.add(new QName(SAMLMetadataSupport.MD_NS, "AssertionConsumerService"));
+ elements.add(SAMLMetadataSupport.ORGANIZATIONNAME_NAME);
+ var attributes = new HashSet<QName>();
+ attributes.add(new QName("entityID"));
+ attributes.add(new QName("index"));
+ attributes.add(XMLConstants.XML_LANG_ATTRIB_NAME);
+
+ var collect = CollectingValidator.<String>getInstance("collect");
+ var validators = new ArrayList<Validator<String>>();
+ validators.add(collect);
+
+ var stage = new StringAttributeValidationStage();
+ stage.setId("test");
+ stage.setElementNames(elements);
+ stage.setQualifiedAttributeNames(attributes);
+ stage.setValidators(validators);
+ stage.initialize();
+ stage.execute(items);
+
+ stage.destroy();
+
+ var values = collect.getValues();
+ collect.destroy();
+
+ System.out.println(values);
+ Assert.assertEquals(values.size(), 18);
+ // Count how many "en"s there are
+ Assert.assertEquals(values.stream().filter(x -> x.equals("en")).count(), 3);
+ // Count how many "shibboleth.net"s there are
+ Assert.assertEquals(values.stream().filter(x -> x.contains("shibboleth.net")).count(), 3);
+ // Count how many indexes (matching single digits) there are
+ Assert.assertEquals(values.stream().filter(x -> x.matches("\\d")).count(), 12);
+ }
+}
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/CollectingValidator.java b/mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/CollectingValidator.java
new file mode 100644
index 0000000..b799aca
--- /dev/null
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/CollectingValidator.java
@@ -0,0 +1,77 @@
+/*
+ * 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.validate.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.metadata.Item;
+import net.shibboleth.metadata.pipeline.StageProcessingException;
+import net.shibboleth.metadata.validate.BaseValidator;
+import net.shibboleth.metadata.validate.Validator;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/**
+ * A {@link Validator} implementation which collects the values passed to it for
+ * validation.
+ *
+ * <p>This can be used in tests to record the nodes which are visited, and the
+ * order in which this happens.</p>
+ *
+ * @param <T> type of the values to be validated
+ */
+public class CollectingValidator<T> extends BaseValidator implements Validator<T> {
+
+ /** Values this validator has seen, in order. */
+ private final @Nonnull List<@Nonnull T> values = new ArrayList<>();
+
+ /**
+ * Return the values recorded by this validator.
+ *
+ * @return the values recorded by this validator
+ */
+ public @Nonnull List<@Nonnull T> getValues() {
+ return values;
+ }
+
+ /**
+ * Convenience method to return an instance of this validator.
+ *
+ * @param id identifier for this instance
+ * @param <TT> type validated by the instance to create
+ * @return new validator instance
+ * @throws ComponentInitializationException if something goes wrong in initialisation
+ */
+ public static @Nonnull <TT> CollectingValidator<TT> getInstance(final @Nonnull String id)
+ throws ComponentInitializationException {
+ final var instance = new CollectingValidator<TT>();
+ instance.setId(id);
+ instance.initialize();
+ return instance;
+ }
+
+ @Override
+ public @Nonnull Action validate(@Nonnull T e, @Nonnull Item<?> item, @Nonnull String stageId)
+ throws StageProcessingException {
+ values.add(e);
+ return Action.CONTINUE;
+ }
+
+}
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java b/mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/package-info.java
similarity index 61%
copy from mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
copy to mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/package-info.java
index a4593be..9c7b22b 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/dom/StringElementValidationStage.java
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/validate/testing/package-info.java
@@ -15,25 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.metadata.dom;
-
-import javax.annotation.Nonnull;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.w3c.dom.Element;
-
-import net.shibboleth.metadata.pipeline.Stage;
-
/**
- * A {@link Stage} allowing validation of DOM {@link Element}s treated as {@link String}s.
+ * Test utility classes for the validation framework.
*/
- at ThreadSafe
-public class StringElementValidationStage extends AbstractElementValidationStage<String> {
-
- @Override
- @Nonnull
- protected String convert(@Nonnull final Element element) {
- return element.getTextContent();
- }
-
-}
+package net.shibboleth.metadata.validate.testing;
diff --git a/mda-framework/src/test/resources/net/shibboleth/metadata/dom/StringAttributeValidationStage-multiple.xml b/mda-framework/src/test/resources/net/shibboleth/metadata/dom/StringAttributeValidationStage-multiple.xml
new file mode 100644
index 0000000..0f34a2a
--- /dev/null
+++ b/mda-framework/src/test/resources/net/shibboleth/metadata/dom/StringAttributeValidationStage-multiple.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntitiesDescriptor Name="urn:example.org:test" cacheDuration="PT4H" validUntil="2050-01-01T00:00:00Z"
+ xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <EntityDescriptor entityID="https://idp.shibboleth.net/idp/shibboleth" cacheDuration="PT3H" validUntil="2049-01-01T00:00:00Z">
+
+ <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
+
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.shibboleth.net/idp/profile/SAML2/POST/SSO"/>
+
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://idp.shibboleth.net/idp/profile/SAML2/POST-SimpleSign/SSO"/>
+
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.shibboleth.net/idp/profile/SAML2/Redirect/SSO"/>
+
+ </IDPSSODescriptor>
+
+ <Organization>
+ <OrganizationName xml:lang="en">Shibboleth.net</OrganizationName>
+ <OrganizationDisplayName xml:lang="en">Shibboleth.net</OrganizationDisplayName>
+ <OrganizationURL xml:lang="en">http://www.shibboleth.net</OrganizationURL>
+ </Organization>
+
+ <ContactPerson contactType="support">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress><!--good-->
+ </ContactPerson>
+
+ <ContactPerson contactType="bogus">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>contact at shibboleth.net</EmailAddress><!-- bad -->
+ </ContactPerson>
+
+ </EntityDescriptor>
+
+ <EntityDescriptor entityID="https://issues.shibboleth.net/shibboleth" cacheDuration="PT2H" validUntil="2048-01-01T00:00:00Z">
+
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/Artifact/SOAP" index="0"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SLO/Artifact"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SLO/POST"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SLO/Redirect"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SLO/SOAP"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML/Artifact" index="0"/>
+
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML/POST" index="1"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML2/Artifact" index="2"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML2/ECP" index="3"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML2/POST" index="4"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://issues.shibboleth.net/jira/Shibboleth.sso/SAML2/POST-SimpleSign" index="5"/>
+
+ <AttributeConsumingService index="1">
+ <ServiceName xml:lang="en">Shibboleth Federated Issue Tracking</ServiceName>
+ <ServiceDescription xml:lang="en"> An issue (bugs, feature requests, tasks) tracking
+ service with automatic registration for users who can supply a supported identifier,
+ such as eduPersonPrincipalName or swissEduPersonUniqueID. </ServiceDescription>
+
+ <RequestedAttribute FriendlyName="eduPersonPrincipalName" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <RequestedAttribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/>
+ <RequestedAttribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/>
+ </AttributeConsumingService>
+ </SPSSODescriptor>
+
+ <Organization>
+ <OrganizationName xml:lang="en">Shibboleth Consortium</OrganizationName>
+ <OrganizationDisplayName xml:lang="en">Shibboleth Consortium</OrganizationDisplayName>
+ <OrganizationURL xml:lang="en">http://www.shibboleth.net/</OrganizationURL>
+ </Organization>
+
+ <ContactPerson contactType="technical">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>contact at shibboleth.net</EmailAddress><!-- bad -->
+ </ContactPerson>
+ <ContactPerson contactType="support">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress><!-- good -->
+ </ContactPerson>
+ <ContactPerson contactType="administrative">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress><!-- good -->
+ </ContactPerson>
+ <ContactPerson contactType="billing">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress><!-- good -->
+ </ContactPerson>
+ <ContactPerson contactType="other">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress><!-- good -->
+ </ContactPerson>
+
+ </EntityDescriptor>
+
+ <EntityDescriptor entityID="https://wiki.shibboleth.net/shibboleth" cacheDuration="PT1H" validUntil="2047-01-01T00:00:00Z">
+
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/Artifact/SOAP" index="0"/>
+
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SLO/Artifact"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SLO/POST"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SLO/Redirect"/>
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SLO/SOAP"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML/Artifact" index="0"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML/POST" index="1"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML2/Artifact" index="2"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML2/ECP" index="3"/>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML2/POST" index="4"/>
+
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://wiki.shibboleth.net/confluence/Shibboleth.sso/SAML2/POST-SimpleSign" index="5"/>
+
+ <AttributeConsumingService index="1">
+ <ServiceName xml:lang="en">Shibboleth Federated Wiki</ServiceName>
+ <ServiceDescription xml:lang="en"> A shared Wiki service with automatic registration
+ for users who can supply a supported identifier, such as eduPersonPrincipalName
+ or swissEduPersonUniqueID. </ServiceDescription>
+ <RequestedAttribute FriendlyName="eduPersonPrincipalName" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <RequestedAttribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/>
+ <RequestedAttribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/>
+
+ </AttributeConsumingService>
+ </SPSSODescriptor>
+
+ <Organization>
+ <OrganizationName xml:lang="en">Shibboleth Consortium</OrganizationName>
+ <OrganizationDisplayName xml:lang="en">Shibboleth Consortium</OrganizationDisplayName>
+ <OrganizationURL xml:lang="en">http://www.shibboleth.net/</OrganizationURL>
+ </Organization>
+ </EntityDescriptor>
+
+</EntitiesDescriptor>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list