[java-identity-provider] 26/27: Redo AttributeMappingNodeProcessor using registry.

Scott Cantor cantor.2 at osu.edu
Fri May 3 14:32:16 EDT 2019


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

scantor pushed a commit to branch feature/IDP-1434
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=368541a29d00a20bf0933967809814ed975c9b92

commit 368541a29d00a20bf0933967809814ed975c9b92
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri May 3 14:12:42 2019 -0400

    Redo AttributeMappingNodeProcessor using registry.
---
 .../impl/MappedAttributeInMetadataMatcher.java     |   2 +-
 .../impl/MappedAttributeInMetadataMatcherTest.java |   2 +-
 idp-attribute-impl/pom.xml                         |   5 -
 .../spring/AttributeMappingNodeProcessorTest.java  |  17 +-
 .../src/test/resources/logback-test.xml            |   3 +
 .../idp/attribute/resolver/filter/service.xml      |  49 +++--
 .../logic/impl/IsAttributeRequiredPredicate.java   |   2 +-
 .../NodeProcessingAttachingBeanPostProcessor.java  |  14 +-
 .../AbstractSAMLAttributeTranscoder.java           |   6 +-
 .../AttributesMapContainer.java                    |  16 +-
 .../impl/AttributeMappingNodeProcessor.java        | 232 +++++++++------------
 ...estedAttributesInAttributeConsumingService.java |  33 ++-
 12 files changed, 176 insertions(+), 205 deletions(-)

diff --git a/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcher.java b/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcher.java
index 4109814..92b8626 100644
--- a/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcher.java
+++ b/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcher.java
@@ -32,7 +32,7 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.filter.Matcher;
 import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
