[java-opensaml] branch main updated: OSJ-392: OpenSAML's strict processing mode does not load ADFS metadata
Brent Putman
putmanb at georgetown.edu
Thu Dec 14 03:04:31 UTC 2023
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch main
in repository java-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=53a72956b916187f1cdf3a141135b90694239fa3
The following commit(s) were added to refs/heads/main by this push:
new 53a72956b OSJ-392: OpenSAML's strict processing mode does not load ADFS metadata
53a72956b is described below
commit 53a72956b916187f1cdf3a141135b90694239fa3
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Tue Nov 28 19:18:58 2023 -0500
OSJ-392: OpenSAML's strict processing mode does not load ADFS metadata
---
.../opensaml/core/xml/AbstractXSAnyAdapter.java | 243 ++++++++++++++++
.../java/org/opensaml/core/xml/XSAnyAdapter.java | 33 +++
.../saml2/core/impl/AssertionUnmarshaller.java | 4 +
.../saml/saml2/core/impl/BaseIDXSAnyAdapter.java | 61 ++++
.../saml2/core/impl/ConditionXSAnyAdapter.java | 35 +++
.../saml2/core/impl/ConditionsUnmarshaller.java | 4 +
.../saml2/core/impl/StatementXSAnyAdapter.java | 35 +++
.../core/impl/SubjectConfirmationUnmarshaller.java | 4 +
.../saml/saml2/core/impl/SubjectUnmarshaller.java | 4 +
.../impl/EntityDescriptorUnmarshaller.java | 4 +
.../metadata/impl/RoleDescriptorXSAnyAdapter.java | 317 +++++++++++++++++++++
.../saml/saml2/metadata/tests/MetadataTest.java | 4 +-
12 files changed, 746 insertions(+), 2 deletions(-)
diff --git a/opensaml-core-api/src/main/java/org/opensaml/core/xml/AbstractXSAnyAdapter.java b/opensaml-core-api/src/main/java/org/opensaml/core/xml/AbstractXSAnyAdapter.java
new file mode 100644
index 000000000..84a0fd253
--- /dev/null
+++ b/opensaml-core-api/src/main/java/org/opensaml/core/xml/AbstractXSAnyAdapter.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed 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 org.opensaml.core.xml;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.core.xml.schema.XSBooleanValue;
+import org.opensaml.core.xml.util.IDIndex;
+import org.w3c.dom.Element;
+
+import net.shibboleth.shared.collection.LockableClassToInstanceMultiMap;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * Abstract base class for implementations that adapt/wrap an instance of {@link XSAny}.
+ */
+public abstract class AbstractXSAnyAdapter implements XSAnyAdapter {
+
+ /** The adapted XSAny instance. */
+ @Nonnull private XSAny adapted;
+
+ /**
+ * Constructor.
+ *
+ * @param xsAny the adapted XSAny instance
+ */
+ protected AbstractXSAnyAdapter(@Nonnull final XSAny xsAny) {
+ adapted = Constraint.isNotNull(xsAny, "Adapted XSAny may not be null");
+ }
+
+ /**
+ * Get the adapted {@link XSAny} instance.
+ *
+ * @return the adapted XSAny
+ */
+ @Nonnull
+ public XSAny getAdapted() {
+ return adapted;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void detach() {
+ adapted.detach();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public Element getDOM() {
+ return adapted.getDOM();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public Element ensureDOM() {
+ return adapted.ensureDOM();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public QName getElementQName() {
+ return adapted.getElementQName();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public IDIndex getIDIndex() {
+ return adapted.getIDIndex();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public NamespaceManager getNamespaceManager() {
+ return adapted.getNamespaceManager();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public Set<Namespace> getNamespaces() {
+ return adapted.getNamespaces();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public String getNoNamespaceSchemaLocation() {
+ return adapted.getNoNamespaceSchemaLocation();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public List<XMLObject> getOrderedChildren() {
+ return adapted.getOrderedChildren();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public XMLObject getParent() {
+ return adapted.getParent();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public String getSchemaLocation() {
+ return adapted.getSchemaLocation();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public QName getSchemaType() {
+ return adapted.getSchemaType();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean hasChildren() {
+ return adapted.hasChildren();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean hasParent() {
+ return adapted.hasParent();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void releaseChildrenDOM(boolean propagateRelease) {
+ adapted.releaseChildrenDOM(propagateRelease);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void releaseDOM() {
+ adapted.releaseDOM();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void releaseParentDOM(boolean propagateRelease) {
+ adapted.releaseParentDOM(propagateRelease);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public XMLObject resolveID(@Nonnull String id) {
+ return adapted.resolveID(id);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public XMLObject resolveIDFromRoot(@Nonnull String id) {
+ return adapted.resolveIDFromRoot(id);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setDOM(@Nullable Element dom) {
+ adapted.setDOM(dom);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setNoNamespaceSchemaLocation(@Nullable String location) {
+ adapted.setNoNamespaceSchemaLocation(location);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setParent(@Nullable XMLObject parent) {
+ adapted.setParent(parent);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setSchemaLocation(@Nullable String location) {
+ adapted.setSchemaLocation(location);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public Boolean isNil() {
+ return adapted.isNil();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public XSBooleanValue isNilXSBoolean() {
+ return adapted.isNilXSBoolean();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setNil(@Nullable Boolean newNil) {
+ adapted.setNil(newNil);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setNil(@Nullable XSBooleanValue newNil) {
+ adapted.setNil(newNil);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ public LockableClassToInstanceMultiMap<Object> getObjectMetadata() {
+ return adapted.getObjectMetadata();
+ }
+
+}
diff --git a/opensaml-core-api/src/main/java/org/opensaml/core/xml/XSAnyAdapter.java b/opensaml-core-api/src/main/java/org/opensaml/core/xml/XSAnyAdapter.java
new file mode 100644
index 000000000..4831a3db8
--- /dev/null
+++ b/opensaml-core-api/src/main/java/org/opensaml/core/xml/XSAnyAdapter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed 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 org.opensaml.core.xml;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.core.xml.schema.XSAny;
+
+/**
+ * Interface for implementations which adapt/wrap an instance of {@link XSAny}.
+ */
+public interface XSAnyAdapter extends XMLObject {
+
+ /**
+ * Get the adapted instance of {@link XSAny}
+ *
+ * @return the adapted instance of XSAny
+ */
+ @Nonnull XSAny getAdapted();
+
+}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionUnmarshaller.java
index cb447c474..7c807eec5 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionUnmarshaller.java
@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
import org.opensaml.saml.saml2.core.Advice;
import org.opensaml.saml.saml2.core.Assertion;
@@ -59,6 +60,9 @@ public class AssertionUnmarshaller extends AbstractSAMLObjectUnmarshaller {
assertion.setAdvice((Advice) childObject);
} else if (childObject instanceof Statement) {
assertion.getStatements().add((Statement) childObject);
+ } else if (Statement.DEFAULT_ELEMENT_NAME.equals(childObject.getElementQName())
+ && XSAny.class.isInstance(childObject)) {
+ assertion.getStatements().add(new StatementXSAnyAdapter(XSAny.class.cast(childObject)));
} else {
super.processChildElement(parentObject, childObject);
}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/BaseIDXSAnyAdapter.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/BaseIDXSAnyAdapter.java
new file mode 100644
index 000000000..6ef1bea7d
--- /dev/null
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/BaseIDXSAnyAdapter.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed 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 org.opensaml.saml.saml2.core.impl;
+
+import javax.xml.namespace.QName;
+
+import org.opensaml.core.xml.AbstractXSAnyAdapter;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.saml.saml2.core.BaseID;
+
+/**
+ * Component that adapts an instance of {@link XSAny} to the interface {@link BaseID}.
+ */
+public class BaseIDXSAnyAdapter extends AbstractXSAnyAdapter implements BaseID {
+
+ /**
+ * Constructor.
+ *
+ * @param xsAny the adapted instance
+ */
+ public BaseIDXSAnyAdapter(XSAny xsAny) {
+ super(xsAny);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getNameQualifier() {
+ return getAdapted().getUnknownAttributes().get(new QName(BaseID.NAME_QUALIFIER_ATTRIB_NAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setNameQualifier(String newNameQualifier) {
+ getAdapted().getUnknownAttributes().put(new QName(BaseID.NAME_QUALIFIER_ATTRIB_NAME), newNameQualifier);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getSPNameQualifier() {
+ return getAdapted().getUnknownAttributes().get(new QName(BaseID.SP_NAME_QUALIFIER_ATTRIB_NAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setSPNameQualifier(String newSPNameQualifier) {
+ getAdapted().getUnknownAttributes().put(new QName(BaseID.SP_NAME_QUALIFIER_ATTRIB_NAME), newSPNameQualifier);
+ }
+
+}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionXSAnyAdapter.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionXSAnyAdapter.java
new file mode 100644
index 000000000..d1425befd
--- /dev/null
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionXSAnyAdapter.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed 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 org.opensaml.saml.saml2.core.impl;
+
+import org.opensaml.core.xml.AbstractXSAnyAdapter;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.saml.saml2.core.Condition;
+
+/**
+ * Component that adapts an instance of {@link XSAny} to the interface {@link Condition}.
+ */
+public class ConditionXSAnyAdapter extends AbstractXSAnyAdapter implements Condition {
+
+ /**
+ * Constructor.
+ *
+ * @param xsAny the adapted instance
+ */
+ public ConditionXSAnyAdapter(XSAny xsAny) {
+ super(xsAny);
+ }
+
+}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionsUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionsUnmarshaller.java
index 8d6d2788c..2c2d0e644 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionsUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/ConditionsUnmarshaller.java
@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
import org.opensaml.saml.saml2.core.Condition;
import org.opensaml.saml.saml2.core.Conditions;
@@ -44,6 +45,9 @@ public class ConditionsUnmarshaller extends AbstractSAMLObjectUnmarshaller {
if (childObject instanceof Condition) {
conditions.getConditions().add((Condition) childObject);
+ } else if (Condition.DEFAULT_ELEMENT_NAME.equals(childObject.getElementQName())
+ && XSAny.class.isInstance(childObject)) {
+ conditions.getConditions().add(new ConditionXSAnyAdapter(XSAny.class.cast(childObject)));
} else {
super.processChildElement(parentObject, childObject);
}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatementXSAnyAdapter.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatementXSAnyAdapter.java
new file mode 100644
index 000000000..436024187
--- /dev/null
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatementXSAnyAdapter.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed 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 org.opensaml.saml.saml2.core.impl;
+
+import org.opensaml.core.xml.AbstractXSAnyAdapter;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.saml.saml2.core.Statement;
+
+/**
+ * Component that adapts an instance of {@link XSAny} to the interface {@link Statement}.
+ */
+public class StatementXSAnyAdapter extends AbstractXSAnyAdapter implements Statement {
+
+ /**
+ * Constructor.
+ *
+ * @param xsAny the adapted instance
+ */
+ public StatementXSAnyAdapter(XSAny xsAny) {
+ super(xsAny);
+ }
+
+}
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectConfirmationUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectConfirmationUnmarshaller.java
index b2174ee3b..e00cdfb1f 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectConfirmationUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectConfirmationUnmarshaller.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
import org.opensaml.saml.saml2.core.BaseID;
import org.opensaml.saml.saml2.core.EncryptedID;
@@ -39,6 +40,9 @@ public class SubjectConfirmationUnmarshaller extends AbstractSAMLObjectUnmarshal
if (childObject instanceof BaseID) {
subjectConfirmation.setBaseID((BaseID) childObject);
+ } else if (BaseID.DEFAULT_ELEMENT_NAME.equals(childObject.getElementQName())
+ && XSAny.class.isInstance(childObject)) {
+ subjectConfirmation.setBaseID(new BaseIDXSAnyAdapter(XSAny.class.cast(childObject)));
} else if (childObject instanceof NameID) {
subjectConfirmation.setNameID((NameID) childObject);
} else if (childObject instanceof EncryptedID) {
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectUnmarshaller.java
index 103e932ff..85e2f70a7 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/SubjectUnmarshaller.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
import org.opensaml.saml.saml2.core.BaseID;
import org.opensaml.saml.saml2.core.EncryptedID;
@@ -38,6 +39,9 @@ public class SubjectUnmarshaller extends AbstractSAMLObjectUnmarshaller {
if (childObject instanceof BaseID) {
subject.setBaseID((BaseID) childObject);
+ } else if (BaseID.DEFAULT_ELEMENT_NAME.equals(childObject.getElementQName())
+ && XSAny.class.isInstance(childObject)) {
+ subject.setBaseID(new BaseIDXSAnyAdapter(XSAny.class.cast(childObject)));
} else if (childObject instanceof NameID) {
subject.setNameID((NameID) childObject);
} else if (childObject instanceof EncryptedID) {
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorUnmarshaller.java
index c58fbdf3d..0f9692da3 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorUnmarshaller.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
import org.opensaml.saml.saml2.common.CacheableSAMLObject;
import org.opensaml.saml.saml2.metadata.Extensions;
@@ -52,6 +53,9 @@ public class EntityDescriptorUnmarshaller extends AbstractSAMLObjectUnmarshaller
entityDescriptor.setSignature((Signature) childObject);
} else if (childObject instanceof RoleDescriptor) {
entityDescriptor.getRoleDescriptors().add((RoleDescriptor) childObject);
+ } else if (RoleDescriptor.DEFAULT_ELEMENT_NAME.equals(childObject.getElementQName())
+ && XSAny.class.isInstance(childObject)) {
+ entityDescriptor.getRoleDescriptors().add(new RoleDescriptorXSAnyAdapter(XSAny.class.cast(childObject)));
} else if (childObject instanceof AffiliationDescriptor) {
entityDescriptor.setAffiliationDescriptor((AffiliationDescriptor) childObject);
} else if (childObject instanceof Organization) {
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorXSAnyAdapter.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorXSAnyAdapter.java
new file mode 100644
index 000000000..b7fc5edee
--- /dev/null
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorXSAnyAdapter.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed 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 org.opensaml.saml.saml2.metadata.impl;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.xml.namespace.QName;
+
+import org.opensaml.core.xml.AbstractXSAnyAdapter;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.core.xml.util.AttributeMap;
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.Endpoint;
+import org.opensaml.saml.saml2.metadata.Extensions;
+import org.opensaml.saml.saml2.metadata.KeyDescriptor;
+import org.opensaml.saml.saml2.metadata.Organization;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
+import org.opensaml.xmlsec.signature.Signature;
+
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.collection.LazyList;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.xml.DOMTypeSupport;
+
+/**
+ * Component that adapts an instance of {@link XSAny} to the interface {@link RoleDescriptor}.
+ */
+public class RoleDescriptorXSAnyAdapter extends AbstractXSAnyAdapter implements RoleDescriptor {
+
+ /**
+ * Constructor.
+ *
+ * @param xsAny the instance to adapt
+ */
+ public RoleDescriptorXSAnyAdapter(XSAny xsAny) {
+ super(xsAny);
+ getAdapted().getUnknownAttributes().registerID(new QName(RoleDescriptor.ID_ATTRIB_NAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getSignatureReferenceID() {
+ return getID();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isSigned() {
+ return getSignature() != null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Signature getSignature() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(Signature.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return (Signature) xmlObjects.get(0);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setSignature(Signature newSignature) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ final Instant validUntil = getValidUntil();
+
+ if (null == validUntil) {
+ return true;
+ }
+
+ return Instant.now().isBefore(validUntil);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Instant getValidUntil() {
+ return DOMTypeSupport.stringToInstant(getAdapted().getUnknownAttributes().get(
+ RoleDescriptor.VALID_UNTIL_ATTRIB_QNAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setValidUntil(Instant validUntil) {
+ getAdapted().getUnknownAttributes().put(RoleDescriptor.VALID_UNTIL_ATTRIB_QNAME,
+ DOMTypeSupport.instantToString(validUntil));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Duration getCacheDuration() {
+ return DOMTypeSupport.stringToDuration(getAdapted().getUnknownAttributes().get(
+ RoleDescriptor.CACHE_DURATION_ATTRIB_QNAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setCacheDuration(Duration duration) {
+ getAdapted().getUnknownAttributes().put(RoleDescriptor.CACHE_DURATION_ATTRIB_QNAME,
+ DOMTypeSupport.durationToString(duration));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public AttributeMap getUnknownAttributes() {
+ return getAdapted().getUnknownAttributes();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getID() {
+ return getAdapted().getUnknownAttributes().get(new QName(RoleDescriptor.ID_ATTRIB_NAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setID(String newID) {
+ getAdapted().getUnknownAttributes().put(new QName(RoleDescriptor.ID_ATTRIB_NAME), newID);
+ }
+
+ /**
+ * Internal method for fetching the supported protocols as a list.
+ *
+ * @return the list, possibly empty
+ */
+ @Nonnull private List<String> fetchSupportedProtocols() {
+ final String rawValue = StringSupport.trimOrNull(getAdapted().getUnknownAttributes().get(
+ new QName(RoleDescriptor.PROTOCOL_ENUMERATION_ATTRIB_NAME)));
+ if (rawValue == null) {
+ return new LazyList<String>();
+ }
+ return StringSupport.stringToList(rawValue, " ");
+ }
+
+ /**
+ * Internal method for storing the list of supported protocols as a string.
+ *
+ * @param protocols the list of protocols
+ */
+ private void storeSupportedProtocols(@Nonnull final List<String> protocols) {
+ if (protocols.isEmpty()) {
+ getAdapted().getUnknownAttributes().remove(new QName(RoleDescriptor.PROTOCOL_ENUMERATION_ATTRIB_NAME));
+ } else {
+ getAdapted().getUnknownAttributes().put(new QName(RoleDescriptor.PROTOCOL_ENUMERATION_ATTRIB_NAME),
+ StringSupport.listToStringValue(protocols, " "));
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<String> getSupportedProtocols() {
+ return CollectionSupport.copyToList(fetchSupportedProtocols());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isSupportedProtocol(String protocol) {
+ return fetchSupportedProtocols().contains(protocol);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addSupportedProtocol(String protocol) {
+ final List<String> protocols = fetchSupportedProtocols();
+ protocols.add(protocol);
+ storeSupportedProtocols(protocols);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void removeSupportedProtocol(String protocol) {
+ final List<String> protocols = fetchSupportedProtocols();
+ protocols.remove(protocol);
+ storeSupportedProtocols(protocols);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void removeSupportedProtocols(Collection<String> protocolsToRemove) {
+ final List<String> protocols = fetchSupportedProtocols();
+ protocols.removeAll(protocolsToRemove);
+ storeSupportedProtocols(protocols);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void removeAllSupportedProtocols() {
+ storeSupportedProtocols(Collections.emptyList());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getErrorURL() {
+ return getAdapted().getUnknownAttributes().get(new QName(RoleDescriptor.ERROR_URL_ATTRIB_NAME));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setErrorURL(String errorURL) {
+ getAdapted().getUnknownAttributes().put(new QName(RoleDescriptor.ERROR_URL_ATTRIB_NAME), errorURL);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Extensions getExtensions() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(Extensions.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+
+ return xmlObjects.stream()
+ .filter(Extensions.class::isInstance)
+ .map(Extensions.class::cast)
+ .findFirst().get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setExtensions(Extensions extensions) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<KeyDescriptor> getKeyDescriptors() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(KeyDescriptor.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return xmlObjects.stream()
+ .filter(KeyDescriptor.class::isInstance)
+ .map(KeyDescriptor.class::cast)
+ .toList();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Organization getOrganization() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(Organization.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return xmlObjects.stream()
+ .filter(Organization.class::isInstance)
+ .map(Organization.class::cast)
+ .findFirst().get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setOrganization(Organization organization) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<ContactPerson> getContactPersons() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(ContactPerson.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return xmlObjects.stream()
+ .filter(ContactPerson.class::isInstance)
+ .map(ContactPerson.class::cast)
+ .toList();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<Endpoint> getEndpoints() {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(Endpoint.DEFAULT_ELEMENT_NAME);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return xmlObjects.stream()
+ .filter(Endpoint.class::isInstance)
+ .map(Endpoint.class::cast)
+ .toList();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<Endpoint> getEndpoints(QName type) {
+ final List<XMLObject> xmlObjects = getAdapted().getUnknownXMLObjects(type);
+ if (xmlObjects.isEmpty()) {
+ return null;
+ }
+ return xmlObjects.stream()
+ .filter(Endpoint.class::isInstance)
+ .map(Endpoint.class::cast)
+ .toList();
+ }
+
+}
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/tests/MetadataTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/tests/MetadataTest.java
index a544f7de1..21b86a8d2 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/tests/MetadataTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/tests/MetadataTest.java
@@ -119,8 +119,8 @@ public class MetadataTest extends XMLObjectBaseTestCase {
}
}
- /** Tests unmarshalling an ADFS metadata document with their "fun" extensions. */
- @Test(enabled=false)
+ /** Tests unmarshalling an ADFS metadata document with their "fun" extensions. See OSJ-392. */
+ @Test
public void testADFSUnmarshall() {
String adfsMDFile = "/org/opensaml/saml/saml2/metadata/adfs-metadata.xml";
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list