[java-shib-metadata] branch main updated: Restore indirected version of PredicateFilterParser.

Scott Cantor cantor.2 at osu.edu
Wed Jul 6 14:13:06 UTC 2022


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-shib-metadata.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-metadata.git;a=commit;h=eead653bbe379e348af2f8335e2d5d5b2dee1343

The following commit(s) were added to refs/heads/main by this push:
     new eead653bb Restore indirected version of PredicateFilterParser.
eead653bb is described below

commit eead653bbe379e348af2f8335e2d5d5b2dee1343
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Jul 6 10:13:04 2022 -0400

    Restore indirected version of PredicateFilterParser.
---
 .../spring/metadata/MetadataNamespaceHandler.java  |   2 +
 .../PredicateFilterDirectionFactoryBean.java       |  63 ++++
 .../metadata/filter/PredicateFilterParser.java     | 336 +++++++++++++++++++++
 3 files changed, 401 insertions(+)

diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/MetadataNamespaceHandler.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/MetadataNamespaceHandler.java
index ea8ae3801..74807e15c 100644
--- a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/MetadataNamespaceHandler.java
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/MetadataNamespaceHandler.java
@@ -29,6 +29,7 @@ import net.shibboleth.spring.metadata.filter.EntityRoleFilterParser;
 import net.shibboleth.spring.metadata.filter.KeyAuthorityParser;
 import net.shibboleth.spring.metadata.filter.NameIDFormatFilterParser;
 import net.shibboleth.spring.metadata.filter.NodeProcessingParser;
+import net.shibboleth.spring.metadata.filter.PredicateFilterParser;
 import net.shibboleth.spring.metadata.filter.RequiredValidUntilParser;
 import net.shibboleth.spring.metadata.filter.SchemaValidationParser;
 import net.shibboleth.spring.metadata.filter.SignatureValidationParser;
@@ -63,6 +64,7 @@ public class MetadataNamespaceHandler extends BaseSpringNamespaceHandler {
                 new LocalDynamicMetadataProviderParser());
 
         // Filters
+        registerBeanDefinitionParser(PredicateFilterParser.TYPE_NAME, new PredicateFilterParser());
         registerBeanDefinitionParser(RequiredValidUntilParser.TYPE_NAME, new RequiredValidUntilParser());
         registerBeanDefinitionParser(AlgorithmFilterParser.TYPE_NAME, new AlgorithmFilterParser());
         registerBeanDefinitionParser(EntityAttributesFilterParser.TYPE_NAME, new EntityAttributesFilterParser());
diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterDirectionFactoryBean.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterDirectionFactoryBean.java
new file mode 100644
index 000000000..aaf1bf678
--- /dev/null
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterDirectionFactoryBean.java
@@ -0,0 +1,63 @@
+/*
+ * 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.spring.metadata.filter;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.saml.metadata.resolver.filter.impl.PredicateFilter;
+import org.opensaml.saml.metadata.resolver.filter.impl.PredicateFilter.Direction;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+/**
+ * Factory bean allow property replacements of the direction going in to a {@link PredicateFilter}.
+ */
+public class PredicateFilterDirectionFactoryBean extends AbstractFactoryBean<PredicateFilter.Direction> {
+
+    /** What we want to set the value from this should be "exclude" or "include".*/
+    @Nullable private final String value;
+    
+    /**
+     * Constructor.
+     * @param what the value to set
+     */
+    public PredicateFilterDirectionFactoryBean(@Nullable final String what) {
+        value = what;
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public Class<?> getObjectType() {
+        return PredicateFilter.Direction.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected Direction createInstance() throws Exception {
+        if (value == null) {
+            throw new BeanCreationException("Predicate filter requires 'direction' attribute");
+        } else if ("exclude".equals(value)) {
+            return PredicateFilter.Direction.EXCLUDE;
+        } else if ("include".equals(value)) {
+            return PredicateFilter.Direction.INCLUDE;
+        } else {
+            throw new BeanCreationException("Predicate filter direction must be 'include' or 'exclude'");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterParser.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterParser.java
new file mode 100644
index 000000000..6507b8467
--- /dev/null
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/PredicateFilterParser.java
@@ -0,0 +1,336 @@
+/*
+ * 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.spring.metadata.filter;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import org.opensaml.saml.common.profile.logic.EntityAttributesPredicate;
+import org.opensaml.saml.common.profile.logic.EntityAttributesPredicate.Candidate;
+import org.opensaml.saml.common.profile.logic.EntityGroupNamePredicate;
+import org.opensaml.saml.common.profile.logic.EntityIdPredicate;
+import org.opensaml.saml.metadata.resolver.filter.impl.PredicateFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.ext.spring.util.AbstractCustomBeanDefinitionParser;
+import net.shibboleth.ext.spring.util.SpringSupport;
+import net.shibboleth.spring.ScriptTypeBeanParser;
+import net.shibboleth.spring.metadata.AbstractMetadataProviderParser;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.logic.PredicateSupport;
+import net.shibboleth.utilities.java.support.logic.ScriptedPredicate;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+
+/**
+ * Parser for a <Predicate> filter.
+ */
+public class PredicateFilterParser extends AbstractCustomBeanDefinitionParser {
+
+    /** Element name. */
+    @Nonnull public static final QName TYPE_NAME =
+            new QName(AbstractMetadataProviderParser.METADATA_NAMESPACE, "Predicate");
+
+    /** Name of class to attempt to instantiate to handle mapped attribute predicate. */
+    @Nonnull @NotEmpty private static final String MAPPED_PREDICATE_CLASS =
+            "net.shibboleth.idp.saml.profile.logic.MappedEntityAttributesPredicate";
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(PredicateFilterParser.class);
+
+    /** Stores class of the predicate handling the mapped entity attribute feature. */
+    @Nullable private Class<? extends Predicate<?>> mappedPredicateClass;
+
+    /** Constructor. */
+    @SuppressWarnings("unchecked")
+    public PredicateFilterParser() {
+        try {
+            mappedPredicateClass = (Class<? extends Predicate<?>>) Class.forName(MAPPED_PREDICATE_CLASS);
+        } catch (final ClassNotFoundException e) {
+            // Will warn later any time we encounter a relevant setting.
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Class<?> getBeanClass(final Element element) {
+        return PredicateFilter.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void doParse(final Element element, final ParserContext parserContext,
+            final BeanDefinitionBuilder builder) {
+
+        if (element.hasAttributeNS(null, "removeEmptyEntitiesDescriptors")) {
+            builder.addPropertyValue("removeEmptyEntitiesDescriptors", SpringSupport.getStringValueAsBoolean(
+                    element.getAttributeNS(null, "removeEmptyEntitiesDescriptors")));
+        }
+
+        final BeanDefinitionBuilder directionBuilder =
+                BeanDefinitionBuilder.genericBeanDefinition(PredicateFilterDirectionFactoryBean.class);
+        directionBuilder.addConstructorArgValue(StringSupport.trimOrNull(element.getAttributeNS(null, "direction")));
+        builder.addConstructorArgValue(directionBuilder.getBeanDefinition());
+
+        if (element.hasAttributeNS(null, "conditionRef")) {
+            log.info("Found conditionRef attribute, ignoring embedded Entity/Group/Tag elements");
+            builder.addConstructorArgReference(StringSupport.trimOrNull(element.getAttributeNS(null, "conditionRef")));
+        } else {
+            builder.addConstructorArgValue(parseCustomElements(element));
+        }
+    }
+
+// Checkstyle: CyclomaticComplexity OFF
+    /**
+     * Parser custom element content into a {@link java.util.function.Predicate} to pass to the filter constructor.
+     * 
+     * @param element root element to parse
+     * 
+     * @return the bean definition of the Predicate to install
+     */
+    @Nonnull public BeanDefinition parseCustomElements(@Nonnull final Element element) {
+
+        // Track which predicates have to be built.
+        final BeanDefinitionBuilder entityIdPredicateBuilder = parseEntityPredicate(element);
+        final BeanDefinitionBuilder groupPredicateBuilder = parseGroupPredicate(element);
+        final BeanDefinitionBuilder tagPredicateBuilder = parseTagPredicate(element);
+        final BeanDefinitionBuilder mappedTagPredicateBuilder = parseMappedTagPredicate(element);
+        final BeanDefinitionBuilder scriptPredicateBuilder = parseScripts(element);
+
+        int count = 0;
+        if (entityIdPredicateBuilder != null) {
+            count++;
+        }
+        if (groupPredicateBuilder != null) {
+            count++;
+        }
+        if (tagPredicateBuilder != null) {
+            count++;
+        }
+        if (mappedTagPredicateBuilder != null) {
+            count++;
+        }
+        if (scriptPredicateBuilder != null) {
+            count++;
+        }
+
+        if (count == 0) {
+            throw new BeanCreationException("No Entity, Group, Tag, or ConditionScript element found");
+        } else if (count == 1) {
+            if (entityIdPredicateBuilder != null) {
+                return entityIdPredicateBuilder.getBeanDefinition();
+            } else if (groupPredicateBuilder != null) {
+                return groupPredicateBuilder.getBeanDefinition();
+            } else if (tagPredicateBuilder != null) {
+                return tagPredicateBuilder.getBeanDefinition();
+            } else if (mappedTagPredicateBuilder != null) {
+                return mappedTagPredicateBuilder.getBeanDefinition();
+            } else {
+                return scriptPredicateBuilder.getBeanDefinition();
+            }
+        } else {
+            final BeanDefinitionBuilder orBuilder =
+                    BeanDefinitionBuilder.rootBeanDefinition(PredicateSupport.class, "or");
+            final ManagedList<BeanDefinition> managedList = new ManagedList<>(count);
+            if (entityIdPredicateBuilder != null) {
+                managedList.add(entityIdPredicateBuilder.getBeanDefinition());
+            }
+            if (groupPredicateBuilder != null) {
+                managedList.add(groupPredicateBuilder.getBeanDefinition());
+            }
+            if (tagPredicateBuilder != null) {
+                managedList.add(tagPredicateBuilder.getBeanDefinition());
+            }
+            if (mappedTagPredicateBuilder != null) {
+                managedList.add(mappedTagPredicateBuilder.getBeanDefinition());
+            }
+            if (scriptPredicateBuilder != null) {
+                managedList.add(scriptPredicateBuilder.getBeanDefinition());
+            }
+            orBuilder.addConstructorArgValue(managedList);
+            return orBuilder.getBeanDefinition();
+        }
+    }
+
+// Checkstyle: CyclomaticComplexity ON
+
+    /**
+     * Parse Entity elements into a builder for an {@link EntityIdPredicate}.
+     * 
+     * @param element root element to parse under
+     * 
+     * @return builder for the predicate, or null if none needed
+     */
+    @Nullable public BeanDefinitionBuilder parseEntityPredicate(@Nonnull final Element element) {
+        final List<Element> entityList =
+                ElementSupport.getChildElementsByTagNameNS(element, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+                        "Entity");
+        if (!entityList.isEmpty()) {
+            final ManagedList<String> managedEntityList = SpringSupport.getElementTextContentAsManagedList(entityList);
+            final BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(EntityIdPredicate.class);
+            builder.addConstructorArgValue(managedEntityList);
+            return builder;
+        }
+
+        return null;
+    }
+
+    /**
+     * Parse Group elements into a builder for an {@link EntityGroupNamePredicate}.
+     * 
+     * @param element root element to parse under
+     * 
+     * @return builder for the predicate, or null if none needed
+     */
+    @Nullable public BeanDefinitionBuilder parseGroupPredicate(@Nonnull final Element element) {
+
+        final List<Element> groupList =
+                ElementSupport.getChildElementsByTagNameNS(element, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+                        "Group");
+        if (!groupList.isEmpty()) {
+            final ManagedList<String> managedGroupList = SpringSupport.getElementTextContentAsManagedList(groupList);
+            final BeanDefinitionBuilder builder =
+                    BeanDefinitionBuilder.genericBeanDefinition(EntityGroupNamePredicate.class);
+            builder.addConstructorArgValue(managedGroupList);
+            return builder;
+        }
+
+        return null;
+    }
+
+    /**
+     * Parse Tag elements into a builder for an {@link EntityAttributesPredicate}.
+     * 
+     * @param element root element to parse under
+     * 
+     * @return builder for the predicate, or null if none needed
+     */
+    @Nullable public BeanDefinitionBuilder parseTagPredicate(@Nonnull final Element element) {
+        final List<Element> tagList =
+                ElementSupport.getChildElementsByTagNameNS(element, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+                        "Tag");
+        if (!tagList.isEmpty()) {
+            final ManagedList<BeanDefinition> managedTagList = new ManagedList<>(tagList.size());
+            for (final Element tag : tagList) {
+                final BeanDefinitionBuilder tagBuilder = BeanDefinitionBuilder.genericBeanDefinition(Candidate.class);
+                tagBuilder.addConstructorArgValue(StringSupport.trimOrNull(tag.getAttributeNS(null, "name")));
+                tagBuilder.addConstructorArgValue(StringSupport.trimOrNull(tag.getAttributeNS(null, "nameFormat")));
+                final List<Element> valueList =
+                        ElementSupport.getChildElementsByTagNameNS(tag,
+                                AbstractMetadataProviderParser.METADATA_NAMESPACE, "Value");
+                if (!valueList.isEmpty()) {
+                    final ManagedList<String> managedValueList =
+                            SpringSupport.getElementTextContentAsManagedList(valueList);
+                    tagBuilder.addPropertyValue("values", managedValueList);
+                }
+                managedTagList.add(tagBuilder.getBeanDefinition());
+            }
+            final BeanDefinitionBuilder builder =
+                    BeanDefinitionBuilder.genericBeanDefinition(EntityAttributesPredicate.class);
+            builder.addConstructorArgValue(managedTagList);
+            builder.addConstructorArgValue(SpringSupport.getStringValueAsBoolean(element.getAttributeNS(null, "trim")));
+            return builder;
+        }
+
+        return null;
+    }
+
+    /**
+     * Parse MappedTag elements into a builder for the relevant predicate class.
+     * 
+     * @param element root element to parse under
+     * 
+     * @return builder for the predicate, or null if none needed
+     */
+    @Nullable public BeanDefinitionBuilder parseMappedTagPredicate(@Nonnull final Element element) {
+        
+        final List<Element> tagList =
+                ElementSupport.getChildElementsByTagNameNS(element, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+                        "MappedTag");
+        if (!tagList.isEmpty()) {
+
+            if (mappedPredicateClass == null) {
+                log.warn("Ignoring MappedTag element(s) due to class instantiation failure at startup");
+                return null;
+            }
+            
+            final ManagedList<BeanDefinition> managedTagList = new ManagedList<>(tagList.size());
+            for (final Element tag : tagList) {
+                final BeanDefinitionBuilder tagBuilder = BeanDefinitionBuilder.genericBeanDefinition(Candidate.class);
+                tagBuilder.addConstructorArgValue(StringSupport.trimOrNull(tag.getAttributeNS(null, "name")));
+                final List<Element> valueList =
+                        ElementSupport.getChildElementsByTagNameNS(tag,
+                                AbstractMetadataProviderParser.METADATA_NAMESPACE, "Value");
+                if (!valueList.isEmpty()) {
+                    final ManagedList<String> managedValueList =
+                            SpringSupport.getElementTextContentAsManagedList(valueList);
+                    tagBuilder.addPropertyValue("values", managedValueList);
+                }
+                managedTagList.add(tagBuilder.getBeanDefinition());
+            }
+            final BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(mappedPredicateClass);
+            builder.addConstructorArgValue(managedTagList);
+            builder.addConstructorArgValue(StringSupport.trimOrNull(element.getAttributeNS(null, "trim")));
+            return builder;
+        }
+
+        return null;
+    }    
+
+    /**
+     * Parse ConditionScript elements into a builder, wrapped in an OR as necessary.
+     * 
+     * @param element root element to parse under
+     * 
+     * @return builder for the predicate, or null if none needed
+     */
+    @Nullable public BeanDefinitionBuilder parseScripts(@Nonnull final Element element) {
+        final List<Element> scriptList =
+                ElementSupport.getChildElementsByTagNameNS(element, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+                        "ConditionScript");
+        if (scriptList.isEmpty()) {
+            return null;
+        } else if (scriptList.size() == 1) {
+            return ScriptTypeBeanParser.parseScriptType(ScriptedPredicate.class, scriptList.get(0));
+        } else {
+            final BeanDefinitionBuilder orBuilder =
+                    BeanDefinitionBuilder.rootBeanDefinition(PredicateSupport.class, "or");
+            final ManagedList<BeanDefinition> managedList = new ManagedList<>(scriptList.size());
+            for (final Element e : scriptList) {
+                managedList.add(ScriptTypeBeanParser.parseScriptType(ScriptedPredicate.class, e).getBeanDefinition());
+            }
+            orBuilder.addConstructorArgValue(managedList);
+            return orBuilder;
+        }
+    }
+    
+    /** {@inheritDoc} */
+    @Override protected boolean shouldGenerateId() {
+        return true;
+    }
+    
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list