diff --git a/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcherTest.java b/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcherTest.java
index 9b875fa..0eb5877 100644
--- a/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcherTest.java
+++ b/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcherTest.java
@@ -44,7 +44,7 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
 import net.shibboleth.idp.attribute.filter.matcher.impl.DataSources;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 
 /**
diff --git a/idp-attribute-impl/pom.xml b/idp-attribute-impl/pom.xml
index 77f3e9f..1587f93 100644
--- a/idp-attribute-impl/pom.xml
+++ b/idp-attribute-impl/pom.xml
@@ -30,11 +30,6 @@
             <version>${project.version}</version>
         </dependency>
 
-        <dependency>
-            <groupId>net.shibboleth.ext</groupId>
-            <artifactId>spring-extensions</artifactId>
-        </dependency>
-
         <!-- Provided Dependencies -->
 
         <!-- Runtime Dependencies -->
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMappingNodeProcessorTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMappingNodeProcessorTest.java
index 6fd00ff..70c654b 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMappingNodeProcessorTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMappingNodeProcessorTest.java
@@ -32,7 +32,7 @@ import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.springframework.context.support.ConversionServiceFactoryBean;
 import org.springframework.context.support.GenericApplicationContext;
-import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -43,8 +43,8 @@ import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.idp.saml.metadata.impl.AttributeMappingNodeProcessor;
 import net.shibboleth.utilities.java.support.service.ReloadableService;
 
@@ -55,13 +55,13 @@ public class AttributeMappingNodeProcessorTest extends XMLObjectBaseTestCase {
 
     private EntityDescriptor entityDescriptor;
 
-    private ReloadableService<AttributeResolver> service;
+    private ReloadableService<AttributeTranscoderRegistry> service;
 
     private AttributeMappingNodeProcessor processor;
 
     private GenericApplicationContext pendingTeardownContext = null;
     
-    @AfterMethod public void tearDownTestContext() {
+    @AfterClass public void tearDownTestContext() {
         if (null == pendingTeardownContext ) {
             return;
         }
@@ -82,7 +82,7 @@ public class AttributeMappingNodeProcessorTest extends XMLObjectBaseTestCase {
         processor = new AttributeMappingNodeProcessor(service);
     }
 
-    private ReloadableService<AttributeResolver> getService() {
+    private ReloadableService<AttributeTranscoderRegistry> getService() {
         GenericApplicationContext context = new GenericApplicationContext();
         setTestContext(context);
         context.setDisplayName("ApplicationContext: ");
@@ -100,8 +100,7 @@ public class AttributeMappingNodeProcessorTest extends XMLObjectBaseTestCase {
         beanDefinitionReader.loadBeanDefinitions("/net/shibboleth/idp/attribute/resolver/filter/service.xml");
         context.refresh();
 
-        final ReloadableService<AttributeResolver> attributeResolverService = context.getBean(ReloadableService.class);
-        return attributeResolverService;
+        return context.getBean(ReloadableService.class);
     }
 
     @Test public void entityAttributes() throws FilterException {
@@ -138,7 +137,7 @@ public class AttributeMappingNodeProcessorTest extends XMLObjectBaseTestCase {
 
         final AttributesMapContainer container = acs.getObjectMetadata().get(AttributesMapContainer.class).get(0);
 
-        final Multimap<String, IdPRequestedAttribute> map = container.get();
+        final Multimap<String,IdPRequestedAttribute> map = container.get();
 
         assertEquals(map.size(), 3);
 
diff --git a/idp-attribute-resolver-spring/src/test/resources/logback-test.xml b/idp-attribute-resolver-spring/src/test/resources/logback-test.xml
index bc9eaee..5c5330f 100644
--- a/idp-attribute-resolver-spring/src/test/resources/logback-test.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/logback-test.xml
@@ -2,8 +2,11 @@
 
 <configuration>
     <logger name="net.shibboleth.idp.attribute.resolver.spring" level="DEBUG"/>
+    <logger name="net.shibboleth.idp.attribute.transcoding.spring" level="DEBUG"/>
     <logger name="net.shibboleth.idp.attribute.resolver" level="DEBUG"/>
+    <logger name="net.shibboleth.idp.attribute.transcoding" level="DEBUG"/>
     <logger name="net.shibboleth.idp.saml.attribute.resolver" level="DEBUG"/>
+    <logger name="net.shibboleth.idp.saml.attribute.transcoding" level="DEBUG"/>
     <logger name="net.shibboleth.ext.spring" level="DEBUG"/>
     <logger name="net.shibboleth.ext.spring.util" level="DEBUG"/>
     <logger name="org.springframework" level="WARN"/>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/filter/service.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/filter/service.xml
index 0a82971..2dfc86e 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/filter/service.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/filter/service.xml
@@ -5,30 +5,17 @@
 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
 	default-init-method="initialize" default-destroy-method="destroy">
-	<bean id="shibboleth.VelocityEngine"
-		class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
-		<property name="velocityProperties">
-			<props>
-				<prop key="resource.loader">classpath, string</prop>
-				<prop key="classpath.resource.loader.class">
-					org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
-				</prop>
-				<prop key="string.resource.loader.class">
-					org.apache.velocity.runtime.resource.loader.StringResourceLoader
-				</prop>
-			</props>
-		</property>
-	</bean>
-	<bean id="shibboleth.AttributeResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+
+	<bean id="shibboleth.AttributeRegistryService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
 		depends-on="shibboleth.VelocityEngine" p:failFast="true"
 		p:reloadCheckDelay="0">
 
 		<constructor-arg name="claz"
-			value="net.shibboleth.idp.attribute.resolver.AttributeResolver" />
+			value="net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry" />
 		<constructor-arg name="strategy">
-			<bean
-				class="net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverServiceStrategy"
-				p:id="ShibbolethAttributeResolver" />
+			<bean class="net.shibboleth.idp.attribute.transcoding.spring.impl.AttributeRegistryServiceStrategy"
+				p:id="shibboleth.AttributeRegistryService"
+				p:namingRegistry="DefaultNamingRegistry" />
 		</constructor-arg>
 		<property name="serviceConfigurations">
 			<util:list>
@@ -38,4 +25,28 @@
 		</property>
 	</bean>
 
+    <util:map id="DefaultNamingRegistry">
+        <entry key="#{T(org.opensaml.saml.saml2.core.Attribute)}">
+            <bean class="net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder.NamingFunction" />
+        </entry>
+        <entry key="#{T(org.opensaml.saml.saml1.core.AttributeDesignator)}">
+            <bean class="net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder.NamingFunction" />
+        </entry>
+    </util:map>
+
+    <bean id="shibboleth.VelocityEngine"
+        class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
+        <property name="velocityProperties">
+            <props>
+                <prop key="resource.loader">classpath, string</prop>
+                <prop key="classpath.resource.loader.class">
+                    org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
+                </prop>
+                <prop key="string.resource.loader.class">
+                    org.apache.velocity.runtime.resource.loader.StringResourceLoader
+                </prop>
+            </props>
+        </property>
+    </bean>
+
 </beans>
\ No newline at end of file
diff --git a/idp-consent-impl/src/main/java/net/shibboleth/idp/consent/logic/impl/IsAttributeRequiredPredicate.java b/idp-consent-impl/src/main/java/net/shibboleth/idp/consent/logic/impl/IsAttributeRequiredPredicate.java
index d64bf06..a23ae41 100644
--- a/idp-consent-impl/src/main/java/net/shibboleth/idp/consent/logic/impl/IsAttributeRequiredPredicate.java
+++ b/idp-consent-impl/src/main/java/net/shibboleth/idp/consent/logic/impl/IsAttributeRequiredPredicate.java
@@ -40,7 +40,7 @@ import com.google.common.collect.Multimap;
 
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.utilities.java.support.logic.Predicate;
 
 /**
diff --git a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/impl/NodeProcessingAttachingBeanPostProcessor.java b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/impl/NodeProcessingAttachingBeanPostProcessor.java
index 4610805..79be3bb 100644
--- a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/impl/NodeProcessingAttachingBeanPostProcessor.java
+++ b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/impl/NodeProcessingAttachingBeanPostProcessor.java
@@ -33,7 +33,7 @@ import org.opensaml.saml.metadata.resolver.filter.impl.NodeProcessingMetadataFil
 import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.saml.metadata.RelyingPartyMetadataProvider;
 import net.shibboleth.idp.saml.metadata.impl.AttributeMappingNodeProcessor;
 import net.shibboleth.idp.saml.security.impl.KeyAuthorityNodeProcessor;
@@ -52,8 +52,8 @@ import net.shibboleth.utilities.java.support.service.ReloadableService;
  */
 public class NodeProcessingAttachingBeanPostProcessor implements BeanPostProcessor {
 
-    /** The attribute resolver we use to map attributes. */
-    @Nullable private final ReloadableService<AttributeResolver> atributeResolverService;
+    /** The registry of decoding rules. */
+    @Nullable private final ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
 
     /**
      * Constructor.
@@ -61,8 +61,8 @@ public class NodeProcessingAttachingBeanPostProcessor implements BeanPostProcess
      * @param service the attribute resolver we use to map attributes
      */
     public NodeProcessingAttachingBeanPostProcessor(
-            @Nullable @ParameterName(name="service") final ReloadableService<AttributeResolver> service) {
-        atributeResolverService = service;
+            @Nullable @ParameterName(name="service") final ReloadableService<AttributeTranscoderRegistry> service) {
+        transcoderRegistry = service;
     }
 
     // Checkstyle: CyclomaticComplexity OFF
@@ -96,8 +96,8 @@ public class NodeProcessingAttachingBeanPostProcessor implements BeanPostProcess
             final NodeProcessingMetadataFilter filterToAttach = new NodeProcessingMetadataFilter();
             final List<MetadataNodeProcessor> processors = new ArrayList<>(
                     Arrays.asList(new EntitiesDescriptorNameProcessor(), new KeyAuthorityNodeProcessor()));
-            if (null != atributeResolverService) {
-                processors.add(new AttributeMappingNodeProcessor(atributeResolverService));
+            if (null != transcoderRegistry) {
+                processors.add(new AttributeMappingNodeProcessor(transcoderRegistry));
             }
             filterToAttach.setNodeProcessors(processors);
             try {
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
index 137b119..33f15c6 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
@@ -132,8 +132,10 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
                 idpAttributeValues.add(idpAttributeValue);
             }
         }
-        
-        log.debug("Decoded {} values for attribute {}", idpAttributeValues.size(), attributeName);
+
+        if (!idpAttributeValues.isEmpty()) {
+            log.debug("Decoded {} values for attribute {}", idpAttributeValues.size(), attributeName);
+        }
         return buildIdPAttribute(profileRequestContext, input, properties, idpAttributeValues);
     }
 
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapContainer.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AttributesMapContainer.java
similarity index 74%
rename from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapContainer.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AttributesMapContainer.java
index 3c7bb17..d27a1df 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapContainer.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AttributesMapContainer.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.saml.attribute.mapping;
+package net.shibboleth.idp.saml.attribute.transcoding;
 
 import net.shibboleth.idp.attribute.IdPAttribute;
 
@@ -23,28 +23,28 @@ import com.google.common.base.Supplier;
 import com.google.common.collect.Multimap;
 
 /**
- * Container for reverse mapped attributes. This gives us a distinguished class to look for in the
+ * Container for decoded attributes. This gives us a distinguished class to look for in the
  * {@link org.opensaml.core.xml.XMLObject#getObjectMetadata()}.
  * 
- * @param <OutType> The type of attribute we are mapping to.
+ * @param <OutType> The type of object decoded
  */
-public class AttributesMapContainer<OutType extends IdPAttribute> implements Supplier<Multimap<String, OutType>> {
+public class AttributesMapContainer<OutType extends IdPAttribute> implements Supplier<Multimap<String,OutType>> {
 
     /** The map we are encapsulating.*/
-    private final Multimap<String, OutType> providedValue;
+    private final Multimap<String,OutType> providedValue;
 
     /**
      * Constructor.
      * 
      * @param value the value to return.
      */
-    public AttributesMapContainer(final Multimap<String, OutType> value) {
+    public AttributesMapContainer(final Multimap<String,OutType> value) {
         providedValue = value;
     }
 
     /** {@inheritDoc} */
-    @Override public Multimap<String, OutType> get() {
+    @Override public Multimap<String,OutType> get() {
         return providedValue;
     }
 
-}
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
index 1fe014d..919434f 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
@@ -17,21 +17,22 @@
 
 package net.shibboleth.idp.saml.metadata.impl;
 
-import java.time.Instant;
-import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Properties;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
+import net.shibboleth.idp.attribute.AttributeDecodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
-import net.shibboleth.idp.saml.attribute.mapping.impl.RequestedAttributesMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.SAML2AttributesMapper;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 import net.shibboleth.utilities.java.support.service.ReloadableService;
 import net.shibboleth.utilities.java.support.service.ServiceableComponent;
@@ -48,6 +49,7 @@ import org.opensaml.saml.saml2.metadata.RequestedAttribute;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 
 /**
@@ -60,178 +62,138 @@ public class AttributeMappingNodeProcessor implements MetadataNodeProcessor {
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeMappingNodeProcessor.class);
 
-    /** Service used to get the resolver used to fetch attributes. */
-    @Nonnull private final ReloadableService<AttributeResolver> attributeResolverService;
-
-    /** Whether the last invocation of {@link #refreshMappers()} failed. */
-    @Nonnull private boolean refreshFailed;
-
-    /** Cached RequestedAttributeMapper. */
-    @Nullable private RequestedAttributesMapper requestedAttributesMapper;
-
-    /** Cached AttributeMapper. */
-    @Nullable private SAML2AttributesMapper attributesMapper;
-
-    /** Date when the cache was last refreshed. */
-    @Nullable private Instant lastReload;
+    /** Service used to get the registry of decoding rules. */
+    @Nonnull private final ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
 
     /**
      * Constructor.
      * 
-     * @param resolverService the service for the attribute resolver we are to derive unmapping info from
-     */
-    public AttributeMappingNodeProcessor(@Nonnull final ReloadableService<AttributeResolver> resolverService) {
-        attributeResolverService = Constraint.isNotNull(resolverService, "AttributeResolver cannot be null");
-    }
-
-    /**
-     * Get the current RequestedAttributesMapper.
-     * 
-     * @return Returns the mapper.
-     */
-    public RequestedAttributesMapper getRequestedAttributesMapper() {
-        return requestedAttributesMapper;
-    }
-
-    /**
-     * Set the current RequestedAttributesMapper.
-     * 
-     * @param mapper what to set.
+     * @param registry the service for the decoding rules
      */
-    public void setRequestedAttributesMapper(@Nullable final RequestedAttributesMapper mapper) {
-        requestedAttributesMapper = mapper;
+    public AttributeMappingNodeProcessor(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
+        transcoderRegistry = Constraint.isNotNull(registry, "AttributeTranscoderRegistry cannot be null");
     }
-
-    /**
-     * Get the current AttributesMapper.
-     * 
-     * @return Returns the mapper.
-     */
-    public SAML2AttributesMapper getAttributesMapper() {
-        return attributesMapper;
-    }
-
-    /**
-     * Set the current AttributesMapper.
-     * 
-     * @param mapper what to set.
-     */
-    public void setAttributesMapper(@Nullable final SAML2AttributesMapper mapper) {
-        attributesMapper = mapper;
-    }
-
-    /**
-     * Inspect the service and see whether we need to reload the mappers.
-     * 
-     * @throws FilterException if the mapping generation fails
-     */
-    protected void refreshMappers() throws FilterException {
-        if (lastReload != null && lastReload.equals(attributeResolverService.getLastSuccessfulReloadInstant())) {
-            // Nothing has changed since we last reloaded.
-            return;
-        }
-
-        // Reload
-        ServiceableComponent<AttributeResolver> component = null;
-        RequestedAttributesMapper ram = null;
-        SAML2AttributesMapper am = null;
+    
+    /** {@inheritDoc} */
+    @Override public void process(final XMLObject metadataNode) throws FilterException {
+        
+        ServiceableComponent<AttributeTranscoderRegistry> component = null;
+        
         try {
-            // get date before we get the component. That way we'll not leak changes.
-            final Instant when = attributeResolverService.getLastSuccessfulReloadInstant();
-            component = attributeResolverService.getServiceableComponent();
-            if (null == component) {
-                if (!refreshFailed) {
-                    log.error("Requested Attributes Mapper: Invalid Attribute resolver configuration.");
+            if (metadataNode instanceof AttributeConsumingService) {
+                component = transcoderRegistry.getServiceableComponent();
+                if (component == null) {
+                    log.error("Attribute transcoding service unavailable");
+                } else {
+                    handleAttributeConsumingService(component.getComponent(), (AttributeConsumingService) metadataNode);
+                }
+            } else if (metadataNode instanceof EntityDescriptor) {
+                component = transcoderRegistry.getServiceableComponent();
+                if (component == null) {
+                    log.error("Attribute transcoding service unavailable");
+                } else {
+                    handleEntityDescriptor(component.getComponent(), (EntityDescriptor) metadataNode);
                 }
-                refreshFailed = true;
-            } else {
-                final AttributeResolver attributeResolver = component.getComponent();
-                ram = new RequestedAttributesMapper(attributeResolver);
-                am = new SAML2AttributesMapper(attributeResolver);
-
-                refreshFailed = false;
-                lastReload = when;
             }
         } finally {
-            if (null != component) {
+            if (component != null) {
                 component.unpinComponent();
             }
         }
-        try {
-            if (null != ram) {
-                ram.initialize();
-            }
-            if (null != am) {
-                am.initialize();
-            }
-        } catch (final ComponentInitializationException e) {
-            throw new FilterException(e);
-        }
-        setRequestedAttributesMapper(ram);
-        setAttributesMapper(am);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void process(final XMLObject metadataNode) throws FilterException {
-        refreshMappers();
-        if (metadataNode instanceof AttributeConsumingService) {
-
-            handleAttributeConsumingService((AttributeConsumingService) metadataNode);
-
-        } else if (metadataNode instanceof EntityDescriptor) {
-            handleEntityDescriptor((EntityDescriptor) metadataNode);
-        }
     }
 
     /**
      * Look inside the {@link AttributeConsumingService} for any {@link RequestedAttribute}s and map them.
      * 
+     * @param registry the registry service
      * @param acs the {@link AttributeConsumingService} to look at
      */
-//CheckStyle: ReturnCount OFF
-    private void handleAttributeConsumingService(final AttributeConsumingService acs) {
+    private void handleAttributeConsumingService(@Nonnull final AttributeTranscoderRegistry registry,
+            @Nonnull final AttributeConsumingService acs) {
+        
         final List<RequestedAttribute> requestedAttributes = acs.getRequestAttributes();
-        final RequestedAttributesMapper mapper = getRequestedAttributesMapper();
-        if (null == requestedAttributes || requestedAttributes.isEmpty() || null == mapper) {
+        if (null == requestedAttributes || requestedAttributes.isEmpty()) {
             return;
         }
-        final Multimap<String, IdPRequestedAttribute> maps = mapper.mapAttributes(requestedAttributes);
-        if (null == maps || maps.isEmpty()) {
-            return;
+        
+        final Multimap<String,IdPAttribute> results = HashMultimap.create();
+        for (final RequestedAttribute req : requestedAttributes) {
+            try {
+                decodeAttribute(registry, req, results);
+            } catch (final AttributeDecodingException e) {
+                log.warn("Error decoding RequestedAttribute '{}'", req.getName(), e);
+            }
+        }
+        
+        if (!results.isEmpty()) {
+            acs.getObjectMetadata().put(new AttributesMapContainer<>(results));
         }
-        acs.getObjectMetadata().put(new AttributesMapContainer<>(maps));
     }
-//CheckStyle: ReturnCount ON
 
     /**
      * Look inside the {@link EntityDescriptor} for entities Attributes and map them.
      * 
+     * @param registry the registry service
      * @param entity the entity
      */
 //CheckStyle: ReturnCount OFF
-    private void handleEntityDescriptor(final EntityDescriptor entity) {
-        final SAML2AttributesMapper mapper = getAttributesMapper();
+    private void handleEntityDescriptor(@Nonnull final AttributeTranscoderRegistry registry,
+            @Nonnull final EntityDescriptor entity) {
         final Extensions extensions = entity.getExtensions();
-        if (null == extensions || null == mapper) {
+        if (null == extensions) {
             return;
         }
+        
         final List<XMLObject> entityAttributesList =
                 extensions.getUnknownXMLObjects(EntityAttributes.DEFAULT_ELEMENT_NAME);
         if (null == entityAttributesList || entityAttributesList.isEmpty()) {
             return;
         }
-        final List<Attribute> entityAttributes = new ArrayList<>();
+        
+        final Multimap<String,IdPAttribute> results = HashMultimap.create();
+        
         for (final XMLObject xmlObj : entityAttributesList) {
             if (xmlObj instanceof EntityAttributes) {
                 final EntityAttributes ea = (EntityAttributes) xmlObj;
-                entityAttributes.addAll(ea.getAttributes());
+                for (final Attribute attr : ea.getAttributes()) {
+                    try {
+                        decodeAttribute(registry, attr, results);
+                    } catch (final AttributeDecodingException e) {
+                        log.warn("Error decoding RequestedAttribute '{}'", attr.getName(), e);
+                    }
+                }
             }
         }
-        final Multimap<String, IdPAttribute> maps = mapper.mapAttributes(entityAttributes);
-        if (null == maps || maps.isEmpty()) {
-            return;
+        
+        if (!results.isEmpty()) {
+            entity.getObjectMetadata().put(new AttributesMapContainer<>(results));
         }
-        entity.getObjectMetadata().put(new AttributesMapContainer<>(maps));
     }
   //CheckStyle: ReturnCount ON
-}
+
+    /**
+     * Access the registry of transcoding rules to decode the input object.
+     * 
+     * @param <T> input type
+     * @param registry  registry of transcoding rules
+     * @param input input object
+     * @param results collection to add results to
+     * 
+     * @throws AttributeDecodingException if an error occurs or no results were obtained
+     */
+    protected <T> void decodeAttribute(@Nonnull final AttributeTranscoderRegistry registry,
+            @Nonnull final T input, @Nonnull @NonnullElements @Live final Multimap<String,IdPAttribute> results)
+                    throws AttributeDecodingException {
+        
+        final Collection<Properties> rulesets = registry.getTranscodingProperties(input);
+        
+        for (final Properties rules : rulesets) {
+            final AttributeTranscoder<T> transcoder = TranscoderSupport.getTranscoder(rules);
+            final IdPAttribute decodedAttribute = transcoder.decode(null, input, rules);
+            if (decodedAttribute != null) {
+                results.put(decodedAttribute.getId(), decodedAttribute);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
index 6590239..d4f4d0c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
@@ -22,9 +22,9 @@ import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.profile.AbstractProfileAction;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapContainer;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.idp.saml.metadata.impl.AttributeMappingNodeProcessor;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 import net.shibboleth.utilities.java.support.service.ReloadableService;
@@ -55,8 +55,8 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
     @Nonnull private Function<ProfileRequestContext, AttributeConsumingServiceContext>
         attributeConsumingServiceContextLookupStrategy;
 
-    /** The attribute resolver we use to map attributes. */
-    @Nullable private ReloadableService<AttributeResolver> attributeResolverService;
+    /** The registry of decoding rules. */
+    @Nullable private ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
 
     /** The context we use to get and put the {@link AttributeConsumingService}.*/
     private AttributeConsumingServiceContext acsContext;
@@ -65,7 +65,6 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
      * Constructor.
      */
     public MapRequestedAttributesInAttributeConsumingService() {
-        super();
         // At this point, by default  the SAMLMetadataContext hangs off the SAMLPeerContext
         attributeConsumingServiceContextLookupStrategy =
                 new ChildContextLookup(AttributeConsumingServiceContext.class).compose(
@@ -86,12 +85,12 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
     }
 
     /**
-     * Sets the service which does the attribute mapping.
+     * Sets the service which provides attribute decoding rules.
      *
-     * @param resolverService the service for the attribute resolver we are to derive unmapping info from
+     * @param registry the registry service
      */
-    public void setResolverService(@Nonnull final ReloadableService<AttributeResolver> resolverService) {
-        attributeResolverService = Constraint.isNotNull(resolverService, "AttributeResolver cannot be null");
+    public void setTranscoderRegistry(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
+        transcoderRegistry = Constraint.isNotNull(registry, "AttributeResolver cannot be null");
     }
 
     /** {@inheritDoc} */
@@ -112,23 +111,23 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
 
         final AttributeConsumingService acs = acsContext.getAttributeConsumingService();
         if (acs == null) {
-            log.trace("{} no AttributeConsumingService to map", getLogPrefix());
+            log.trace("{} No AttributeConsumingService to map", getLogPrefix());
             return;
         }
         
-        if (acs.getRequestAttributes().isEmpty() ||
-            acs.getObjectMetadata().containsKey(AttributesMapContainer.class) ||
-            acs.getParent() != null) {
-            log.trace("{} skipping mapping for AttributeConsumingService", getLogPrefix());
+        if (acs.getRequestAttributes().isEmpty() || acs.getObjectMetadata().containsKey(AttributesMapContainer.class) ||
+                acs.getParent() != null) {
+            log.trace("{} Skipping decode of AttributeConsumingService", getLogPrefix());
             // Nothing to map, already mapped, or attached to metadata (and hence already scanned)
             return;
         }
+        
         try {
-            final AttributeMappingNodeProcessor processor = new AttributeMappingNodeProcessor(attributeResolverService);
-            log.debug("{} mapping requested Attributes for generated AttributeConsumingService", getLogPrefix());
+            final AttributeMappingNodeProcessor processor = new AttributeMappingNodeProcessor(transcoderRegistry);
+            log.debug("{} Decoding RequestedAttributes for generated AttributeConsumingService", getLogPrefix());
             processor.process(acs);
         } catch (final FilterException e) {
-            log.error("{} Error mapping Attributesresponding to request", getLogPrefix(), e);
+            log.error("{} Error decoding RequestedAttributes", getLogPrefix(), e);
             ActionSupport.buildEvent(profileRequestContext, EventIds.RUNTIME_EXCEPTION);
         }
     }

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


More information about the commits mailing list